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 <dt-bindings/sound/qcom,q6asm.h>
6 #include <linux/init.h>
7 #include <linux/err.h>
8 #include <linux/module.h>
9 #include <linux/of.h>
10 #include <linux/platform_device.h>
11 #include <linux/slab.h>
12 #include <sound/soc.h>
13 #include <sound/soc-dapm.h>
14 #include <sound/pcm.h>
15 #include <linux/spinlock.h>
16 #include <sound/compress_driver.h>
17 #include <asm/div64.h>
18 #include <asm/dma.h>
19 #include <linux/dma-mapping.h>
20 #include <sound/pcm_params.h>
21 #include "q6asm.h"
22 #include "q6routing.h"
23 #include "q6dsp-errno.h"
24
25 #define DRV_NAME "q6asm-fe-dai"
26
27 #define PLAYBACK_MIN_NUM_PERIODS 2
28 #define PLAYBACK_MAX_NUM_PERIODS 8
29 #define PLAYBACK_MAX_PERIOD_SIZE 65536
30 #define PLAYBACK_MIN_PERIOD_SIZE 128
31 #define CAPTURE_MIN_NUM_PERIODS 2
32 #define CAPTURE_MAX_NUM_PERIODS 8
33 #define CAPTURE_MAX_PERIOD_SIZE 4096
34 #define CAPTURE_MIN_PERIOD_SIZE 320
35 #define SID_MASK_DEFAULT 0xF
36
37 /* Default values used if user space does not set */
38 #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
39 #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
40 #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
41 #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
42
43 #define ALAC_CH_LAYOUT_MONO ((101 << 16) | 1)
44 #define ALAC_CH_LAYOUT_STEREO ((101 << 16) | 2)
45
46 enum stream_state {
47 Q6ASM_STREAM_IDLE = 0,
48 Q6ASM_STREAM_STOPPED,
49 Q6ASM_STREAM_RUNNING,
50 };
51
52 struct q6asm_dai_rtd {
53 struct snd_pcm_substream *substream;
54 struct snd_compr_stream *cstream;
55 struct snd_codec codec;
56 struct snd_dma_buffer dma_buffer;
57 spinlock_t lock;
58 phys_addr_t phys;
59 unsigned int pcm_size;
60 unsigned int pcm_count;
61 unsigned int periods;
62 uint64_t bytes_sent;
63 uint64_t bytes_received;
64 uint64_t copied_total;
65 uint16_t bits_per_sample;
66 snd_pcm_uframes_t queue_ptr;
67 uint16_t source; /* Encoding source bit mask */
68 struct audio_client *audio_client;
69 uint32_t next_track_stream_id;
70 bool next_track;
71 uint32_t stream_id;
72 uint16_t session_id;
73 enum stream_state state;
74 uint32_t initial_samples_drop;
75 uint32_t trailing_samples_drop;
76 bool notify_on_drain;
77 };
78
79 struct q6asm_dai_data {
80 struct snd_soc_dai_driver *dais;
81 int num_dais;
82 long long int sid;
83 };
84
85 static const struct snd_pcm_hardware q6asm_dai_hardware_capture = {
86 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
87 SNDRV_PCM_INFO_BLOCK_TRANSFER |
88 SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR |
89 SNDRV_PCM_INFO_MMAP_VALID |
90 SNDRV_PCM_INFO_INTERLEAVED |
91 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
92 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
93 SNDRV_PCM_FMTBIT_S24_LE),
94 .rates = SNDRV_PCM_RATE_8000_48000,
95 .rate_min = 8000,
96 .rate_max = 48000,
97 .channels_min = 1,
98 .channels_max = 4,
99 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
100 CAPTURE_MAX_PERIOD_SIZE,
101 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
102 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
103 .periods_min = CAPTURE_MIN_NUM_PERIODS,
104 .periods_max = CAPTURE_MAX_NUM_PERIODS,
105 .fifo_size = 0,
106 };
107
108 static const struct snd_pcm_hardware q6asm_dai_hardware_playback = {
109 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BATCH |
110 SNDRV_PCM_INFO_BLOCK_TRANSFER |
111 SNDRV_PCM_INFO_MMAP_VALID |
112 SNDRV_PCM_INFO_NO_REWINDS | SNDRV_PCM_INFO_SYNC_APPLPTR |
113 SNDRV_PCM_INFO_INTERLEAVED |
114 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
115 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
116 SNDRV_PCM_FMTBIT_S24_LE),
117 .rates = SNDRV_PCM_RATE_8000_192000,
118 .rate_min = 8000,
119 .rate_max = 192000,
120 .channels_min = 1,
121 .channels_max = 8,
122 .buffer_bytes_max = (PLAYBACK_MAX_NUM_PERIODS *
123 PLAYBACK_MAX_PERIOD_SIZE),
124 .period_bytes_min = PLAYBACK_MIN_PERIOD_SIZE,
125 .period_bytes_max = PLAYBACK_MAX_PERIOD_SIZE,
126 .periods_min = PLAYBACK_MIN_NUM_PERIODS,
127 .periods_max = PLAYBACK_MAX_NUM_PERIODS,
128 .fifo_size = 0,
129 };
130
131 #define Q6ASM_FEDAI_DRIVER(num) { \
132 .playback = { \
133 .stream_name = "MultiMedia"#num" Playback", \
134 .rates = (SNDRV_PCM_RATE_8000_48000 | \
135 SNDRV_PCM_RATE_12000 | \
136 SNDRV_PCM_RATE_24000 | \
137 SNDRV_PCM_RATE_88200 | \
138 SNDRV_PCM_RATE_96000 | \
139 SNDRV_PCM_RATE_176400 | \
140 SNDRV_PCM_RATE_192000), \
141 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
142 SNDRV_PCM_FMTBIT_S24_LE), \
143 .channels_min = 1, \
144 .channels_max = 8, \
145 .rate_min = 8000, \
146 .rate_max = 192000, \
147 }, \
148 .capture = { \
149 .stream_name = "MultiMedia"#num" Capture", \
150 .rates = (SNDRV_PCM_RATE_8000_48000 | \
151 SNDRV_PCM_RATE_12000 | \
152 SNDRV_PCM_RATE_24000), \
153 .formats = (SNDRV_PCM_FMTBIT_S16_LE | \
154 SNDRV_PCM_FMTBIT_S24_LE), \
155 .channels_min = 1, \
156 .channels_max = 4, \
157 .rate_min = 8000, \
158 .rate_max = 48000, \
159 }, \
160 .name = "MultiMedia"#num, \
161 .id = MSM_FRONTEND_DAI_MULTIMEDIA##num, \
162 }
163
164 static const struct snd_compr_codec_caps q6asm_compr_caps = {
165 .num_descriptors = 1,
166 .descriptor[0].max_ch = 2,
167 .descriptor[0].sample_rates = { 8000, 11025, 12000, 16000, 22050,
168 24000, 32000, 44100, 48000, 88200,
169 96000, 176400, 192000 },
170 .descriptor[0].num_sample_rates = 13,
171 .descriptor[0].bit_rate[0] = 320,
172 .descriptor[0].bit_rate[1] = 128,
173 .descriptor[0].num_bitrates = 2,
174 .descriptor[0].profiles = 0,
175 .descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
176 .descriptor[0].formats = 0,
177 };
178
event_handler(uint32_t opcode,uint32_t token,void * payload,void * priv)179 static void event_handler(uint32_t opcode, uint32_t token,
180 void *payload, void *priv)
181 {
182 struct q6asm_dai_rtd *prtd = priv;
183 struct snd_pcm_substream *substream = prtd->substream;
184
185 switch (opcode) {
186 case ASM_CLIENT_EVENT_CMD_RUN_DONE:
187 break;
188 case ASM_CLIENT_EVENT_CMD_EOS_DONE:
189 break;
190 case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
191 snd_pcm_period_elapsed(substream);
192 break;
193 case ASM_CLIENT_EVENT_DATA_READ_DONE:
194 snd_pcm_period_elapsed(substream);
195 if (prtd->state == Q6ASM_STREAM_RUNNING)
196 q6asm_read(prtd->audio_client, prtd->stream_id);
197
198 break;
199 default:
200 break;
201 }
202 }
203
q6asm_dai_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)204 static int q6asm_dai_prepare(struct snd_soc_component *component,
205 struct snd_pcm_substream *substream)
206 {
207 struct snd_pcm_runtime *runtime = substream->runtime;
208 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream);
209 struct q6asm_dai_rtd *prtd = runtime->private_data;
210 struct q6asm_dai_data *pdata;
211 struct device *dev = component->dev;
212 int ret, i;
213
214 pdata = snd_soc_component_get_drvdata(component);
215 if (!pdata)
216 return -EINVAL;
217
218 if (!prtd || !prtd->audio_client) {
219 dev_err(dev, "%s: private data null or audio client freed\n",
220 __func__);
221 return -EINVAL;
222 }
223
224 prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
225 /* rate and channels are sent to audio driver */
226 if (prtd->state == Q6ASM_STREAM_RUNNING) {
227 /* clear the previous setup if any */
228 ret = q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
229 if (ret < 0) {
230 dev_err(dev, "Failed to close q6asm stream %d\n", prtd->stream_id);
231 return ret;
232 }
233
234 ret = q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
235 if (ret < 0) {
236 dev_err(dev, "Failed to unmap memory regions for q6asm stream %d\n",
237 prtd->stream_id);
238 return ret;
239 }
240
241 q6routing_stream_close(soc_prtd->dai_link->id,
242 substream->stream);
243 prtd->state = Q6ASM_STREAM_STOPPED;
244 }
245
246 ret = q6asm_map_memory_regions(substream->stream, prtd->audio_client,
247 prtd->phys,
248 (prtd->pcm_size / prtd->periods),
249 prtd->periods);
250
251 if (ret < 0) {
252 dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n",
253 ret);
254 return -ENOMEM;
255 }
256
257 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
258 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id,
259 FORMAT_LINEAR_PCM,
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,
263 FORMAT_LINEAR_PCM,
264 prtd->bits_per_sample);
265 }
266
267 if (ret < 0) {
268 dev_err(dev, "%s: q6asm_open_write failed\n", __func__);
269 goto open_err;
270 }
271
272 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
273 ret = q6routing_stream_open(soc_prtd->dai_link->id, LEGACY_PCM_MODE,
274 prtd->session_id, substream->stream);
275 if (ret) {
276 dev_err(dev, "%s: stream reg failed ret:%d\n", __func__, ret);
277 goto routing_err;
278 }
279
280 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
281 ret = q6asm_media_format_block_multi_ch_pcm(
282 prtd->audio_client, prtd->stream_id,
283 runtime->rate, runtime->channels, NULL,
284 prtd->bits_per_sample);
285 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
286 ret = q6asm_enc_cfg_blk_pcm_format_support(prtd->audio_client,
287 prtd->stream_id,
288 runtime->rate,
289 runtime->channels,
290 prtd->bits_per_sample);
291
292 /* Queue the buffers */
293 for (i = 0; i < runtime->periods; i++)
294 q6asm_read(prtd->audio_client, prtd->stream_id);
295
296 }
297 if (ret < 0)
298 dev_info(dev, "%s: CMD Format block failed\n", __func__);
299 else
300 prtd->state = Q6ASM_STREAM_RUNNING;
301
302 return ret;
303
304 routing_err:
305 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
306 open_err:
307 q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
308
309 return ret;
310 }
311
q6asm_dai_ack(struct snd_soc_component * component,struct snd_pcm_substream * substream)312 static int q6asm_dai_ack(struct snd_soc_component *component, struct snd_pcm_substream *substream)
313 {
314 struct snd_pcm_runtime *runtime = substream->runtime;
315 struct q6asm_dai_rtd *prtd = runtime->private_data;
316 int i, ret = 0, avail_periods;
317
318 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && prtd->state == Q6ASM_STREAM_RUNNING) {
319 avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
320 for (i = 0; i < avail_periods; i++) {
321 ret = q6asm_write_async(prtd->audio_client, prtd->stream_id,
322 prtd->pcm_count, 0, 0, 0);
323
324 if (ret < 0) {
325 dev_err(component->dev, "Error queuing playback buffer %d\n", ret);
326 return ret;
327 }
328 prtd->queue_ptr += runtime->period_size;
329 }
330 }
331
332 return ret;
333 }
334
q6asm_dai_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)335 static int q6asm_dai_trigger(struct snd_soc_component *component,
336 struct snd_pcm_substream *substream, int cmd)
337 {
338 int ret = 0;
339 struct snd_pcm_runtime *runtime = substream->runtime;
340 struct q6asm_dai_rtd *prtd = runtime->private_data;
341
342 switch (cmd) {
343 case SNDRV_PCM_TRIGGER_START:
344 case SNDRV_PCM_TRIGGER_RESUME:
345 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
346 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
347 0, 0, 0);
348 break;
349 case SNDRV_PCM_TRIGGER_STOP:
350 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
351 CMD_EOS);
352 break;
353 case SNDRV_PCM_TRIGGER_SUSPEND:
354 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
355 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
356 CMD_PAUSE);
357 break;
358 default:
359 ret = -EINVAL;
360 break;
361 }
362
363 return ret;
364 }
365
q6asm_dai_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)366 static int q6asm_dai_open(struct snd_soc_component *component,
367 struct snd_pcm_substream *substream)
368 {
369 struct snd_pcm_runtime *runtime = substream->runtime;
370 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream);
371 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0);
372 struct q6asm_dai_rtd *prtd;
373 struct q6asm_dai_data *pdata;
374 struct device *dev = component->dev;
375 int ret = 0;
376 int stream_id;
377
378 stream_id = cpu_dai->driver->id;
379
380 pdata = snd_soc_component_get_drvdata(component);
381 if (!pdata) {
382 dev_err(dev, "Drv data not found ..\n");
383 return -EINVAL;
384 }
385
386 prtd = kzalloc_obj(*prtd);
387 if (prtd == NULL)
388 return -ENOMEM;
389
390 prtd->substream = substream;
391 prtd->audio_client = q6asm_audio_client_alloc(dev,
392 (q6asm_cb)event_handler, prtd, stream_id,
393 LEGACY_PCM_MODE);
394 if (IS_ERR(prtd->audio_client)) {
395 dev_info(dev, "%s: Could not allocate memory\n", __func__);
396 ret = PTR_ERR(prtd->audio_client);
397 kfree(prtd);
398 return ret;
399 }
400
401 /* DSP expects stream id from 1 */
402 prtd->stream_id = 1;
403
404 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
405 runtime->hw = q6asm_dai_hardware_playback;
406 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
407 runtime->hw = q6asm_dai_hardware_capture;
408
409 /* Ensure that buffer size is a multiple of period size */
410 ret = snd_pcm_hw_constraint_integer(runtime,
411 SNDRV_PCM_HW_PARAM_PERIODS);
412 if (ret < 0)
413 dev_info(dev, "snd_pcm_hw_constraint_integer failed\n");
414
415 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
416 ret = snd_pcm_hw_constraint_minmax(runtime,
417 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
418 PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE,
419 PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE);
420 if (ret < 0) {
421 dev_err(dev, "constraint for buffer bytes min max ret = %d\n",
422 ret);
423 }
424 }
425
426 ret = snd_pcm_hw_constraint_step(runtime, 0,
427 SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 480);
428 if (ret < 0) {
429 dev_err(dev, "constraint for period bytes step ret = %d\n",
430 ret);
431 }
432 ret = snd_pcm_hw_constraint_step(runtime, 0,
433 SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 480);
434 if (ret < 0) {
435 dev_err(dev, "constraint for buffer bytes step ret = %d\n",
436 ret);
437 }
438
439 runtime->private_data = prtd;
440
441 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
442 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_playback);
443 runtime->dma_bytes = q6asm_dai_hardware_playback.buffer_bytes_max;
444 } else {
445 snd_soc_set_runtime_hwparams(substream, &q6asm_dai_hardware_capture);
446 runtime->dma_bytes = q6asm_dai_hardware_capture.buffer_bytes_max;
447 }
448
449 if (pdata->sid < 0)
450 prtd->phys = substream->dma_buffer.addr;
451 else
452 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
453
454 return 0;
455 }
456
q6asm_dai_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)457 static int q6asm_dai_close(struct snd_soc_component *component,
458 struct snd_pcm_substream *substream)
459 {
460 struct snd_pcm_runtime *runtime = substream->runtime;
461 struct snd_soc_pcm_runtime *soc_prtd = snd_soc_substream_to_rtd(substream);
462 struct q6asm_dai_rtd *prtd = runtime->private_data;
463
464 if (prtd->audio_client) {
465 if (prtd->state == Q6ASM_STREAM_RUNNING) {
466 q6asm_cmd(prtd->audio_client, prtd->stream_id,
467 CMD_CLOSE);
468 q6asm_unmap_memory_regions(substream->stream,
469 prtd->audio_client);
470 }
471 q6asm_audio_client_free(prtd->audio_client);
472 prtd->audio_client = NULL;
473 }
474 q6routing_stream_close(soc_prtd->dai_link->id,
475 substream->stream);
476 kfree(prtd);
477 return 0;
478 }
479
q6asm_dai_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)480 static snd_pcm_uframes_t q6asm_dai_pointer(struct snd_soc_component *component,
481 struct snd_pcm_substream *substream)
482 {
483
484 struct snd_pcm_runtime *runtime = substream->runtime;
485 struct q6asm_dai_rtd *prtd = runtime->private_data;
486 snd_pcm_uframes_t ptr;
487
488 ptr = q6asm_get_hw_pointer(prtd->audio_client, substream->stream) * runtime->period_size;
489 if (ptr)
490 return ptr - 1;
491
492 return 0;
493 }
494
q6asm_dai_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)495 static int q6asm_dai_hw_params(struct snd_soc_component *component,
496 struct snd_pcm_substream *substream,
497 struct snd_pcm_hw_params *params)
498 {
499 struct snd_pcm_runtime *runtime = substream->runtime;
500 struct q6asm_dai_rtd *prtd = runtime->private_data;
501
502 prtd->pcm_size = params_buffer_bytes(params);
503 prtd->periods = params_periods(params);
504
505 switch (params_format(params)) {
506 case SNDRV_PCM_FORMAT_S16_LE:
507 prtd->bits_per_sample = 16;
508 break;
509 case SNDRV_PCM_FORMAT_S24_LE:
510 prtd->bits_per_sample = 24;
511 break;
512 }
513
514 return 0;
515 }
516
compress_event_handler(uint32_t opcode,uint32_t token,void * payload,void * priv)517 static void compress_event_handler(uint32_t opcode, uint32_t token,
518 void *payload, void *priv)
519 {
520 struct q6asm_dai_rtd *prtd = priv;
521 struct snd_compr_stream *substream = prtd->cstream;
522 u32 wflags = 0;
523 uint64_t avail;
524 uint32_t bytes_written, bytes_to_write;
525 bool is_last_buffer = false;
526
527 guard(spinlock_irqsave)(&prtd->lock);
528
529 switch (opcode) {
530 case ASM_CLIENT_EVENT_CMD_RUN_DONE:
531 if (!prtd->bytes_sent) {
532 q6asm_stream_remove_initial_silence(prtd->audio_client,
533 prtd->stream_id,
534 prtd->initial_samples_drop);
535
536 q6asm_write_async(prtd->audio_client, prtd->stream_id,
537 prtd->pcm_count, 0, 0, 0);
538 prtd->bytes_sent += prtd->pcm_count;
539 }
540
541 break;
542
543 case ASM_CLIENT_EVENT_CMD_EOS_DONE:
544 if (prtd->notify_on_drain) {
545 if (substream->partial_drain) {
546 /*
547 * Close old stream and make it stale, switch
548 * the active stream now!
549 */
550 q6asm_cmd_nowait(prtd->audio_client,
551 prtd->stream_id,
552 CMD_CLOSE);
553 /*
554 * vaild stream ids start from 1, So we are
555 * toggling this between 1 and 2.
556 */
557 prtd->stream_id = (prtd->stream_id == 1 ? 2 : 1);
558 }
559
560 snd_compr_drain_notify(prtd->cstream);
561 prtd->notify_on_drain = false;
562
563 }
564 break;
565
566 case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
567
568 bytes_written = token >> ASM_WRITE_TOKEN_LEN_SHIFT;
569 prtd->copied_total += bytes_written;
570 snd_compr_fragment_elapsed(substream);
571
572 if (prtd->state != Q6ASM_STREAM_RUNNING)
573 break;
574
575 avail = prtd->bytes_received - prtd->bytes_sent;
576 if (avail > prtd->pcm_count) {
577 bytes_to_write = prtd->pcm_count;
578 } else {
579 if (substream->partial_drain || prtd->notify_on_drain)
580 is_last_buffer = true;
581 bytes_to_write = avail;
582 }
583
584 if (bytes_to_write) {
585 if (substream->partial_drain && is_last_buffer) {
586 wflags |= ASM_LAST_BUFFER_FLAG;
587 q6asm_stream_remove_trailing_silence(prtd->audio_client,
588 prtd->stream_id,
589 prtd->trailing_samples_drop);
590 }
591
592 q6asm_write_async(prtd->audio_client, prtd->stream_id,
593 bytes_to_write, 0, 0, wflags);
594
595 prtd->bytes_sent += bytes_to_write;
596 }
597
598 if (prtd->notify_on_drain && is_last_buffer)
599 q6asm_cmd_nowait(prtd->audio_client,
600 prtd->stream_id, CMD_EOS);
601
602 break;
603
604 default:
605 break;
606 }
607 }
608
q6asm_dai_compr_open(struct snd_soc_component * component,struct snd_compr_stream * stream)609 static int q6asm_dai_compr_open(struct snd_soc_component *component,
610 struct snd_compr_stream *stream)
611 {
612 struct snd_soc_pcm_runtime *rtd = stream->private_data;
613 struct snd_compr_runtime *runtime = stream->runtime;
614 struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
615 struct q6asm_dai_data *pdata;
616 struct device *dev = component->dev;
617 struct q6asm_dai_rtd *prtd;
618 int stream_id, size, ret;
619
620 stream_id = cpu_dai->driver->id;
621 pdata = snd_soc_component_get_drvdata(component);
622 if (!pdata) {
623 dev_err(dev, "Drv data not found ..\n");
624 return -EINVAL;
625 }
626
627 prtd = kzalloc_obj(*prtd);
628 if (!prtd)
629 return -ENOMEM;
630
631 /* DSP expects stream id from 1 */
632 prtd->stream_id = 1;
633
634 prtd->cstream = stream;
635 prtd->audio_client = q6asm_audio_client_alloc(dev,
636 (q6asm_cb)compress_event_handler,
637 prtd, stream_id, LEGACY_PCM_MODE);
638 if (IS_ERR(prtd->audio_client)) {
639 dev_err(dev, "Could not allocate memory\n");
640 ret = PTR_ERR(prtd->audio_client);
641 goto free_prtd;
642 }
643
644 size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
645 COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
646 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size,
647 &prtd->dma_buffer);
648 if (ret) {
649 dev_err(dev, "Cannot allocate buffer(s)\n");
650 goto free_client;
651 }
652
653 if (pdata->sid < 0)
654 prtd->phys = prtd->dma_buffer.addr;
655 else
656 prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
657
658 snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
659 spin_lock_init(&prtd->lock);
660 runtime->private_data = prtd;
661
662 return 0;
663
664 free_client:
665 q6asm_audio_client_free(prtd->audio_client);
666 free_prtd:
667 kfree(prtd);
668
669 return ret;
670 }
671
q6asm_dai_compr_free(struct snd_soc_component * component,struct snd_compr_stream * stream)672 static int q6asm_dai_compr_free(struct snd_soc_component *component,
673 struct snd_compr_stream *stream)
674 {
675 struct snd_compr_runtime *runtime = stream->runtime;
676 struct q6asm_dai_rtd *prtd = runtime->private_data;
677 struct snd_soc_pcm_runtime *rtd = stream->private_data;
678
679 if (prtd->audio_client) {
680 if (prtd->state == Q6ASM_STREAM_RUNNING) {
681 q6asm_cmd(prtd->audio_client, prtd->stream_id,
682 CMD_CLOSE);
683 if (prtd->next_track_stream_id) {
684 q6asm_cmd(prtd->audio_client,
685 prtd->next_track_stream_id,
686 CMD_CLOSE);
687 }
688
689 q6asm_unmap_memory_regions(stream->direction,
690 prtd->audio_client);
691 }
692 snd_dma_free_pages(&prtd->dma_buffer);
693 q6asm_audio_client_free(prtd->audio_client);
694 prtd->audio_client = NULL;
695 }
696 q6routing_stream_close(rtd->dai_link->id, stream->direction);
697 kfree(prtd);
698
699 return 0;
700 }
701
__q6asm_dai_compr_set_codec_params(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_codec * codec,int stream_id)702 static int __q6asm_dai_compr_set_codec_params(struct snd_soc_component *component,
703 struct snd_compr_stream *stream,
704 struct snd_codec *codec,
705 int stream_id)
706 {
707 struct snd_compr_runtime *runtime = stream->runtime;
708 struct q6asm_dai_rtd *prtd = runtime->private_data;
709 struct q6asm_flac_cfg flac_cfg;
710 struct q6asm_wma_cfg wma_cfg;
711 struct q6asm_alac_cfg alac_cfg;
712 struct q6asm_ape_cfg ape_cfg;
713 unsigned int wma_v9 = 0;
714 struct device *dev = component->dev;
715 int ret;
716 union snd_codec_options *codec_options;
717 struct snd_dec_flac *flac;
718 struct snd_dec_wma *wma;
719 struct snd_dec_alac *alac;
720 struct snd_dec_ape *ape;
721
722 codec_options = &(prtd->codec.options);
723
724 memcpy(&prtd->codec, codec, sizeof(*codec));
725
726 switch (codec->id) {
727 case SND_AUDIOCODEC_FLAC:
728
729 memset(&flac_cfg, 0x0, sizeof(struct q6asm_flac_cfg));
730 flac = &codec_options->flac_d;
731
732 flac_cfg.ch_cfg = codec->ch_in;
733 flac_cfg.sample_rate = codec->sample_rate;
734 flac_cfg.stream_info_present = 1;
735 flac_cfg.sample_size = flac->sample_size;
736 flac_cfg.min_blk_size = flac->min_blk_size;
737 flac_cfg.max_blk_size = flac->max_blk_size;
738 flac_cfg.max_frame_size = flac->max_frame_size;
739 flac_cfg.min_frame_size = flac->min_frame_size;
740
741 ret = q6asm_stream_media_format_block_flac(prtd->audio_client,
742 stream_id,
743 &flac_cfg);
744 if (ret < 0) {
745 dev_err(dev, "FLAC CMD Format block failed:%d\n", ret);
746 return -EIO;
747 }
748 break;
749
750 case SND_AUDIOCODEC_WMA:
751 wma = &codec_options->wma_d;
752
753 memset(&wma_cfg, 0x0, sizeof(struct q6asm_wma_cfg));
754
755 wma_cfg.sample_rate = codec->sample_rate;
756 wma_cfg.num_channels = codec->ch_in;
757 wma_cfg.bytes_per_sec = codec->bit_rate / 8;
758 wma_cfg.block_align = codec->align;
759 wma_cfg.bits_per_sample = prtd->bits_per_sample;
760 wma_cfg.enc_options = wma->encoder_option;
761 wma_cfg.adv_enc_options = wma->adv_encoder_option;
762 wma_cfg.adv_enc_options2 = wma->adv_encoder_option2;
763
764 if (wma_cfg.num_channels == 1)
765 wma_cfg.channel_mask = 4; /* Mono Center */
766 else if (wma_cfg.num_channels == 2)
767 wma_cfg.channel_mask = 3; /* Stereo FL/FR */
768 else
769 return -EINVAL;
770
771 /* check the codec profile */
772 switch (codec->profile) {
773 case SND_AUDIOPROFILE_WMA9:
774 wma_cfg.fmtag = 0x161;
775 wma_v9 = 1;
776 break;
777
778 case SND_AUDIOPROFILE_WMA10:
779 wma_cfg.fmtag = 0x166;
780 break;
781
782 case SND_AUDIOPROFILE_WMA9_PRO:
783 wma_cfg.fmtag = 0x162;
784 break;
785
786 case SND_AUDIOPROFILE_WMA9_LOSSLESS:
787 wma_cfg.fmtag = 0x163;
788 break;
789
790 case SND_AUDIOPROFILE_WMA10_LOSSLESS:
791 wma_cfg.fmtag = 0x167;
792 break;
793
794 default:
795 dev_err(dev, "Unknown WMA profile:%x\n",
796 codec->profile);
797 return -EIO;
798 }
799
800 if (wma_v9)
801 ret = q6asm_stream_media_format_block_wma_v9(
802 prtd->audio_client, stream_id,
803 &wma_cfg);
804 else
805 ret = q6asm_stream_media_format_block_wma_v10(
806 prtd->audio_client, stream_id,
807 &wma_cfg);
808 if (ret < 0) {
809 dev_err(dev, "WMA9 CMD failed:%d\n", ret);
810 return -EIO;
811 }
812 break;
813
814 case SND_AUDIOCODEC_ALAC:
815 memset(&alac_cfg, 0x0, sizeof(alac_cfg));
816 alac = &codec_options->alac_d;
817
818 alac_cfg.sample_rate = codec->sample_rate;
819 alac_cfg.avg_bit_rate = codec->bit_rate;
820 alac_cfg.bit_depth = prtd->bits_per_sample;
821 alac_cfg.num_channels = codec->ch_in;
822
823 alac_cfg.frame_length = alac->frame_length;
824 alac_cfg.pb = alac->pb;
825 alac_cfg.mb = alac->mb;
826 alac_cfg.kb = alac->kb;
827 alac_cfg.max_run = alac->max_run;
828 alac_cfg.compatible_version = alac->compatible_version;
829 alac_cfg.max_frame_bytes = alac->max_frame_bytes;
830
831 switch (codec->ch_in) {
832 case 1:
833 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_MONO;
834 break;
835 case 2:
836 alac_cfg.channel_layout_tag = ALAC_CH_LAYOUT_STEREO;
837 break;
838 }
839 ret = q6asm_stream_media_format_block_alac(prtd->audio_client,
840 stream_id,
841 &alac_cfg);
842 if (ret < 0) {
843 dev_err(dev, "ALAC CMD Format block failed:%d\n", ret);
844 return -EIO;
845 }
846 break;
847
848 case SND_AUDIOCODEC_APE:
849 memset(&ape_cfg, 0x0, sizeof(ape_cfg));
850 ape = &codec_options->ape_d;
851
852 ape_cfg.sample_rate = codec->sample_rate;
853 ape_cfg.num_channels = codec->ch_in;
854 ape_cfg.bits_per_sample = prtd->bits_per_sample;
855
856 ape_cfg.compatible_version = ape->compatible_version;
857 ape_cfg.compression_level = ape->compression_level;
858 ape_cfg.format_flags = ape->format_flags;
859 ape_cfg.blocks_per_frame = ape->blocks_per_frame;
860 ape_cfg.final_frame_blocks = ape->final_frame_blocks;
861 ape_cfg.total_frames = ape->total_frames;
862 ape_cfg.seek_table_present = ape->seek_table_present;
863
864 ret = q6asm_stream_media_format_block_ape(prtd->audio_client,
865 stream_id,
866 &ape_cfg);
867 if (ret < 0) {
868 dev_err(dev, "APE CMD Format block failed:%d\n", ret);
869 return -EIO;
870 }
871 break;
872
873 default:
874 break;
875 }
876
877 return 0;
878 }
879
q6asm_dai_compr_set_params(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_params * params)880 static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
881 struct snd_compr_stream *stream,
882 struct snd_compr_params *params)
883 {
884 struct snd_compr_runtime *runtime = stream->runtime;
885 struct q6asm_dai_rtd *prtd = runtime->private_data;
886 struct snd_soc_pcm_runtime *rtd = stream->private_data;
887 int dir = stream->direction;
888 struct q6asm_dai_data *pdata;
889 struct device *dev = component->dev;
890 int ret;
891
892 pdata = snd_soc_component_get_drvdata(component);
893 if (!pdata)
894 return -EINVAL;
895
896 if (!prtd || !prtd->audio_client) {
897 dev_err(dev, "private data null or audio client freed\n");
898 return -EINVAL;
899 }
900
901 prtd->periods = runtime->fragments;
902 prtd->pcm_count = runtime->fragment_size;
903 prtd->pcm_size = runtime->fragments * runtime->fragment_size;
904 prtd->bits_per_sample = 16;
905
906 if (dir == SND_COMPRESS_PLAYBACK) {
907 ret = q6asm_open_write(prtd->audio_client, prtd->stream_id, params->codec.id,
908 params->codec.profile, prtd->bits_per_sample,
909 true);
910
911 if (ret < 0) {
912 dev_err(dev, "q6asm_open_write failed\n");
913 goto open_err;
914 }
915 }
916
917 prtd->session_id = q6asm_get_session_id(prtd->audio_client);
918 ret = q6routing_stream_open(rtd->dai_link->id, LEGACY_PCM_MODE,
919 prtd->session_id, dir);
920 if (ret) {
921 dev_err(dev, "Stream reg failed ret:%d\n", ret);
922 goto routing_err;
923 }
924
925 ret = __q6asm_dai_compr_set_codec_params(component, stream,
926 ¶ms->codec,
927 prtd->stream_id);
928 if (ret) {
929 dev_err(dev, "codec param setup failed ret:%d\n", ret);
930 goto q6_err;
931 }
932
933 ret = q6asm_map_memory_regions(dir, prtd->audio_client, prtd->phys,
934 (prtd->pcm_size / prtd->periods),
935 prtd->periods);
936
937 if (ret < 0) {
938 dev_err(dev, "Buffer Mapping failed ret:%d\n", ret);
939 ret = -ENOMEM;
940 goto q6_err;
941 }
942
943 prtd->state = Q6ASM_STREAM_RUNNING;
944
945 return 0;
946
947 q6_err:
948 q6routing_stream_close(rtd->dai_link->id, dir);
949 routing_err:
950 q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
951
952 open_err:
953 return ret;
954 }
955
q6asm_dai_compr_set_metadata(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_metadata * metadata)956 static int q6asm_dai_compr_set_metadata(struct snd_soc_component *component,
957 struct snd_compr_stream *stream,
958 struct snd_compr_metadata *metadata)
959 {
960 struct snd_compr_runtime *runtime = stream->runtime;
961 struct q6asm_dai_rtd *prtd = runtime->private_data;
962 int ret = 0;
963
964 switch (metadata->key) {
965 case SNDRV_COMPRESS_ENCODER_PADDING:
966 prtd->trailing_samples_drop = metadata->value[0];
967 break;
968 case SNDRV_COMPRESS_ENCODER_DELAY:
969 prtd->initial_samples_drop = metadata->value[0];
970 if (prtd->next_track_stream_id) {
971 ret = q6asm_open_write(prtd->audio_client,
972 prtd->next_track_stream_id,
973 prtd->codec.id,
974 prtd->codec.profile,
975 prtd->bits_per_sample,
976 true);
977 if (ret < 0) {
978 dev_err(component->dev, "q6asm_open_write failed\n");
979 return ret;
980 }
981 ret = __q6asm_dai_compr_set_codec_params(component, stream,
982 &prtd->codec,
983 prtd->next_track_stream_id);
984 if (ret < 0) {
985 dev_err(component->dev, "q6asm_open_write failed\n");
986 return ret;
987 }
988
989 ret = q6asm_stream_remove_initial_silence(prtd->audio_client,
990 prtd->next_track_stream_id,
991 prtd->initial_samples_drop);
992 prtd->next_track_stream_id = 0;
993
994 }
995
996 break;
997 default:
998 ret = -EINVAL;
999 break;
1000 }
1001
1002 return ret;
1003 }
1004
q6asm_dai_compr_trigger(struct snd_soc_component * component,struct snd_compr_stream * stream,int cmd)1005 static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
1006 struct snd_compr_stream *stream, int cmd)
1007 {
1008 struct snd_compr_runtime *runtime = stream->runtime;
1009 struct q6asm_dai_rtd *prtd = runtime->private_data;
1010 int ret = 0;
1011
1012 switch (cmd) {
1013 case SNDRV_PCM_TRIGGER_START:
1014 case SNDRV_PCM_TRIGGER_RESUME:
1015 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
1016 ret = q6asm_run_nowait(prtd->audio_client, prtd->stream_id,
1017 0, 0, 0);
1018 break;
1019 case SNDRV_PCM_TRIGGER_STOP:
1020 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
1021 CMD_EOS);
1022 break;
1023 case SNDRV_PCM_TRIGGER_SUSPEND:
1024 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
1025 ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
1026 CMD_PAUSE);
1027 break;
1028 case SND_COMPR_TRIGGER_NEXT_TRACK:
1029 prtd->next_track = true;
1030 prtd->next_track_stream_id = (prtd->stream_id == 1 ? 2 : 1);
1031 break;
1032 case SND_COMPR_TRIGGER_DRAIN:
1033 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
1034 prtd->notify_on_drain = true;
1035 break;
1036 default:
1037 ret = -EINVAL;
1038 break;
1039 }
1040
1041 return ret;
1042 }
1043
q6asm_dai_compr_pointer(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_tstamp64 * tstamp)1044 static int q6asm_dai_compr_pointer(struct snd_soc_component *component,
1045 struct snd_compr_stream *stream,
1046 struct snd_compr_tstamp64 *tstamp)
1047 {
1048 struct snd_compr_runtime *runtime = stream->runtime;
1049 struct q6asm_dai_rtd *prtd = runtime->private_data;
1050 uint64_t temp_copied_total;
1051
1052 guard(spinlock_irqsave)(&prtd->lock);
1053
1054 tstamp->copied_total = prtd->copied_total;
1055 temp_copied_total = tstamp->copied_total;
1056 tstamp->byte_offset = do_div(temp_copied_total, prtd->pcm_size);
1057
1058 return 0;
1059 }
1060
q6asm_compr_copy(struct snd_soc_component * component,struct snd_compr_stream * stream,char __user * buf,size_t count)1061 static int q6asm_compr_copy(struct snd_soc_component *component,
1062 struct snd_compr_stream *stream, char __user *buf,
1063 size_t count)
1064 {
1065 struct snd_compr_runtime *runtime = stream->runtime;
1066 struct q6asm_dai_rtd *prtd = runtime->private_data;
1067 u32 wflags = 0;
1068 uint64_t avail, bytes_in_flight = 0;
1069 void *dstn;
1070 size_t copy;
1071 u32 app_pointer;
1072 uint64_t bytes_received;
1073 uint64_t temp_bytes_received;
1074
1075 bytes_received = prtd->bytes_received;
1076 temp_bytes_received = bytes_received;
1077
1078 /**
1079 * Make sure that next track data pointer is aligned at 32 bit boundary
1080 * This is a Mandatory requirement from DSP data buffers alignment
1081 */
1082 if (prtd->next_track) {
1083 bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
1084 temp_bytes_received = bytes_received;
1085 }
1086
1087 app_pointer = do_div(temp_bytes_received, prtd->pcm_size);
1088 dstn = prtd->dma_buffer.area + app_pointer;
1089
1090 if (count < prtd->pcm_size - app_pointer) {
1091 if (copy_from_user(dstn, buf, count))
1092 return -EFAULT;
1093 } else {
1094 copy = prtd->pcm_size - app_pointer;
1095 if (copy_from_user(dstn, buf, copy))
1096 return -EFAULT;
1097 if (copy_from_user(prtd->dma_buffer.area, buf + copy,
1098 count - copy))
1099 return -EFAULT;
1100 }
1101
1102 guard(spinlock_irqsave)(&prtd->lock);
1103
1104 bytes_in_flight = prtd->bytes_received - prtd->copied_total;
1105
1106 if (prtd->next_track) {
1107 prtd->next_track = false;
1108 prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count);
1109 prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count);
1110 }
1111
1112 prtd->bytes_received = bytes_received + count;
1113
1114 /* Kick off the data to dsp if its starving!! */
1115 if (prtd->state == Q6ASM_STREAM_RUNNING && (bytes_in_flight == 0)) {
1116 uint32_t bytes_to_write = prtd->pcm_count;
1117
1118 avail = prtd->bytes_received - prtd->bytes_sent;
1119
1120 if (avail < prtd->pcm_count)
1121 bytes_to_write = avail;
1122
1123 q6asm_write_async(prtd->audio_client, prtd->stream_id,
1124 bytes_to_write, 0, 0, wflags);
1125 prtd->bytes_sent += bytes_to_write;
1126 }
1127
1128 return count;
1129 }
1130
q6asm_dai_compr_mmap(struct snd_soc_component * component,struct snd_compr_stream * stream,struct vm_area_struct * vma)1131 static int q6asm_dai_compr_mmap(struct snd_soc_component *component,
1132 struct snd_compr_stream *stream,
1133 struct vm_area_struct *vma)
1134 {
1135 struct snd_compr_runtime *runtime = stream->runtime;
1136 struct q6asm_dai_rtd *prtd = runtime->private_data;
1137 struct device *dev = component->dev;
1138
1139 return dma_mmap_coherent(dev, vma,
1140 prtd->dma_buffer.area, prtd->dma_buffer.addr,
1141 prtd->dma_buffer.bytes);
1142 }
1143
q6asm_dai_compr_get_caps(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_caps * caps)1144 static int q6asm_dai_compr_get_caps(struct snd_soc_component *component,
1145 struct snd_compr_stream *stream,
1146 struct snd_compr_caps *caps)
1147 {
1148 caps->direction = SND_COMPRESS_PLAYBACK;
1149 caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
1150 caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
1151 caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
1152 caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
1153 caps->num_codecs = 5;
1154 caps->codecs[0] = SND_AUDIOCODEC_MP3;
1155 caps->codecs[1] = SND_AUDIOCODEC_FLAC;
1156 caps->codecs[2] = SND_AUDIOCODEC_WMA;
1157 caps->codecs[3] = SND_AUDIOCODEC_ALAC;
1158 caps->codecs[4] = SND_AUDIOCODEC_APE;
1159
1160 return 0;
1161 }
1162
q6asm_dai_compr_get_codec_caps(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_codec_caps * codec)1163 static int q6asm_dai_compr_get_codec_caps(struct snd_soc_component *component,
1164 struct snd_compr_stream *stream,
1165 struct snd_compr_codec_caps *codec)
1166 {
1167 switch (codec->codec) {
1168 case SND_AUDIOCODEC_MP3:
1169 *codec = q6asm_compr_caps;
1170 break;
1171 default:
1172 break;
1173 }
1174
1175 return 0;
1176 }
1177
1178 static const struct snd_compress_ops q6asm_dai_compress_ops = {
1179 .open = q6asm_dai_compr_open,
1180 .free = q6asm_dai_compr_free,
1181 .set_params = q6asm_dai_compr_set_params,
1182 .set_metadata = q6asm_dai_compr_set_metadata,
1183 .pointer = q6asm_dai_compr_pointer,
1184 .trigger = q6asm_dai_compr_trigger,
1185 .get_caps = q6asm_dai_compr_get_caps,
1186 .get_codec_caps = q6asm_dai_compr_get_codec_caps,
1187 .mmap = q6asm_dai_compr_mmap,
1188 .copy = q6asm_compr_copy,
1189 };
1190
q6asm_dai_pcm_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)1191 static int q6asm_dai_pcm_new(struct snd_soc_component *component,
1192 struct snd_soc_pcm_runtime *rtd)
1193 {
1194 struct snd_pcm *pcm = rtd->pcm;
1195 size_t size = q6asm_dai_hardware_playback.buffer_bytes_max;
1196
1197 return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
1198 component->dev, size);
1199 }
1200
1201 static const struct snd_soc_dapm_widget q6asm_dapm_widgets[] = {
1202 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, SND_SOC_NOPM, 0, 0),
1203 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, SND_SOC_NOPM, 0, 0),
1204 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, SND_SOC_NOPM, 0, 0),
1205 SND_SOC_DAPM_AIF_IN("MM_DL4", "MultiMedia4 Playback", 0, SND_SOC_NOPM, 0, 0),
1206 SND_SOC_DAPM_AIF_IN("MM_DL5", "MultiMedia5 Playback", 0, SND_SOC_NOPM, 0, 0),
1207 SND_SOC_DAPM_AIF_IN("MM_DL6", "MultiMedia6 Playback", 0, SND_SOC_NOPM, 0, 0),
1208 SND_SOC_DAPM_AIF_IN("MM_DL7", "MultiMedia7 Playback", 0, SND_SOC_NOPM, 0, 0),
1209 SND_SOC_DAPM_AIF_IN("MM_DL8", "MultiMedia8 Playback", 0, SND_SOC_NOPM, 0, 0),
1210 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, SND_SOC_NOPM, 0, 0),
1211 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, SND_SOC_NOPM, 0, 0),
1212 SND_SOC_DAPM_AIF_OUT("MM_UL3", "MultiMedia3 Capture", 0, SND_SOC_NOPM, 0, 0),
1213 SND_SOC_DAPM_AIF_OUT("MM_UL4", "MultiMedia4 Capture", 0, SND_SOC_NOPM, 0, 0),
1214 SND_SOC_DAPM_AIF_OUT("MM_UL5", "MultiMedia5 Capture", 0, SND_SOC_NOPM, 0, 0),
1215 SND_SOC_DAPM_AIF_OUT("MM_UL6", "MultiMedia6 Capture", 0, SND_SOC_NOPM, 0, 0),
1216 SND_SOC_DAPM_AIF_OUT("MM_UL7", "MultiMedia7 Capture", 0, SND_SOC_NOPM, 0, 0),
1217 SND_SOC_DAPM_AIF_OUT("MM_UL8", "MultiMedia8 Capture", 0, SND_SOC_NOPM, 0, 0),
1218 };
1219
1220 static const struct snd_soc_component_driver q6asm_fe_dai_component = {
1221 .name = DRV_NAME,
1222 .open = q6asm_dai_open,
1223 .hw_params = q6asm_dai_hw_params,
1224 .close = q6asm_dai_close,
1225 .prepare = q6asm_dai_prepare,
1226 .trigger = q6asm_dai_trigger,
1227 .ack = q6asm_dai_ack,
1228 .pointer = q6asm_dai_pointer,
1229 .pcm_new = q6asm_dai_pcm_new,
1230 .compress_ops = &q6asm_dai_compress_ops,
1231 .dapm_widgets = q6asm_dapm_widgets,
1232 .num_dapm_widgets = ARRAY_SIZE(q6asm_dapm_widgets),
1233 .legacy_dai_naming = 1,
1234 };
1235
1236 static struct snd_soc_dai_driver q6asm_fe_dais_template[] = {
1237 Q6ASM_FEDAI_DRIVER(1),
1238 Q6ASM_FEDAI_DRIVER(2),
1239 Q6ASM_FEDAI_DRIVER(3),
1240 Q6ASM_FEDAI_DRIVER(4),
1241 Q6ASM_FEDAI_DRIVER(5),
1242 Q6ASM_FEDAI_DRIVER(6),
1243 Q6ASM_FEDAI_DRIVER(7),
1244 Q6ASM_FEDAI_DRIVER(8),
1245 };
1246
1247 static const struct snd_soc_dai_ops q6asm_dai_ops = {
1248 .compress_new = snd_soc_new_compress,
1249 };
1250
of_q6asm_parse_dai_data(struct device * dev,struct q6asm_dai_data * pdata)1251 static int of_q6asm_parse_dai_data(struct device *dev,
1252 struct q6asm_dai_data *pdata)
1253 {
1254 struct snd_soc_dai_driver *dai_drv;
1255 struct snd_soc_pcm_stream empty_stream;
1256 struct device_node *node;
1257 int ret, id, dir, idx = 0;
1258
1259
1260 pdata->num_dais = of_get_child_count(dev->of_node);
1261 if (!pdata->num_dais) {
1262 dev_err(dev, "No dais found in DT\n");
1263 return -EINVAL;
1264 }
1265
1266 pdata->dais = devm_kcalloc(dev, pdata->num_dais, sizeof(*dai_drv),
1267 GFP_KERNEL);
1268 if (!pdata->dais)
1269 return -ENOMEM;
1270
1271 memset(&empty_stream, 0, sizeof(empty_stream));
1272
1273 for_each_child_of_node(dev->of_node, node) {
1274 ret = of_property_read_u32(node, "reg", &id);
1275 if (ret || id >= MAX_SESSIONS || id < 0) {
1276 dev_err(dev, "valid dai id not found:%d\n", ret);
1277 continue;
1278 }
1279
1280 dai_drv = &pdata->dais[idx++];
1281 *dai_drv = q6asm_fe_dais_template[id];
1282
1283 ret = of_property_read_u32(node, "direction", &dir);
1284 if (ret)
1285 continue;
1286
1287 if (dir == Q6ASM_DAI_RX)
1288 dai_drv->capture = empty_stream;
1289 else if (dir == Q6ASM_DAI_TX)
1290 dai_drv->playback = empty_stream;
1291
1292 if (of_property_read_bool(node, "is-compress-dai"))
1293 dai_drv->ops = &q6asm_dai_ops;
1294 }
1295
1296 return 0;
1297 }
1298
q6asm_dai_probe(struct platform_device * pdev)1299 static int q6asm_dai_probe(struct platform_device *pdev)
1300 {
1301 struct device *dev = &pdev->dev;
1302 struct device_node *node = dev->of_node;
1303 struct of_phandle_args args;
1304 struct q6asm_dai_data *pdata;
1305 int rc;
1306
1307 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
1308 if (!pdata)
1309 return -ENOMEM;
1310
1311 rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
1312 if (rc < 0)
1313 pdata->sid = -1;
1314 else
1315 pdata->sid = args.args[0] & SID_MASK_DEFAULT;
1316
1317 dev_set_drvdata(dev, pdata);
1318
1319 rc = of_q6asm_parse_dai_data(dev, pdata);
1320 if (rc)
1321 return rc;
1322
1323 return devm_snd_soc_register_component(dev, &q6asm_fe_dai_component,
1324 pdata->dais, pdata->num_dais);
1325 }
1326
1327 #ifdef CONFIG_OF
1328 static const struct of_device_id q6asm_dai_device_id[] = {
1329 { .compatible = "qcom,q6asm-dais" },
1330 {},
1331 };
1332 MODULE_DEVICE_TABLE(of, q6asm_dai_device_id);
1333 #endif
1334
1335 static struct platform_driver q6asm_dai_platform_driver = {
1336 .driver = {
1337 .name = "q6asm-dai",
1338 .of_match_table = of_match_ptr(q6asm_dai_device_id),
1339 },
1340 .probe = q6asm_dai_probe,
1341 };
1342 module_platform_driver(q6asm_dai_platform_driver);
1343
1344 MODULE_DESCRIPTION("Q6ASM dai driver");
1345 MODULE_LICENSE("GPL v2");
1346