1 // SPDX-License-Identifier: GPL-2.0
3 // Socionext UniPhier AIO Compress Audio driver.
5 // Copyright (c) 2017-2018 Socionext Inc.
7 #include <linux/bitfield.h>
8 #include <linux/circ_buf.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/errno.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <sound/core.h>
14 #include <sound/pcm.h>
15 #include <sound/soc.h>
19 static int uniphier_aio_compr_prepare(struct snd_compr_stream
*cstream
);
20 static int uniphier_aio_compr_hw_free(struct snd_compr_stream
*cstream
);
22 static int uniphier_aio_comprdma_new(struct snd_soc_pcm_runtime
*rtd
)
24 struct snd_compr
*compr
= rtd
->compr
;
25 struct device
*dev
= compr
->card
->dev
;
26 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
27 struct uniphier_aio_sub
*sub
= &aio
->sub
[compr
->direction
];
28 size_t size
= AUD_RING_SIZE
;
29 int dma_dir
= DMA_FROM_DEVICE
, ret
;
31 ret
= dma_set_mask_and_coherent(dev
, DMA_BIT_MASK(33));
35 sub
->compr_area
= kzalloc(size
, GFP_KERNEL
);
39 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
40 dma_dir
= DMA_TO_DEVICE
;
42 sub
->compr_addr
= dma_map_single(dev
, sub
->compr_area
, size
, dma_dir
);
43 if (dma_mapping_error(dev
, sub
->compr_addr
)) {
44 kfree(sub
->compr_area
);
45 sub
->compr_area
= NULL
;
50 sub
->compr_bytes
= size
;
55 static int uniphier_aio_comprdma_free(struct snd_soc_pcm_runtime
*rtd
)
57 struct snd_compr
*compr
= rtd
->compr
;
58 struct device
*dev
= compr
->card
->dev
;
59 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
60 struct uniphier_aio_sub
*sub
= &aio
->sub
[compr
->direction
];
61 int dma_dir
= DMA_FROM_DEVICE
;
63 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
)
64 dma_dir
= DMA_TO_DEVICE
;
66 dma_unmap_single(dev
, sub
->compr_addr
, sub
->compr_bytes
, dma_dir
);
67 kfree(sub
->compr_area
);
68 sub
->compr_area
= NULL
;
73 static int uniphier_aio_compr_open(struct snd_compr_stream
*cstream
)
75 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
76 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
77 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
83 sub
->cstream
= cstream
;
84 sub
->pass_through
= 1;
85 sub
->use_mmap
= false;
87 ret
= uniphier_aio_comprdma_new(rtd
);
98 static int uniphier_aio_compr_free(struct snd_compr_stream
*cstream
)
100 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
101 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
102 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
105 ret
= uniphier_aio_compr_hw_free(cstream
);
108 ret
= uniphier_aio_comprdma_free(rtd
);
117 static int uniphier_aio_compr_get_params(struct snd_compr_stream
*cstream
,
118 struct snd_codec
*params
)
120 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
121 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
122 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
124 *params
= sub
->cparams
.codec
;
129 static int uniphier_aio_compr_set_params(struct snd_compr_stream
*cstream
,
130 struct snd_compr_params
*params
)
132 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
133 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
134 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
135 struct device
*dev
= &aio
->chip
->pdev
->dev
;
138 if (params
->codec
.id
!= SND_AUDIOCODEC_IEC61937
) {
139 dev_err(dev
, "Codec ID is not supported(%d)\n",
143 if (params
->codec
.profile
!= SND_AUDIOPROFILE_IEC61937_SPDIF
) {
144 dev_err(dev
, "Codec profile is not supported(%d)\n",
145 params
->codec
.profile
);
149 /* IEC frame type will be changed after received valid data */
150 sub
->iec_pc
= IEC61937_PC_AAC
;
152 sub
->cparams
= *params
;
158 ret
= uniphier_aio_compr_prepare(cstream
);
165 static int uniphier_aio_compr_hw_free(struct snd_compr_stream
*cstream
)
167 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
168 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
169 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
176 static int uniphier_aio_compr_prepare(struct snd_compr_stream
*cstream
)
178 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
179 struct snd_compr_runtime
*runtime
= cstream
->runtime
;
180 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
181 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
182 int bytes
= runtime
->fragment_size
;
186 ret
= aiodma_ch_set_param(sub
);
190 spin_lock_irqsave(&sub
->lock
, flags
);
191 ret
= aiodma_rb_set_buffer(sub
, sub
->compr_addr
,
192 sub
->compr_addr
+ sub
->compr_bytes
,
194 spin_unlock_irqrestore(&sub
->lock
, flags
);
198 ret
= aio_port_set_param(sub
, sub
->pass_through
, &sub
->params
);
201 ret
= aio_oport_set_stream_type(sub
, sub
->iec_pc
);
204 aio_port_set_enable(sub
, 1);
206 ret
= aio_if_set_param(sub
, sub
->pass_through
);
213 static int uniphier_aio_compr_trigger(struct snd_compr_stream
*cstream
,
216 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
217 struct snd_compr_runtime
*runtime
= cstream
->runtime
;
218 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
219 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
220 struct device
*dev
= &aio
->chip
->pdev
->dev
;
221 int bytes
= runtime
->fragment_size
, ret
= 0;
224 spin_lock_irqsave(&sub
->lock
, flags
);
226 case SNDRV_PCM_TRIGGER_START
:
227 aiodma_rb_sync(sub
, sub
->compr_addr
, sub
->compr_bytes
, bytes
);
228 aiodma_ch_set_enable(sub
, 1);
232 case SNDRV_PCM_TRIGGER_STOP
:
234 aiodma_ch_set_enable(sub
, 0);
238 dev_warn(dev
, "Unknown trigger(%d)\n", cmd
);
241 spin_unlock_irqrestore(&sub
->lock
, flags
);
246 static int uniphier_aio_compr_pointer(struct snd_compr_stream
*cstream
,
247 struct snd_compr_tstamp
*tstamp
)
249 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
250 struct snd_compr_runtime
*runtime
= cstream
->runtime
;
251 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
252 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
253 int bytes
= runtime
->fragment_size
;
257 spin_lock_irqsave(&sub
->lock
, flags
);
259 aiodma_rb_sync(sub
, sub
->compr_addr
, sub
->compr_bytes
, bytes
);
261 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
263 /* Size of AIO output format is double of IEC61937 */
264 tstamp
->copied_total
= sub
->rd_total
/ 2;
267 tstamp
->copied_total
= sub
->rd_total
;
269 tstamp
->byte_offset
= pos
;
271 spin_unlock_irqrestore(&sub
->lock
, flags
);
276 static int aio_compr_send_to_hw(struct uniphier_aio_sub
*sub
,
277 char __user
*buf
, size_t dstsize
)
279 u32 __user
*srcbuf
= (u32 __user
*)buf
;
280 u32
*dstbuf
= (u32
*)(sub
->compr_area
+ sub
->wr_offs
);
281 int src
= 0, dst
= 0, ret
;
282 u32 frm
, frm_a
, frm_b
;
284 while (dstsize
> 0) {
285 ret
= get_user(frm
, srcbuf
+ src
);
290 frm_a
= frm
& 0xffff;
291 frm_b
= (frm
>> 16) & 0xffff;
293 if (frm
== IEC61937_HEADER_SIGN
) {
296 /* Next data is Pc and Pd */
297 sub
->iec_header
= true;
299 u16 pc
= be16_to_cpu((__be16
)frm_a
);
301 if (sub
->iec_header
&& sub
->iec_pc
!= pc
) {
302 /* Force overwrite IEC frame type */
304 ret
= aio_oport_set_stream_type(sub
, pc
);
308 sub
->iec_header
= false;
310 dstbuf
[dst
++] = frm_a
;
311 dstbuf
[dst
++] = frm_b
;
313 dstsize
-= sizeof(u32
) * 2;
319 static int uniphier_aio_compr_copy(struct snd_compr_stream
*cstream
,
320 char __user
*buf
, size_t count
)
322 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
323 struct snd_compr_runtime
*runtime
= cstream
->runtime
;
324 struct device
*carddev
= rtd
->compr
->card
->dev
;
325 struct uniphier_aio
*aio
= uniphier_priv(rtd
->cpu_dai
);
326 struct uniphier_aio_sub
*sub
= &aio
->sub
[cstream
->direction
];
327 size_t cnt
= min_t(size_t, count
, aio_rb_space_to_end(sub
) / 2);
328 int bytes
= runtime
->fragment_size
;
333 if (cnt
< sizeof(u32
))
336 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
337 dma_addr_t dmapos
= sub
->compr_addr
+ sub
->wr_offs
;
339 /* Size of AIO output format is double of IEC61937 */
342 dma_sync_single_for_cpu(carddev
, dmapos
, s
, DMA_TO_DEVICE
);
343 ret
= aio_compr_send_to_hw(sub
, buf
, s
);
344 dma_sync_single_for_device(carddev
, dmapos
, s
, DMA_TO_DEVICE
);
346 dma_addr_t dmapos
= sub
->compr_addr
+ sub
->rd_offs
;
350 dma_sync_single_for_cpu(carddev
, dmapos
, s
, DMA_FROM_DEVICE
);
351 ret
= copy_to_user(buf
, sub
->compr_area
+ sub
->rd_offs
, s
);
352 dma_sync_single_for_device(carddev
, dmapos
, s
, DMA_FROM_DEVICE
);
357 spin_lock_irqsave(&sub
->lock
, flags
);
359 sub
->threshold
= 2 * bytes
;
360 aiodma_rb_set_threshold(sub
, sub
->compr_bytes
, 2 * bytes
);
362 if (sub
->swm
->dir
== PORT_DIR_OUTPUT
) {
364 if (sub
->wr_offs
>= sub
->compr_bytes
)
365 sub
->wr_offs
-= sub
->compr_bytes
;
368 if (sub
->rd_offs
>= sub
->compr_bytes
)
369 sub
->rd_offs
-= sub
->compr_bytes
;
371 aiodma_rb_sync(sub
, sub
->compr_addr
, sub
->compr_bytes
, bytes
);
373 spin_unlock_irqrestore(&sub
->lock
, flags
);
378 static int uniphier_aio_compr_get_caps(struct snd_compr_stream
*cstream
,
379 struct snd_compr_caps
*caps
)
381 caps
->num_codecs
= 1;
382 caps
->min_fragment_size
= AUD_MIN_FRAGMENT_SIZE
;
383 caps
->max_fragment_size
= AUD_MAX_FRAGMENT_SIZE
;
384 caps
->min_fragments
= AUD_MIN_FRAGMENT
;
385 caps
->max_fragments
= AUD_MAX_FRAGMENT
;
386 caps
->codecs
[0] = SND_AUDIOCODEC_IEC61937
;
391 static const struct snd_compr_codec_caps caps_iec
= {
392 .num_descriptors
= 1,
393 .descriptor
[0].max_ch
= 8,
394 .descriptor
[0].num_sample_rates
= 0,
395 .descriptor
[0].num_bitrates
= 0,
396 .descriptor
[0].profiles
= SND_AUDIOPROFILE_IEC61937_SPDIF
,
397 .descriptor
[0].modes
= SND_AUDIOMODE_IEC_AC3
|
398 SND_AUDIOMODE_IEC_MPEG1
|
399 SND_AUDIOMODE_IEC_MP3
|
400 SND_AUDIOMODE_IEC_DTS
,
401 .descriptor
[0].formats
= 0,
404 static int uniphier_aio_compr_get_codec_caps(struct snd_compr_stream
*stream
,
405 struct snd_compr_codec_caps
*codec
)
407 if (codec
->codec
== SND_AUDIOCODEC_IEC61937
)
415 const struct snd_compr_ops uniphier_aio_compr_ops
= {
416 .open
= uniphier_aio_compr_open
,
417 .free
= uniphier_aio_compr_free
,
418 .get_params
= uniphier_aio_compr_get_params
,
419 .set_params
= uniphier_aio_compr_set_params
,
420 .trigger
= uniphier_aio_compr_trigger
,
421 .pointer
= uniphier_aio_compr_pointer
,
422 .copy
= uniphier_aio_compr_copy
,
423 .get_caps
= uniphier_aio_compr_get_caps
,
424 .get_codec_caps
= uniphier_aio_compr_get_codec_caps
,