1 // SPDX-License-Identifier: GPL-2.0
3 // Socionext UniPhier AIO DMA driver.
5 // Copyright (c) 2016-2018 Socionext Inc.
7 #include <linux/dma-mapping.h>
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <sound/core.h>
12 #include <sound/pcm.h>
13 #include <sound/soc.h>
17 static struct snd_pcm_hardware uniphier_aiodma_hw
= {
18 .info
= SNDRV_PCM_INFO_MMAP
|
19 SNDRV_PCM_INFO_MMAP_VALID
|
20 SNDRV_PCM_INFO_INTERLEAVED
,
21 .period_bytes_min
= 256,
22 .period_bytes_max
= 4096,
25 .buffer_bytes_max
= 128 * 1024,
28 static void aiodma_pcm_irq(struct uniphier_aio_sub
*sub
)
30 struct snd_pcm_runtime
*runtime
= sub
->substream
->runtime
;
31 int bytes
= runtime
->period_size
*
32 runtime
->channels
* samples_to_bytes(runtime
, 1);
35 spin_lock(&sub
->lock
);
36 ret
= aiodma_rb_set_threshold(sub
, runtime
->dma_bytes
,
37 sub
->threshold
+ bytes
);
39 sub
->threshold
+= bytes
;
41 aiodma_rb_sync(sub
, runtime
->dma_addr
, runtime
->dma_bytes
, bytes
);
42 aiodma_rb_clear_irq(sub
);
43 spin_unlock(&sub
->lock
);
45 snd_pcm_period_elapsed(sub
->substream
);
48 static void aiodma_compr_irq(struct uniphier_aio_sub
*sub
)
50 struct snd_compr_runtime
*runtime
= sub
->cstream
->runtime
;
51 int bytes
= runtime
->fragment_size
;
54 spin_lock(&sub
->lock
);
55 ret
= aiodma_rb_set_threshold(sub
, sub
->compr_bytes
,
56 sub
->threshold
+ bytes
);
58 sub
->threshold
+= bytes
;
60 aiodma_rb_sync(sub
, sub
->compr_addr
, sub
->compr_bytes
, bytes
);
61 aiodma_rb_clear_irq(sub
);
62 spin_unlock(&sub
->lock
);
64 snd_compr_fragment_elapsed(sub
->cstream
);
67 static irqreturn_t
aiodma_irq(int irq
, void *p
)
69 struct platform_device
*pdev
= p
;
70 struct uniphier_aio_chip
*chip
= platform_get_drvdata(pdev
);
71 irqreturn_t ret
= IRQ_NONE
;
74 for (i
= 0; i
< chip
->num_aios
; i
++) {
75 struct uniphier_aio
*aio
= &chip
->aios
[i
];
77 for (j
= 0; j
< ARRAY_SIZE(aio
->sub
); j
++) {
78 struct uniphier_aio_sub
*sub
= &aio
->sub
[j
];
80 /* Skip channel that does not trigger */
81 if (!sub
->running
|| !aiodma_rb_is_irq(sub
))
87 aiodma_compr_irq(sub
);
96 static int uniphier_aiodma_open(struct snd_soc_component
*component
,
97 struct snd_pcm_substream
*substream
)
99 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
101 snd_soc_set_runtime_hwparams(substream
, &uniphier_aiodma_hw
);
103 return snd_pcm_hw_constraint_step(runtime
, 0,
104 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
, 256);
107 static int uniphier_aiodma_prepare(struct snd_soc_component
*component
,
108 struct snd_pcm_substream
*substream
)
110 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
111 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
112 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
113 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
114 int bytes
= runtime
->period_size
*
115 runtime
->channels
* samples_to_bytes(runtime
, 1);
119 ret
= aiodma_ch_set_param(sub
);
123 spin_lock_irqsave(&sub
->lock
, flags
);
124 ret
= aiodma_rb_set_buffer(sub
, runtime
->dma_addr
,
125 runtime
->dma_addr
+ runtime
->dma_bytes
,
127 spin_unlock_irqrestore(&sub
->lock
, flags
);
134 static int uniphier_aiodma_trigger(struct snd_soc_component
*component
,
135 struct snd_pcm_substream
*substream
, int cmd
)
137 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
138 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
139 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
140 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
141 struct device
*dev
= &aio
->chip
->pdev
->dev
;
142 int bytes
= runtime
->period_size
*
143 runtime
->channels
* samples_to_bytes(runtime
, 1);
146 spin_lock_irqsave(&sub
->lock
, flags
);
148 case SNDRV_PCM_TRIGGER_START
:
149 aiodma_rb_sync(sub
, runtime
->dma_addr
, runtime
->dma_bytes
,
151 aiodma_ch_set_enable(sub
, 1);
155 case SNDRV_PCM_TRIGGER_STOP
:
157 aiodma_ch_set_enable(sub
, 0);
161 dev_warn(dev
, "Unknown trigger(%d) ignored\n", cmd
);
164 spin_unlock_irqrestore(&sub
->lock
, flags
);
169 static snd_pcm_uframes_t
uniphier_aiodma_pointer(
170 struct snd_soc_component
*component
,
171 struct snd_pcm_substream
*substream
)
173 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
174 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
175 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
176 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
177 int bytes
= runtime
->period_size
*
178 runtime
->channels
* samples_to_bytes(runtime
, 1);
180 snd_pcm_uframes_t pos
;
182 spin_lock_irqsave(&sub
->lock
, flags
);
183 aiodma_rb_sync(sub
, runtime
->dma_addr
, runtime
->dma_bytes
, bytes
);
185 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
186 pos
= bytes_to_frames(runtime
, sub
->rd_offs
);
188 pos
= bytes_to_frames(runtime
, sub
->wr_offs
);
189 spin_unlock_irqrestore(&sub
->lock
, flags
);
194 static int uniphier_aiodma_mmap(struct snd_soc_component
*component
,
195 struct snd_pcm_substream
*substream
,
196 struct vm_area_struct
*vma
)
198 vma
->vm_page_prot
= pgprot_writecombine(vma
->vm_page_prot
);
200 return remap_pfn_range(vma
, vma
->vm_start
,
201 substream
->dma_buffer
.addr
>> PAGE_SHIFT
,
202 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
);
205 static int uniphier_aiodma_new(struct snd_soc_component
*component
,
206 struct snd_soc_pcm_runtime
*rtd
)
208 struct device
*dev
= rtd
->card
->snd_card
->dev
;
209 struct snd_pcm
*pcm
= rtd
->pcm
;
212 ret
= dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(33));
216 snd_pcm_set_managed_buffer_all(pcm
,
217 SNDRV_DMA_TYPE_DEV
, dev
,
218 uniphier_aiodma_hw
.buffer_bytes_max
,
219 uniphier_aiodma_hw
.buffer_bytes_max
);
223 static const struct snd_soc_component_driver uniphier_soc_platform
= {
224 .open
= uniphier_aiodma_open
,
225 .prepare
= uniphier_aiodma_prepare
,
226 .trigger
= uniphier_aiodma_trigger
,
227 .pointer
= uniphier_aiodma_pointer
,
228 .mmap
= uniphier_aiodma_mmap
,
229 .pcm_construct
= uniphier_aiodma_new
,
230 .compr_ops
= &uniphier_aio_compr_ops
,
233 static const struct regmap_config aiodma_regmap_config
= {
237 .max_register
= 0x7fffc,
238 .cache_type
= REGCACHE_NONE
,
242 * uniphier_aiodma_soc_register_platform - register the AIO DMA
243 * @pdev: the platform device
245 * Register and setup the DMA of AIO to transfer the sound data to device.
246 * This function need to call once at driver startup and need NOT to call
247 * unregister function.
249 * Return: Zero if successful, otherwise a negative value on error.
251 int uniphier_aiodma_soc_register_platform(struct platform_device
*pdev
)
253 struct uniphier_aio_chip
*chip
= platform_get_drvdata(pdev
);
254 struct device
*dev
= &pdev
->dev
;
258 preg
= devm_platform_ioremap_resource(pdev
, 0);
260 return PTR_ERR(preg
);
262 chip
->regmap
= devm_regmap_init_mmio(dev
, preg
,
263 &aiodma_regmap_config
);
264 if (IS_ERR(chip
->regmap
))
265 return PTR_ERR(chip
->regmap
);
267 irq
= platform_get_irq(pdev
, 0);
271 ret
= devm_request_irq(dev
, irq
, aiodma_irq
,
272 IRQF_SHARED
, dev_name(dev
), pdev
);
276 return devm_snd_soc_register_component(dev
, &uniphier_soc_platform
,
279 EXPORT_SYMBOL_GPL(uniphier_aiodma_soc_register_platform
);