ASoC: dt-bindings: q6asm: Add Q6ASM_DAI_{TX_RX, TX, RX} defines
[linux-2.6-microblaze.git] / sound / soc / qcom / qdsp6 / q6asm-dai.c
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");