1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
3 // Copyright (c) 2018 BayLibre, SAS.
4 // Author: Jerome Brunet <jbrunet@baylibre.com>
7 #include <linux/of_irq.h>
8 #include <linux/of_platform.h>
9 #include <linux/module.h>
10 #include <linux/regmap.h>
11 #include <linux/reset.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include <sound/soc-dai.h>
19 * This file implements the platform operations common to the playback and
20 * capture frontend DAI. The logic behind this two types of fifo is very
21 * similar but some difference exist.
22 * These differences are handled in the respective DAI drivers
25 static struct snd_pcm_hardware axg_fifo_hw
= {
26 .info
= (SNDRV_PCM_INFO_INTERLEAVED
|
28 SNDRV_PCM_INFO_MMAP_VALID
|
29 SNDRV_PCM_INFO_BLOCK_TRANSFER
|
30 SNDRV_PCM_INFO_PAUSE
),
32 .formats
= AXG_FIFO_FORMATS
,
36 .channels_max
= AXG_FIFO_CH_MAX
,
37 .period_bytes_min
= AXG_FIFO_BURST
,
38 .period_bytes_max
= UINT_MAX
,
40 .periods_max
= UINT_MAX
,
42 /* No real justification for this */
43 .buffer_bytes_max
= 1 * 1024 * 1024,
46 static struct snd_soc_dai
*axg_fifo_dai(struct snd_pcm_substream
*ss
)
48 struct snd_soc_pcm_runtime
*rtd
= ss
->private_data
;
50 return asoc_rtd_to_cpu(rtd
, 0);
53 static struct axg_fifo
*axg_fifo_data(struct snd_pcm_substream
*ss
)
55 struct snd_soc_dai
*dai
= axg_fifo_dai(ss
);
57 return snd_soc_dai_get_drvdata(dai
);
60 static struct device
*axg_fifo_dev(struct snd_pcm_substream
*ss
)
62 struct snd_soc_dai
*dai
= axg_fifo_dai(ss
);
67 static void __dma_enable(struct axg_fifo
*fifo
, bool enable
)
69 regmap_update_bits(fifo
->map
, FIFO_CTRL0
, CTRL0_DMA_EN
,
70 enable
? CTRL0_DMA_EN
: 0);
73 int axg_fifo_pcm_trigger(struct snd_soc_component
*component
,
74 struct snd_pcm_substream
*ss
, int cmd
)
76 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
79 case SNDRV_PCM_TRIGGER_START
:
80 case SNDRV_PCM_TRIGGER_RESUME
:
81 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
82 __dma_enable(fifo
, true);
84 case SNDRV_PCM_TRIGGER_SUSPEND
:
85 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
86 case SNDRV_PCM_TRIGGER_STOP
:
87 __dma_enable(fifo
, false);
95 EXPORT_SYMBOL_GPL(axg_fifo_pcm_trigger
);
97 snd_pcm_uframes_t
axg_fifo_pcm_pointer(struct snd_soc_component
*component
,
98 struct snd_pcm_substream
*ss
)
100 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
101 struct snd_pcm_runtime
*runtime
= ss
->runtime
;
104 regmap_read(fifo
->map
, FIFO_STATUS2
, &addr
);
106 return bytes_to_frames(runtime
, addr
- (unsigned int)runtime
->dma_addr
);
108 EXPORT_SYMBOL_GPL(axg_fifo_pcm_pointer
);
110 int axg_fifo_pcm_hw_params(struct snd_soc_component
*component
,
111 struct snd_pcm_substream
*ss
,
112 struct snd_pcm_hw_params
*params
)
114 struct snd_pcm_runtime
*runtime
= ss
->runtime
;
115 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
116 unsigned int burst_num
, period
, threshold
;
119 period
= params_period_bytes(params
);
121 /* Setup dma memory pointers */
122 end_ptr
= runtime
->dma_addr
+ runtime
->dma_bytes
- AXG_FIFO_BURST
;
123 regmap_write(fifo
->map
, FIFO_START_ADDR
, runtime
->dma_addr
);
124 regmap_write(fifo
->map
, FIFO_FINISH_ADDR
, end_ptr
);
126 /* Setup interrupt periodicity */
127 burst_num
= period
/ AXG_FIFO_BURST
;
128 regmap_write(fifo
->map
, FIFO_INT_ADDR
, burst_num
);
131 * Start the fifo request on the smallest of the following:
132 * - Half the fifo size
133 * - Half the period size
135 threshold
= min(period
/ 2, fifo
->depth
/ 2);
138 * With the threshold in bytes, register value is:
139 * V = (threshold / burst) - 1
141 threshold
/= AXG_FIFO_BURST
;
142 regmap_field_write(fifo
->field_threshold
,
143 threshold
? threshold
- 1 : 0);
145 /* Enable block count irq */
146 regmap_update_bits(fifo
->map
, FIFO_CTRL0
,
147 CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT
),
148 CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT
));
152 EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_params
);
154 int g12a_fifo_pcm_hw_params(struct snd_soc_component
*component
,
155 struct snd_pcm_substream
*ss
,
156 struct snd_pcm_hw_params
*params
)
158 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
159 struct snd_pcm_runtime
*runtime
= ss
->runtime
;
162 ret
= axg_fifo_pcm_hw_params(component
, ss
, params
);
166 /* Set the initial memory address of the DMA */
167 regmap_write(fifo
->map
, FIFO_INIT_ADDR
, runtime
->dma_addr
);
171 EXPORT_SYMBOL_GPL(g12a_fifo_pcm_hw_params
);
173 int axg_fifo_pcm_hw_free(struct snd_soc_component
*component
,
174 struct snd_pcm_substream
*ss
)
176 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
178 /* Disable the block count irq */
179 regmap_update_bits(fifo
->map
, FIFO_CTRL0
,
180 CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT
), 0);
184 EXPORT_SYMBOL_GPL(axg_fifo_pcm_hw_free
);
186 static void axg_fifo_ack_irq(struct axg_fifo
*fifo
, u8 mask
)
188 regmap_update_bits(fifo
->map
, FIFO_CTRL1
,
189 CTRL1_INT_CLR(FIFO_INT_MASK
),
190 CTRL1_INT_CLR(mask
));
192 /* Clear must also be cleared */
193 regmap_update_bits(fifo
->map
, FIFO_CTRL1
,
194 CTRL1_INT_CLR(FIFO_INT_MASK
),
198 static irqreturn_t
axg_fifo_pcm_irq_block(int irq
, void *dev_id
)
200 struct snd_pcm_substream
*ss
= dev_id
;
201 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
204 regmap_read(fifo
->map
, FIFO_STATUS1
, &status
);
206 status
= STATUS1_INT_STS(status
) & FIFO_INT_MASK
;
207 if (status
& FIFO_INT_COUNT_REPEAT
)
208 snd_pcm_period_elapsed(ss
);
210 dev_dbg(axg_fifo_dev(ss
), "unexpected irq - STS 0x%02x\n",
214 axg_fifo_ack_irq(fifo
, status
);
216 return IRQ_RETVAL(status
);
219 int axg_fifo_pcm_open(struct snd_soc_component
*component
,
220 struct snd_pcm_substream
*ss
)
222 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
223 struct device
*dev
= axg_fifo_dev(ss
);
226 snd_soc_set_runtime_hwparams(ss
, &axg_fifo_hw
);
229 * Make sure the buffer and period size are multiple of the FIFO
232 ret
= snd_pcm_hw_constraint_step(ss
->runtime
, 0,
233 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
238 ret
= snd_pcm_hw_constraint_step(ss
->runtime
, 0,
239 SNDRV_PCM_HW_PARAM_PERIOD_BYTES
,
244 ret
= request_irq(fifo
->irq
, axg_fifo_pcm_irq_block
, 0,
249 /* Enable pclk to access registers and clock the fifo ip */
250 ret
= clk_prepare_enable(fifo
->pclk
);
254 /* Setup status2 so it reports the memory pointer */
255 regmap_update_bits(fifo
->map
, FIFO_CTRL1
,
256 CTRL1_STATUS2_SEL_MASK
,
257 CTRL1_STATUS2_SEL(STATUS2_SEL_DDR_READ
));
259 /* Make sure the dma is initially disabled */
260 __dma_enable(fifo
, false);
262 /* Disable irqs until params are ready */
263 regmap_update_bits(fifo
->map
, FIFO_CTRL0
,
264 CTRL0_INT_EN(FIFO_INT_MASK
), 0);
266 /* Clear any pending interrupt */
267 axg_fifo_ack_irq(fifo
, FIFO_INT_MASK
);
269 /* Take memory arbitror out of reset */
270 ret
= reset_control_deassert(fifo
->arb
);
277 clk_disable_unprepare(fifo
->pclk
);
279 free_irq(fifo
->irq
, ss
);
282 EXPORT_SYMBOL_GPL(axg_fifo_pcm_open
);
284 int axg_fifo_pcm_close(struct snd_soc_component
*component
,
285 struct snd_pcm_substream
*ss
)
287 struct axg_fifo
*fifo
= axg_fifo_data(ss
);
290 /* Put the memory arbitror back in reset */
291 ret
= reset_control_assert(fifo
->arb
);
293 /* Disable fifo ip and register access */
294 clk_disable_unprepare(fifo
->pclk
);
297 free_irq(fifo
->irq
, ss
);
301 EXPORT_SYMBOL_GPL(axg_fifo_pcm_close
);
303 int axg_fifo_pcm_new(struct snd_soc_pcm_runtime
*rtd
, unsigned int type
)
305 struct snd_card
*card
= rtd
->card
->snd_card
;
306 size_t size
= axg_fifo_hw
.buffer_bytes_max
;
308 snd_pcm_set_managed_buffer(rtd
->pcm
->streams
[type
].substream
,
309 SNDRV_DMA_TYPE_DEV
, card
->dev
,
313 EXPORT_SYMBOL_GPL(axg_fifo_pcm_new
);
315 static const struct regmap_config axg_fifo_regmap_cfg
= {
319 .max_register
= FIFO_CTRL2
,
322 int axg_fifo_probe(struct platform_device
*pdev
)
324 struct device
*dev
= &pdev
->dev
;
325 const struct axg_fifo_match_data
*data
;
326 struct axg_fifo
*fifo
;
330 data
= of_device_get_match_data(dev
);
332 dev_err(dev
, "failed to match device\n");
336 fifo
= devm_kzalloc(dev
, sizeof(*fifo
), GFP_KERNEL
);
339 platform_set_drvdata(pdev
, fifo
);
341 regs
= devm_platform_ioremap_resource(pdev
, 0);
343 return PTR_ERR(regs
);
345 fifo
->map
= devm_regmap_init_mmio(dev
, regs
, &axg_fifo_regmap_cfg
);
346 if (IS_ERR(fifo
->map
)) {
347 dev_err(dev
, "failed to init regmap: %ld\n",
349 return PTR_ERR(fifo
->map
);
352 fifo
->pclk
= devm_clk_get(dev
, NULL
);
353 if (IS_ERR(fifo
->pclk
)) {
354 if (PTR_ERR(fifo
->pclk
) != -EPROBE_DEFER
)
355 dev_err(dev
, "failed to get pclk: %ld\n",
356 PTR_ERR(fifo
->pclk
));
357 return PTR_ERR(fifo
->pclk
);
360 fifo
->arb
= devm_reset_control_get_exclusive(dev
, NULL
);
361 if (IS_ERR(fifo
->arb
)) {
362 if (PTR_ERR(fifo
->arb
) != -EPROBE_DEFER
)
363 dev_err(dev
, "failed to get arb reset: %ld\n",
365 return PTR_ERR(fifo
->arb
);
368 fifo
->irq
= of_irq_get(dev
->of_node
, 0);
369 if (fifo
->irq
<= 0) {
370 dev_err(dev
, "failed to get irq: %d\n", fifo
->irq
);
374 fifo
->field_threshold
=
375 devm_regmap_field_alloc(dev
, fifo
->map
, data
->field_threshold
);
376 if (IS_ERR(fifo
->field_threshold
))
377 return PTR_ERR(fifo
->field_threshold
);
379 ret
= of_property_read_u32(dev
->of_node
, "amlogic,fifo-depth",
382 /* Error out for anything but a missing property */
386 * If the property is missing, it might be because of an old
387 * DT. In such case, assume the smallest known fifo depth
390 dev_warn(dev
, "fifo depth not found, assume %u bytes\n",
394 return devm_snd_soc_register_component(dev
, data
->component_drv
,
397 EXPORT_SYMBOL_GPL(axg_fifo_probe
);
399 MODULE_DESCRIPTION("Amlogic AXG/G12A fifo driver");
400 MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
401 MODULE_LICENSE("GPL v2");