1 // SPDX-License-Identifier: GPL-2.0
3 // Xilinx ASoC audio formatter support
5 // Copyright (C) 2018 Xilinx, Inc.
7 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
11 #include <linux/module.h>
12 #include <linux/of_address.h>
13 #include <linux/of_irq.h>
14 #include <linux/sizes.h>
16 #include <sound/asoundef.h>
17 #include <sound/soc.h>
18 #include <sound/pcm_params.h>
20 #define DRV_NAME "xlnx_formatter_pcm"
22 #define XLNX_S2MM_OFFSET 0
23 #define XLNX_MM2S_OFFSET 0x100
25 #define XLNX_AUD_CORE_CONFIG 0x4
26 #define XLNX_AUD_CTRL 0x10
27 #define XLNX_AUD_STS 0x14
29 #define AUD_CTRL_RESET_MASK BIT(1)
30 #define AUD_CFG_MM2S_MASK BIT(15)
31 #define AUD_CFG_S2MM_MASK BIT(31)
33 #define XLNX_AUD_FS_MULTIPLIER 0x18
34 #define XLNX_AUD_PERIOD_CONFIG 0x1C
35 #define XLNX_AUD_BUFF_ADDR_LSB 0x20
36 #define XLNX_AUD_BUFF_ADDR_MSB 0x24
37 #define XLNX_AUD_XFER_COUNT 0x28
38 #define XLNX_AUD_CH_STS_START 0x2C
39 #define XLNX_BYTES_PER_CH 0x44
40 #define XLNX_AUD_ALIGN_BYTES 64
42 #define AUD_STS_IOC_IRQ_MASK BIT(31)
43 #define AUD_STS_CH_STS_MASK BIT(29)
44 #define AUD_CTRL_IOC_IRQ_MASK BIT(13)
45 #define AUD_CTRL_TOUT_IRQ_MASK BIT(14)
46 #define AUD_CTRL_DMA_EN_MASK BIT(0)
48 #define CFG_MM2S_CH_MASK GENMASK(11, 8)
49 #define CFG_MM2S_CH_SHIFT 8
50 #define CFG_MM2S_XFER_MASK GENMASK(14, 13)
51 #define CFG_MM2S_XFER_SHIFT 13
52 #define CFG_MM2S_PKG_MASK BIT(12)
54 #define CFG_S2MM_CH_MASK GENMASK(27, 24)
55 #define CFG_S2MM_CH_SHIFT 24
56 #define CFG_S2MM_XFER_MASK GENMASK(30, 29)
57 #define CFG_S2MM_XFER_SHIFT 29
58 #define CFG_S2MM_PKG_MASK BIT(28)
60 #define AUD_CTRL_DATA_WIDTH_SHIFT 16
61 #define AUD_CTRL_ACTIVE_CH_SHIFT 19
62 #define PERIOD_CFG_PERIODS_SHIFT 16
66 #define PERIOD_BYTES_MIN 192
67 #define PERIOD_BYTES_MAX (50 * 1024)
68 #define XLNX_PARAM_UNKNOWN 0
78 struct xlnx_pcm_drv_data {
84 struct snd_pcm_substream *play_stream;
85 struct snd_pcm_substream *capture_stream;
91 * struct xlnx_pcm_stream_param - stream configuration
92 * @mmio: base address offset
93 * @interleaved: audio channels arrangement in buffer
94 * @xfer_mode: data formatting mode during transfer
95 * @ch_limit: Maximum channels supported
96 * @buffer_size: stream ring buffer size
98 struct xlnx_pcm_stream_param {
106 static const struct snd_pcm_hardware xlnx_pcm_hardware = {
107 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
108 SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_PAUSE |
109 SNDRV_PCM_INFO_RESUME,
110 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |
111 SNDRV_PCM_FMTBIT_S24_LE,
114 .rates = SNDRV_PCM_RATE_8000_192000,
117 .buffer_bytes_max = PERIODS_MAX * PERIOD_BYTES_MAX,
118 .period_bytes_min = PERIOD_BYTES_MIN,
119 .period_bytes_max = PERIOD_BYTES_MAX,
120 .periods_min = PERIODS_MIN,
121 .periods_max = PERIODS_MAX,
131 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val,
134 u32 padded, srate, bit_depth, status[2];
136 if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) {
137 status[0] = chsts_reg1_val & 0xff;
138 status[1] = (chsts_reg1_val >> 16) & 0xff;
140 switch (status[0] & IEC958_AES0_PRO_FS) {
141 case IEC958_AES0_PRO_FS_44100:
144 case IEC958_AES0_PRO_FS_48000:
147 case IEC958_AES0_PRO_FS_32000:
150 case IEC958_AES0_PRO_FS_NOTID:
152 srate = XLNX_PARAM_UNKNOWN;
156 switch (status[1] & IEC958_AES2_PRO_SBITS) {
157 case IEC958_AES2_PRO_WORDLEN_NOTID:
158 case IEC958_AES2_PRO_SBITS_20:
161 case IEC958_AES2_PRO_SBITS_24:
165 bit_depth = XLNX_PARAM_UNKNOWN;
169 switch (status[1] & IEC958_AES2_PRO_WORDLEN) {
170 case IEC958_AES2_PRO_WORDLEN_20_16:
171 bit_depth = 16 + padded;
173 case IEC958_AES2_PRO_WORDLEN_22_18:
174 bit_depth = 18 + padded;
176 case IEC958_AES2_PRO_WORDLEN_23_19:
177 bit_depth = 19 + padded;
179 case IEC958_AES2_PRO_WORDLEN_24_20:
180 bit_depth = 20 + padded;
182 case IEC958_AES2_PRO_WORDLEN_NOTID:
184 bit_depth = XLNX_PARAM_UNKNOWN;
189 status[0] = (chsts_reg1_val >> 24) & 0xff;
190 status[1] = chsts_reg2_val & 0xff;
192 switch (status[0] & IEC958_AES3_CON_FS) {
193 case IEC958_AES3_CON_FS_44100:
196 case IEC958_AES3_CON_FS_48000:
199 case IEC958_AES3_CON_FS_32000:
203 srate = XLNX_PARAM_UNKNOWN;
207 if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24)
212 switch (status[1] & IEC958_AES4_CON_WORDLEN) {
213 case IEC958_AES4_CON_WORDLEN_20_16:
214 bit_depth = 16 + padded;
216 case IEC958_AES4_CON_WORDLEN_22_18:
217 bit_depth = 18 + padded;
219 case IEC958_AES4_CON_WORDLEN_23_19:
220 bit_depth = 19 + padded;
222 case IEC958_AES4_CON_WORDLEN_24_20:
223 bit_depth = 20 + padded;
225 case IEC958_AES4_CON_WORDLEN_21_17:
226 bit_depth = 17 + padded;
228 case IEC958_AES4_CON_WORDLEN_NOTID:
230 bit_depth = XLNX_PARAM_UNKNOWN;
236 if (srate != XLNX_PARAM_UNKNOWN)
237 dev_info(dev, "sample rate = %d\n", srate);
239 dev_info(dev, "sample rate = unknown\n");
241 if (bit_depth != XLNX_PARAM_UNKNOWN)
242 dev_info(dev, "bit_depth = %d\n", bit_depth);
244 dev_info(dev, "bit_depth = unknown\n");
247 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base)
249 u32 val, retries = 0;
251 val = readl(mmio_base + XLNX_AUD_CTRL);
252 val |= AUD_CTRL_RESET_MASK;
253 writel(val, mmio_base + XLNX_AUD_CTRL);
255 val = readl(mmio_base + XLNX_AUD_CTRL);
256 /* Poll for maximum timeout of approximately 100ms (1 * 100)*/
257 while ((val & AUD_CTRL_RESET_MASK) && (retries < 100)) {
260 val = readl(mmio_base + XLNX_AUD_CTRL);
262 if (val & AUD_CTRL_RESET_MASK)
268 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream)
272 val = readl(mmio_base + XLNX_AUD_CTRL);
273 val &= ~AUD_CTRL_IOC_IRQ_MASK;
274 if (stream == SNDRV_PCM_STREAM_CAPTURE)
275 val &= ~AUD_CTRL_TOUT_IRQ_MASK;
277 writel(val, mmio_base + XLNX_AUD_CTRL);
280 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg)
284 struct device *dev = arg;
285 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
287 reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS;
289 if (val & AUD_STS_IOC_IRQ_MASK) {
290 writel(val & AUD_STS_IOC_IRQ_MASK, reg);
291 if (adata->play_stream)
292 snd_pcm_period_elapsed(adata->play_stream);
299 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg)
303 struct device *dev = arg;
304 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(dev);
306 reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS;
308 if (val & AUD_STS_IOC_IRQ_MASK) {
309 writel(val & AUD_STS_IOC_IRQ_MASK, reg);
310 if (adata->capture_stream)
311 snd_pcm_period_elapsed(adata->capture_stream);
318 static int xlnx_formatter_set_sysclk(struct snd_soc_component *component,
319 int clk_id, int source, unsigned int freq, int dir)
321 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
323 adata->sysclk = freq;
327 static int xlnx_formatter_pcm_open(struct snd_soc_component *component,
328 struct snd_pcm_substream *substream)
331 u32 val, data_format_mode;
332 u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift;
333 struct xlnx_pcm_stream_param *stream_data;
334 struct snd_pcm_runtime *runtime = substream->runtime;
335 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
337 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
338 !adata->mm2s_presence)
340 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
341 !adata->s2mm_presence)
344 stream_data = kzalloc(sizeof(*stream_data), GFP_KERNEL);
348 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
349 ch_count_mask = CFG_MM2S_CH_MASK;
350 ch_count_shift = CFG_MM2S_CH_SHIFT;
351 data_xfer_mode = CFG_MM2S_XFER_MASK;
352 data_xfer_shift = CFG_MM2S_XFER_SHIFT;
353 data_format_mode = CFG_MM2S_PKG_MASK;
354 stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET;
355 adata->play_stream = substream;
358 ch_count_mask = CFG_S2MM_CH_MASK;
359 ch_count_shift = CFG_S2MM_CH_SHIFT;
360 data_xfer_mode = CFG_S2MM_XFER_MASK;
361 data_xfer_shift = CFG_S2MM_XFER_SHIFT;
362 data_format_mode = CFG_S2MM_PKG_MASK;
363 stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET;
364 adata->capture_stream = substream;
367 val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG);
369 if (!(val & data_format_mode))
370 stream_data->interleaved = true;
372 stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift;
373 stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift;
374 dev_info(component->dev,
375 "stream %d : format = %d mode = %d ch_limit = %d\n",
376 substream->stream, stream_data->interleaved,
377 stream_data->xfer_mode, stream_data->ch_limit);
379 snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware);
380 runtime->private_data = stream_data;
382 /* Resize the period bytes as divisible by 64 */
383 err = snd_pcm_hw_constraint_step(runtime, 0,
384 SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
385 XLNX_AUD_ALIGN_BYTES);
387 dev_err(component->dev,
388 "Unable to set constraint on period bytes\n");
392 /* Resize the buffer bytes as divisible by 64 */
393 err = snd_pcm_hw_constraint_step(runtime, 0,
394 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
395 XLNX_AUD_ALIGN_BYTES);
397 dev_err(component->dev,
398 "Unable to set constraint on buffer bytes\n");
402 /* Set periods as integer multiple */
403 err = snd_pcm_hw_constraint_integer(runtime,
404 SNDRV_PCM_HW_PARAM_PERIODS);
406 dev_err(component->dev,
407 "Unable to set constraint on periods to be integer\n");
411 /* enable DMA IOC irq */
412 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
413 val |= AUD_CTRL_IOC_IRQ_MASK;
414 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
419 static int xlnx_formatter_pcm_close(struct snd_soc_component *component,
420 struct snd_pcm_substream *substream)
423 struct xlnx_pcm_stream_param *stream_data =
424 substream->runtime->private_data;
426 ret = xlnx_formatter_pcm_reset(stream_data->mmio);
428 dev_err(component->dev, "audio formatter reset failed\n");
431 xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream);
438 static snd_pcm_uframes_t
439 xlnx_formatter_pcm_pointer(struct snd_soc_component *component,
440 struct snd_pcm_substream *substream)
443 struct snd_pcm_runtime *runtime = substream->runtime;
444 struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
446 pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT);
448 if (pos >= stream_data->buffer_size)
451 return bytes_to_frames(runtime, pos);
454 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
455 struct snd_pcm_substream *substream,
456 struct snd_pcm_hw_params *params)
458 u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample;
459 u32 aes_reg1_val, aes_reg2_val;
461 struct snd_pcm_runtime *runtime = substream->runtime;
462 struct xlnx_pcm_stream_param *stream_data = runtime->private_data;
463 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev);
465 active_ch = params_channels(params);
466 if (active_ch > stream_data->ch_limit)
469 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
471 unsigned int mclk_fs = adata->sysclk / params_rate(params);
473 if (adata->sysclk % params_rate(params) != 0) {
474 dev_warn(component->dev, "sysclk %u not divisible by rate %u\n",
475 adata->sysclk, params_rate(params));
479 writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER);
482 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE &&
483 stream_data->xfer_mode == AES_TO_PCM) {
484 val = readl(stream_data->mmio + XLNX_AUD_STS);
485 if (val & AUD_STS_CH_STS_MASK) {
486 aes_reg1_val = readl(stream_data->mmio +
487 XLNX_AUD_CH_STS_START);
488 aes_reg2_val = readl(stream_data->mmio +
489 XLNX_AUD_CH_STS_START + 0x4);
491 xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val,
496 size = params_buffer_bytes(params);
498 stream_data->buffer_size = size;
500 low = lower_32_bits(runtime->dma_addr);
501 high = upper_32_bits(runtime->dma_addr);
502 writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
503 writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
505 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
506 bits_per_sample = params_width(params);
507 switch (bits_per_sample) {
509 val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT);
512 val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT);
515 val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT);
518 val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT);
521 val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT);
527 val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT;
528 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
530 val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT)
531 | params_period_bytes(params);
532 writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG);
533 bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch);
534 writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH);
539 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component,
540 struct snd_pcm_substream *substream,
544 struct xlnx_pcm_stream_param *stream_data =
545 substream->runtime->private_data;
548 case SNDRV_PCM_TRIGGER_START:
549 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
550 case SNDRV_PCM_TRIGGER_RESUME:
551 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
552 val |= AUD_CTRL_DMA_EN_MASK;
553 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
555 case SNDRV_PCM_TRIGGER_STOP:
556 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
557 case SNDRV_PCM_TRIGGER_SUSPEND:
558 val = readl(stream_data->mmio + XLNX_AUD_CTRL);
559 val &= ~AUD_CTRL_DMA_EN_MASK;
560 writel(val, stream_data->mmio + XLNX_AUD_CTRL);
567 static int xlnx_formatter_pcm_new(struct snd_soc_component *component,
568 struct snd_soc_pcm_runtime *rtd)
570 snd_pcm_set_managed_buffer_all(rtd->pcm,
571 SNDRV_DMA_TYPE_DEV, component->dev,
572 xlnx_pcm_hardware.buffer_bytes_max,
573 xlnx_pcm_hardware.buffer_bytes_max);
577 static const struct snd_soc_component_driver xlnx_asoc_component = {
579 .set_sysclk = xlnx_formatter_set_sysclk,
580 .open = xlnx_formatter_pcm_open,
581 .close = xlnx_formatter_pcm_close,
582 .hw_params = xlnx_formatter_pcm_hw_params,
583 .trigger = xlnx_formatter_pcm_trigger,
584 .pointer = xlnx_formatter_pcm_pointer,
585 .pcm_construct = xlnx_formatter_pcm_new,
588 static int xlnx_formatter_pcm_probe(struct platform_device *pdev)
592 struct xlnx_pcm_drv_data *aud_drv_data;
593 struct device *dev = &pdev->dev;
595 aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL);
599 aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk");
600 if (IS_ERR(aud_drv_data->axi_clk)) {
601 ret = PTR_ERR(aud_drv_data->axi_clk);
602 dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret);
605 ret = clk_prepare_enable(aud_drv_data->axi_clk);
608 "failed to enable s_axi_lite_aclk(%d)\n", ret);
612 aud_drv_data->mmio = devm_platform_ioremap_resource(pdev, 0);
613 if (IS_ERR(aud_drv_data->mmio)) {
614 dev_err(dev, "audio formatter ioremap failed\n");
615 ret = PTR_ERR(aud_drv_data->mmio);
619 val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG);
620 if (val & AUD_CFG_MM2S_MASK) {
621 aud_drv_data->mm2s_presence = true;
622 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
625 dev_err(dev, "audio formatter reset failed\n");
628 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
630 SNDRV_PCM_STREAM_PLAYBACK);
632 aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev,
634 if (aud_drv_data->mm2s_irq < 0) {
635 ret = aud_drv_data->mm2s_irq;
638 ret = devm_request_irq(dev, aud_drv_data->mm2s_irq,
639 xlnx_mm2s_irq_handler, 0,
640 "xlnx_formatter_pcm_mm2s_irq", dev);
642 dev_err(dev, "xlnx audio mm2s irq request failed\n");
646 if (val & AUD_CFG_S2MM_MASK) {
647 aud_drv_data->s2mm_presence = true;
648 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio +
651 dev_err(dev, "audio formatter reset failed\n");
654 xlnx_formatter_disable_irqs(aud_drv_data->mmio +
656 SNDRV_PCM_STREAM_CAPTURE);
658 aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev,
660 if (aud_drv_data->s2mm_irq < 0) {
661 ret = aud_drv_data->s2mm_irq;
664 ret = devm_request_irq(dev, aud_drv_data->s2mm_irq,
665 xlnx_s2mm_irq_handler, 0,
666 "xlnx_formatter_pcm_s2mm_irq",
669 dev_err(dev, "xlnx audio s2mm irq request failed\n");
674 dev_set_drvdata(dev, aud_drv_data);
676 ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component,
679 dev_err(dev, "pcm platform device register failed\n");
686 clk_disable_unprepare(aud_drv_data->axi_clk);
690 static void xlnx_formatter_pcm_remove(struct platform_device *pdev)
693 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev);
695 if (adata->s2mm_presence)
696 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET);
698 /* Try MM2S reset, even if S2MM reset fails */
699 if (adata->mm2s_presence)
700 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET);
703 dev_err(&pdev->dev, "audio formatter reset failed\n");
705 clk_disable_unprepare(adata->axi_clk);
708 static const struct of_device_id xlnx_formatter_pcm_of_match[] = {
709 { .compatible = "xlnx,audio-formatter-1.0"},
712 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match);
714 static struct platform_driver xlnx_formatter_pcm_driver = {
715 .probe = xlnx_formatter_pcm_probe,
716 .remove_new = xlnx_formatter_pcm_remove,
719 .of_match_table = xlnx_formatter_pcm_of_match,
723 module_platform_driver(xlnx_formatter_pcm_driver);
724 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>");
725 MODULE_LICENSE("GPL v2");