diff options
Diffstat (limited to 'sound/soc/meson/axg-fifo.c')
-rw-r--r-- | sound/soc/meson/axg-fifo.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index d6f3eefb8f09..c12b0d5e8ebf 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -34,7 +34,7 @@ static struct snd_pcm_hardware axg_fifo_hw = { .rate_max = 192000, .channels_min = 1, .channels_max = AXG_FIFO_CH_MAX, - .period_bytes_min = AXG_FIFO_MIN_DEPTH, + .period_bytes_min = AXG_FIFO_BURST, .period_bytes_max = UINT_MAX, .periods_min = 2, .periods_max = UINT_MAX, @@ -113,13 +113,10 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = ss->runtime; struct axg_fifo *fifo = axg_fifo_data(ss); + unsigned int burst_num, period, threshold; dma_addr_t end_ptr; - unsigned int burst_num; - int ret; - ret = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(params)); - if (ret < 0) - return ret; + period = params_period_bytes(params); /* Setup dma memory pointers */ end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST; @@ -127,9 +124,24 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, regmap_write(fifo->map, FIFO_FINISH_ADDR, end_ptr); /* Setup interrupt periodicity */ - burst_num = params_period_bytes(params) / AXG_FIFO_BURST; + burst_num = period / AXG_FIFO_BURST; regmap_write(fifo->map, FIFO_INT_ADDR, burst_num); + /* + * Start the fifo request on the smallest of the following: + * - Half the fifo size + * - Half the period size + */ + threshold = min(period / 2, fifo->depth / 2); + + /* + * With the threshold in bytes, register value is: + * V = (threshold / burst) - 1 + */ + threshold /= AXG_FIFO_BURST; + regmap_field_write(fifo->field_threshold, + threshold ? threshold - 1 : 0); + /* Enable block count irq */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), @@ -167,7 +179,7 @@ int axg_fifo_pcm_hw_free(struct snd_soc_component *component, regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), 0); - return snd_pcm_lib_free_pages(ss); + return 0; } EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free); @@ -215,17 +227,17 @@ int axg_fifo_pcm_open(struct snd_soc_component *component, /* * Make sure the buffer and period size are multiple of the FIFO - * minimum depth size + * burst */ ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret; ret = snd_pcm_hw_constraint_step(ss->runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, - AXG_FIFO_MIN_DEPTH); + AXG_FIFO_BURST); if (ret) return ret; @@ -287,9 +299,9 @@ int axg_fifo_pcm_new(struct snd_soc_pcm_runtime *rtd, unsigned int type) struct snd_card *card = rtd->card->snd_card; size_t size = axg_fifo_hw.buffer_bytes_max; - snd_pcm_lib_preallocate_pages(rtd->pcm->streams[type].substream, - SNDRV_DMA_TYPE_DEV, card->dev, - size, size); + snd_pcm_set_managed_buffer(rtd->pcm->streams[type].substream, + SNDRV_DMA_TYPE_DEV, card->dev, + size, size); return 0; } EXPORT_SYMBOL_GPL(axg_fifo_pcm_new); @@ -307,6 +319,7 @@ int axg_fifo_probe(struct platform_device *pdev) const struct axg_fifo_match_data *data; struct axg_fifo *fifo; void __iomem *regs; + int ret; data = of_device_get_match_data(dev); if (!data) { @@ -352,6 +365,26 @@ int axg_fifo_probe(struct platform_device *pdev) return fifo->irq; } + fifo->field_threshold = + devm_regmap_field_alloc(dev, fifo->map, data->field_threshold); + if (IS_ERR(fifo->field_threshold)) + return PTR_ERR(fifo->field_threshold); + + ret = of_property_read_u32(dev->of_node, "amlogic,fifo-depth", + &fifo->depth); + if (ret) { + /* Error out for anything but a missing property */ + if (ret != -EINVAL) + return ret; + /* + * If the property is missing, it might be because of an old + * DT. In such case, assume the smallest known fifo depth + */ + fifo->depth = 256; + dev_warn(dev, "fifo depth not found, assume %u bytes\n", + fifo->depth); + } + return devm_snd_soc_register_component(dev, data->component_drv, data->dai_drv, 1); } |