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_pcm_substream
*substream
)
98 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
100 snd_soc_set_runtime_hwparams(substream
, &uniphier_aiodma_hw
);
102 return snd_pcm_hw_constraint_step(runtime
, 0,
103 SNDRV_PCM_HW_PARAM_BUFFER_BYTES
, 256);
106 static int uniphier_aiodma_hw_params(struct snd_pcm_substream
*substream
,
107 struct snd_pcm_hw_params
*params
)
109 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
110 substream
->runtime
->dma_bytes
= params_buffer_bytes(params
);
115 static int uniphier_aiodma_hw_free(struct snd_pcm_substream
*substream
)
117 snd_pcm_set_runtime_buffer(substream
, NULL
);
118 substream
->runtime
->dma_bytes
= 0;
123 static int uniphier_aiodma_prepare(struct snd_pcm_substream
*substream
)
125 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
126 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
127 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
128 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
129 int bytes
= runtime
->period_size
*
130 runtime
->channels
* samples_to_bytes(runtime
, 1);
134 ret
= aiodma_ch_set_param(sub
);
138 spin_lock_irqsave(&sub
->lock
, flags
);
139 ret
= aiodma_rb_set_buffer(sub
, runtime
->dma_addr
,
140 runtime
->dma_addr
+ runtime
->dma_bytes
,
142 spin_unlock_irqrestore(&sub
->lock
, flags
);
149 static int uniphier_aiodma_trigger(struct snd_pcm_substream
*substream
, int cmd
)
151 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
152 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
153 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
154 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
155 struct device
*dev
= &aio
->chip
->pdev
->dev
;
156 int bytes
= runtime
->period_size
*
157 runtime
->channels
* samples_to_bytes(runtime
, 1);
160 spin_lock_irqsave(&sub
->lock
, flags
);
162 case SNDRV_PCM_TRIGGER_START
:
163 aiodma_rb_sync(sub
, runtime
->dma_addr
, runtime
->dma_bytes
,
165 aiodma_ch_set_enable(sub
, 1);
169 case SNDRV_PCM_TRIGGER_STOP
:
171 aiodma_ch_set_enable(sub
, 0);
175 dev_warn(dev
, "Unknown trigger(%d) ignored\n", cmd
);
178 spin_unlock_irqrestore(&sub
->lock
, flags
);
183 static snd_pcm_uframes_t
uniphier_aiodma_pointer(
184 struct snd_pcm_substream
*substream
)
186 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
187 struct snd_soc_pcm_runtime
*rtd
= snd_pcm_substream_chip(substream
);
188 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
189 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
190 int bytes
= runtime
->period_size
*
191 runtime
->channels
* samples_to_bytes(runtime
, 1);
193 snd_pcm_uframes_t pos
;
195 spin_lock_irqsave(&sub
->lock
, flags
);
196 aiodma_rb_sync(sub
, runtime
->dma_addr
, runtime
->dma_bytes
, bytes
);
198 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
199 pos
= bytes_to_frames(runtime
, sub
->rd_offs
);
201 pos
= bytes_to_frames(runtime
, sub
->wr_offs
);
202 spin_unlock_irqrestore(&sub
->lock
, flags
);
207 static int uniphier_aiodma_mmap(struct snd_pcm_substream
*substream
,
208 struct vm_area_struct
*vma
)
210 vma
->vm_page_prot
= pgprot_writecombine(vma
->vm_page_prot
);
212 return remap_pfn_range(vma
, vma
->vm_start
,
213 substream
->dma_buffer
.addr
>> PAGE_SHIFT
,
214 vma
->vm_end
- vma
->vm_start
, vma
->vm_page_prot
);
217 static const struct snd_pcm_ops uniphier_aiodma_ops
= {
218 .open
= uniphier_aiodma_open
,
219 .ioctl
= snd_pcm_lib_ioctl
,
220 .hw_params
= uniphier_aiodma_hw_params
,
221 .hw_free
= uniphier_aiodma_hw_free
,
222 .prepare
= uniphier_aiodma_prepare
,
223 .trigger
= uniphier_aiodma_trigger
,
224 .pointer
= uniphier_aiodma_pointer
,
225 .mmap
= uniphier_aiodma_mmap
,
228 static int uniphier_aiodma_new(struct snd_soc_pcm_runtime
*rtd
)
230 struct device
*dev
= rtd
->card
->snd_card
->dev
;
231 struct snd_pcm
*pcm
= rtd
->pcm
;
234 ret
= dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(33));
238 snd_pcm_lib_preallocate_pages_for_all(pcm
,
239 SNDRV_DMA_TYPE_DEV
, dev
,
240 uniphier_aiodma_hw
.buffer_bytes_max
,
241 uniphier_aiodma_hw
.buffer_bytes_max
);
245 static void uniphier_aiodma_free(struct snd_pcm
*pcm
)
247 snd_pcm_lib_preallocate_free_for_all(pcm
);
250 static const struct snd_soc_component_driver uniphier_soc_platform
= {
251 .pcm_new
= uniphier_aiodma_new
,
252 .pcm_free
= uniphier_aiodma_free
,
253 .ops
= &uniphier_aiodma_ops
,
254 .compr_ops
= &uniphier_aio_compr_ops
,
257 static const struct regmap_config aiodma_regmap_config
= {
261 .max_register
= 0x7fffc,
262 .cache_type
= REGCACHE_NONE
,
266 * uniphier_aiodma_soc_register_platform - register the AIO DMA
267 * @pdev: the platform device
269 * Register and setup the DMA of AIO to transfer the sound data to device.
270 * This function need to call once at driver startup and need NOT to call
271 * unregister function.
273 * Return: Zero if successful, otherwise a negative value on error.
275 int uniphier_aiodma_soc_register_platform(struct platform_device
*pdev
)
277 struct uniphier_aio_chip
*chip
= platform_get_drvdata(pdev
);
278 struct device
*dev
= &pdev
->dev
;
282 preg
= devm_platform_ioremap_resource(pdev
, 0);
284 return PTR_ERR(preg
);
286 chip
->regmap
= devm_regmap_init_mmio(dev
, preg
,
287 &aiodma_regmap_config
);
288 if (IS_ERR(chip
->regmap
))
289 return PTR_ERR(chip
->regmap
);
291 irq
= platform_get_irq(pdev
, 0);
295 ret
= devm_request_irq(dev
, irq
, aiodma_irq
,
296 IRQF_SHARED
, dev_name(dev
), pdev
);
300 return devm_snd_soc_register_component(dev
, &uniphier_soc_platform
,
303 EXPORT_SYMBOL_GPL(uniphier_aiodma_soc_register_platform
);