1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2021, Linaro Limited
4 #include <linux/init.h>
6 #include <linux/module.h>
8 #include <linux/platform_device.h>
9 #include <linux/slab.h>
10 #include <sound/soc.h>
11 #include <sound/soc-dapm.h>
12 #include <linux/spinlock.h>
13 #include <sound/pcm.h>
15 #include <linux/dma-mapping.h>
16 #include <sound/pcm_params.h>
19 #define DRV_NAME "q6apm-dai"
21 #define PLAYBACK_MIN_NUM_PERIODS 2
22 #define PLAYBACK_MAX_NUM_PERIODS 8
23 #define PLAYBACK_MAX_PERIOD_SIZE 65536
24 #define PLAYBACK_MIN_PERIOD_SIZE 128
25 #define CAPTURE_MIN_NUM_PERIODS 2
26 #define CAPTURE_MAX_NUM_PERIODS 8
27 #define CAPTURE_MAX_PERIOD_SIZE 4096
28 #define CAPTURE_MIN_PERIOD_SIZE 320
29 #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE)
30 #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE)
31 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
32 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
33 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
34 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
35 #define SID_MASK_DEFAULT 0xF
37 static const struct snd_compr_codec_caps q6apm_compr_caps
= {
39 .descriptor
[0].max_ch
= 2,
40 .descriptor
[0].sample_rates
= { 8000, 11025, 12000, 16000, 22050,
41 24000, 32000, 44100, 48000, 88200,
42 96000, 176400, 192000 },
43 .descriptor
[0].num_sample_rates
= 13,
44 .descriptor
[0].bit_rate
[0] = 320,
45 .descriptor
[0].bit_rate
[1] = 128,
46 .descriptor
[0].num_bitrates
= 2,
47 .descriptor
[0].profiles
= 0,
48 .descriptor
[0].modes
= SND_AUDIOCHANMODE_MP3_STEREO
,
49 .descriptor
[0].formats
= 0,
53 Q6APM_STREAM_IDLE
= 0,
58 struct q6apm_dai_rtd
{
59 struct snd_pcm_substream
*substream
;
60 struct snd_compr_stream
*cstream
;
61 struct snd_codec codec
;
62 struct snd_compr_params codec_param
;
63 struct snd_dma_buffer dma_buffer
;
65 unsigned int pcm_size
;
66 unsigned int pcm_count
;
67 unsigned int pos
; /* Buffer position */
69 unsigned int bytes_sent
;
70 unsigned int bytes_received
;
71 unsigned int copied_total
;
72 uint16_t bits_per_sample
;
74 enum stream_state state
;
75 struct q6apm_graph
*graph
;
80 struct q6apm_dai_data
{
84 static const struct snd_pcm_hardware q6apm_dai_hardware_capture
= {
85 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_BLOCK_TRANSFER
|
86 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_INTERLEAVED
|
87 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
|
88 SNDRV_PCM_INFO_BATCH
),
89 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE
),
90 .rates
= SNDRV_PCM_RATE_8000_48000
,
95 .buffer_bytes_max
= CAPTURE_MAX_NUM_PERIODS
* CAPTURE_MAX_PERIOD_SIZE
,
96 .period_bytes_min
= CAPTURE_MIN_PERIOD_SIZE
,
97 .period_bytes_max
= CAPTURE_MAX_PERIOD_SIZE
,
98 .periods_min
= CAPTURE_MIN_NUM_PERIODS
,
99 .periods_max
= CAPTURE_MAX_NUM_PERIODS
,
103 static const struct snd_pcm_hardware q6apm_dai_hardware_playback
= {
104 .info
= (SNDRV_PCM_INFO_MMAP
| SNDRV_PCM_INFO_BLOCK_TRANSFER
|
105 SNDRV_PCM_INFO_MMAP_VALID
| SNDRV_PCM_INFO_INTERLEAVED
|
106 SNDRV_PCM_INFO_PAUSE
| SNDRV_PCM_INFO_RESUME
|
107 SNDRV_PCM_INFO_BATCH
),
108 .formats
= (SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE
),
109 .rates
= SNDRV_PCM_RATE_8000_192000
,
114 .buffer_bytes_max
= (PLAYBACK_MAX_NUM_PERIODS
* PLAYBACK_MAX_PERIOD_SIZE
),
115 .period_bytes_min
= PLAYBACK_MIN_PERIOD_SIZE
,
116 .period_bytes_max
= PLAYBACK_MAX_PERIOD_SIZE
,
117 .periods_min
= PLAYBACK_MIN_NUM_PERIODS
,
118 .periods_max
= PLAYBACK_MAX_NUM_PERIODS
,
122 static void event_handler(uint32_t opcode
, uint32_t token
, void *payload
, void *priv
)
124 struct q6apm_dai_rtd
*prtd
= priv
;
125 struct snd_pcm_substream
*substream
= prtd
->substream
;
129 case APM_CLIENT_EVENT_CMD_EOS_DONE
:
130 prtd
->state
= Q6APM_STREAM_STOPPED
;
132 case APM_CLIENT_EVENT_DATA_WRITE_DONE
:
133 spin_lock_irqsave(&prtd
->lock
, flags
);
134 prtd
->pos
+= prtd
->pcm_count
;
135 spin_unlock_irqrestore(&prtd
->lock
, flags
);
136 snd_pcm_period_elapsed(substream
);
137 if (prtd
->state
== Q6APM_STREAM_RUNNING
)
138 q6apm_write_async(prtd
->graph
, prtd
->pcm_count
, 0, 0, 0);
141 case APM_CLIENT_EVENT_DATA_READ_DONE
:
142 spin_lock_irqsave(&prtd
->lock
, flags
);
143 prtd
->pos
+= prtd
->pcm_count
;
144 spin_unlock_irqrestore(&prtd
->lock
, flags
);
145 snd_pcm_period_elapsed(substream
);
146 if (prtd
->state
== Q6APM_STREAM_RUNNING
)
147 q6apm_read(prtd
->graph
);
155 static void event_handler_compr(uint32_t opcode
, uint32_t token
,
156 void *payload
, void *priv
)
158 struct q6apm_dai_rtd
*prtd
= priv
;
159 struct snd_compr_stream
*substream
= prtd
->cstream
;
163 uint32_t bytes_written
, bytes_to_write
;
164 bool is_last_buffer
= false;
167 case APM_CLIENT_EVENT_CMD_EOS_DONE
:
168 spin_lock_irqsave(&prtd
->lock
, flags
);
169 if (prtd
->notify_on_drain
) {
170 snd_compr_drain_notify(prtd
->cstream
);
171 prtd
->notify_on_drain
= false;
173 prtd
->state
= Q6APM_STREAM_STOPPED
;
175 spin_unlock_irqrestore(&prtd
->lock
, flags
);
177 case APM_CLIENT_EVENT_DATA_WRITE_DONE
:
178 spin_lock_irqsave(&prtd
->lock
, flags
);
179 bytes_written
= token
>> APM_WRITE_TOKEN_LEN_SHIFT
;
180 prtd
->copied_total
+= bytes_written
;
181 snd_compr_fragment_elapsed(substream
);
183 if (prtd
->state
!= Q6APM_STREAM_RUNNING
) {
184 spin_unlock_irqrestore(&prtd
->lock
, flags
);
188 avail
= prtd
->bytes_received
- prtd
->bytes_sent
;
190 if (avail
> prtd
->pcm_count
) {
191 bytes_to_write
= prtd
->pcm_count
;
193 if (substream
->partial_drain
|| prtd
->notify_on_drain
)
194 is_last_buffer
= true;
195 bytes_to_write
= avail
;
198 if (bytes_to_write
) {
199 if (substream
->partial_drain
&& is_last_buffer
)
200 wflags
|= APM_LAST_BUFFER_FLAG
;
202 q6apm_write_async(prtd
->graph
,
203 bytes_to_write
, 0, 0, wflags
);
205 prtd
->bytes_sent
+= bytes_to_write
;
207 if (prtd
->notify_on_drain
&& is_last_buffer
)
208 audioreach_shared_memory_send_eos(prtd
->graph
);
211 spin_unlock_irqrestore(&prtd
->lock
, flags
);
218 static int q6apm_dai_prepare(struct snd_soc_component
*component
,
219 struct snd_pcm_substream
*substream
)
221 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
222 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
223 struct audioreach_module_config cfg
;
224 struct device
*dev
= component
->dev
;
225 struct q6apm_dai_data
*pdata
;
228 pdata
= snd_soc_component_get_drvdata(component
);
232 if (!prtd
|| !prtd
->graph
) {
233 dev_err(dev
, "%s: private data null or audio client freed\n", __func__
);
237 cfg
.direction
= substream
->stream
;
238 cfg
.sample_rate
= runtime
->rate
;
239 cfg
.num_channels
= runtime
->channels
;
240 cfg
.bit_width
= prtd
->bits_per_sample
;
241 cfg
.fmt
= SND_AUDIOCODEC_PCM
;
242 audioreach_set_default_channel_mapping(cfg
.channel_map
, runtime
->channels
);
245 /* clear the previous setup if any */
246 q6apm_graph_stop(prtd
->graph
);
247 q6apm_unmap_memory_regions(prtd
->graph
, substream
->stream
);
250 prtd
->pcm_count
= snd_pcm_lib_period_bytes(substream
);
252 /* rate and channels are sent to audio driver */
253 ret
= q6apm_graph_media_format_shmem(prtd
->graph
, &cfg
);
255 dev_err(dev
, "%s: q6apm_open_write failed\n", __func__
);
259 ret
= q6apm_graph_media_format_pcm(prtd
->graph
, &cfg
);
261 dev_err(dev
, "%s: CMD Format block failed\n", __func__
);
263 ret
= q6apm_map_memory_regions(prtd
->graph
, substream
->stream
, prtd
->phys
,
264 (prtd
->pcm_size
/ prtd
->periods
), prtd
->periods
);
267 dev_err(dev
, "Audio Start: Buffer Allocation failed rc = %d\n", ret
);
271 ret
= q6apm_graph_prepare(prtd
->graph
);
273 dev_err(dev
, "Failed to prepare Graph %d\n", ret
);
277 ret
= q6apm_graph_start(prtd
->graph
);
279 dev_err(dev
, "Failed to Start Graph %d\n", ret
);
283 if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
285 /* Queue the buffers for Capture ONLY after graph is started */
286 for (i
= 0; i
< runtime
->periods
; i
++)
287 q6apm_read(prtd
->graph
);
291 /* Now that graph as been prepared and started update the internal state accordingly */
292 prtd
->state
= Q6APM_STREAM_RUNNING
;
297 static int q6apm_dai_trigger(struct snd_soc_component
*component
,
298 struct snd_pcm_substream
*substream
, int cmd
)
300 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
301 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
305 case SNDRV_PCM_TRIGGER_START
:
306 case SNDRV_PCM_TRIGGER_RESUME
:
307 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
308 /* start writing buffers for playback only as we already queued capture buffers */
309 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
310 ret
= q6apm_write_async(prtd
->graph
, prtd
->pcm_count
, 0, 0, 0);
312 case SNDRV_PCM_TRIGGER_STOP
:
313 /* TODO support be handled via SoftPause Module */
314 prtd
->state
= Q6APM_STREAM_STOPPED
;
316 case SNDRV_PCM_TRIGGER_SUSPEND
:
317 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
327 static int q6apm_dai_open(struct snd_soc_component
*component
,
328 struct snd_pcm_substream
*substream
)
330 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
331 struct snd_soc_pcm_runtime
*soc_prtd
= snd_soc_substream_to_rtd(substream
);
332 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_prtd
, 0);
333 struct device
*dev
= component
->dev
;
334 struct q6apm_dai_data
*pdata
;
335 struct q6apm_dai_rtd
*prtd
;
338 graph_id
= cpu_dai
->driver
->id
;
340 pdata
= snd_soc_component_get_drvdata(component
);
342 dev_err(dev
, "Drv data not found ..\n");
346 prtd
= kzalloc(sizeof(*prtd
), GFP_KERNEL
);
350 spin_lock_init(&prtd
->lock
);
351 prtd
->substream
= substream
;
352 prtd
->graph
= q6apm_graph_open(dev
, event_handler
, prtd
, graph_id
);
353 if (IS_ERR(prtd
->graph
)) {
354 dev_err(dev
, "%s: Could not allocate memory\n", __func__
);
355 ret
= PTR_ERR(prtd
->graph
);
359 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
360 runtime
->hw
= q6apm_dai_hardware_playback
;
361 else if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
362 runtime
->hw
= q6apm_dai_hardware_capture
;
364 /* Ensure that buffer size is a multiple of period size */
365 ret
= snd_pcm_hw_constraint_integer(runtime
, SNDRV_PCM_HW_PARAM_PERIODS
);
367 dev_err(dev
, "snd_pcm_hw_constraint_integer failed\n");
371 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
372 ret
= snd_pcm_hw_constraint_minmax(runtime
, SNDRV_PCM_HW_PARAM_BUFFER_BYTES
,
373 BUFFER_BYTES_MIN
, BUFFER_BYTES_MAX
);
375 dev_err(dev
, "constraint for buffer bytes min max ret = %d\n", ret
);
380 ret
= snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES
, 32);
382 dev_err(dev
, "constraint for period bytes step ret = %d\n", ret
);
386 ret
= snd_pcm_hw_constraint_step(runtime
, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES
, 32);
388 dev_err(dev
, "constraint for buffer bytes step ret = %d\n", ret
);
392 runtime
->private_data
= prtd
;
393 runtime
->dma_bytes
= BUFFER_BYTES_MAX
;
395 prtd
->phys
= substream
->dma_buffer
.addr
;
397 prtd
->phys
= substream
->dma_buffer
.addr
| (pdata
->sid
<< 32);
406 static int q6apm_dai_close(struct snd_soc_component
*component
,
407 struct snd_pcm_substream
*substream
)
409 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
410 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
412 if (prtd
->state
) { /* only stop graph that is started */
413 q6apm_graph_stop(prtd
->graph
);
414 q6apm_unmap_memory_regions(prtd
->graph
, substream
->stream
);
417 q6apm_graph_close(prtd
->graph
);
420 runtime
->private_data
= NULL
;
425 static snd_pcm_uframes_t
q6apm_dai_pointer(struct snd_soc_component
*component
,
426 struct snd_pcm_substream
*substream
)
428 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
429 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
430 snd_pcm_uframes_t ptr
;
433 spin_lock_irqsave(&prtd
->lock
, flags
);
434 if (prtd
->pos
== prtd
->pcm_size
)
437 ptr
= bytes_to_frames(runtime
, prtd
->pos
);
438 spin_unlock_irqrestore(&prtd
->lock
, flags
);
443 static int q6apm_dai_hw_params(struct snd_soc_component
*component
,
444 struct snd_pcm_substream
*substream
,
445 struct snd_pcm_hw_params
*params
)
447 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
448 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
450 prtd
->pcm_size
= params_buffer_bytes(params
);
451 prtd
->periods
= params_periods(params
);
453 switch (params_format(params
)) {
454 case SNDRV_PCM_FORMAT_S16_LE
:
455 prtd
->bits_per_sample
= 16;
457 case SNDRV_PCM_FORMAT_S24_LE
:
458 prtd
->bits_per_sample
= 24;
467 static int q6apm_dai_pcm_new(struct snd_soc_component
*component
, struct snd_soc_pcm_runtime
*rtd
)
469 int size
= BUFFER_BYTES_MAX
;
471 return snd_pcm_set_fixed_buffer_all(rtd
->pcm
, SNDRV_DMA_TYPE_DEV
, component
->dev
, size
);
474 static int q6apm_dai_compr_open(struct snd_soc_component
*component
,
475 struct snd_compr_stream
*stream
)
477 struct snd_soc_pcm_runtime
*rtd
= stream
->private_data
;
478 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(rtd
, 0);
479 struct snd_compr_runtime
*runtime
= stream
->runtime
;
480 struct q6apm_dai_rtd
*prtd
;
481 struct q6apm_dai_data
*pdata
;
482 struct device
*dev
= component
->dev
;
486 graph_id
= cpu_dai
->driver
->id
;
487 pdata
= snd_soc_component_get_drvdata(component
);
491 prtd
= kzalloc(sizeof(*prtd
), GFP_KERNEL
);
495 prtd
->cstream
= stream
;
496 prtd
->graph
= q6apm_graph_open(dev
, event_handler_compr
, prtd
, graph_id
);
497 if (IS_ERR(prtd
->graph
)) {
498 ret
= PTR_ERR(prtd
->graph
);
503 runtime
->private_data
= prtd
;
504 runtime
->dma_bytes
= BUFFER_BYTES_MAX
;
505 size
= COMPR_PLAYBACK_MAX_FRAGMENT_SIZE
* COMPR_PLAYBACK_MAX_NUM_FRAGMENTS
;
506 ret
= snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
, dev
, size
, &prtd
->dma_buffer
);
511 prtd
->phys
= prtd
->dma_buffer
.addr
;
513 prtd
->phys
= prtd
->dma_buffer
.addr
| (pdata
->sid
<< 32);
515 snd_compr_set_runtime_buffer(stream
, &prtd
->dma_buffer
);
516 spin_lock_init(&prtd
->lock
);
518 q6apm_enable_compress_module(dev
, prtd
->graph
, true);
522 static int q6apm_dai_compr_free(struct snd_soc_component
*component
,
523 struct snd_compr_stream
*stream
)
525 struct snd_compr_runtime
*runtime
= stream
->runtime
;
526 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
528 q6apm_graph_stop(prtd
->graph
);
529 q6apm_unmap_memory_regions(prtd
->graph
, SNDRV_PCM_STREAM_PLAYBACK
);
530 q6apm_graph_close(prtd
->graph
);
531 snd_dma_free_pages(&prtd
->dma_buffer
);
534 runtime
->private_data
= NULL
;
539 static int q6apm_dai_compr_get_caps(struct snd_soc_component
*component
,
540 struct snd_compr_stream
*stream
,
541 struct snd_compr_caps
*caps
)
543 caps
->direction
= SND_COMPRESS_PLAYBACK
;
544 caps
->min_fragment_size
= COMPR_PLAYBACK_MIN_FRAGMENT_SIZE
;
545 caps
->max_fragment_size
= COMPR_PLAYBACK_MAX_FRAGMENT_SIZE
;
546 caps
->min_fragments
= COMPR_PLAYBACK_MIN_NUM_FRAGMENTS
;
547 caps
->max_fragments
= COMPR_PLAYBACK_MAX_NUM_FRAGMENTS
;
548 caps
->num_codecs
= 3;
549 caps
->codecs
[0] = SND_AUDIOCODEC_MP3
;
550 caps
->codecs
[1] = SND_AUDIOCODEC_AAC
;
551 caps
->codecs
[2] = SND_AUDIOCODEC_FLAC
;
556 static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component
*component
,
557 struct snd_compr_stream
*stream
,
558 struct snd_compr_codec_caps
*codec
)
560 switch (codec
->codec
) {
561 case SND_AUDIOCODEC_MP3
:
562 *codec
= q6apm_compr_caps
;
571 static int q6apm_dai_compr_pointer(struct snd_soc_component
*component
,
572 struct snd_compr_stream
*stream
,
573 struct snd_compr_tstamp
*tstamp
)
575 struct snd_compr_runtime
*runtime
= stream
->runtime
;
576 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
579 spin_lock_irqsave(&prtd
->lock
, flags
);
580 tstamp
->copied_total
= prtd
->copied_total
;
581 tstamp
->byte_offset
= prtd
->copied_total
% prtd
->pcm_size
;
582 spin_unlock_irqrestore(&prtd
->lock
, flags
);
587 static int q6apm_dai_compr_trigger(struct snd_soc_component
*component
,
588 struct snd_compr_stream
*stream
, int cmd
)
590 struct snd_compr_runtime
*runtime
= stream
->runtime
;
591 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
595 case SNDRV_PCM_TRIGGER_START
:
596 case SNDRV_PCM_TRIGGER_RESUME
:
597 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
598 ret
= q6apm_write_async(prtd
->graph
, prtd
->pcm_count
, 0, 0, NO_TIMESTAMP
);
600 case SNDRV_PCM_TRIGGER_STOP
:
602 case SNDRV_PCM_TRIGGER_SUSPEND
:
603 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
605 case SND_COMPR_TRIGGER_NEXT_TRACK
:
606 prtd
->next_track
= true;
608 case SND_COMPR_TRIGGER_DRAIN
:
609 case SND_COMPR_TRIGGER_PARTIAL_DRAIN
:
610 prtd
->notify_on_drain
= true;
620 static int q6apm_dai_compr_ack(struct snd_soc_component
*component
, struct snd_compr_stream
*stream
,
623 struct snd_compr_runtime
*runtime
= stream
->runtime
;
624 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
627 spin_lock_irqsave(&prtd
->lock
, flags
);
628 prtd
->bytes_received
+= count
;
629 spin_unlock_irqrestore(&prtd
->lock
, flags
);
634 static int q6apm_dai_compr_set_params(struct snd_soc_component
*component
,
635 struct snd_compr_stream
*stream
,
636 struct snd_compr_params
*params
)
638 struct snd_compr_runtime
*runtime
= stream
->runtime
;
639 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
640 struct q6apm_dai_data
*pdata
;
641 struct audioreach_module_config cfg
;
642 struct snd_codec
*codec
= ¶ms
->codec
;
643 int dir
= stream
->direction
;
646 pdata
= snd_soc_component_get_drvdata(component
);
650 prtd
->periods
= runtime
->fragments
;
651 prtd
->pcm_count
= runtime
->fragment_size
;
652 prtd
->pcm_size
= runtime
->fragments
* runtime
->fragment_size
;
653 prtd
->bits_per_sample
= 16;
657 if (prtd
->next_track
!= true) {
658 memcpy(&prtd
->codec
, codec
, sizeof(*codec
));
660 ret
= q6apm_set_real_module_id(component
->dev
, prtd
->graph
, codec
->id
);
665 cfg
.sample_rate
= codec
->sample_rate
;
666 cfg
.num_channels
= 2;
667 cfg
.bit_width
= prtd
->bits_per_sample
;
669 audioreach_set_default_channel_mapping(cfg
.channel_map
,
671 memcpy(&cfg
.codec
, codec
, sizeof(*codec
));
673 ret
= q6apm_graph_media_format_shmem(prtd
->graph
, &cfg
);
677 ret
= q6apm_graph_media_format_pcm(prtd
->graph
, &cfg
);
681 ret
= q6apm_map_memory_regions(prtd
->graph
, SNDRV_PCM_STREAM_PLAYBACK
,
682 prtd
->phys
, (prtd
->pcm_size
/ prtd
->periods
),
687 ret
= q6apm_graph_prepare(prtd
->graph
);
691 ret
= q6apm_graph_start(prtd
->graph
);
697 cfg
.sample_rate
= codec
->sample_rate
;
698 cfg
.num_channels
= 2;
699 cfg
.bit_width
= prtd
->bits_per_sample
;
701 memcpy(&cfg
.codec
, codec
, sizeof(*codec
));
703 ret
= audioreach_compr_set_param(prtd
->graph
, &cfg
);
707 prtd
->state
= Q6APM_STREAM_RUNNING
;
712 static int q6apm_dai_compr_set_metadata(struct snd_soc_component
*component
,
713 struct snd_compr_stream
*stream
,
714 struct snd_compr_metadata
*metadata
)
716 struct snd_compr_runtime
*runtime
= stream
->runtime
;
717 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
720 switch (metadata
->key
) {
721 case SNDRV_COMPRESS_ENCODER_PADDING
:
722 q6apm_remove_trailing_silence(component
->dev
, prtd
->graph
,
725 case SNDRV_COMPRESS_ENCODER_DELAY
:
726 q6apm_remove_initial_silence(component
->dev
, prtd
->graph
,
737 static int q6apm_dai_compr_mmap(struct snd_soc_component
*component
,
738 struct snd_compr_stream
*stream
,
739 struct vm_area_struct
*vma
)
741 struct snd_compr_runtime
*runtime
= stream
->runtime
;
742 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
743 struct device
*dev
= component
->dev
;
745 return dma_mmap_coherent(dev
, vma
, prtd
->dma_buffer
.area
, prtd
->dma_buffer
.addr
,
746 prtd
->dma_buffer
.bytes
);
749 static int q6apm_compr_copy(struct snd_soc_component
*component
,
750 struct snd_compr_stream
*stream
, char __user
*buf
,
753 struct snd_compr_runtime
*runtime
= stream
->runtime
;
754 struct q6apm_dai_rtd
*prtd
= runtime
->private_data
;
761 uint32_t bytes_to_write
;
762 int avail
, bytes_in_flight
= 0;
764 bytes_received
= prtd
->bytes_received
;
767 * Make sure that next track data pointer is aligned at 32 bit boundary
768 * This is a Mandatory requirement from DSP data buffers alignment
770 if (prtd
->next_track
)
771 bytes_received
= ALIGN(prtd
->bytes_received
, prtd
->pcm_count
);
773 app_pointer
= bytes_received
/prtd
->pcm_size
;
774 app_pointer
= bytes_received
- (app_pointer
* prtd
->pcm_size
);
775 dstn
= prtd
->dma_buffer
.area
+ app_pointer
;
777 if (count
< prtd
->pcm_size
- app_pointer
) {
778 if (copy_from_user(dstn
, buf
, count
))
781 copy
= prtd
->pcm_size
- app_pointer
;
782 if (copy_from_user(dstn
, buf
, copy
))
784 if (copy_from_user(prtd
->dma_buffer
.area
, buf
+ copy
, count
- copy
))
788 spin_lock_irqsave(&prtd
->lock
, flags
);
789 bytes_in_flight
= prtd
->bytes_received
- prtd
->copied_total
;
791 if (prtd
->next_track
) {
792 prtd
->next_track
= false;
793 prtd
->copied_total
= ALIGN(prtd
->copied_total
, prtd
->pcm_count
);
794 prtd
->bytes_sent
= ALIGN(prtd
->bytes_sent
, prtd
->pcm_count
);
797 prtd
->bytes_received
= bytes_received
+ count
;
799 /* Kick off the data to dsp if its starving!! */
800 if (prtd
->state
== Q6APM_STREAM_RUNNING
&& (bytes_in_flight
== 0)) {
801 bytes_to_write
= prtd
->pcm_count
;
802 avail
= prtd
->bytes_received
- prtd
->bytes_sent
;
804 if (avail
< prtd
->pcm_count
)
805 bytes_to_write
= avail
;
807 q6apm_write_async(prtd
->graph
, bytes_to_write
, 0, 0, wflags
);
808 prtd
->bytes_sent
+= bytes_to_write
;
811 spin_unlock_irqrestore(&prtd
->lock
, flags
);
816 static const struct snd_compress_ops q6apm_dai_compress_ops
= {
817 .open
= q6apm_dai_compr_open
,
818 .free
= q6apm_dai_compr_free
,
819 .get_caps
= q6apm_dai_compr_get_caps
,
820 .get_codec_caps
= q6apm_dai_compr_get_codec_caps
,
821 .pointer
= q6apm_dai_compr_pointer
,
822 .trigger
= q6apm_dai_compr_trigger
,
823 .ack
= q6apm_dai_compr_ack
,
824 .set_params
= q6apm_dai_compr_set_params
,
825 .set_metadata
= q6apm_dai_compr_set_metadata
,
826 .mmap
= q6apm_dai_compr_mmap
,
827 .copy
= q6apm_compr_copy
,
830 static const struct snd_soc_component_driver q6apm_fe_dai_component
= {
832 .open
= q6apm_dai_open
,
833 .close
= q6apm_dai_close
,
834 .prepare
= q6apm_dai_prepare
,
835 .pcm_construct
= q6apm_dai_pcm_new
,
836 .hw_params
= q6apm_dai_hw_params
,
837 .pointer
= q6apm_dai_pointer
,
838 .trigger
= q6apm_dai_trigger
,
839 .compress_ops
= &q6apm_dai_compress_ops
,
840 .use_dai_pcm_id
= true,
843 static int q6apm_dai_probe(struct platform_device
*pdev
)
845 struct device
*dev
= &pdev
->dev
;
846 struct device_node
*node
= dev
->of_node
;
847 struct q6apm_dai_data
*pdata
;
848 struct of_phandle_args args
;
851 pdata
= devm_kzalloc(dev
, sizeof(*pdata
), GFP_KERNEL
);
855 rc
= of_parse_phandle_with_fixed_args(node
, "iommus", 1, 0, &args
);
859 pdata
->sid
= args
.args
[0] & SID_MASK_DEFAULT
;
861 dev_set_drvdata(dev
, pdata
);
863 return devm_snd_soc_register_component(dev
, &q6apm_fe_dai_component
, NULL
, 0);
867 static const struct of_device_id q6apm_dai_device_id
[] = {
868 { .compatible
= "qcom,q6apm-dais" },
871 MODULE_DEVICE_TABLE(of
, q6apm_dai_device_id
);
874 static struct platform_driver q6apm_dai_platform_driver
= {
877 .of_match_table
= of_match_ptr(q6apm_dai_device_id
),
879 .probe
= q6apm_dai_probe
,
881 module_platform_driver(q6apm_dai_platform_driver
);
883 MODULE_DESCRIPTION("Q6APM dai driver");
884 MODULE_LICENSE("GPL");