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)
40 #define Q6ASM_DAI_TX_RX 0
41 #define Q6ASM_DAI_TX 1
42 #define Q6ASM_DAI_RX 2
44 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1)
45 #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2)
48 Q6ASM_STREAM_IDLE = 0,
53 struct q6asm_dai_rtd {
54 struct snd_pcm_substream *substream;
55 struct snd_compr_stream *cstream;
56 struct snd_compr_params codec_param;
57 struct snd_dma_buffer dma_buffer;
60 unsigned int pcm_size;
61 unsigned int pcm_count;
62 unsigned int pcm_irq_pos; /* IRQ position */
64 unsigned int bytes_sent;
65 unsigned int bytes_received;
66 unsigned int copied_total;
67 uint16_t bits_per_sample;
68 uint16_t source; /* Encoding source bit mask */
69 struct audio_client *audio_client;
71 enum stream_state state;
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,
188 prtd->pcm_count, 0, 0, NO_TIMESTAMP);
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,
198 prtd->pcm_count, 0, 0, NO_TIMESTAMP);
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);
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 = substream->private_data;
219 struct q6asm_dai_rtd *prtd = runtime->private_data;
220 struct q6asm_dai_data *pdata;
223 pdata = snd_soc_component_get_drvdata(component);
227 if (!prtd || !prtd->audio_client) {
228 pr_err("%s: private data null or audio client freed\n",
233 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
234 prtd->pcm_irq_pos = 0;
235 /* rate and channels are sent to audio driver */
237 /* clear the previous setup if any */
238 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
239 q6asm_unmap_memory_regions(substream->stream,
241 q6routing_stream_close(soc_prtd->dai_link->id,
245 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
247 (prtd->pcm_size / prtd->periods),
251 pr_err("Audio Start: Buffer Allocation failed rc = %d\n",
256 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
257 ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM,
258 0, prtd->bits_per_sample);
259 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
260 ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM,
261 prtd->bits_per_sample);
265 pr_err("%s: q6asm_open_write failed\n", __func__);
266 q6asm_audio_client_free(prtd->audio_client);
267 prtd->audio_client = NULL;
271 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
272 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
273 prtd->session_id, substream->stream);
275 pr_err("%s: stream reg failed ret:%d\n", __func__, ret);
279 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
280 ret = q6asm_media_format_block_multi_ch_pcm(
281 prtd->audio_client, runtime->rate,
282 runtime->channels, NULL,
283 prtd->bits_per_sample);
284 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
285 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
286 runtime->rate, runtime->channels,
287 prtd->bits_per_sample);
289 /* Queue the buffers */
290 for (i = 0; i < runtime->periods; i++)
291 q6asm_read(prtd->audio_client);
295 pr_info("%s: CMD Format block failed\n", __func__);
297 prtd->state = Q6ASM_STREAM_RUNNING;
302 static int q6asm_dai_trigger(struct snd_soc_component *component,
303 struct snd_pcm_substream *substream, int cmd)
306 struct snd_pcm_runtime *runtime = substream->runtime;
307 struct q6asm_dai_rtd *prtd = runtime->private_data;
310 case SNDRV_PCM_TRIGGER_START:
311 case SNDRV_PCM_TRIGGER_RESUME:
312 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
313 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
315 case SNDRV_PCM_TRIGGER_STOP:
316 prtd->state = Q6ASM_STREAM_STOPPED;
317 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
319 case SNDRV_PCM_TRIGGER_SUSPEND:
320 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
321 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
331 static int q6asm_dai_open(struct snd_soc_component *component,
332 struct snd_pcm_substream *substream)
334 struct snd_pcm_runtime *runtime = substream->runtime;
335 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
336 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0);
337 struct q6asm_dai_rtd *prtd;
338 struct q6asm_dai_data *pdata;
339 struct device *dev = component->dev;
343 stream_id = cpu_dai->driver->id;
345 pdata = snd_soc_component_get_drvdata(component);
347 pr_err("Drv data not found ..\n");
351 prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL);
355 prtd->substream = substream;
356 prtd->audio_client = q6asm_audio_client_alloc(dev,
357 (q6asm_cb)event_handler, prtd, stream_id,
359 if (IS_ERR(prtd->audio_client)) {
360 pr_info("%s: Could not allocate memory\n", __func__);
361 ret = PTR_ERR(prtd->audio_client);
366 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
367 runtime->hw = q6asm_dai_hardware_playback;
368 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
369 runtime->hw = q6asm_dai_hardware_capture;
371 ret = snd_pcm_hw_constraint_list(runtime, 0,
372 SNDRV_PCM_HW_PARAM_RATE,
373 &constraints_sample_rates);
375 pr_info("snd_pcm_hw_constraint_list failed\n");
376 /* Ensure that buffer size is a multiple of period size */
377 ret = snd_pcm_hw_constraint_integer(runtime,
378 SNDRV_PCM_HW_PARAM_PERIODS);
380 pr_info("snd_pcm_hw_constraint_integer failed\n");
382 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
383 ret = snd_pcm_hw_constraint_minmax(runtime,
384 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
385 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
386 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
388 pr_err("constraint for buffer bytes min max ret = %d\n",
393 ret = snd_pcm_hw_constraint_step(runtime, 0,
394 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
396 pr_err("constraint for period bytes step ret = %d\n",
399 ret = snd_pcm_hw_constraint_step(runtime, 0,
400 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
402 pr_err("constraint for buffer bytes step ret = %d\n",
406 runtime->private_data = prtd;
408 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
410 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
414 prtd->phys = substream->dma_buffer.addr;
416 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
418 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
423 static int q6asm_dai_close(struct snd_soc_component *component,
424 struct snd_pcm_substream *substream)
426 struct snd_pcm_runtime *runtime = substream->runtime;
427 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
428 struct q6asm_dai_rtd *prtd = runtime->private_data;
430 if (prtd->audio_client) {
432 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
434 q6asm_unmap_memory_regions(substream->stream,
436 q6asm_audio_client_free(prtd->audio_client);
437 prtd->audio_client = NULL;
439 q6routing_stream_close(soc_prtd->dai_link->id,
445 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
446 struct snd_pcm_substream *substream)
449 struct snd_pcm_runtime *runtime = substream->runtime;
450 struct q6asm_dai_rtd *prtd = runtime->private_data;
452 if (prtd->pcm_irq_pos >= prtd->pcm_size)
453 prtd->pcm_irq_pos = 0;
455 return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
458 static int q6asm_dai_mmap(struct snd_soc_component *component,
459 struct snd_pcm_substream *substream,
460 struct vm_area_struct *vma)
462 struct snd_pcm_runtime *runtime = substream->runtime;
463 struct device *dev = component->dev;
465 return dma_mmap_coherent(dev, vma,
466 runtime->dma_area, runtime->dma_addr,
470 static int q6asm_dai_hw_params(struct snd_soc_component *component,
471 struct snd_pcm_substream *substream,
472 struct snd_pcm_hw_params *params)
474 struct snd_pcm_runtime *runtime = substream->runtime;
475 struct q6asm_dai_rtd *prtd = runtime->private_data;
477 prtd->pcm_size = params_buffer_bytes(params);
478 prtd->periods = params_periods(params);
480 switch (params_format(params)) {
481 case SNDRV_PCM_FORMAT_S16_LE:
482 prtd->bits_per_sample = 16;
484 case SNDRV_PCM_FORMAT_S24_LE:
485 prtd->bits_per_sample = 24;
492 static void compress_event_handler(uint32_t opcode, uint32_t token,
493 void *payload, void *priv)
495 struct q6asm_dai_rtd *prtd = priv;
496 struct snd_compr_stream *substream = prtd->cstream;
501 case ASM_CLIENT_EVENT_CMD_RUN_DONE:
502 spin_lock_irqsave(&prtd->lock, flags);
503 if (!prtd->bytes_sent) {
504 q6asm_write_async(prtd->audio_client, prtd->pcm_count,
506 prtd->bytes_sent += prtd->pcm_count;
509 spin_unlock_irqrestore(&prtd->lock, flags);
512 case ASM_CLIENT_EVENT_CMD_EOS_DONE:
513 prtd->state = Q6ASM_STREAM_STOPPED;
516 case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
517 spin_lock_irqsave(&prtd->lock, flags);
519 prtd->copied_total += prtd->pcm_count;
520 snd_compr_fragment_elapsed(substream);
522 if (prtd->state != Q6ASM_STREAM_RUNNING) {
523 spin_unlock_irqrestore(&prtd->lock, flags);
527 avail = prtd->bytes_received - prtd->bytes_sent;
529 if (avail >= prtd->pcm_count) {
530 q6asm_write_async(prtd->audio_client,
531 prtd->pcm_count, 0, 0, NO_TIMESTAMP);
532 prtd->bytes_sent += prtd->pcm_count;
535 spin_unlock_irqrestore(&prtd->lock, flags);
543 static int q6asm_dai_compr_open(struct snd_soc_component *component,
544 struct snd_compr_stream *stream)
546 struct snd_soc_pcm_runtime *rtd = stream->private_data;
547 struct snd_compr_runtime *runtime = stream->runtime;
548 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
549 struct q6asm_dai_data *pdata;
550 struct device *dev = component->dev;
551 struct q6asm_dai_rtd *prtd;
552 int stream_id, size, ret;
554 stream_id = cpu_dai->driver->id;
555 pdata = snd_soc_component_get_drvdata(component);
557 dev_err(dev, "Drv data not found ..\n");
561 prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
565 prtd->cstream = stream;
566 prtd->audio_client = q6asm_audio_client_alloc(dev,
567 (q6asm_cb)compress_event_handler,
568 prtd, stream_id, LEGACY_PCM_MODE);
569 if (IS_ERR(prtd->audio_client)) {
570 dev_err(dev, "Could not allocate memory\n");
571 ret = PTR_ERR(prtd->audio_client);
575 size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
576 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
577 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
580 dev_err(dev, "Cannot allocate buffer(s)\n");
585 prtd->phys = prtd->dma_buffer.addr;
587 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
589 snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
590 spin_lock_init(&prtd->lock);
591 runtime->private_data = prtd;
596 q6asm_audio_client_free(prtd->audio_client);
603 static int q6asm_dai_compr_free(struct snd_soc_component *component,
604 struct snd_compr_stream *stream)
606 struct snd_compr_runtime *runtime = stream->runtime;
607 struct q6asm_dai_rtd *prtd = runtime->private_data;
608 struct snd_soc_pcm_runtime *rtd = stream->private_data;
610 if (prtd->audio_client) {
612 q6asm_cmd(prtd->audio_client, CMD_CLOSE);
614 snd_dma_free_pages(&prtd->dma_buffer);
615 q6asm_unmap_memory_regions(stream->direction,
617 q6asm_audio_client_free(prtd->audio_client);
618 prtd->audio_client = NULL;
620 q6routing_stream_close(rtd->dai_link->id, stream->direction);
626 static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
627 struct snd_compr_stream *stream,
628 struct snd_compr_params *params)
630 struct snd_compr_runtime *runtime = stream->runtime;
631 struct q6asm_dai_rtd *prtd = runtime->private_data;
632 struct snd_soc_pcm_runtime *rtd = stream->private_data;
633 int dir = stream->direction;
634 struct q6asm_dai_data *pdata;
635 struct q6asm_flac_cfg flac_cfg;
636 struct q6asm_wma_cfg wma_cfg;
637 struct q6asm_alac_cfg alac_cfg;
638 struct q6asm_ape_cfg ape_cfg;
639 unsigned int wma_v9 = 0;
640 struct device *dev = component->dev;
642 union snd_codec_options *codec_options;
643 struct snd_dec_flac *flac;
644 struct snd_dec_wma *wma;
645 struct snd_dec_alac *alac;
646 struct snd_dec_ape *ape;
648 codec_options = &(prtd->codec_param.codec.options);
651 memcpy(&prtd->codec_param, params, sizeof(*params));
653 pdata = snd_soc_component_get_drvdata(component);
657 if (!prtd || !prtd->audio_client) {
658 dev_err(dev, "private data null or audio client freed\n");
662 prtd->periods = runtime->fragments;
663 prtd->pcm_count = runtime->fragment_size;
664 prtd->pcm_size = runtime->fragments * runtime->fragment_size;
665 prtd->bits_per_sample = 16;
666 if (dir == SND_COMPRESS_PLAYBACK) {
667 ret = q6asm_open_write(prtd->audio_client, params->codec.id,
668 params->codec.profile, prtd->bits_per_sample);
671 dev_err(dev, "q6asm_open_write failed\n");
672 q6asm_audio_client_free(prtd->audio_client);
673 prtd->audio_client = NULL;
678 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
679 ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
680 prtd->session_id, dir);
682 dev_err(dev, "Stream reg failed ret:%d\n", ret);
686 switch (params->codec.id) {
687 case SND_AUDIOCODEC_FLAC:
689 memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg));
690 flac = &codec_options->flac_d;
692 flac_cfg.ch_cfg = params->codec.ch_in;
693 flac_cfg.sample_rate = params->codec.sample_rate;
694 flac_cfg.stream_info_present = 1;
695 flac_cfg.sample_size = flac->sample_size;
696 flac_cfg.min_blk_size = flac->min_blk_size;
697 flac_cfg.max_blk_size = flac->max_blk_size;
698 flac_cfg.max_frame_size = flac->max_frame_size;
699 flac_cfg.min_frame_size = flac->min_frame_size;
701 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
704 dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
709 case SND_AUDIOCODEC_WMA:
710 wma = &codec_options->wma_d;
712 memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg));
714 wma_cfg.sample_rate = params->codec.sample_rate;
715 wma_cfg.num_channels = params->codec.ch_in;
716 wma_cfg.bytes_per_sec = params->codec.bit_rate / 8;
717 wma_cfg.block_align = params->codec.align;
718 wma_cfg.bits_per_sample = prtd->bits_per_sample;
719 wma_cfg.enc_options = wma->encoder_option;
720 wma_cfg.adv_enc_options = wma->adv_encoder_option;
721 wma_cfg.adv_enc_options2 = wma->adv_encoder_option2;
723 if (wma_cfg.num_channels == 1)
724 wma_cfg.channel_mask = 4; /* Mono Center */
725 else if (wma_cfg.num_channels == 2)
726 wma_cfg.channel_mask = 3; /* Stereo FL/FR */
730 /* check the codec profile */
731 switch (params->codec.profile) {
732 case SND_AUDIOPROFILE_WMA9:
733 wma_cfg.fmtag = 0x161;
737 case SND_AUDIOPROFILE_WMA10:
738 wma_cfg.fmtag = 0x166;
741 case SND_AUDIOPROFILE_WMA9_PRO:
742 wma_cfg.fmtag = 0x162;
745 case SND_AUDIOPROFILE_WMA9_LOSSLESS:
746 wma_cfg.fmtag = 0x163;
749 case SND_AUDIOPROFILE_WMA10_LOSSLESS:
750 wma_cfg.fmtag = 0x167;
754 dev_err(dev, "Unknown WMA profile:%x\n",
755 params->codec.profile);
760 ret = q6asm_stream_media_format_block_wma_v9(
761 prtd->audio_client, &wma_cfg);
763 ret = q6asm_stream_media_format_block_wma_v10(
764 prtd->audio_client, &wma_cfg);
766 dev_err(dev, "WMA9 CMD failed:%d\n", ret);
771 case SND_AUDIOCODEC_ALAC:
772 memset(&alac_cfg, 0x0, sizeof(alac_cfg));
773 alac = &codec_options->alac_d;
775 alac_cfg.sample_rate = params->codec.sample_rate;
776 alac_cfg.avg_bit_rate = params->codec.bit_rate;
777 alac_cfg.bit_depth = prtd->bits_per_sample;
778 alac_cfg.num_channels = params->codec.ch_in;
780 alac_cfg.frame_length = alac->frame_length;
781 alac_cfg.pb = alac->pb;
782 alac_cfg.mb = alac->mb;
783 alac_cfg.kb = alac->kb;
784 alac_cfg.max_run = alac->max_run;
785 alac_cfg.compatible_version = alac->compatible_version;
786 alac_cfg.max_frame_bytes = alac->max_frame_bytes;
788 switch (params->codec.ch_in) {
790 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO;
793 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO;
796 ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
799 dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
804 case SND_AUDIOCODEC_APE:
805 memset(&ape_cfg, 0x0, sizeof(ape_cfg));
806 ape = &codec_options->ape_d;
808 ape_cfg.sample_rate = params->codec.sample_rate;
809 ape_cfg.num_channels = params->codec.ch_in;
810 ape_cfg.bits_per_sample = prtd->bits_per_sample;
812 ape_cfg.compatible_version = ape->compatible_version;
813 ape_cfg.compression_level = ape->compression_level;
814 ape_cfg.format_flags = ape->format_flags;
815 ape_cfg.blocks_per_frame = ape->blocks_per_frame;
816 ape_cfg.final_frame_blocks = ape->final_frame_blocks;
817 ape_cfg.total_frames = ape->total_frames;
818 ape_cfg.seek_table_present = ape->seek_table_present;
820 ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
823 dev_err(dev, "APE CMD Format block failed:%d\n", ret);
832 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
833 (prtd->pcm_size / prtd->periods),
837 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
841 prtd->state = Q6ASM_STREAM_RUNNING;
846 static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
847 struct snd_compr_stream *stream, int cmd)
849 struct snd_compr_runtime *runtime = stream->runtime;
850 struct q6asm_dai_rtd *prtd = runtime->private_data;
854 case SNDRV_PCM_TRIGGER_START:
855 case SNDRV_PCM_TRIGGER_RESUME:
856 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
857 ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
859 case SNDRV_PCM_TRIGGER_STOP:
860 prtd->state = Q6ASM_STREAM_STOPPED;
861 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
863 case SNDRV_PCM_TRIGGER_SUSPEND:
864 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
865 ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
875 static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
876 struct snd_compr_stream *stream,
877 struct snd_compr_tstamp *tstamp)
879 struct snd_compr_runtime *runtime = stream->runtime;
880 struct q6asm_dai_rtd *prtd = runtime->private_data;
883 spin_lock_irqsave(&prtd->lock, flags);
885 tstamp->copied_total = prtd->copied_total;
886 tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
888 spin_unlock_irqrestore(&prtd->lock, flags);
893 static int q6asm_dai_compr_ack(struct snd_soc_component *component,
894 struct snd_compr_stream *stream,
897 struct snd_compr_runtime *runtime = stream->runtime;
898 struct q6asm_dai_rtd *prtd = runtime->private_data;
901 spin_lock_irqsave(&prtd->lock, flags);
902 prtd->bytes_received += count;
903 spin_unlock_irqrestore(&prtd->lock, flags);
908 static int q6asm_dai_compr_mmap(struct snd_soc_component *component,
909 struct snd_compr_stream *stream,
910 struct vm_area_struct *vma)
912 struct snd_compr_runtime *runtime = stream->runtime;
913 struct q6asm_dai_rtd *prtd = runtime->private_data;
914 struct device *dev = component->dev;
916 return dma_mmap_coherent(dev, vma,
917 prtd->dma_buffer.area, prtd->dma_buffer.addr,
918 prtd->dma_buffer.bytes);
921 static int q6asm_dai_compr_get_caps(struct snd_soc_component *component,
922 struct snd_compr_stream *stream,
923 struct snd_compr_caps *caps)
925 caps->direction = SND_COMPRESS_PLAYBACK;
926 caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
927 caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
928 caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
929 caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
930 caps->num_codecs = 5;
931 caps->codecs[0] = SND_AUDIOCODEC_MP3;
932 caps->codecs[1] = SND_AUDIOCODEC_FLAC;
933 caps->codecs[2] = SND_AUDIOCODEC_WMA;
934 caps->codecs[3] = SND_AUDIOCODEC_ALAC;
935 caps->codecs[4] = SND_AUDIOCODEC_APE;
940 static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component,
941 struct snd_compr_stream *stream,
942 struct snd_compr_codec_caps *codec)
944 switch (codec->codec) {
945 case SND_AUDIOCODEC_MP3:
946 *codec = q6asm_compr_caps;
955 static struct snd_compress_ops q6asm_dai_compress_ops = {
956 .open = q6asm_dai_compr_open,
957 .free = q6asm_dai_compr_free,
958 .set_params = q6asm_dai_compr_set_params,
959 .pointer = q6asm_dai_compr_pointer,
960 .trigger = q6asm_dai_compr_trigger,
961 .get_caps = q6asm_dai_compr_get_caps,
962 .get_codec_caps = q6asm_dai_compr_get_codec_caps,
963 .mmap = q6asm_dai_compr_mmap,
964 .ack = q6asm_dai_compr_ack,
967 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
968 struct snd_soc_pcm_runtime *rtd)
970 struct snd_pcm_substream *psubstream, *csubstream;
971 struct snd_pcm *pcm = rtd->pcm;
975 dev = component->dev;
976 size = q6asm_dai_hardware_playback.buffer_bytes_max;
977 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
979 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
980 &psubstream->dma_buffer);
982 dev_err(dev, "Cannot allocate buffer(s)\n");
987 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
989 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
990 &csubstream->dma_buffer);
992 dev_err(dev, "Cannot allocate buffer(s)\n");
994 snd_dma_free_pages(&psubstream->dma_buffer);
1002 static void q6asm_dai_pcm_free(struct snd_soc_component *component,
1003 struct snd_pcm *pcm)
1005 struct snd_pcm_substream *substream;
1008 for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
1009 substream = pcm->streams[i].substream;
1011 snd_dma_free_pages(&substream->dma_buffer);
1012 substream->dma_buffer.area = NULL;
1013 substream->dma_buffer.addr = 0;
1018 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
1020 .open = q6asm_dai_open,
1021 .hw_params = q6asm_dai_hw_params,
1022 .close = q6asm_dai_close,
1023 .prepare = q6asm_dai_prepare,
1024 .trigger = q6asm_dai_trigger,
1025 .pointer = q6asm_dai_pointer,
1026 .mmap = q6asm_dai_mmap,
1027 .pcm_construct = q6asm_dai_pcm_new,
1028 .pcm_destruct = q6asm_dai_pcm_free,
1029 .compress_ops = &q6asm_dai_compress_ops,
1032 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
1033 Q6ASM_FEDAI_DRIVER(1),
1034 Q6ASM_FEDAI_DRIVER(2),
1035 Q6ASM_FEDAI_DRIVER(3),
1036 Q6ASM_FEDAI_DRIVER(4),
1037 Q6ASM_FEDAI_DRIVER(5),
1038 Q6ASM_FEDAI_DRIVER(6),
1039 Q6ASM_FEDAI_DRIVER(7),
1040 Q6ASM_FEDAI_DRIVER(8),
1043 static int of_q6asm_parse_dai_data(struct device *dev,
1044 struct q6asm_dai_data *pdata)
1046 struct snd_soc_dai_driver *dai_drv;
1047 struct snd_soc_pcm_stream empty_stream;
1048 struct device_node *node;
1049 int ret, id, dir, idx = 0;
1052 pdata->num_dais = of_get_child_count(dev->of_node);
1053 if (!pdata->num_dais) {
1054 dev_err(dev, "No dais found in DT\n");
1058 pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv),
1063 memset(&empty_stream, 0, sizeof(empty_stream));
1065 for_each_child_of_node(dev->of_node, node) {
1066 ret = of_property_read_u32(node, "reg", &id);
1067 if (ret || id >= MAX_SESSIONS || id < 0) {
1068 dev_err(dev, "valid dai id not found:%d\n", ret);
1072 dai_drv = &pdata->dais[idx++];
1073 *dai_drv = q6asm_fe_dais_template[id];
1075 ret = of_property_read_u32(node, "direction", &dir);
1079 if (dir == Q6ASM_DAI_RX)
1080 dai_drv->capture = empty_stream;
1081 else if (dir == Q6ASM_DAI_TX)
1082 dai_drv->playback = empty_stream;
1084 if (of_property_read_bool(node, "is-compress-dai"))
1085 dai_drv->compress_new = snd_soc_new_compress;
1091 static int q6asm_dai_probe(struct platform_device *pdev)
1093 struct device *dev = &pdev->dev;
1094 struct device_node *node = dev->of_node;
1095 struct of_phandle_args args;
1096 struct q6asm_dai_data *pdata;
1099 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1103 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
1107 pdata->sid = args.args[0] & SID_MASK_DEFAULT;
1109 dev_set_drvdata(dev, pdata);
1111 rc = of_q6asm_parse_dai_data(dev, pdata);
1115 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
1116 pdata->dais, pdata->num_dais);
1119 static const struct of_device_id q6asm_dai_device_id[] = {
1120 { .compatible = "qcom,q6asm-dais" },
1123 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
1125 static struct platform_driver q6asm_dai_platform_driver = {
1127 .name = "q6asm-dai",
1128 .of_match_table = of_match_ptr(q6asm_dai_device_id),
1130 .probe = q6asm_dai_probe,
1132 module_platform_driver(q6asm_dai_platform_driver);
1134 MODULE_DESCRIPTION("Q6ASM dai driver");
1135 MODULE_LICENSE("GPL v2");