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