arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / intel / catpt / pcm.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright(c) 2020 Intel Corporation. All rights reserved.
4 //
5 // Author: Cezary Rojewski <cezary.rojewski@intel.com>
6 //
7
8 #include <linux/pm_runtime.h>
9 #include <sound/soc.h>
10 #include <sound/pcm_params.h>
11 #include <uapi/sound/tlv.h>
12 #include "core.h"
13 #include "messages.h"
14
15 struct catpt_stream_template {
16         enum catpt_path_id path_id;
17         enum catpt_stream_type type;
18         u32 persistent_size;
19         u8 num_entries;
20         struct catpt_module_entry entries[];
21 };
22
23 static struct catpt_stream_template system_pb = {
24         .path_id = CATPT_PATH_SSP0_OUT,
25         .type = CATPT_STRM_TYPE_SYSTEM,
26         .num_entries = 1,
27         .entries = {{ CATPT_MODID_PCM_SYSTEM, 0 }},
28 };
29
30 static struct catpt_stream_template system_cp = {
31         .path_id = CATPT_PATH_SSP0_IN,
32         .type = CATPT_STRM_TYPE_CAPTURE,
33         .num_entries = 1,
34         .entries = {{ CATPT_MODID_PCM_CAPTURE, 0 }},
35 };
36
37 static struct catpt_stream_template offload_pb = {
38         .path_id = CATPT_PATH_SSP0_OUT,
39         .type = CATPT_STRM_TYPE_RENDER,
40         .num_entries = 1,
41         .entries = {{ CATPT_MODID_PCM, 0 }},
42 };
43
44 static struct catpt_stream_template loopback_cp = {
45         .path_id = CATPT_PATH_SSP0_OUT,
46         .type = CATPT_STRM_TYPE_LOOPBACK,
47         .num_entries = 1,
48         .entries = {{ CATPT_MODID_PCM_REFERENCE, 0 }},
49 };
50
51 static struct catpt_stream_template bluetooth_pb = {
52         .path_id = CATPT_PATH_SSP1_OUT,
53         .type = CATPT_STRM_TYPE_BLUETOOTH_RENDER,
54         .num_entries = 1,
55         .entries = {{ CATPT_MODID_BLUETOOTH_RENDER, 0 }},
56 };
57
58 static struct catpt_stream_template bluetooth_cp = {
59         .path_id = CATPT_PATH_SSP1_IN,
60         .type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE,
61         .num_entries = 1,
62         .entries = {{ CATPT_MODID_BLUETOOTH_CAPTURE, 0 }},
63 };
64
65 static struct catpt_stream_template *catpt_topology[] = {
66         [CATPT_STRM_TYPE_RENDER]                = &offload_pb,
67         [CATPT_STRM_TYPE_SYSTEM]                = &system_pb,
68         [CATPT_STRM_TYPE_CAPTURE]               = &system_cp,
69         [CATPT_STRM_TYPE_LOOPBACK]              = &loopback_cp,
70         [CATPT_STRM_TYPE_BLUETOOTH_RENDER]      = &bluetooth_pb,
71         [CATPT_STRM_TYPE_BLUETOOTH_CAPTURE]     = &bluetooth_cp,
72 };
73
74 static struct catpt_stream_template *
75 catpt_get_stream_template(struct snd_pcm_substream *substream)
76 {
77         struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
78         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0);
79         enum catpt_stream_type type;
80
81         type = cpu_dai->driver->id;
82
83         /* account for capture in bidirectional dais */
84         switch (type) {
85         case CATPT_STRM_TYPE_SYSTEM:
86                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
87                         type = CATPT_STRM_TYPE_CAPTURE;
88                 break;
89         case CATPT_STRM_TYPE_BLUETOOTH_RENDER:
90                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
91                         type = CATPT_STRM_TYPE_BLUETOOTH_CAPTURE;
92                 break;
93         default:
94                 break;
95         }
96
97         return catpt_topology[type];
98 }
99
100 struct catpt_stream_runtime *
101 catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
102 {
103         struct catpt_stream_runtime *pos, *result = NULL;
104
105         spin_lock(&cdev->list_lock);
106         list_for_each_entry(pos, &cdev->stream_list, node) {
107                 if (pos->info.stream_hw_id == stream_hw_id) {
108                         result = pos;
109                         break;
110                 }
111         }
112
113         spin_unlock(&cdev->list_lock);
114         return result;
115 }
116
117 static u32 catpt_stream_read_position(struct catpt_dev *cdev,
118                                       struct catpt_stream_runtime *stream)
119 {
120         u32 pos;
121
122         memcpy_fromio(&pos, cdev->lpe_ba + stream->info.read_pos_regaddr,
123                       sizeof(pos));
124         return pos;
125 }
126
127 static u32 catpt_stream_volume(struct catpt_dev *cdev,
128                                struct catpt_stream_runtime *stream, u32 channel)
129 {
130         u32 volume, offset;
131
132         if (channel >= CATPT_CHANNELS_MAX)
133                 channel = 0;
134
135         offset = stream->info.volume_regaddr[channel];
136         memcpy_fromio(&volume, cdev->lpe_ba + offset, sizeof(volume));
137         return volume;
138 }
139
140 static u32 catpt_mixer_volume(struct catpt_dev *cdev,
141                               struct catpt_mixer_stream_info *info, u32 channel)
142 {
143         u32 volume, offset;
144
145         if (channel >= CATPT_CHANNELS_MAX)
146                 channel = 0;
147
148         offset = info->volume_regaddr[channel];
149         memcpy_fromio(&volume, cdev->lpe_ba + offset, sizeof(volume));
150         return volume;
151 }
152
153 static void catpt_arrange_page_table(struct snd_pcm_substream *substream,
154                                      struct snd_dma_buffer *pgtbl)
155 {
156         struct snd_pcm_runtime *rtm = substream->runtime;
157         struct snd_dma_buffer *databuf = snd_pcm_get_dma_buf(substream);
158         int i, pages;
159
160         pages = snd_sgbuf_aligned_pages(rtm->dma_bytes);
161
162         for (i = 0; i < pages; i++) {
163                 u32 pfn, offset;
164                 u32 *page_table;
165
166                 pfn = PFN_DOWN(snd_sgbuf_get_addr(databuf, i * PAGE_SIZE));
167                 /* incrementing by 2 on even and 3 on odd */
168                 offset = ((i << 2) + i) >> 1;
169                 page_table = (u32 *)(pgtbl->area + offset);
170
171                 if (i & 1)
172                         *page_table |= (pfn << 4);
173                 else
174                         *page_table |= pfn;
175         }
176 }
177
178 static u32 catpt_get_channel_map(enum catpt_channel_config config)
179 {
180         switch (config) {
181         case CATPT_CHANNEL_CONFIG_MONO:
182                 return GENMASK(31, 4) | CATPT_CHANNEL_CENTER;
183
184         case CATPT_CHANNEL_CONFIG_STEREO:
185                 return GENMASK(31, 8) | CATPT_CHANNEL_LEFT
186                                       | (CATPT_CHANNEL_RIGHT << 4);
187
188         case CATPT_CHANNEL_CONFIG_2_POINT_1:
189                 return GENMASK(31, 12) | CATPT_CHANNEL_LEFT
190                                        | (CATPT_CHANNEL_RIGHT << 4)
191                                        | (CATPT_CHANNEL_LFE << 8);
192
193         case CATPT_CHANNEL_CONFIG_3_POINT_0:
194                 return GENMASK(31, 12) | CATPT_CHANNEL_LEFT
195                                        | (CATPT_CHANNEL_CENTER << 4)
196                                        | (CATPT_CHANNEL_RIGHT << 8);
197
198         case CATPT_CHANNEL_CONFIG_3_POINT_1:
199                 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
200                                        | (CATPT_CHANNEL_CENTER << 4)
201                                        | (CATPT_CHANNEL_RIGHT << 8)
202                                        | (CATPT_CHANNEL_LFE << 12);
203
204         case CATPT_CHANNEL_CONFIG_QUATRO:
205                 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
206                                        | (CATPT_CHANNEL_RIGHT << 4)
207                                        | (CATPT_CHANNEL_LEFT_SURROUND << 8)
208                                        | (CATPT_CHANNEL_RIGHT_SURROUND << 12);
209
210         case CATPT_CHANNEL_CONFIG_4_POINT_0:
211                 return GENMASK(31, 16) | CATPT_CHANNEL_LEFT
212                                        | (CATPT_CHANNEL_CENTER << 4)
213                                        | (CATPT_CHANNEL_RIGHT << 8)
214                                        | (CATPT_CHANNEL_CENTER_SURROUND << 12);
215
216         case CATPT_CHANNEL_CONFIG_5_POINT_0:
217                 return GENMASK(31, 20) | CATPT_CHANNEL_LEFT
218                                        | (CATPT_CHANNEL_CENTER << 4)
219                                        | (CATPT_CHANNEL_RIGHT << 8)
220                                        | (CATPT_CHANNEL_LEFT_SURROUND << 12)
221                                        | (CATPT_CHANNEL_RIGHT_SURROUND << 16);
222
223         case CATPT_CHANNEL_CONFIG_5_POINT_1:
224                 return GENMASK(31, 24) | CATPT_CHANNEL_CENTER
225                                        | (CATPT_CHANNEL_LEFT << 4)
226                                        | (CATPT_CHANNEL_RIGHT << 8)
227                                        | (CATPT_CHANNEL_LEFT_SURROUND << 12)
228                                        | (CATPT_CHANNEL_RIGHT_SURROUND << 16)
229                                        | (CATPT_CHANNEL_LFE << 20);
230
231         case CATPT_CHANNEL_CONFIG_DUAL_MONO:
232                 return GENMASK(31, 8) | CATPT_CHANNEL_LEFT
233                                       | (CATPT_CHANNEL_LEFT << 4);
234
235         default:
236                 return U32_MAX;
237         }
238 }
239
240 static enum catpt_channel_config catpt_get_channel_config(u32 num_channels)
241 {
242         switch (num_channels) {
243         case 6:
244                 return CATPT_CHANNEL_CONFIG_5_POINT_1;
245         case 5:
246                 return CATPT_CHANNEL_CONFIG_5_POINT_0;
247         case 4:
248                 return CATPT_CHANNEL_CONFIG_QUATRO;
249         case 3:
250                 return CATPT_CHANNEL_CONFIG_2_POINT_1;
251         case 1:
252                 return CATPT_CHANNEL_CONFIG_MONO;
253         case 2:
254         default:
255                 return CATPT_CHANNEL_CONFIG_STEREO;
256         }
257 }
258
259 static int catpt_dai_startup(struct snd_pcm_substream *substream,
260                              struct snd_soc_dai *dai)
261 {
262         struct catpt_stream_template *template;
263         struct catpt_stream_runtime *stream;
264         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
265         struct resource *res;
266         int ret;
267
268         template = catpt_get_stream_template(substream);
269
270         stream = kzalloc(sizeof(*stream), GFP_KERNEL);
271         if (!stream)
272                 return -ENOMEM;
273
274         ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, cdev->dev, PAGE_SIZE,
275                                   &stream->pgtbl);
276         if (ret)
277                 goto err_pgtbl;
278
279         res = catpt_request_region(&cdev->dram, template->persistent_size);
280         if (!res) {
281                 ret = -EBUSY;
282                 goto err_request;
283         }
284
285         catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask);
286
287         stream->template = template;
288         stream->persistent = res;
289         stream->substream = substream;
290         INIT_LIST_HEAD(&stream->node);
291         snd_soc_dai_set_dma_data(dai, substream, stream);
292
293         spin_lock(&cdev->list_lock);
294         list_add_tail(&stream->node, &cdev->stream_list);
295         spin_unlock(&cdev->list_lock);
296
297         return 0;
298
299 err_request:
300         snd_dma_free_pages(&stream->pgtbl);
301 err_pgtbl:
302         kfree(stream);
303         return ret;
304 }
305
306 static void catpt_dai_shutdown(struct snd_pcm_substream *substream,
307                                struct snd_soc_dai *dai)
308 {
309         struct catpt_stream_runtime *stream;
310         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
311
312         stream = snd_soc_dai_get_dma_data(dai, substream);
313
314         spin_lock(&cdev->list_lock);
315         list_del(&stream->node);
316         spin_unlock(&cdev->list_lock);
317
318         release_resource(stream->persistent);
319         kfree(stream->persistent);
320         catpt_dsp_update_srampge(cdev, &cdev->dram, cdev->spec->dram_mask);
321
322         snd_dma_free_pages(&stream->pgtbl);
323         kfree(stream);
324         snd_soc_dai_set_dma_data(dai, substream, NULL);
325 }
326
327 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol);
328
329 static int catpt_dai_apply_usettings(struct snd_soc_dai *dai,
330                                      struct catpt_stream_runtime *stream)
331 {
332         struct snd_soc_component *component = dai->component;
333         struct snd_kcontrol *pos;
334         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
335         const char *name;
336         int ret;
337         u32 id = stream->info.stream_hw_id;
338
339         /* only selected streams have individual controls */
340         switch (id) {
341         case CATPT_PIN_ID_OFFLOAD1:
342                 name = "Media0 Playback Volume";
343                 break;
344         case CATPT_PIN_ID_OFFLOAD2:
345                 name = "Media1 Playback Volume";
346                 break;
347         case CATPT_PIN_ID_CAPTURE1:
348                 name = "Mic Capture Volume";
349                 break;
350         case CATPT_PIN_ID_REFERENCE:
351                 name = "Loopback Mute";
352                 break;
353         default:
354                 return 0;
355         }
356
357         list_for_each_entry(pos, &component->card->snd_card->controls, list) {
358                 if (pos->private_data == component &&
359                     !strncmp(name, pos->id.name, sizeof(pos->id.name)))
360                         break;
361         }
362         if (list_entry_is_head(pos, &component->card->snd_card->controls, list))
363                 return -ENOENT;
364
365         if (stream->template->type != CATPT_STRM_TYPE_LOOPBACK)
366                 return catpt_set_dspvol(cdev, id, (long *)pos->private_value);
367         ret = catpt_ipc_mute_loopback(cdev, id, *(bool *)pos->private_value);
368         if (ret)
369                 return CATPT_IPC_ERROR(ret);
370         return 0;
371 }
372
373 static int catpt_dai_hw_params(struct snd_pcm_substream *substream,
374                                struct snd_pcm_hw_params *params,
375                                struct snd_soc_dai *dai)
376 {
377         struct snd_pcm_runtime *rtm = substream->runtime;
378         struct snd_dma_buffer *dmab;
379         struct catpt_stream_runtime *stream;
380         struct catpt_audio_format afmt;
381         struct catpt_ring_info rinfo;
382         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
383         int ret;
384
385         stream = snd_soc_dai_get_dma_data(dai, substream);
386         if (stream->allocated)
387                 return 0;
388
389         memset(&afmt, 0, sizeof(afmt));
390         afmt.sample_rate = params_rate(params);
391         afmt.bit_depth = params_physical_width(params);
392         afmt.valid_bit_depth = params_width(params);
393         afmt.num_channels = params_channels(params);
394         afmt.channel_config = catpt_get_channel_config(afmt.num_channels);
395         afmt.channel_map = catpt_get_channel_map(afmt.channel_config);
396         afmt.interleaving = CATPT_INTERLEAVING_PER_CHANNEL;
397
398         dmab = snd_pcm_get_dma_buf(substream);
399         catpt_arrange_page_table(substream, &stream->pgtbl);
400
401         memset(&rinfo, 0, sizeof(rinfo));
402         rinfo.page_table_addr = stream->pgtbl.addr;
403         rinfo.num_pages = DIV_ROUND_UP(rtm->dma_bytes, PAGE_SIZE);
404         rinfo.size = rtm->dma_bytes;
405         rinfo.offset = 0;
406         rinfo.ring_first_page_pfn = PFN_DOWN(snd_sgbuf_get_addr(dmab, 0));
407
408         ret = catpt_ipc_alloc_stream(cdev, stream->template->path_id,
409                                      stream->template->type,
410                                      &afmt, &rinfo,
411                                      stream->template->num_entries,
412                                      stream->template->entries,
413                                      stream->persistent,
414                                      cdev->scratch,
415                                      &stream->info);
416         if (ret)
417                 return CATPT_IPC_ERROR(ret);
418
419         ret = catpt_dai_apply_usettings(dai, stream);
420         if (ret)
421                 return ret;
422
423         stream->allocated = true;
424         return 0;
425 }
426
427 static int catpt_dai_hw_free(struct snd_pcm_substream *substream,
428                              struct snd_soc_dai *dai)
429 {
430         struct catpt_stream_runtime *stream;
431         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
432
433         stream = snd_soc_dai_get_dma_data(dai, substream);
434         if (!stream->allocated)
435                 return 0;
436
437         catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id);
438         catpt_ipc_free_stream(cdev, stream->info.stream_hw_id);
439
440         stream->allocated = false;
441         return 0;
442 }
443
444 static int catpt_dai_prepare(struct snd_pcm_substream *substream,
445                              struct snd_soc_dai *dai)
446 {
447         struct catpt_stream_runtime *stream;
448         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
449         int ret;
450
451         stream = snd_soc_dai_get_dma_data(dai, substream);
452         if (stream->prepared)
453                 return 0;
454
455         ret = catpt_ipc_reset_stream(cdev, stream->info.stream_hw_id);
456         if (ret)
457                 return CATPT_IPC_ERROR(ret);
458
459         ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
460         if (ret)
461                 return CATPT_IPC_ERROR(ret);
462
463         stream->prepared = true;
464         return 0;
465 }
466
467 static int catpt_dai_trigger(struct snd_pcm_substream *substream, int cmd,
468                              struct snd_soc_dai *dai)
469 {
470         struct snd_pcm_runtime *runtime = substream->runtime;
471         struct catpt_stream_runtime *stream;
472         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
473         snd_pcm_uframes_t pos;
474         int ret;
475
476         stream = snd_soc_dai_get_dma_data(dai, substream);
477
478         switch (cmd) {
479         case SNDRV_PCM_TRIGGER_START:
480                 /* only offload is set_write_pos driven */
481                 if (stream->template->type != CATPT_STRM_TYPE_RENDER)
482                         goto resume_stream;
483
484                 pos = frames_to_bytes(runtime, runtime->start_threshold);
485                 /*
486                  * Dsp operates on buffer halves, thus max 2x set_write_pos
487                  * (entire buffer filled) prior to stream start.
488                  */
489                 ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id,
490                                               pos, false, false);
491                 if (ret)
492                         return CATPT_IPC_ERROR(ret);
493                 fallthrough;
494         case SNDRV_PCM_TRIGGER_RESUME:
495         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
496         resume_stream:
497                 catpt_dsp_update_lpclock(cdev);
498                 ret = catpt_ipc_resume_stream(cdev, stream->info.stream_hw_id);
499                 if (ret)
500                         return CATPT_IPC_ERROR(ret);
501                 break;
502
503         case SNDRV_PCM_TRIGGER_STOP:
504                 stream->prepared = false;
505                 fallthrough;
506         case SNDRV_PCM_TRIGGER_SUSPEND:
507         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
508                 ret = catpt_ipc_pause_stream(cdev, stream->info.stream_hw_id);
509                 catpt_dsp_update_lpclock(cdev);
510                 if (ret)
511                         return CATPT_IPC_ERROR(ret);
512                 break;
513
514         default:
515                 break;
516         }
517
518         return 0;
519 }
520
521 void catpt_stream_update_position(struct catpt_dev *cdev,
522                                   struct catpt_stream_runtime *stream,
523                                   struct catpt_notify_position *pos)
524 {
525         struct snd_pcm_substream *substream = stream->substream;
526         struct snd_pcm_runtime *r = substream->runtime;
527         snd_pcm_uframes_t dsppos, newpos;
528         int ret;
529
530         dsppos = bytes_to_frames(r, pos->stream_position);
531
532         if (!stream->prepared)
533                 goto exit;
534         /* only offload is set_write_pos driven */
535         if (stream->template->type != CATPT_STRM_TYPE_RENDER)
536                 goto exit;
537
538         if (dsppos >= r->buffer_size / 2)
539                 newpos = r->buffer_size / 2;
540         else
541                 newpos = 0;
542         /*
543          * Dsp operates on buffer halves, thus on every notify position
544          * (buffer half consumed) update wp to allow stream progression.
545          */
546         ret = catpt_ipc_set_write_pos(cdev, stream->info.stream_hw_id,
547                                       frames_to_bytes(r, newpos),
548                                       false, false);
549         if (ret) {
550                 dev_err(cdev->dev, "update position for stream %d failed: %d\n",
551                         stream->info.stream_hw_id, ret);
552                 return;
553         }
554 exit:
555         snd_pcm_period_elapsed(substream);
556 }
557
558 /* 200 ms for 2 32-bit channels at 48kHz (native format) */
559 #define CATPT_BUFFER_MAX_SIZE   76800
560 #define CATPT_PCM_PERIODS_MAX   4
561 #define CATPT_PCM_PERIODS_MIN   2
562
563 static const struct snd_pcm_hardware catpt_pcm_hardware = {
564         .info                   = SNDRV_PCM_INFO_MMAP |
565                                   SNDRV_PCM_INFO_MMAP_VALID |
566                                   SNDRV_PCM_INFO_INTERLEAVED |
567                                   SNDRV_PCM_INFO_PAUSE |
568                                   SNDRV_PCM_INFO_RESUME |
569                                   SNDRV_PCM_INFO_NO_PERIOD_WAKEUP,
570         .formats                = SNDRV_PCM_FMTBIT_S16_LE |
571                                   SNDRV_PCM_FMTBIT_S24_LE |
572                                   SNDRV_PCM_FMTBIT_S32_LE,
573         .period_bytes_min       = PAGE_SIZE,
574         .period_bytes_max       = CATPT_BUFFER_MAX_SIZE / CATPT_PCM_PERIODS_MIN,
575         .periods_min            = CATPT_PCM_PERIODS_MIN,
576         .periods_max            = CATPT_PCM_PERIODS_MAX,
577         .buffer_bytes_max       = CATPT_BUFFER_MAX_SIZE,
578 };
579
580 static int catpt_component_pcm_construct(struct snd_soc_component *component,
581                                          struct snd_soc_pcm_runtime *rtm)
582 {
583         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
584
585         snd_pcm_set_managed_buffer_all(rtm->pcm, SNDRV_DMA_TYPE_DEV_SG,
586                                        cdev->dev,
587                                        catpt_pcm_hardware.buffer_bytes_max,
588                                        catpt_pcm_hardware.buffer_bytes_max);
589
590         return 0;
591 }
592
593 static int catpt_component_open(struct snd_soc_component *component,
594                                 struct snd_pcm_substream *substream)
595 {
596         struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
597
598         if (!rtm->dai_link->no_pcm)
599                 snd_soc_set_runtime_hwparams(substream, &catpt_pcm_hardware);
600         return 0;
601 }
602
603 static snd_pcm_uframes_t
604 catpt_component_pointer(struct snd_soc_component *component,
605                         struct snd_pcm_substream *substream)
606 {
607         struct snd_soc_pcm_runtime *rtm = snd_soc_substream_to_rtd(substream);
608         struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtm, 0);
609         struct catpt_stream_runtime *stream;
610         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
611         u32 pos;
612
613         if (rtm->dai_link->no_pcm)
614                 return 0;
615
616         stream = snd_soc_dai_get_dma_data(cpu_dai, substream);
617         pos = catpt_stream_read_position(cdev, stream);
618
619         return bytes_to_frames(substream->runtime, pos);
620 }
621
622 static const struct snd_soc_dai_ops catpt_fe_dai_ops = {
623         .startup = catpt_dai_startup,
624         .shutdown = catpt_dai_shutdown,
625         .hw_params = catpt_dai_hw_params,
626         .hw_free = catpt_dai_hw_free,
627         .prepare = catpt_dai_prepare,
628         .trigger = catpt_dai_trigger,
629 };
630
631 static int catpt_dai_pcm_new(struct snd_soc_pcm_runtime *rtm,
632                              struct snd_soc_dai *dai)
633 {
634         struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtm, 0);
635         struct catpt_ssp_device_format devfmt;
636         struct catpt_dev *cdev = dev_get_drvdata(dai->dev);
637         int ret;
638
639         devfmt.iface = dai->driver->id;
640         devfmt.channels = codec_dai->driver->capture.channels_max;
641
642         switch (devfmt.iface) {
643         case CATPT_SSP_IFACE_0:
644                 devfmt.mclk = CATPT_MCLK_FREQ_24_MHZ;
645
646                 switch (devfmt.channels) {
647                 case 4:
648                         devfmt.mode = CATPT_SSP_MODE_TDM_PROVIDER;
649                         devfmt.clock_divider = 4;
650                         break;
651                 case 2:
652                 default:
653                         devfmt.mode = CATPT_SSP_MODE_I2S_PROVIDER;
654                         devfmt.clock_divider = 9;
655                         break;
656                 }
657                 break;
658
659         case CATPT_SSP_IFACE_1:
660                 devfmt.mclk = CATPT_MCLK_OFF;
661                 devfmt.mode = CATPT_SSP_MODE_I2S_CONSUMER;
662                 devfmt.clock_divider = 0;
663                 break;
664         }
665
666         /* see if this is a new configuration */
667         if (!memcmp(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt)))
668                 return 0;
669
670         ret = pm_runtime_resume_and_get(cdev->dev);
671         if (ret < 0 && ret != -EACCES)
672                 return ret;
673
674         ret = catpt_ipc_set_device_format(cdev, &devfmt);
675
676         pm_runtime_mark_last_busy(cdev->dev);
677         pm_runtime_put_autosuspend(cdev->dev);
678
679         if (ret)
680                 return CATPT_IPC_ERROR(ret);
681
682         /* store device format set for given SSP */
683         memcpy(&cdev->devfmt[devfmt.iface], &devfmt, sizeof(devfmt));
684         return 0;
685 }
686
687 static const struct snd_soc_dai_ops catpt_dai_ops = {
688         .pcm_new = catpt_dai_pcm_new,
689 };
690
691 static struct snd_soc_dai_driver dai_drivers[] = {
692 /* FE DAIs */
693 {
694         .name  = "System Pin",
695         .id = CATPT_STRM_TYPE_SYSTEM,
696         .ops = &catpt_fe_dai_ops,
697         .playback = {
698                 .stream_name = "System Playback",
699                 .channels_min = 2,
700                 .channels_max = 2,
701                 .rates = SNDRV_PCM_RATE_48000,
702                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
703         },
704         .capture = {
705                 .stream_name = "Analog Capture",
706                 .channels_min = 2,
707                 .channels_max = 4,
708                 .rates = SNDRV_PCM_RATE_48000,
709                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
710         },
711 },
712 {
713         .name  = "Offload0 Pin",
714         .id = CATPT_STRM_TYPE_RENDER,
715         .ops = &catpt_fe_dai_ops,
716         .playback = {
717                 .stream_name = "Offload0 Playback",
718                 .channels_min = 2,
719                 .channels_max = 2,
720                 .rates = SNDRV_PCM_RATE_8000_192000,
721                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
722         },
723 },
724 {
725         .name  = "Offload1 Pin",
726         .id = CATPT_STRM_TYPE_RENDER,
727         .ops = &catpt_fe_dai_ops,
728         .playback = {
729                 .stream_name = "Offload1 Playback",
730                 .channels_min = 2,
731                 .channels_max = 2,
732                 .rates = SNDRV_PCM_RATE_8000_192000,
733                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
734         },
735 },
736 {
737         .name  = "Loopback Pin",
738         .id = CATPT_STRM_TYPE_LOOPBACK,
739         .ops = &catpt_fe_dai_ops,
740         .capture = {
741                 .stream_name = "Loopback Capture",
742                 .channels_min = 2,
743                 .channels_max = 2,
744                 .rates = SNDRV_PCM_RATE_48000,
745                 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
746         },
747 },
748 {
749         .name  = "Bluetooth Pin",
750         .id = CATPT_STRM_TYPE_BLUETOOTH_RENDER,
751         .ops = &catpt_fe_dai_ops,
752         .playback = {
753                 .stream_name = "Bluetooth Playback",
754                 .channels_min = 1,
755                 .channels_max = 1,
756                 .rates = SNDRV_PCM_RATE_8000,
757                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
758         },
759         .capture = {
760                 .stream_name = "Bluetooth Capture",
761                 .channels_min = 1,
762                 .channels_max = 1,
763                 .rates = SNDRV_PCM_RATE_8000,
764                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
765         },
766 },
767 /* BE DAIs */
768 {
769         .name = "ssp0-port",
770         .id = CATPT_SSP_IFACE_0,
771         .playback = {
772                 .channels_min = 1,
773                 .channels_max = 8,
774         },
775         .capture = {
776                 .channels_min = 1,
777                 .channels_max = 8,
778         },
779         .ops = &catpt_dai_ops,
780 },
781 {
782         .name = "ssp1-port",
783         .id = CATPT_SSP_IFACE_1,
784         .playback = {
785                 .channels_min = 1,
786                 .channels_max = 8,
787         },
788         .capture = {
789                 .channels_min = 1,
790                 .channels_max = 8,
791         },
792         .ops = &catpt_dai_ops,
793 },
794 };
795
796 #define DSP_VOLUME_MAX          S32_MAX /* 0db */
797 #define DSP_VOLUME_STEP_MAX     30
798
799 static u32 ctlvol_to_dspvol(u32 value)
800 {
801         if (value > DSP_VOLUME_STEP_MAX)
802                 value = 0;
803         return DSP_VOLUME_MAX >> (DSP_VOLUME_STEP_MAX - value);
804 }
805
806 static u32 dspvol_to_ctlvol(u32 volume)
807 {
808         if (volume > DSP_VOLUME_MAX)
809                 return DSP_VOLUME_STEP_MAX;
810         return volume ? __fls(volume) : 0;
811 }
812
813 static int catpt_set_dspvol(struct catpt_dev *cdev, u8 stream_id, long *ctlvol)
814 {
815         u32 dspvol;
816         int ret, i;
817
818         for (i = 1; i < CATPT_CHANNELS_MAX; i++)
819                 if (ctlvol[i] != ctlvol[0])
820                         break;
821
822         if (i == CATPT_CHANNELS_MAX) {
823                 dspvol = ctlvol_to_dspvol(ctlvol[0]);
824
825                 ret = catpt_ipc_set_volume(cdev, stream_id,
826                                            CATPT_ALL_CHANNELS_MASK, dspvol,
827                                            0, CATPT_AUDIO_CURVE_NONE);
828         } else {
829                 for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
830                         dspvol = ctlvol_to_dspvol(ctlvol[i]);
831
832                         ret = catpt_ipc_set_volume(cdev, stream_id,
833                                                    i, dspvol,
834                                                    0, CATPT_AUDIO_CURVE_NONE);
835                         if (ret)
836                                 break;
837                 }
838         }
839
840         if (ret)
841                 return CATPT_IPC_ERROR(ret);
842         return 0;
843 }
844
845 static int catpt_volume_info(struct snd_kcontrol *kcontrol,
846                              struct snd_ctl_elem_info *uinfo)
847 {
848         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
849         uinfo->count = CATPT_CHANNELS_MAX;
850         uinfo->value.integer.min = 0;
851         uinfo->value.integer.max = DSP_VOLUME_STEP_MAX;
852         return 0;
853 }
854
855 static int catpt_mixer_volume_get(struct snd_kcontrol *kcontrol,
856                                   struct snd_ctl_elem_value *ucontrol)
857 {
858         struct snd_soc_component *component =
859                 snd_soc_kcontrol_component(kcontrol);
860         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
861         u32 dspvol;
862         int ret;
863         int i;
864
865         ret = pm_runtime_resume_and_get(cdev->dev);
866         if (ret < 0 && ret != -EACCES)
867                 return ret;
868
869         for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
870                 dspvol = catpt_mixer_volume(cdev, &cdev->mixer, i);
871                 ucontrol->value.integer.value[i] = dspvol_to_ctlvol(dspvol);
872         }
873
874         pm_runtime_mark_last_busy(cdev->dev);
875         pm_runtime_put_autosuspend(cdev->dev);
876
877         return 0;
878 }
879
880 static int catpt_mixer_volume_put(struct snd_kcontrol *kcontrol,
881                                   struct snd_ctl_elem_value *ucontrol)
882 {
883         struct snd_soc_component *component =
884                 snd_soc_kcontrol_component(kcontrol);
885         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
886         int ret;
887
888         ret = pm_runtime_resume_and_get(cdev->dev);
889         if (ret < 0 && ret != -EACCES)
890                 return ret;
891
892         ret = catpt_set_dspvol(cdev, cdev->mixer.mixer_hw_id,
893                                ucontrol->value.integer.value);
894
895         pm_runtime_mark_last_busy(cdev->dev);
896         pm_runtime_put_autosuspend(cdev->dev);
897
898         return ret;
899 }
900
901 static int catpt_stream_volume_get(struct snd_kcontrol *kcontrol,
902                                    struct snd_ctl_elem_value *ucontrol,
903                                    enum catpt_pin_id pin_id)
904 {
905         struct snd_soc_component *component =
906                 snd_soc_kcontrol_component(kcontrol);
907         struct catpt_stream_runtime *stream;
908         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
909         long *ctlvol = (long *)kcontrol->private_value;
910         u32 dspvol;
911         int ret;
912         int i;
913
914         stream = catpt_stream_find(cdev, pin_id);
915         if (!stream) {
916                 for (i = 0; i < CATPT_CHANNELS_MAX; i++)
917                         ucontrol->value.integer.value[i] = ctlvol[i];
918                 return 0;
919         }
920
921         ret = pm_runtime_resume_and_get(cdev->dev);
922         if (ret < 0 && ret != -EACCES)
923                 return ret;
924
925         for (i = 0; i < CATPT_CHANNELS_MAX; i++) {
926                 dspvol = catpt_stream_volume(cdev, stream, i);
927                 ucontrol->value.integer.value[i] = dspvol_to_ctlvol(dspvol);
928         }
929
930         pm_runtime_mark_last_busy(cdev->dev);
931         pm_runtime_put_autosuspend(cdev->dev);
932
933         return 0;
934 }
935
936 static int catpt_stream_volume_put(struct snd_kcontrol *kcontrol,
937                                    struct snd_ctl_elem_value *ucontrol,
938                                    enum catpt_pin_id pin_id)
939 {
940         struct snd_soc_component *component =
941                 snd_soc_kcontrol_component(kcontrol);
942         struct catpt_stream_runtime *stream;
943         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
944         long *ctlvol = (long *)kcontrol->private_value;
945         int ret, i;
946
947         stream = catpt_stream_find(cdev, pin_id);
948         if (!stream) {
949                 for (i = 0; i < CATPT_CHANNELS_MAX; i++)
950                         ctlvol[i] = ucontrol->value.integer.value[i];
951                 return 0;
952         }
953
954         ret = pm_runtime_resume_and_get(cdev->dev);
955         if (ret < 0 && ret != -EACCES)
956                 return ret;
957
958         ret = catpt_set_dspvol(cdev, stream->info.stream_hw_id,
959                                ucontrol->value.integer.value);
960
961         pm_runtime_mark_last_busy(cdev->dev);
962         pm_runtime_put_autosuspend(cdev->dev);
963
964         if (ret)
965                 return ret;
966
967         for (i = 0; i < CATPT_CHANNELS_MAX; i++)
968                 ctlvol[i] = ucontrol->value.integer.value[i];
969         return 0;
970 }
971
972 static int catpt_offload1_volume_get(struct snd_kcontrol *kctl,
973                                      struct snd_ctl_elem_value *uctl)
974 {
975         return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_OFFLOAD1);
976 }
977
978 static int catpt_offload1_volume_put(struct snd_kcontrol *kctl,
979                                      struct snd_ctl_elem_value *uctl)
980 {
981         return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_OFFLOAD1);
982 }
983
984 static int catpt_offload2_volume_get(struct snd_kcontrol *kctl,
985                                      struct snd_ctl_elem_value *uctl)
986 {
987         return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_OFFLOAD2);
988 }
989
990 static int catpt_offload2_volume_put(struct snd_kcontrol *kctl,
991                                      struct snd_ctl_elem_value *uctl)
992 {
993         return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_OFFLOAD2);
994 }
995
996 static int catpt_capture_volume_get(struct snd_kcontrol *kctl,
997                                     struct snd_ctl_elem_value *uctl)
998 {
999         return catpt_stream_volume_get(kctl, uctl, CATPT_PIN_ID_CAPTURE1);
1000 }
1001
1002 static int catpt_capture_volume_put(struct snd_kcontrol *kctl,
1003                                     struct snd_ctl_elem_value *uctl)
1004 {
1005         return catpt_stream_volume_put(kctl, uctl, CATPT_PIN_ID_CAPTURE1);
1006 }
1007
1008 static int catpt_loopback_switch_get(struct snd_kcontrol *kcontrol,
1009                                      struct snd_ctl_elem_value *ucontrol)
1010 {
1011         ucontrol->value.integer.value[0] = *(bool *)kcontrol->private_value;
1012         return 0;
1013 }
1014
1015 static int catpt_loopback_switch_put(struct snd_kcontrol *kcontrol,
1016                                      struct snd_ctl_elem_value *ucontrol)
1017 {
1018         struct snd_soc_component *component =
1019                 snd_soc_kcontrol_component(kcontrol);
1020         struct catpt_stream_runtime *stream;
1021         struct catpt_dev *cdev = dev_get_drvdata(component->dev);
1022         bool mute;
1023         int ret;
1024
1025         mute = (bool)ucontrol->value.integer.value[0];
1026         stream = catpt_stream_find(cdev, CATPT_PIN_ID_REFERENCE);
1027         if (!stream) {
1028                 *(bool *)kcontrol->private_value = mute;
1029                 return 0;
1030         }
1031
1032         ret = pm_runtime_resume_and_get(cdev->dev);
1033         if (ret < 0 && ret != -EACCES)
1034                 return ret;
1035
1036         ret = catpt_ipc_mute_loopback(cdev, stream->info.stream_hw_id, mute);
1037
1038         pm_runtime_mark_last_busy(cdev->dev);
1039         pm_runtime_put_autosuspend(cdev->dev);
1040
1041         if (ret)
1042                 return CATPT_IPC_ERROR(ret);
1043
1044         *(bool *)kcontrol->private_value = mute;
1045         return 0;
1046 }
1047
1048 static int catpt_waves_switch_get(struct snd_kcontrol *kcontrol,
1049                                   struct snd_ctl_elem_value *ucontrol)
1050 {
1051         return 0;
1052 }
1053
1054 static int catpt_waves_switch_put(struct snd_kcontrol *kcontrol,
1055                                   struct snd_ctl_elem_value *ucontrol)
1056 {
1057         return 0;
1058 }
1059
1060 static int catpt_waves_param_get(struct snd_kcontrol *kcontrol,
1061                                  unsigned int __user *bytes,
1062                                  unsigned int size)
1063 {
1064         return 0;
1065 }
1066
1067 static int catpt_waves_param_put(struct snd_kcontrol *kcontrol,
1068                                  const unsigned int __user *bytes,
1069                                  unsigned int size)
1070 {
1071         return 0;
1072 }
1073
1074 static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1);
1075
1076 #define CATPT_VOLUME_CTL(kname, sname) \
1077 {       .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1078         .name = (kname), \
1079         .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
1080                   SNDRV_CTL_ELEM_ACCESS_READWRITE, \
1081         .info = catpt_volume_info, \
1082         .get = catpt_##sname##_volume_get, \
1083         .put = catpt_##sname##_volume_put, \
1084         .tlv.p = catpt_volume_tlv, \
1085         .private_value = (unsigned long) \
1086                 &(long[CATPT_CHANNELS_MAX]) {0} }
1087
1088 static const struct snd_kcontrol_new component_kcontrols[] = {
1089 /* Master volume (mixer stream) */
1090 CATPT_VOLUME_CTL("Master Playback Volume", mixer),
1091 /* Individual volume controls for offload and capture */
1092 CATPT_VOLUME_CTL("Media0 Playback Volume", offload1),
1093 CATPT_VOLUME_CTL("Media1 Playback Volume", offload2),
1094 CATPT_VOLUME_CTL("Mic Capture Volume", capture),
1095 SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&(bool[1]) {0},
1096                     catpt_loopback_switch_get, catpt_loopback_switch_put),
1097 /* Enable or disable WAVES module */
1098 SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
1099                     catpt_waves_switch_get, catpt_waves_switch_put),
1100 /* WAVES module parameter control */
1101 SND_SOC_BYTES_TLV("Waves Set Param", 128,
1102                   catpt_waves_param_get, catpt_waves_param_put),
1103 };
1104
1105 static const struct snd_soc_dapm_widget component_widgets[] = {
1106         SND_SOC_DAPM_AIF_IN("SSP0 CODEC IN", NULL, 0, SND_SOC_NOPM, 0, 0),
1107         SND_SOC_DAPM_AIF_OUT("SSP0 CODEC OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
1108         SND_SOC_DAPM_AIF_IN("SSP1 BT IN", NULL, 0, SND_SOC_NOPM, 0, 0),
1109         SND_SOC_DAPM_AIF_OUT("SSP1 BT OUT", NULL, 0, SND_SOC_NOPM, 0, 0),
1110
1111         SND_SOC_DAPM_MIXER("Playback VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1112 };
1113
1114 static const struct snd_soc_dapm_route component_routes[] = {
1115         {"Playback VMixer", NULL, "System Playback"},
1116         {"Playback VMixer", NULL, "Offload0 Playback"},
1117         {"Playback VMixer", NULL, "Offload1 Playback"},
1118
1119         {"SSP0 CODEC OUT", NULL, "Playback VMixer"},
1120
1121         {"Analog Capture", NULL, "SSP0 CODEC IN"},
1122         {"Loopback Capture", NULL, "SSP0 CODEC IN"},
1123
1124         {"SSP1 BT OUT", NULL, "Bluetooth Playback"},
1125         {"Bluetooth Capture", NULL, "SSP1 BT IN"},
1126 };
1127
1128 static const struct snd_soc_component_driver catpt_comp_driver = {
1129         .name = "catpt-platform",
1130
1131         .pcm_construct = catpt_component_pcm_construct,
1132         .open = catpt_component_open,
1133         .pointer = catpt_component_pointer,
1134
1135         .controls = component_kcontrols,
1136         .num_controls = ARRAY_SIZE(component_kcontrols),
1137         .dapm_widgets = component_widgets,
1138         .num_dapm_widgets = ARRAY_SIZE(component_widgets),
1139         .dapm_routes = component_routes,
1140         .num_dapm_routes = ARRAY_SIZE(component_routes),
1141 };
1142
1143 int catpt_arm_stream_templates(struct catpt_dev *cdev)
1144 {
1145         struct resource *res;
1146         u32 scratch_size = 0;
1147         int i, j;
1148
1149         for (i = 0; i < ARRAY_SIZE(catpt_topology); i++) {
1150                 struct catpt_stream_template *template;
1151                 struct catpt_module_entry *entry;
1152                 struct catpt_module_type *type;
1153
1154                 template = catpt_topology[i];
1155                 template->persistent_size = 0;
1156
1157                 for (j = 0; j < template->num_entries; j++) {
1158                         entry = &template->entries[j];
1159                         type = &cdev->modules[entry->module_id];
1160
1161                         if (!type->loaded)
1162                                 return -ENOENT;
1163
1164                         entry->entry_point = type->entry_point;
1165                         template->persistent_size += type->persistent_size;
1166                         if (type->scratch_size > scratch_size)
1167                                 scratch_size = type->scratch_size;
1168                 }
1169         }
1170
1171         if (scratch_size) {
1172                 /* allocate single scratch area for all modules */
1173                 res = catpt_request_region(&cdev->dram, scratch_size);
1174                 if (!res)
1175                         return -EBUSY;
1176                 cdev->scratch = res;
1177         }
1178
1179         return 0;
1180 }
1181
1182 int catpt_register_plat_component(struct catpt_dev *cdev)
1183 {
1184         struct snd_soc_component *component;
1185         int ret;
1186
1187         component = devm_kzalloc(cdev->dev, sizeof(*component), GFP_KERNEL);
1188         if (!component)
1189                 return -ENOMEM;
1190
1191         ret = snd_soc_component_initialize(component, &catpt_comp_driver,
1192                                            cdev->dev);
1193         if (ret)
1194                 return ret;
1195
1196         component->name = catpt_comp_driver.name;
1197         return snd_soc_add_component(component, dai_drivers,
1198                                      ARRAY_SIZE(dai_drivers));
1199 }