ASoC: meson: axg-fifo: fix fifo threshold setup
[platform/kernel/linux-starfive.git] / sound / soc / meson / axg-fifo.c
index 772eda8..4365086 100644 (file)
@@ -113,8 +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;
+
+       period = params_period_bytes(params);
 
        /* Setup dma memory pointers */
        end_ptr = runtime->dma_addr + runtime->dma_bytes - AXG_FIFO_BURST;
@@ -122,9 +124,25 @@ 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,
+                       (unsigned int)AXG_FIFO_MIN_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),
@@ -347,6 +365,11 @@ 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);
+
        return devm_snd_soc_register_component(dev, data->component_drv,
                                               data->dai_drv, 1);
 }