xref: /openbmc/linux/sound/soc/qcom/qdsp6/q6asm-dai.c (revision 5fa1f768)
1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
3 // Copyright (c) 2018, Linaro Limited
4 
5 #include <linux/init.h>
6 #include <linux/err.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>
15 #include <asm/dma.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/of_device.h>
18 #include <sound/pcm_params.h>
19 #include "q6asm.h"
20 #include "q6routing.h"
21 #include "q6dsp-errno.h"
22 
23 #define DRV_NAME	"q6asm-fe-dai"
24 
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
34 
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 
41 #define ALAC_CH_LAYOUT_MONO   ((101 << 16) | 1)
42 #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2)
43 
44 enum stream_state {
45 	Q6ASM_STREAM_IDLE = 0,
46 	Q6ASM_STREAM_STOPPED,
47 	Q6ASM_STREAM_RUNNING,
48 };
49 
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;
55 	spinlock_t lock;
56 	phys_addr_t phys;
57 	unsigned int pcm_size;
58 	unsigned int pcm_count;
59 	unsigned int pcm_irq_pos;       /* IRQ position */
60 	unsigned int periods;
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;
67 	uint16_t session_id;
68 	enum stream_state state;
69 };
70 
71 struct q6asm_dai_data {
72 	struct snd_soc_dai_driver *dais;
73 	int num_dais;
74 	long long int sid;
75 };
76 
77 static const struct snd_pcm_hardware q6asm_dai_hardware_capture = {
78 	.info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
79 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
80 				SNDRV_PCM_INFO_MMAP_VALID |
81 				SNDRV_PCM_INFO_INTERLEAVED |
82 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
83 	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
84 				SNDRV_PCM_FMTBIT_S24_LE),
85 	.rates =                SNDRV_PCM_RATE_8000_48000,
86 	.rate_min =             8000,
87 	.rate_max =             48000,
88 	.channels_min =         1,
89 	.channels_max =         4,
90 	.buffer_bytes_max =     CAPTURE_MAX_NUM_PERIODS *
91 				CAPTURE_MAX_PERIOD_SIZE,
92 	.period_bytes_min =	CAPTURE_MIN_PERIOD_SIZE,
93 	.period_bytes_max =     CAPTURE_MAX_PERIOD_SIZE,
94 	.periods_min =          CAPTURE_MIN_NUM_PERIODS,
95 	.periods_max =          CAPTURE_MAX_NUM_PERIODS,
96 	.fifo_size =            0,
97 };
98 
99 static struct snd_pcm_hardware q6asm_dai_hardware_playback = {
100 	.info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
101 				SNDRV_PCM_INFO_BLOCK_TRANSFER |
102 				SNDRV_PCM_INFO_MMAP_VALID |
103 				SNDRV_PCM_INFO_INTERLEAVED |
104 				SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
105 	.formats =              (SNDRV_PCM_FMTBIT_S16_LE |
106 				SNDRV_PCM_FMTBIT_S24_LE),
107 	.rates =                SNDRV_PCM_RATE_8000_192000,
108 	.rate_min =             8000,
109 	.rate_max =             192000,
110 	.channels_min =         1,
111 	.channels_max =         8,
112 	.buffer_bytes_max =     (PLAYBACK_MAX_NUM_PERIODS *
113 				PLAYBACK_MAX_PERIOD_SIZE),
114 	.period_bytes_min =	PLAYBACK_MIN_PERIOD_SIZE,
115 	.period_bytes_max =     PLAYBACK_MAX_PERIOD_SIZE,
116 	.periods_min =          PLAYBACK_MIN_NUM_PERIODS,
117 	.periods_max =          PLAYBACK_MAX_NUM_PERIODS,
118 	.fifo_size =            0,
119 };
120 
121 #define Q6ASM_FEDAI_DRIVER(num) { \
122 		.playback = {						\
123 			.stream_name = "MultiMedia"#num" Playback",	\
124 			.rates = (SNDRV_PCM_RATE_8000_192000|		\
125 					SNDRV_PCM_RATE_KNOT),		\
126 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |		\
127 					SNDRV_PCM_FMTBIT_S24_LE),	\
128 			.channels_min = 1,				\
129 			.channels_max = 8,				\
130 			.rate_min =     8000,				\
131 			.rate_max =	192000,				\
132 		},							\
133 		.capture = {						\
134 			.stream_name = "MultiMedia"#num" Capture",	\
135 			.rates = (SNDRV_PCM_RATE_8000_48000|		\
136 					SNDRV_PCM_RATE_KNOT),		\
137 			.formats = (SNDRV_PCM_FMTBIT_S16_LE |		\
138 				    SNDRV_PCM_FMTBIT_S24_LE),		\
139 			.channels_min = 1,				\
140 			.channels_max = 4,				\
141 			.rate_min =     8000,				\
142 			.rate_max =	48000,				\
143 		},							\
144 		.name = "MultiMedia"#num,				\
145 		.id = MSM_FRONTEND_DAI_MULTIMEDIA##num,			\
146 	}
147 
148 /* Conventional and unconventional sample rate supported */
149 static unsigned int supported_sample_rates[] = {
150 	8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000,
151 	88200, 96000, 176400, 192000
152 };
153 
154 static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
155 	.count = ARRAY_SIZE(supported_sample_rates),
156 	.list = supported_sample_rates,
157 	.mask = 0,
158 };
159 
160 static const struct snd_compr_codec_caps q6asm_compr_caps = {
161 	.num_descriptors = 1,
162 	.descriptor[0].max_ch = 2,
163 	.descriptor[0].sample_rates = {	8000, 11025, 12000, 16000, 22050,
164 					24000, 32000, 44100, 48000, 88200,
165 					96000, 176400, 192000 },
166 	.descriptor[0].num_sample_rates = 13,
167 	.descriptor[0].bit_rate[0] = 320,
168 	.descriptor[0].bit_rate[1] = 128,
169 	.descriptor[0].num_bitrates = 2,
170 	.descriptor[0].profiles = 0,
171 	.descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
172 	.descriptor[0].formats = 0,
173 };
174 
175 static void event_handler(uint32_t opcode, uint32_t token,
176 			  void *payload, void *priv)
177 {
178 	struct q6asm_dai_rtd *prtd = priv;
179 	struct snd_pcm_substream *substream = prtd->substream;
180 
181 	switch (opcode) {
182 	case ASM_CLIENT_EVENT_CMD_RUN_DONE:
183 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
184 			q6asm_write_async(prtd->audio_client,
185 				   prtd->pcm_count, 0, 0, NO_TIMESTAMP);
186 		break;
187 	case ASM_CLIENT_EVENT_CMD_EOS_DONE:
188 		prtd->state = Q6ASM_STREAM_STOPPED;
189 		break;
190 	case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
191 		prtd->pcm_irq_pos += prtd->pcm_count;
192 		snd_pcm_period_elapsed(substream);
193 		if (prtd->state == Q6ASM_STREAM_RUNNING)
194 			q6asm_write_async(prtd->audio_client,
195 					   prtd->pcm_count, 0, 0, NO_TIMESTAMP);
196 
197 		break;
198 		}
199 	case ASM_CLIENT_EVENT_DATA_READ_DONE:
200 		prtd->pcm_irq_pos += prtd->pcm_count;
201 		snd_pcm_period_elapsed(substream);
202 		if (prtd->state == Q6ASM_STREAM_RUNNING)
203 			q6asm_read(prtd->audio_client);
204 
205 		break;
206 	default:
207 		break;
208 	}
209 }
210 
211 static int q6asm_dai_prepare(struct snd_soc_component *component,
212 			     struct snd_pcm_substream *substream)
213 {
214 	struct snd_pcm_runtime *runtime = substream->runtime;
215 	struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
216 	struct q6asm_dai_rtd *prtd = runtime->private_data;
217 	struct q6asm_dai_data *pdata;
218 	struct device *dev = component->dev;
219 	int ret, i;
220 
221 	pdata = snd_soc_component_get_drvdata(component);
222 	if (!pdata)
223 		return -EINVAL;
224 
225 	if (!prtd || !prtd->audio_client) {
226 		dev_err(dev, "%s: private data null or audio client freed\n",
227 			__func__);
228 		return -EINVAL;
229 	}
230 
231 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
232 	prtd->pcm_irq_pos = 0;
233 	/* rate and channels are sent to audio driver */
234 	if (prtd->state) {
235 		/* clear the previous setup if any  */
236 		q6asm_cmd(prtd->audio_client, CMD_CLOSE);
237 		q6asm_unmap_memory_regions(substream->stream,
238 					   prtd->audio_client);
239 		q6routing_stream_close(soc_prtd->dai_link->id,
240 					 substream->stream);
241 	}
242 
243 	ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
244 				       prtd->phys,
245 				       (prtd->pcm_size / prtd->periods),
246 				       prtd->periods);
247 
248 	if (ret < 0) {
249 		dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n",
250 							ret);
251 		return -ENOMEM;
252 	}
253 
254 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
255 		ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM,
256 				       0, prtd->bits_per_sample);
257 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
258 		ret = q6asm_open_read(prtd->audio_client, FORMAT_LINEAR_PCM,
259 				       prtd->bits_per_sample);
260 	}
261 
262 	if (ret < 0) {
263 		dev_err(dev, "%s: q6asm_open_write failed\n", __func__);
264 		q6asm_audio_client_free(prtd->audio_client);
265 		prtd->audio_client = NULL;
266 		return -ENOMEM;
267 	}
268 
269 	prtd->session_id = q6asm_get_session_id(prtd->audio_client);
270 	ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
271 			      prtd->session_id, substream->stream);
272 	if (ret) {
273 		dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret);
274 		return ret;
275 	}
276 
277 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
278 		ret = q6asm_media_format_block_multi_ch_pcm(
279 				prtd->audio_client, runtime->rate,
280 				runtime->channels, NULL,
281 				prtd->bits_per_sample);
282 	} else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
283 		ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
284 					runtime->rate, runtime->channels,
285 					prtd->bits_per_sample);
286 
287 		/* Queue the buffers */
288 		for (i = 0; i < runtime->periods; i++)
289 			q6asm_read(prtd->audio_client);
290 
291 	}
292 	if (ret < 0)
293 		dev_info(dev, "%s: CMD Format block failed\n", __func__);
294 
295 	prtd->state = Q6ASM_STREAM_RUNNING;
296 
297 	return 0;
298 }
299 
300 static int q6asm_dai_trigger(struct snd_soc_component *component,
301 			     struct snd_pcm_substream *substream, int cmd)
302 {
303 	int ret = 0;
304 	struct snd_pcm_runtime *runtime = substream->runtime;
305 	struct q6asm_dai_rtd *prtd = runtime->private_data;
306 
307 	switch (cmd) {
308 	case SNDRV_PCM_TRIGGER_START:
309 	case SNDRV_PCM_TRIGGER_RESUME:
310 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
311 		ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
312 		break;
313 	case SNDRV_PCM_TRIGGER_STOP:
314 		prtd->state = Q6ASM_STREAM_STOPPED;
315 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
316 		break;
317 	case SNDRV_PCM_TRIGGER_SUSPEND:
318 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
319 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
320 		break;
321 	default:
322 		ret = -EINVAL;
323 		break;
324 	}
325 
326 	return ret;
327 }
328 
329 static int q6asm_dai_open(struct snd_soc_component *component,
330 			  struct snd_pcm_substream *substream)
331 {
332 	struct snd_pcm_runtime *runtime = substream->runtime;
333 	struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
334 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_prtd, 0);
335 	struct q6asm_dai_rtd *prtd;
336 	struct q6asm_dai_data *pdata;
337 	struct device *dev = component->dev;
338 	int ret = 0;
339 	int stream_id;
340 
341 	stream_id = cpu_dai->driver->id;
342 
343 	pdata = snd_soc_component_get_drvdata(component);
344 	if (!pdata) {
345 		dev_err(dev, "Drv data not found ..\n");
346 		return -EINVAL;
347 	}
348 
349 	prtd = kzalloc(sizeof(struct q6asm_dai_rtd), GFP_KERNEL);
350 	if (prtd == NULL)
351 		return -ENOMEM;
352 
353 	prtd->substream = substream;
354 	prtd->audio_client = q6asm_audio_client_alloc(dev,
355 				(q6asm_cb)event_handler, prtd, stream_id,
356 				LEGACY_PCM_MODE);
357 	if (IS_ERR(prtd->audio_client)) {
358 		dev_info(dev, "%s: Could not allocate memory\n", __func__);
359 		ret = PTR_ERR(prtd->audio_client);
360 		kfree(prtd);
361 		return ret;
362 	}
363 
364 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
365 		runtime->hw = q6asm_dai_hardware_playback;
366 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
367 		runtime->hw = q6asm_dai_hardware_capture;
368 
369 	ret = snd_pcm_hw_constraint_list(runtime, 0,
370 				SNDRV_PCM_HW_PARAM_RATE,
371 				&constraints_sample_rates);
372 	if (ret < 0)
373 		dev_info(dev, "snd_pcm_hw_constraint_list failed\n");
374 	/* Ensure that buffer size is a multiple of period size */
375 	ret = snd_pcm_hw_constraint_integer(runtime,
376 					    SNDRV_PCM_HW_PARAM_PERIODS);
377 	if (ret < 0)
378 		dev_info(dev, "snd_pcm_hw_constraint_integer failed\n");
379 
380 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
381 		ret = snd_pcm_hw_constraint_minmax(runtime,
382 			SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
383 			PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
384 			PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
385 		if (ret < 0) {
386 			dev_err(dev, "constraint for buffer bytes min max ret = %d\n",
387 				ret);
388 		}
389 	}
390 
391 	ret = snd_pcm_hw_constraint_step(runtime, 0,
392 		SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
393 	if (ret < 0) {
394 		dev_err(dev, "constraint for period bytes step ret = %d\n",
395 								ret);
396 	}
397 	ret = snd_pcm_hw_constraint_step(runtime, 0,
398 		SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
399 	if (ret < 0) {
400 		dev_err(dev, "constraint for buffer bytes step ret = %d\n",
401 								ret);
402 	}
403 
404 	runtime->private_data = prtd;
405 
406 	snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
407 
408 	runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
409 
410 
411 	if (pdata->sid < 0)
412 		prtd->phys = substream->dma_buffer.addr;
413 	else
414 		prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
415 
416 	snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
417 
418 	return 0;
419 }
420 
421 static int q6asm_dai_close(struct snd_soc_component *component,
422 			   struct snd_pcm_substream *substream)
423 {
424 	struct snd_pcm_runtime *runtime = substream->runtime;
425 	struct snd_soc_pcm_runtime *soc_prtd = asoc_substream_to_rtd(substream);
426 	struct q6asm_dai_rtd *prtd = runtime->private_data;
427 
428 	if (prtd->audio_client) {
429 		if (prtd->state)
430 			q6asm_cmd(prtd->audio_client, CMD_CLOSE);
431 
432 		q6asm_unmap_memory_regions(substream->stream,
433 					   prtd->audio_client);
434 		q6asm_audio_client_free(prtd->audio_client);
435 		prtd->audio_client = NULL;
436 	}
437 	q6routing_stream_close(soc_prtd->dai_link->id,
438 						substream->stream);
439 	kfree(prtd);
440 	return 0;
441 }
442 
443 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
444 					   struct snd_pcm_substream *substream)
445 {
446 
447 	struct snd_pcm_runtime *runtime = substream->runtime;
448 	struct q6asm_dai_rtd *prtd = runtime->private_data;
449 
450 	if (prtd->pcm_irq_pos >= prtd->pcm_size)
451 		prtd->pcm_irq_pos = 0;
452 
453 	return bytes_to_frames(runtime, (prtd->pcm_irq_pos));
454 }
455 
456 static int q6asm_dai_mmap(struct snd_soc_component *component,
457 			  struct snd_pcm_substream *substream,
458 			  struct vm_area_struct *vma)
459 {
460 	struct snd_pcm_runtime *runtime = substream->runtime;
461 	struct device *dev = component->dev;
462 
463 	return dma_mmap_coherent(dev, vma,
464 			runtime->dma_area, runtime->dma_addr,
465 			runtime->dma_bytes);
466 }
467 
468 static int q6asm_dai_hw_params(struct snd_soc_component *component,
469 			       struct snd_pcm_substream *substream,
470 			       struct snd_pcm_hw_params *params)
471 {
472 	struct snd_pcm_runtime *runtime = substream->runtime;
473 	struct q6asm_dai_rtd *prtd = runtime->private_data;
474 
475 	prtd->pcm_size = params_buffer_bytes(params);
476 	prtd->periods = params_periods(params);
477 
478 	switch (params_format(params)) {
479 	case SNDRV_PCM_FORMAT_S16_LE:
480 		prtd->bits_per_sample = 16;
481 		break;
482 	case SNDRV_PCM_FORMAT_S24_LE:
483 		prtd->bits_per_sample = 24;
484 		break;
485 	}
486 
487 	return 0;
488 }
489 
490 static void compress_event_handler(uint32_t opcode, uint32_t token,
491 				   void *payload, void *priv)
492 {
493 	struct q6asm_dai_rtd *prtd = priv;
494 	struct snd_compr_stream *substream = prtd->cstream;
495 	unsigned long flags;
496 	uint64_t avail;
497 
498 	switch (opcode) {
499 	case ASM_CLIENT_EVENT_CMD_RUN_DONE:
500 		spin_lock_irqsave(&prtd->lock, flags);
501 		if (!prtd->bytes_sent) {
502 			q6asm_write_async(prtd->audio_client, prtd->pcm_count,
503 					  0, 0, NO_TIMESTAMP);
504 			prtd->bytes_sent += prtd->pcm_count;
505 		}
506 
507 		spin_unlock_irqrestore(&prtd->lock, flags);
508 		break;
509 
510 	case ASM_CLIENT_EVENT_CMD_EOS_DONE:
511 		prtd->state = Q6ASM_STREAM_STOPPED;
512 		break;
513 
514 	case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
515 		spin_lock_irqsave(&prtd->lock, flags);
516 
517 		prtd->copied_total += prtd->pcm_count;
518 		snd_compr_fragment_elapsed(substream);
519 
520 		if (prtd->state != Q6ASM_STREAM_RUNNING) {
521 			spin_unlock_irqrestore(&prtd->lock, flags);
522 			break;
523 		}
524 
525 		avail = prtd->bytes_received - prtd->bytes_sent;
526 
527 		if (avail >= prtd->pcm_count) {
528 			q6asm_write_async(prtd->audio_client,
529 					   prtd->pcm_count, 0, 0, NO_TIMESTAMP);
530 			prtd->bytes_sent += prtd->pcm_count;
531 		}
532 
533 		spin_unlock_irqrestore(&prtd->lock, flags);
534 		break;
535 
536 	default:
537 		break;
538 	}
539 }
540 
541 static int q6asm_dai_compr_open(struct snd_soc_component *component,
542 				struct snd_compr_stream *stream)
543 {
544 	struct snd_soc_pcm_runtime *rtd = stream->private_data;
545 	struct snd_compr_runtime *runtime = stream->runtime;
546 	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
547 	struct q6asm_dai_data *pdata;
548 	struct device *dev = component->dev;
549 	struct q6asm_dai_rtd *prtd;
550 	int stream_id, size, ret;
551 
552 	stream_id = cpu_dai->driver->id;
553 	pdata = snd_soc_component_get_drvdata(component);
554 	if (!pdata) {
555 		dev_err(dev, "Drv data not found ..\n");
556 		return -EINVAL;
557 	}
558 
559 	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
560 	if (!prtd)
561 		return -ENOMEM;
562 
563 	prtd->cstream = stream;
564 	prtd->audio_client = q6asm_audio_client_alloc(dev,
565 					(q6asm_cb)compress_event_handler,
566 					prtd, stream_id, LEGACY_PCM_MODE);
567 	if (IS_ERR(prtd->audio_client)) {
568 		dev_err(dev, "Could not allocate memory\n");
569 		ret = PTR_ERR(prtd->audio_client);
570 		goto free_prtd;
571 	}
572 
573 	size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
574 			COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
575 	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
576 				  &prtd->dma_buffer);
577 	if (ret) {
578 		dev_err(dev, "Cannot allocate buffer(s)\n");
579 		goto free_client;
580 	}
581 
582 	if (pdata->sid < 0)
583 		prtd->phys = prtd->dma_buffer.addr;
584 	else
585 		prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
586 
587 	snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
588 	spin_lock_init(&prtd->lock);
589 	runtime->private_data = prtd;
590 
591 	return 0;
592 
593 free_client:
594 	q6asm_audio_client_free(prtd->audio_client);
595 free_prtd:
596 	kfree(prtd);
597 
598 	return ret;
599 }
600 
601 static int q6asm_dai_compr_free(struct snd_soc_component *component,
602 				struct snd_compr_stream *stream)
603 {
604 	struct snd_compr_runtime *runtime = stream->runtime;
605 	struct q6asm_dai_rtd *prtd = runtime->private_data;
606 	struct snd_soc_pcm_runtime *rtd = stream->private_data;
607 
608 	if (prtd->audio_client) {
609 		if (prtd->state)
610 			q6asm_cmd(prtd->audio_client, CMD_CLOSE);
611 
612 		snd_dma_free_pages(&prtd->dma_buffer);
613 		q6asm_unmap_memory_regions(stream->direction,
614 					   prtd->audio_client);
615 		q6asm_audio_client_free(prtd->audio_client);
616 		prtd->audio_client = NULL;
617 	}
618 	q6routing_stream_close(rtd->dai_link->id, stream->direction);
619 	kfree(prtd);
620 
621 	return 0;
622 }
623 
624 static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
625 				      struct snd_compr_stream *stream,
626 				      struct snd_compr_params *params)
627 {
628 	struct snd_compr_runtime *runtime = stream->runtime;
629 	struct q6asm_dai_rtd *prtd = runtime->private_data;
630 	struct snd_soc_pcm_runtime *rtd = stream->private_data;
631 	int dir = stream->direction;
632 	struct q6asm_dai_data *pdata;
633 	struct q6asm_flac_cfg flac_cfg;
634 	struct q6asm_wma_cfg wma_cfg;
635 	struct q6asm_alac_cfg alac_cfg;
636 	struct q6asm_ape_cfg ape_cfg;
637 	unsigned int wma_v9 = 0;
638 	struct device *dev = component->dev;
639 	int ret;
640 	union snd_codec_options *codec_options;
641 	struct snd_dec_flac *flac;
642 	struct snd_dec_wma *wma;
643 	struct snd_dec_alac *alac;
644 	struct snd_dec_ape *ape;
645 
646 	codec_options = &(prtd->codec_param.codec.options);
647 
648 
649 	memcpy(&prtd->codec_param, params, sizeof(*params));
650 
651 	pdata = snd_soc_component_get_drvdata(component);
652 	if (!pdata)
653 		return -EINVAL;
654 
655 	if (!prtd || !prtd->audio_client) {
656 		dev_err(dev, "private data null or audio client freed\n");
657 		return -EINVAL;
658 	}
659 
660 	prtd->periods = runtime->fragments;
661 	prtd->pcm_count = runtime->fragment_size;
662 	prtd->pcm_size = runtime->fragments * runtime->fragment_size;
663 	prtd->bits_per_sample = 16;
664 	if (dir == SND_COMPRESS_PLAYBACK) {
665 		ret = q6asm_open_write(prtd->audio_client, params->codec.id,
666 				params->codec.profile, prtd->bits_per_sample);
667 
668 		if (ret < 0) {
669 			dev_err(dev, "q6asm_open_write failed\n");
670 			q6asm_audio_client_free(prtd->audio_client);
671 			prtd->audio_client = NULL;
672 			return ret;
673 		}
674 	}
675 
676 	prtd->session_id = q6asm_get_session_id(prtd->audio_client);
677 	ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
678 			      prtd->session_id, dir);
679 	if (ret) {
680 		dev_err(dev, "Stream reg failed ret:%d\n", ret);
681 		return ret;
682 	}
683 
684 	switch (params->codec.id) {
685 	case SND_AUDIOCODEC_FLAC:
686 
687 		memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg));
688 		flac = &codec_options->flac_d;
689 
690 		flac_cfg.ch_cfg = params->codec.ch_in;
691 		flac_cfg.sample_rate =  params->codec.sample_rate;
692 		flac_cfg.stream_info_present = 1;
693 		flac_cfg.sample_size = flac->sample_size;
694 		flac_cfg.min_blk_size = flac->min_blk_size;
695 		flac_cfg.max_blk_size = flac->max_blk_size;
696 		flac_cfg.max_frame_size = flac->max_frame_size;
697 		flac_cfg.min_frame_size = flac->min_frame_size;
698 
699 		ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
700 							   &flac_cfg);
701 		if (ret < 0) {
702 			dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
703 			return -EIO;
704 		}
705 		break;
706 
707 	case SND_AUDIOCODEC_WMA:
708 		wma = &codec_options->wma_d;
709 
710 		memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg));
711 
712 		wma_cfg.sample_rate =  params->codec.sample_rate;
713 		wma_cfg.num_channels = params->codec.ch_in;
714 		wma_cfg.bytes_per_sec = params->codec.bit_rate / 8;
715 		wma_cfg.block_align = params->codec.align;
716 		wma_cfg.bits_per_sample = prtd->bits_per_sample;
717 		wma_cfg.enc_options = wma->encoder_option;
718 		wma_cfg.adv_enc_options = wma->adv_encoder_option;
719 		wma_cfg.adv_enc_options2 = wma->adv_encoder_option2;
720 
721 		if (wma_cfg.num_channels == 1)
722 			wma_cfg.channel_mask = 4; /* Mono Center */
723 		else if (wma_cfg.num_channels == 2)
724 			wma_cfg.channel_mask = 3; /* Stereo FL/FR */
725 		else
726 			return -EINVAL;
727 
728 		/* check the codec profile */
729 		switch (params->codec.profile) {
730 		case SND_AUDIOPROFILE_WMA9:
731 			wma_cfg.fmtag = 0x161;
732 			wma_v9 = 1;
733 			break;
734 
735 		case SND_AUDIOPROFILE_WMA10:
736 			wma_cfg.fmtag = 0x166;
737 			break;
738 
739 		case SND_AUDIOPROFILE_WMA9_PRO:
740 			wma_cfg.fmtag = 0x162;
741 			break;
742 
743 		case SND_AUDIOPROFILE_WMA9_LOSSLESS:
744 			wma_cfg.fmtag = 0x163;
745 			break;
746 
747 		case SND_AUDIOPROFILE_WMA10_LOSSLESS:
748 			wma_cfg.fmtag = 0x167;
749 			break;
750 
751 		default:
752 			dev_err(dev, "Unknown WMA profile:%x\n",
753 				params->codec.profile);
754 			return -EIO;
755 		}
756 
757 		if (wma_v9)
758 			ret = q6asm_stream_media_format_block_wma_v9(
759 					prtd->audio_client, &wma_cfg);
760 		else
761 			ret = q6asm_stream_media_format_block_wma_v10(
762 					prtd->audio_client, &wma_cfg);
763 		if (ret < 0) {
764 			dev_err(dev, "WMA9 CMD failed:%d\n", ret);
765 			return -EIO;
766 		}
767 		break;
768 
769 	case SND_AUDIOCODEC_ALAC:
770 		memset(&alac_cfg, 0x0, sizeof(alac_cfg));
771 		alac = &codec_options->alac_d;
772 
773 		alac_cfg.sample_rate = params->codec.sample_rate;
774 		alac_cfg.avg_bit_rate = params->codec.bit_rate;
775 		alac_cfg.bit_depth = prtd->bits_per_sample;
776 		alac_cfg.num_channels = params->codec.ch_in;
777 
778 		alac_cfg.frame_length = alac->frame_length;
779 		alac_cfg.pb = alac->pb;
780 		alac_cfg.mb = alac->mb;
781 		alac_cfg.kb = alac->kb;
782 		alac_cfg.max_run = alac->max_run;
783 		alac_cfg.compatible_version = alac->compatible_version;
784 		alac_cfg.max_frame_bytes = alac->max_frame_bytes;
785 
786 		switch (params->codec.ch_in) {
787 		case 1:
788 			alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO;
789 			break;
790 		case 2:
791 			alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO;
792 			break;
793 		}
794 		ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
795 							   &alac_cfg);
796 		if (ret < 0) {
797 			dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
798 			return -EIO;
799 		}
800 		break;
801 
802 	case SND_AUDIOCODEC_APE:
803 		memset(&ape_cfg, 0x0, sizeof(ape_cfg));
804 		ape = &codec_options->ape_d;
805 
806 		ape_cfg.sample_rate = params->codec.sample_rate;
807 		ape_cfg.num_channels = params->codec.ch_in;
808 		ape_cfg.bits_per_sample = prtd->bits_per_sample;
809 
810 		ape_cfg.compatible_version = ape->compatible_version;
811 		ape_cfg.compression_level = ape->compression_level;
812 		ape_cfg.format_flags = ape->format_flags;
813 		ape_cfg.blocks_per_frame = ape->blocks_per_frame;
814 		ape_cfg.final_frame_blocks = ape->final_frame_blocks;
815 		ape_cfg.total_frames = ape->total_frames;
816 		ape_cfg.seek_table_present = ape->seek_table_present;
817 
818 		ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
819 							  &ape_cfg);
820 		if (ret < 0) {
821 			dev_err(dev, "APE CMD Format block failed:%d\n", ret);
822 			return -EIO;
823 		}
824 		break;
825 
826 	default:
827 		break;
828 	}
829 
830 	ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
831 				       (prtd->pcm_size / prtd->periods),
832 				       prtd->periods);
833 
834 	if (ret < 0) {
835 		dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
836 		return -ENOMEM;
837 	}
838 
839 	prtd->state = Q6ASM_STREAM_RUNNING;
840 
841 	return 0;
842 }
843 
844 static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
845 				   struct snd_compr_stream *stream, int cmd)
846 {
847 	struct snd_compr_runtime *runtime = stream->runtime;
848 	struct q6asm_dai_rtd *prtd = runtime->private_data;
849 	int ret = 0;
850 
851 	switch (cmd) {
852 	case SNDRV_PCM_TRIGGER_START:
853 	case SNDRV_PCM_TRIGGER_RESUME:
854 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
855 		ret = q6asm_run_nowait(prtd->audio_client, 0, 0, 0);
856 		break;
857 	case SNDRV_PCM_TRIGGER_STOP:
858 		prtd->state = Q6ASM_STREAM_STOPPED;
859 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_EOS);
860 		break;
861 	case SNDRV_PCM_TRIGGER_SUSPEND:
862 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
863 		ret = q6asm_cmd_nowait(prtd->audio_client, CMD_PAUSE);
864 		break;
865 	default:
866 		ret = -EINVAL;
867 		break;
868 	}
869 
870 	return ret;
871 }
872 
873 static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
874 				   struct snd_compr_stream *stream,
875 				   struct snd_compr_tstamp *tstamp)
876 {
877 	struct snd_compr_runtime *runtime = stream->runtime;
878 	struct q6asm_dai_rtd *prtd = runtime->private_data;
879 	unsigned long flags;
880 
881 	spin_lock_irqsave(&prtd->lock, flags);
882 
883 	tstamp->copied_total = prtd->copied_total;
884 	tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
885 
886 	spin_unlock_irqrestore(&prtd->lock, flags);
887 
888 	return 0;
889 }
890 
891 static int q6asm_dai_compr_ack(struct snd_soc_component *component,
892 			       struct snd_compr_stream *stream,
893 			       size_t count)
894 {
895 	struct snd_compr_runtime *runtime = stream->runtime;
896 	struct q6asm_dai_rtd *prtd = runtime->private_data;
897 	unsigned long flags;
898 
899 	spin_lock_irqsave(&prtd->lock, flags);
900 	prtd->bytes_received += count;
901 	spin_unlock_irqrestore(&prtd->lock, flags);
902 
903 	return count;
904 }
905 
906 static int q6asm_dai_compr_mmap(struct snd_soc_component *component,
907 				struct snd_compr_stream *stream,
908 				struct vm_area_struct *vma)
909 {
910 	struct snd_compr_runtime *runtime = stream->runtime;
911 	struct q6asm_dai_rtd *prtd = runtime->private_data;
912 	struct device *dev = component->dev;
913 
914 	return dma_mmap_coherent(dev, vma,
915 			prtd->dma_buffer.area, prtd->dma_buffer.addr,
916 			prtd->dma_buffer.bytes);
917 }
918 
919 static int q6asm_dai_compr_get_caps(struct snd_soc_component *component,
920 				    struct snd_compr_stream *stream,
921 				    struct snd_compr_caps *caps)
922 {
923 	caps->direction = SND_COMPRESS_PLAYBACK;
924 	caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
925 	caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
926 	caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
927 	caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
928 	caps->num_codecs = 5;
929 	caps->codecs[0] = SND_AUDIOCODEC_MP3;
930 	caps->codecs[1] = SND_AUDIOCODEC_FLAC;
931 	caps->codecs[2] = SND_AUDIOCODEC_WMA;
932 	caps->codecs[3] = SND_AUDIOCODEC_ALAC;
933 	caps->codecs[4] = SND_AUDIOCODEC_APE;
934 
935 	return 0;
936 }
937 
938 static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component,
939 					  struct snd_compr_stream *stream,
940 					  struct snd_compr_codec_caps *codec)
941 {
942 	switch (codec->codec) {
943 	case SND_AUDIOCODEC_MP3:
944 		*codec = q6asm_compr_caps;
945 		break;
946 	default:
947 		break;
948 	}
949 
950 	return 0;
951 }
952 
953 static struct snd_compress_ops q6asm_dai_compress_ops = {
954 	.open		= q6asm_dai_compr_open,
955 	.free		= q6asm_dai_compr_free,
956 	.set_params	= q6asm_dai_compr_set_params,
957 	.pointer	= q6asm_dai_compr_pointer,
958 	.trigger	= q6asm_dai_compr_trigger,
959 	.get_caps	= q6asm_dai_compr_get_caps,
960 	.get_codec_caps	= q6asm_dai_compr_get_codec_caps,
961 	.mmap		= q6asm_dai_compr_mmap,
962 	.ack		= q6asm_dai_compr_ack,
963 };
964 
965 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
966 			     struct snd_soc_pcm_runtime *rtd)
967 {
968 	struct snd_pcm_substream *psubstream, *csubstream;
969 	struct snd_pcm *pcm = rtd->pcm;
970 	struct device *dev;
971 	int size, ret;
972 
973 	dev = component->dev;
974 	size = q6asm_dai_hardware_playback.buffer_bytes_max;
975 	psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
976 	if (psubstream) {
977 		ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
978 					  &psubstream->dma_buffer);
979 		if (ret) {
980 			dev_err(dev, "Cannot allocate buffer(s)\n");
981 			return ret;
982 		}
983 	}
984 
985 	csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
986 	if (csubstream) {
987 		ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
988 					  &csubstream->dma_buffer);
989 		if (ret) {
990 			dev_err(dev, "Cannot allocate buffer(s)\n");
991 			if (psubstream)
992 				snd_dma_free_pages(&psubstream->dma_buffer);
993 			return ret;
994 		}
995 	}
996 
997 	return 0;
998 }
999 
1000 static void q6asm_dai_pcm_free(struct snd_soc_component *component,
1001 			       struct snd_pcm *pcm)
1002 {
1003 	struct snd_pcm_substream *substream;
1004 	int i;
1005 
1006 	for (i = 0; i < ARRAY_SIZE(pcm->streams); i++) {
1007 		substream = pcm->streams[i].substream;
1008 		if (substream) {
1009 			snd_dma_free_pages(&substream->dma_buffer);
1010 			substream->dma_buffer.area = NULL;
1011 			substream->dma_buffer.addr = 0;
1012 		}
1013 	}
1014 }
1015 
1016 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
1017 	.name		= DRV_NAME,
1018 	.open		= q6asm_dai_open,
1019 	.hw_params	= q6asm_dai_hw_params,
1020 	.close		= q6asm_dai_close,
1021 	.prepare	= q6asm_dai_prepare,
1022 	.trigger	= q6asm_dai_trigger,
1023 	.pointer	= q6asm_dai_pointer,
1024 	.mmap		= q6asm_dai_mmap,
1025 	.pcm_construct	= q6asm_dai_pcm_new,
1026 	.pcm_destruct	= q6asm_dai_pcm_free,
1027 	.compress_ops	= &q6asm_dai_compress_ops,
1028 };
1029 
1030 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
1031 	Q6ASM_FEDAI_DRIVER(1),
1032 	Q6ASM_FEDAI_DRIVER(2),
1033 	Q6ASM_FEDAI_DRIVER(3),
1034 	Q6ASM_FEDAI_DRIVER(4),
1035 	Q6ASM_FEDAI_DRIVER(5),
1036 	Q6ASM_FEDAI_DRIVER(6),
1037 	Q6ASM_FEDAI_DRIVER(7),
1038 	Q6ASM_FEDAI_DRIVER(8),
1039 };
1040 
1041 static int of_q6asm_parse_dai_data(struct device *dev,
1042 				    struct q6asm_dai_data *pdata)
1043 {
1044 	struct snd_soc_dai_driver *dai_drv;
1045 	struct snd_soc_pcm_stream empty_stream;
1046 	struct device_node *node;
1047 	int ret, id, dir, idx = 0;
1048 
1049 
1050 	pdata->num_dais = of_get_child_count(dev->of_node);
1051 	if (!pdata->num_dais) {
1052 		dev_err(dev, "No dais found in DT\n");
1053 		return -EINVAL;
1054 	}
1055 
1056 	pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv),
1057 				   GFP_KERNEL);
1058 	if (!pdata->dais)
1059 		return -ENOMEM;
1060 
1061 	memset(&empty_stream, 0, sizeof(empty_stream));
1062 
1063 	for_each_child_of_node(dev->of_node, node) {
1064 		ret = of_property_read_u32(node, "reg", &id);
1065 		if (ret || id >= MAX_SESSIONS || id < 0) {
1066 			dev_err(dev, "valid dai id not found:%d\n", ret);
1067 			continue;
1068 		}
1069 
1070 		dai_drv = &pdata->dais[idx++];
1071 		*dai_drv = q6asm_fe_dais_template[id];
1072 
1073 		ret = of_property_read_u32(node, "direction", &dir);
1074 		if (ret)
1075 			continue;
1076 
1077 		if (dir == Q6ASM_DAI_RX)
1078 			dai_drv->capture = empty_stream;
1079 		else if (dir == Q6ASM_DAI_TX)
1080 			dai_drv->playback = empty_stream;
1081 
1082 		if (of_property_read_bool(node, "is-compress-dai"))
1083 			dai_drv->compress_new = snd_soc_new_compress;
1084 	}
1085 
1086 	return 0;
1087 }
1088 
1089 static int q6asm_dai_probe(struct platform_device *pdev)
1090 {
1091 	struct device *dev = &pdev->dev;
1092 	struct device_node *node = dev->of_node;
1093 	struct of_phandle_args args;
1094 	struct q6asm_dai_data *pdata;
1095 	int rc;
1096 
1097 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1098 	if (!pdata)
1099 		return -ENOMEM;
1100 
1101 	rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
1102 	if (rc < 0)
1103 		pdata->sid = -1;
1104 	else
1105 		pdata->sid = args.args[0] & SID_MASK_DEFAULT;
1106 
1107 	dev_set_drvdata(dev, pdata);
1108 
1109 	rc = of_q6asm_parse_dai_data(dev, pdata);
1110 	if (rc)
1111 		return rc;
1112 
1113 	return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
1114 					       pdata->dais, pdata->num_dais);
1115 }
1116 
1117 static const struct of_device_id q6asm_dai_device_id[] = {
1118 	{ .compatible = "qcom,q6asm-dais" },
1119 	{},
1120 };
1121 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
1122 
1123 static struct platform_driver q6asm_dai_platform_driver = {
1124 	.driver = {
1125 		.name = "q6asm-dai",
1126 		.of_match_table = of_match_ptr(q6asm_dai_device_id),
1127 	},
1128 	.probe = q6asm_dai_probe,
1129 };
1130 module_platform_driver(q6asm_dai_platform_driver);
1131 
1132 MODULE_DESCRIPTION("Q6ASM dai driver");
1133 MODULE_LICENSE("GPL v2");
1134