1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
3 // Copyright (c) 2018, Linaro Limited
5 #include <linux/init.h>
7 #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 <sound/pcm.h>
13 #include <linux/spinlock.h>
14 #include <sound/compress_driver.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/of_device.h>
18 #include <sound/pcm_params.h>
20 #include "q6routing.h"
21 #include "q6dsp-errno.h"
23 #define DRV_NAME "q6asm-fe-dai"
25 #define PLAYBACK_MIN_NUM_PERIODS 2
26 #define PLAYBACK_MAX_NUM_PERIODS 8
27 #define PLAYBACK_MAX_PERIOD_SIZE 65536
28 #define PLAYBACK_MIN_PERIOD_SIZE 128
29 #define CAPTURE_MIN_NUM_PERIODS 2
30 #define CAPTURE_MAX_NUM_PERIODS 8
31 #define CAPTURE_MAX_PERIOD_SIZE 4096
32 #define CAPTURE_MIN_PERIOD_SIZE 320
33 #define SID_MASK_DEFAULT 0xF
35 /* Default values used if user space does not set */
36 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
37 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
38 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
39 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
41 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1)
42 #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2)
45 Q6ASM_STREAM_IDLE = 0,
50 struct q6asm_dai_rtd {
51 struct snd_pcm_substream *substream;
52 struct snd_compr_stream *cstream;
53 struct snd_compr_params codec_param;
54 struct snd_dma_buffer dma_buffer;
57 unsigned int pcm_size;
58 unsigned int pcm_count;
59 unsigned int pcm_irq_pos; /* IRQ position */
61 unsigned int bytes_sent;
62 unsigned int bytes_received;
63 unsigned int copied_total;
64 uint16_t bits_per_sample;
65 uint16_t source; /* Encoding source bit mask */
66 struct audio_client *audio_client;
69 enum stream_state state;
70 uint32_t initial_samples_drop;
71 uint32_t trailing_samples_drop;
74 struct q6asm_dai_data {
75 struct snd_soc_dai_driver *dais;
80 static const struct snd_pcm_hardware q6asm_dai_hardware_capture = {
81 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
82 SNDRV_PCM_INFO_BLOCK_TRANSFER |
83 SNDRV_PCM_INFO_MMAP_VALID |
84 SNDRV_PCM_INFO_INTERLEAVED |
85 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
86 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
87 SNDRV_PCM_FMTBIT_S24_LE),
88 .rates = SNDRV_PCM_RATE_8000_48000,
93 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
94 CAPTURE_MAX_PERIOD_SIZE,
95 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
96 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
97 .periods_min = CAPTURE_MIN_NUM_PERIODS,
98 .periods_max = CAPTURE_MAX_NUM_PERIODS,
102 static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
103 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
104 SNDRV_PCM_INFO_BLOCK_TRANSFER |
105 SNDRV_PCM_INFO_MMAP_VALID |
106 SNDRV_PCM_INFO_INTERLEAVED |
107 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
108 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
109 SNDRV_PCM_FMTBIT_S24_LE),
110 .rates = SNDRV_PCM_RATE_8000_192000,
115 .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS *
116 PLAYBACK_MAX_PERIOD_SIZE),
117 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
118 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
119 .periods_min = PLAYBACK_MIN_NUM_PERIODS,
120 .periods_max = PLAYBACK_MAX_NUM_PERIODS,
124 #define Q6ASM_FEDAI_DRIVER(num) { \
126 .stream_name = "MultiMedia"#num" Playback", \
127 .rates = (SNDRV_PCM_RATE_8000_192000| \
128 SNDRV_PCM_RATE_KNOT), \
129 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
130 SNDRV_PCM_FMTBIT_S24_LE), \
134 .rate_max = 192000, \
137 .stream_name = "MultiMedia"#num" Capture", \
138 .rates = (SNDRV_PCM_RATE_8000_48000| \
139 SNDRV_PCM_RATE_KNOT), \
140 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
141 SNDRV_PCM_FMTBIT_S24_LE), \
147 .name = "MultiMedia"#num, \
148 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \
151 /* Conventional and unconventional sample rate supported */
152 static unsigned int supported_sample_rates[] = {
153 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
154 88200, 96000, 176400, 192000
157 static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
158 .count = ARRAY_SIZE(supported_sample_rates),
159 .list = supported_sample_rates,
163 static const struct snd_compr_codec_caps q6asm_compr_caps = {
164 .num_descriptors = 1,
165 .descriptor[0].max_ch = 2,
166 .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050,
167 24000, 32000, 44100, 48000, 88200,
168 96000, 176400, 192000 },
169 .descriptor[0].num_sample_rates = 13,
170 .descriptor[0].bit_rate[0] = 320,
171 .descriptor[0].bit_rate[1] = 128,
172 .descriptor[0].num_bitrates = 2,
173 .descriptor[0].profiles = 0,
174 .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
175 .descriptor[0].formats = 0,
178 static void event_handler(uint32_t opcode, uint32_t token,
179 void *payload, void *priv)
181 struct q6asm_dai_rtd *prtd = priv;
182 struct snd_pcm_substream *substream = prtd->substream;
185 case ASM_CLIENT_EVENT_CMD_RUN_DONE:
186 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
187 q6asm_write_async(prtd->audio_client, prtd->stream_id,
188 prtd->pcm_count, 0, 0, 0);
190 case ASM_CLIENT_EVENT_CMD_EOS_DONE:
191 prtd->state = Q6ASM_STREAM_STOPPED;
193 case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
194 prtd->pcm_irq_pos += prtd->pcm_count;
195 snd_pcm_period_elapsed(substream);
196 if (prtd->state == Q6ASM_STREAM_RUNNING)
197 q6asm_write_async(prtd->audio_client, prtd->stream_id,
198 prtd->pcm_count, 0, 0, 0);
202 case ASM_CLIENT_EVENT_DATA_READ_DONE:
203 prtd->pcm_irq_pos += prtd->pcm_count;
204 snd_pcm_period_elapsed(substream);
205 if (prtd->state == Q6ASM_STREAM_RUNNING)
206 q6asm_read(prtd->audio_client, prtd->stream_id);
214 static int q6asm_dai_prepare(struct snd_soc_component *component,
215 struct snd_pcm_substream *substream)
217 struct snd_pcm_runtime *runtime = substream->runtime;
218 struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
219 struct q6asm_dai_rtd *prtd = runtime->private_data;
220 struct q6asm_dai_data *pdata;
221 struct device *dev = component->dev;
224 pdata = snd_soc_component_get_drvdata(component);
228 if (!prtd || !prtd->audio_client) {
229 dev_err(dev, "%s: private data null or audio client freed\n",
234 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
235 prtd->pcm_irq_pos = 0;
236 /* rate and channels are sent to audio driver */
238 /* clear the previous setup if any */
239 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
240 q6asm_unmap_memory_regions(substream->stream,
242 q6routing_stream_close(soc_prtd->dai_link->id,
246 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
248 (prtd->pcm_size / prtd->periods),
252 dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n",
257 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
258 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
260 0, prtd->bits_per_sample, false);
261 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
262 ret = q6asm_open_read(prtd->audio_client, prtd->stream_id,
264 prtd->bits_per_sample);
268 dev_err(dev, "%s: q6asm_open_write failed\n", __func__);
269 q6asm_audio_client_free(prtd->audio_client);
270 prtd->audio_client = NULL;
274 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
275 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
276 prtd->session_id, substream->stream);
278 dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret);
282 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
283 ret = q6asm_media_format_block_multi_ch_pcm(
284 prtd->audio_client, prtd->stream_id,
285 runtime->rate, runtime->channels, NULL,
286 prtd->bits_per_sample);
287 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
288 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
292 prtd->bits_per_sample);
294 /* Queue the buffers */
295 for (i = 0; i < runtime->periods; i++)
296 q6asm_read(prtd->audio_client, prtd->stream_id);
300 dev_info(dev, "%s: CMD Format block failed\n", __func__);
302 prtd->state = Q6ASM_STREAM_RUNNING;
307 static int q6asm_dai_trigger(struct snd_soc_component *component,
308 struct snd_pcm_substream *substream, int cmd)
311 struct snd_pcm_runtime *runtime = substream->runtime;
312 struct q6asm_dai_rtd *prtd = runtime->private_data;
315 case SNDRV_PCM_TRIGGER_START:
316 case SNDRV_PCM_TRIGGER_RESUME:
317 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
318 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
321 case SNDRV_PCM_TRIGGER_STOP:
322 prtd->state = Q6ASM_STREAM_STOPPED;
323 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
326 case SNDRV_PCM_TRIGGER_SUSPEND:
327 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
328 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
339 static int q6asm_dai_open(struct snd_soc_component *component,
340 struct snd_pcm_substream *substream)
342 struct snd_pcm_runtime *runtime = substream->runtime;
343 struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
344 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0);
345 struct q6asm_dai_rtd *prtd;
346 struct q6asm_dai_data *pdata;
347 struct device *dev = component->dev;
351 stream_id = cpu_dai->driver->id;
353 pdata = snd_soc_component_get_drvdata(component);
355 dev_err(dev, "Drv data not found ..\n");
359 prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL);
363 prtd->substream = substream;
364 prtd->audio_client = q6asm_audio_client_alloc(dev,
365 (q6asm_cb)event_handler, prtd, stream_id,
367 if (IS_ERR(prtd->audio_client)) {
368 dev_info(dev, "%s: Could not allocate memory\n", __func__);
369 ret = PTR_ERR(prtd->audio_client);
374 /* DSP expects stream id from 1 */
377 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
378 runtime->hw = q6asm_dai_hardware_playback;
379 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
380 runtime->hw = q6asm_dai_hardware_capture;
382 ret = snd_pcm_hw_constraint_list(runtime, 0,
383 SNDRV_PCM_HW_PARAM_RATE,
384 &constraints_sample_rates);
386 dev_info(dev, "snd_pcm_hw_constraint_list failed\n");
387 /* Ensure that buffer size is a multiple of period size */
388 ret = snd_pcm_hw_constraint_integer(runtime,
389 SNDRV_PCM_HW_PARAM_PERIODS);
391 dev_info(dev, "snd_pcm_hw_constraint_integer failed\n");
393 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
394 ret = snd_pcm_hw_constraint_minmax(runtime,
395 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
396 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
397 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
399 dev_err(dev, "constraint for buffer bytes min max ret = %d\n",
404 ret = snd_pcm_hw_constraint_step(runtime, 0,
405 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
407 dev_err(dev, "constraint for period bytes step ret = %d\n",
410 ret = snd_pcm_hw_constraint_step(runtime, 0,
411 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
413 dev_err(dev, "constraint for buffer bytes step ret = %d\n",
417 runtime->private_data = prtd;
419 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
421 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
425 prtd->phys = substream->dma_buffer.addr;
427 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
429 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
434 static int q6asm_dai_close(struct snd_soc_component *component,
435 struct snd_pcm_substream *substream)
437 struct snd_pcm_runtime *runtime = substream->runtime;
438 struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
439 struct q6asm_dai_rtd *prtd = runtime->private_data;
441 if (prtd->audio_client) {
443 q6asm_cmd(prtd->audio_client, prtd->stream_id,
446 q6asm_unmap_memory_regions(substream->stream,
448 q6asm_audio_client_free(prtd->audio_client);
449 prtd->audio_client = NULL;
451 q6routing_stream_close(soc_prtd->dai_link->id,
457 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
458 struct snd_pcm_substream *substream)
461 struct snd_pcm_runtime *runtime = substream->runtime;
462 struct q6asm_dai_rtd *prtd = runtime->private_data;
464 if (prtd->pcm_irq_pos >= prtd->pcm_size)
465 prtd->pcm_irq_pos = 0;
467 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
470 static int q6asm_dai_mmap(struct snd_soc_component *component,
471 struct snd_pcm_substream *substream,
472 struct vm_area_struct *vma)
474 struct snd_pcm_runtime *runtime = substream->runtime;
475 struct device *dev = component->dev;
477 return dma_mmap_coherent(dev, vma,
478 runtime->dma_area, runtime->dma_addr,
482 static int q6asm_dai_hw_params(struct snd_soc_component *component,
483 struct snd_pcm_substream *substream,
484 struct snd_pcm_hw_params *params)
486 struct snd_pcm_runtime *runtime = substream->runtime;
487 struct q6asm_dai_rtd *prtd = runtime->private_data;
489 prtd->pcm_size = params_buffer_bytes(params);
490 prtd->periods = params_periods(params);
492 switch (params_format(params)) {
493 case SNDRV_PCM_FORMAT_S16_LE:
494 prtd->bits_per_sample = 16;
496 case SNDRV_PCM_FORMAT_S24_LE:
497 prtd->bits_per_sample = 24;
504 static void compress_event_handler(uint32_t opcode, uint32_t token,
505 void *payload, void *priv)
507 struct q6asm_dai_rtd *prtd = priv;
508 struct snd_compr_stream *substream = prtd->cstream;
511 uint32_t bytes_written;
514 case ASM_CLIENT_EVENT_CMD_RUN_DONE:
515 spin_lock_irqsave(&prtd->lock, flags);
516 if (!prtd->bytes_sent) {
517 q6asm_write_async(prtd->audio_client, prtd->stream_id,
518 prtd->pcm_count, 0, 0, 0);
519 prtd->bytes_sent += prtd->pcm_count;
522 spin_unlock_irqrestore(&prtd->lock, flags);
525 case ASM_CLIENT_EVENT_CMD_EOS_DONE:
526 prtd->state = Q6ASM_STREAM_STOPPED;
529 case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
530 spin_lock_irqsave(&prtd->lock, flags);
532 bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT;
533 prtd->copied_total += bytes_written;
534 snd_compr_fragment_elapsed(substream);
536 if (prtd->state != Q6ASM_STREAM_RUNNING) {
537 spin_unlock_irqrestore(&prtd->lock, flags);
541 avail = prtd->bytes_received - prtd->bytes_sent;
543 if (avail >= prtd->pcm_count) {
544 q6asm_write_async(prtd->audio_client, prtd->stream_id,
545 prtd->pcm_count, 0, 0, 0);
546 prtd->bytes_sent += prtd->pcm_count;
549 spin_unlock_irqrestore(&prtd->lock, flags);
557 static int q6asm_dai_compr_open(struct snd_soc_component *component,
558 struct snd_compr_stream *stream)
560 struct snd_soc_pcm_runtime *rtd = stream->private_data;
561 struct snd_compr_runtime *runtime = stream->runtime;
562 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
563 struct q6asm_dai_data *pdata;
564 struct device *dev = component->dev;
565 struct q6asm_dai_rtd *prtd;
566 int stream_id, size, ret;
568 stream_id = cpu_dai->driver->id;
569 pdata = snd_soc_component_get_drvdata(component);
571 dev_err(dev, "Drv data not found ..\n");
575 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
579 /* DSP expects stream id from 1 */
582 prtd->cstream = stream;
583 prtd->audio_client = q6asm_audio_client_alloc(dev,
584 (q6asm_cb)compress_event_handler,
585 prtd, stream_id, LEGACY_PCM_MODE);
586 if (IS_ERR(prtd->audio_client)) {
587 dev_err(dev, "Could not allocate memory\n");
588 ret = PTR_ERR(prtd->audio_client);
592 size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
593 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
594 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
597 dev_err(dev, "Cannot allocate buffer(s)\n");
602 prtd->phys = prtd->dma_buffer.addr;
604 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
606 snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
607 spin_lock_init(&prtd->lock);
608 runtime->private_data = prtd;
613 q6asm_audio_client_free(prtd->audio_client);
620 static int q6asm_dai_compr_free(struct snd_soc_component *component,
621 struct snd_compr_stream *stream)
623 struct snd_compr_runtime *runtime = stream->runtime;
624 struct q6asm_dai_rtd *prtd = runtime->private_data;
625 struct snd_soc_pcm_runtime *rtd = stream->private_data;
627 if (prtd->audio_client) {
629 q6asm_cmd(prtd->audio_client, prtd->stream_id,
632 snd_dma_free_pages(&prtd->dma_buffer);
633 q6asm_unmap_memory_regions(stream->direction,
635 q6asm_audio_client_free(prtd->audio_client);
636 prtd->audio_client = NULL;
638 q6routing_stream_close(rtd->dai_link->id, stream->direction);
644 static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
645 struct snd_compr_stream *stream,
646 struct snd_compr_params *params)
648 struct snd_compr_runtime *runtime = stream->runtime;
649 struct q6asm_dai_rtd *prtd = runtime->private_data;
650 struct snd_soc_pcm_runtime *rtd = stream->private_data;
651 int dir = stream->direction;
652 struct q6asm_dai_data *pdata;
653 struct q6asm_flac_cfg flac_cfg;
654 struct q6asm_wma_cfg wma_cfg;
655 struct q6asm_alac_cfg alac_cfg;
656 struct q6asm_ape_cfg ape_cfg;
657 unsigned int wma_v9 = 0;
658 struct device *dev = component->dev;
660 union snd_codec_options *codec_options;
661 struct snd_dec_flac *flac;
662 struct snd_dec_wma *wma;
663 struct snd_dec_alac *alac;
664 struct snd_dec_ape *ape;
666 codec_options = &(prtd->codec_param.codec.options);
669 memcpy(&prtd->codec_param, params, sizeof(*params));
671 pdata = snd_soc_component_get_drvdata(component);
675 if (!prtd || !prtd->audio_client) {
676 dev_err(dev, "private data null or audio client freed\n");
680 prtd->periods = runtime->fragments;
681 prtd->pcm_count = runtime->fragment_size;
682 prtd->pcm_size = runtime->fragments * runtime->fragment_size;
683 prtd->bits_per_sample = 16;
684 if (dir == SND_COMPRESS_PLAYBACK) {
685 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
686 params->codec.id, params->codec.profile,
687 prtd->bits_per_sample, true);
690 dev_err(dev, "q6asm_open_write failed\n");
691 q6asm_audio_client_free(prtd->audio_client);
692 prtd->audio_client = NULL;
697 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
698 ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
699 prtd->session_id, dir);
701 dev_err(dev, "Stream reg failed ret:%d\n", ret);
705 switch (params->codec.id) {
706 case SND_AUDIOCODEC_FLAC:
708 memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg));
709 flac = &codec_options->flac_d;
711 flac_cfg.ch_cfg = params->codec.ch_in;
712 flac_cfg.sample_rate = params->codec.sample_rate;
713 flac_cfg.stream_info_present = 1;
714 flac_cfg.sample_size = flac->sample_size;
715 flac_cfg.min_blk_size = flac->min_blk_size;
716 flac_cfg.max_blk_size = flac->max_blk_size;
717 flac_cfg.max_frame_size = flac->max_frame_size;
718 flac_cfg.min_frame_size = flac->min_frame_size;
720 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
724 dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
729 case SND_AUDIOCODEC_WMA:
730 wma = &codec_options->wma_d;
732 memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg));
734 wma_cfg.sample_rate = params->codec.sample_rate;
735 wma_cfg.num_channels = params->codec.ch_in;
736 wma_cfg.bytes_per_sec = params->codec.bit_rate / 8;
737 wma_cfg.block_align = params->codec.align;
738 wma_cfg.bits_per_sample = prtd->bits_per_sample;
739 wma_cfg.enc_options = wma->encoder_option;
740 wma_cfg.adv_enc_options = wma->adv_encoder_option;
741 wma_cfg.adv_enc_options2 = wma->adv_encoder_option2;
743 if (wma_cfg.num_channels == 1)
744 wma_cfg.channel_mask = 4; /* Mono Center */
745 else if (wma_cfg.num_channels == 2)
746 wma_cfg.channel_mask = 3; /* Stereo FL/FR */
750 /* check the codec profile */
751 switch (params->codec.profile) {
752 case SND_AUDIOPROFILE_WMA9:
753 wma_cfg.fmtag = 0x161;
757 case SND_AUDIOPROFILE_WMA10:
758 wma_cfg.fmtag = 0x166;
761 case SND_AUDIOPROFILE_WMA9_PRO:
762 wma_cfg.fmtag = 0x162;
765 case SND_AUDIOPROFILE_WMA9_LOSSLESS:
766 wma_cfg.fmtag = 0x163;
769 case SND_AUDIOPROFILE_WMA10_LOSSLESS:
770 wma_cfg.fmtag = 0x167;
774 dev_err(dev, "Unknown WMA profile:%x\n",
775 params->codec.profile);
780 ret = q6asm_stream_media_format_block_wma_v9(
781 prtd->audio_client, prtd->stream_id,
784 ret = q6asm_stream_media_format_block_wma_v10(
785 prtd->audio_client, prtd->stream_id,
788 dev_err(dev, "WMA9 CMD failed:%d\n", ret);
793 case SND_AUDIOCODEC_ALAC:
794 memset(&alac_cfg, 0x0, sizeof(alac_cfg));
795 alac = &codec_options->alac_d;
797 alac_cfg.sample_rate = params->codec.sample_rate;
798 alac_cfg.avg_bit_rate = params->codec.bit_rate;
799 alac_cfg.bit_depth = prtd->bits_per_sample;
800 alac_cfg.num_channels = params->codec.ch_in;
802 alac_cfg.frame_length = alac->frame_length;
803 alac_cfg.pb = alac->pb;
804 alac_cfg.mb = alac->mb;
805 alac_cfg.kb = alac->kb;
806 alac_cfg.max_run = alac->max_run;
807 alac_cfg.compatible_version = alac->compatible_version;
808 alac_cfg.max_frame_bytes = alac->max_frame_bytes;
810 switch (params->codec.ch_in) {
812 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO;
815 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO;
818 ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
822 dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
827 case SND_AUDIOCODEC_APE:
828 memset(&ape_cfg, 0x0, sizeof(ape_cfg));
829 ape = &codec_options->ape_d;
831 ape_cfg.sample_rate = params->codec.sample_rate;
832 ape_cfg.num_channels = params->codec.ch_in;
833 ape_cfg.bits_per_sample = prtd->bits_per_sample;
835 ape_cfg.compatible_version = ape->compatible_version;
836 ape_cfg.compression_level = ape->compression_level;
837 ape_cfg.format_flags = ape->format_flags;
838 ape_cfg.blocks_per_frame = ape->blocks_per_frame;
839 ape_cfg.final_frame_blocks = ape->final_frame_blocks;
840 ape_cfg.total_frames = ape->total_frames;
841 ape_cfg.seek_table_present = ape->seek_table_present;
843 ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
847 dev_err(dev, "APE CMD Format block failed:%d\n", ret);
856 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
857 (prtd->pcm_size / prtd->periods),
861 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
865 prtd->state = Q6ASM_STREAM_RUNNING;
870 static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component,
871 struct snd_compr_stream *stream,
872 struct snd_compr_metadata *metadata)
874 struct snd_compr_runtime *runtime = stream->runtime;
875 struct q6asm_dai_rtd *prtd = runtime->private_data;
878 switch (metadata->key) {
879 case SNDRV_COMPRESS_ENCODER_PADDING:
880 prtd->trailing_samples_drop = metadata->value[0];
882 case SNDRV_COMPRESS_ENCODER_DELAY:
883 prtd->initial_samples_drop = metadata->value[0];
893 static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
894 struct snd_compr_stream *stream, int cmd)
896 struct snd_compr_runtime *runtime = stream->runtime;
897 struct q6asm_dai_rtd *prtd = runtime->private_data;
901 case SNDRV_PCM_TRIGGER_START:
902 case SNDRV_PCM_TRIGGER_RESUME:
903 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
904 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
907 case SNDRV_PCM_TRIGGER_STOP:
908 prtd->state = Q6ASM_STREAM_STOPPED;
909 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
912 case SNDRV_PCM_TRIGGER_SUSPEND:
913 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
914 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
925 static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
926 struct snd_compr_stream *stream,
927 struct snd_compr_tstamp *tstamp)
929 struct snd_compr_runtime *runtime = stream->runtime;
930 struct q6asm_dai_rtd *prtd = runtime->private_data;
933 spin_lock_irqsave(&prtd->lock, flags);
935 tstamp->copied_total = prtd->copied_total;
936 tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
938 spin_unlock_irqrestore(&prtd->lock, flags);
943 static int q6asm_dai_compr_ack(struct snd_soc_component *component,
944 struct snd_compr_stream *stream,
947 struct snd_compr_runtime *runtime = stream->runtime;
948 struct q6asm_dai_rtd *prtd = runtime->private_data;
951 spin_lock_irqsave(&prtd->lock, flags);
952 prtd->bytes_received += count;
953 spin_unlock_irqrestore(&prtd->lock, flags);
958 static int q6asm_dai_compr_mmap(struct snd_soc_component *component,
959 struct snd_compr_stream *stream,
960 struct vm_area_struct *vma)
962 struct snd_compr_runtime *runtime = stream->runtime;
963 struct q6asm_dai_rtd *prtd = runtime->private_data;
964 struct device *dev = component->dev;
966 return dma_mmap_coherent(dev, vma,
967 prtd->dma_buffer.area, prtd->dma_buffer.addr,
968 prtd->dma_buffer.bytes);
971 static int q6asm_dai_compr_get_caps(struct snd_soc_component *component,
972 struct snd_compr_stream *stream,
973 struct snd_compr_caps *caps)
975 caps->direction = SND_COMPRESS_PLAYBACK;
976 caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
977 caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
978 caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
979 caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
980 caps->num_codecs = 5;
981 caps->codecs[0] = SND_AUDIOCODEC_MP3;
982 caps->codecs[1] = SND_AUDIOCODEC_FLAC;
983 caps->codecs[2] = SND_AUDIOCODEC_WMA;
984 caps->codecs[3] = SND_AUDIOCODEC_ALAC;
985 caps->codecs[4] = SND_AUDIOCODEC_APE;
990 static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component,
991 struct snd_compr_stream *stream,
992 struct snd_compr_codec_caps *codec)
994 switch (codec->codec) {
995 case SND_AUDIOCODEC_MP3:
996 *codec = q6asm_compr_caps;
1005 static struct snd_compress_ops q6asm_dai_compress_ops = {
1006 .open = q6asm_dai_compr_open,
1007 .free = q6asm_dai_compr_free,
1008 .set_params = q6asm_dai_compr_set_params,
1009 .set_metadata = q6asm_dai_compr_set_metadata,
1010 .pointer = q6asm_dai_compr_pointer,
1011 .trigger = q6asm_dai_compr_trigger,
1012 .get_caps = q6asm_dai_compr_get_caps,
1013 .get_codec_caps = q6asm_dai_compr_get_codec_caps,
1014 .mmap = q6asm_dai_compr_mmap,
1015 .ack = q6asm_dai_compr_ack,
1018 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
1019 struct snd_soc_pcm_runtime *rtd)
1021 struct snd_pcm_substream *psubstream, *csubstream;
1022 struct snd_pcm *pcm = rtd->pcm;
1026 dev = component->dev;
1027 size = q6asm_dai_hardware_playback.buffer_bytes_max;
1028 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1030 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
1031 &psubstream->dma_buffer);
1033 dev_err(dev, "Cannot allocate buffer(s)\n");
1038 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1040 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
1041 &csubstream->dma_buffer);
1043 dev_err(dev, "Cannot allocate buffer(s)\n");
1045 snd_dma_free_pages(&psubstream->dma_buffer);
1053 static void q6asm_dai_pcm_free(struct snd_soc_component *component,
1054 struct snd_pcm *pcm)
1056 struct snd_pcm_substream *substream;
1059 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
1060 substream = pcm->streams[i].substream;
1062 snd_dma_free_pages(&substream->dma_buffer);
1063 substream->dma_buffer.area = NULL;
1064 substream->dma_buffer.addr = 0;
1069 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
1071 .open = q6asm_dai_open,
1072 .hw_params = q6asm_dai_hw_params,
1073 .close = q6asm_dai_close,
1074 .prepare = q6asm_dai_prepare,
1075 .trigger = q6asm_dai_trigger,
1076 .pointer = q6asm_dai_pointer,
1077 .mmap = q6asm_dai_mmap,
1078 .pcm_construct = q6asm_dai_pcm_new,
1079 .pcm_destruct = q6asm_dai_pcm_free,
1080 .compress_ops = &q6asm_dai_compress_ops,
1083 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
1084 Q6ASM_FEDAI_DRIVER(1),
1085 Q6ASM_FEDAI_DRIVER(2),
1086 Q6ASM_FEDAI_DRIVER(3),
1087 Q6ASM_FEDAI_DRIVER(4),
1088 Q6ASM_FEDAI_DRIVER(5),
1089 Q6ASM_FEDAI_DRIVER(6),
1090 Q6ASM_FEDAI_DRIVER(7),
1091 Q6ASM_FEDAI_DRIVER(8),
1094 static int of_q6asm_parse_dai_data(struct device *dev,
1095 struct q6asm_dai_data *pdata)
1097 struct snd_soc_dai_driver *dai_drv;
1098 struct snd_soc_pcm_stream empty_stream;
1099 struct device_node *node;
1100 int ret, id, dir, idx = 0;
1103 pdata->num_dais = of_get_child_count(dev->of_node);
1104 if (!pdata->num_dais) {
1105 dev_err(dev, "No dais found in DT\n");
1109 pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv),
1114 memset(&empty_stream, 0, sizeof(empty_stream));
1116 for_each_child_of_node(dev->of_node, node) {
1117 ret = of_property_read_u32(node, "reg", &id);
1118 if (ret || id >= MAX_SESSIONS || id < 0) {
1119 dev_err(dev, "valid dai id not found:%d\n", ret);
1123 dai_drv = &pdata->dais[idx++];
1124 *dai_drv = q6asm_fe_dais_template[id];
1126 ret = of_property_read_u32(node, "direction", &dir);
1130 if (dir == Q6ASM_DAI_RX)
1131 dai_drv->capture = empty_stream;
1132 else if (dir == Q6ASM_DAI_TX)
1133 dai_drv->playback = empty_stream;
1135 if (of_property_read_bool(node, "is-compress-dai"))
1136 dai_drv->compress_new = snd_soc_new_compress;
1142 static int q6asm_dai_probe(struct platform_device *pdev)
1144 struct device *dev = &pdev->dev;
1145 struct device_node *node = dev->of_node;
1146 struct of_phandle_args args;
1147 struct q6asm_dai_data *pdata;
1150 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1154 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
1158 pdata->sid = args.args[0] & SID_MASK_DEFAULT;
1160 dev_set_drvdata(dev, pdata);
1162 rc = of_q6asm_parse_dai_data(dev, pdata);
1166 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
1167 pdata->dais, pdata->num_dais);
1170 static const struct of_device_id q6asm_dai_device_id[] = {
1171 { .compatible = "qcom,q6asm-dais" },
1174 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
1176 static struct platform_driver q6asm_dai_platform_driver = {
1178 .name = "q6asm-dai",
1179 .of_match_table = of_match_ptr(q6asm_dai_device_id),
1181 .probe = q6asm_dai_probe,
1183 module_platform_driver(q6asm_dai_platform_driver);
1185 MODULE_DESCRIPTION("Q6ASM dai driver");
1186 MODULE_LICENSE("GPL v2");