Merge tag 'pull-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / sound / soc / qcom / lpass-platform.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
4  *
5  * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
6  */
7
8 #include <linux/dma-mapping.h>
9 #include <linux/export.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/platform_device.h>
13 #include <sound/pcm_params.h>
14 #include <linux/regmap.h>
15 #include <sound/soc.h>
16 #include "lpass-lpaif-reg.h"
17 #include "lpass.h"
18
19 #define DRV_NAME "lpass-platform"
20
21 #define LPASS_PLATFORM_BUFFER_SIZE      (24 *  2 * 1024)
22 #define LPASS_PLATFORM_PERIODS          2
23 #define LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE (8 * 1024)
24 #define LPASS_VA_CDC_DMA_LPM_BUFF_SIZE (12 * 1024)
25 #define LPASS_CDC_DMA_REGISTER_FIELDS_MAX 15
26
27 static const struct snd_pcm_hardware lpass_platform_pcm_hardware = {
28         .info                   =       SNDRV_PCM_INFO_MMAP |
29                                         SNDRV_PCM_INFO_MMAP_VALID |
30                                         SNDRV_PCM_INFO_INTERLEAVED |
31                                         SNDRV_PCM_INFO_PAUSE |
32                                         SNDRV_PCM_INFO_RESUME,
33         .formats                =       SNDRV_PCM_FMTBIT_S16 |
34                                         SNDRV_PCM_FMTBIT_S24 |
35                                         SNDRV_PCM_FMTBIT_S32,
36         .rates                  =       SNDRV_PCM_RATE_8000_192000,
37         .rate_min               =       8000,
38         .rate_max               =       192000,
39         .channels_min           =       1,
40         .channels_max           =       8,
41         .buffer_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE,
42         .period_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE /
43                                                 LPASS_PLATFORM_PERIODS,
44         .period_bytes_min       =       LPASS_PLATFORM_BUFFER_SIZE /
45                                                 LPASS_PLATFORM_PERIODS,
46         .periods_min            =       LPASS_PLATFORM_PERIODS,
47         .periods_max            =       LPASS_PLATFORM_PERIODS,
48         .fifo_size              =       0,
49 };
50
51 static const struct snd_pcm_hardware lpass_platform_rxtx_hardware = {
52         .info                   =       SNDRV_PCM_INFO_MMAP |
53                                         SNDRV_PCM_INFO_MMAP_VALID |
54                                         SNDRV_PCM_INFO_INTERLEAVED |
55                                         SNDRV_PCM_INFO_PAUSE |
56                                         SNDRV_PCM_INFO_RESUME,
57         .formats                =       SNDRV_PCM_FMTBIT_S16 |
58                                         SNDRV_PCM_FMTBIT_S24 |
59                                         SNDRV_PCM_FMTBIT_S32,
60         .rates                  =       SNDRV_PCM_RATE_8000_192000,
61         .rate_min               =       8000,
62         .rate_max               =       192000,
63         .channels_min           =       1,
64         .channels_max           =       8,
65         .buffer_bytes_max       =       LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE,
66         .period_bytes_max       =       LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE /
67                                                 LPASS_PLATFORM_PERIODS,
68         .period_bytes_min       =       LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE /
69                                                 LPASS_PLATFORM_PERIODS,
70         .periods_min            =       LPASS_PLATFORM_PERIODS,
71         .periods_max            =       LPASS_PLATFORM_PERIODS,
72         .fifo_size              =       0,
73 };
74
75 static const struct snd_pcm_hardware lpass_platform_va_hardware = {
76         .info                   =       SNDRV_PCM_INFO_MMAP |
77                                         SNDRV_PCM_INFO_MMAP_VALID |
78                                         SNDRV_PCM_INFO_INTERLEAVED |
79                                         SNDRV_PCM_INFO_PAUSE |
80                                         SNDRV_PCM_INFO_RESUME,
81         .formats                =       SNDRV_PCM_FMTBIT_S16 |
82                                         SNDRV_PCM_FMTBIT_S24 |
83                                         SNDRV_PCM_FMTBIT_S32,
84         .rates                  =       SNDRV_PCM_RATE_8000_192000,
85         .rate_min               =       8000,
86         .rate_max               =       192000,
87         .channels_min           =       1,
88         .channels_max           =       8,
89         .buffer_bytes_max       =       LPASS_VA_CDC_DMA_LPM_BUFF_SIZE,
90         .period_bytes_max       =       LPASS_VA_CDC_DMA_LPM_BUFF_SIZE /
91                                                 LPASS_PLATFORM_PERIODS,
92         .period_bytes_min       =       LPASS_VA_CDC_DMA_LPM_BUFF_SIZE /
93                                                 LPASS_PLATFORM_PERIODS,
94         .periods_min            =       LPASS_PLATFORM_PERIODS,
95         .periods_max            =       LPASS_PLATFORM_PERIODS,
96         .fifo_size              =       0,
97 };
98
99 static int lpass_platform_alloc_rxtx_dmactl_fields(struct device *dev,
100                                          struct regmap *map)
101 {
102         struct lpass_data *drvdata = dev_get_drvdata(dev);
103         struct lpass_variant *v = drvdata->variant;
104         struct lpaif_dmactl *rd_dmactl, *wr_dmactl;
105         int rval;
106
107         rd_dmactl = devm_kzalloc(dev, sizeof(*rd_dmactl), GFP_KERNEL);
108         if (!rd_dmactl)
109                 return -ENOMEM;
110
111         wr_dmactl = devm_kzalloc(dev, sizeof(*wr_dmactl), GFP_KERNEL);
112         if (!wr_dmactl)
113                 return -ENOMEM;
114
115         drvdata->rxtx_rd_dmactl = rd_dmactl;
116         drvdata->rxtx_wr_dmactl = wr_dmactl;
117
118         rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
119                                             &v->rxtx_rdma_intf, LPASS_CDC_DMA_REGISTER_FIELDS_MAX);
120         if (rval)
121                 return rval;
122
123         return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
124                                             &v->rxtx_wrdma_intf, LPASS_CDC_DMA_REGISTER_FIELDS_MAX);
125 }
126
127 static int lpass_platform_alloc_va_dmactl_fields(struct device *dev,
128                                          struct regmap *map)
129 {
130         struct lpass_data *drvdata = dev_get_drvdata(dev);
131         struct lpass_variant *v = drvdata->variant;
132         struct lpaif_dmactl *wr_dmactl;
133
134         wr_dmactl = devm_kzalloc(dev, sizeof(*wr_dmactl), GFP_KERNEL);
135         if (!wr_dmactl)
136                 return -ENOMEM;
137
138         drvdata->va_wr_dmactl = wr_dmactl;
139         return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
140                                             &v->va_wrdma_intf, LPASS_CDC_DMA_REGISTER_FIELDS_MAX);
141 }
142
143
144 static int lpass_platform_alloc_dmactl_fields(struct device *dev,
145                                          struct regmap *map)
146 {
147         struct lpass_data *drvdata = dev_get_drvdata(dev);
148         struct lpass_variant *v = drvdata->variant;
149         struct lpaif_dmactl *rd_dmactl, *wr_dmactl;
150         int rval;
151
152         drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
153                                           GFP_KERNEL);
154         if (drvdata->rd_dmactl == NULL)
155                 return -ENOMEM;
156
157         drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
158                                           GFP_KERNEL);
159         if (drvdata->wr_dmactl == NULL)
160                 return -ENOMEM;
161
162         rd_dmactl = drvdata->rd_dmactl;
163         wr_dmactl = drvdata->wr_dmactl;
164
165         rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
166                                             &v->rdma_intf, 6);
167         if (rval)
168                 return rval;
169
170         return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
171                                             &v->wrdma_intf, 6);
172 }
173
174 static int lpass_platform_alloc_hdmidmactl_fields(struct device *dev,
175                                          struct regmap *map)
176 {
177         struct lpass_data *drvdata = dev_get_drvdata(dev);
178         struct lpass_variant *v = drvdata->variant;
179         struct lpaif_dmactl *rd_dmactl;
180
181         rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), GFP_KERNEL);
182         if (rd_dmactl == NULL)
183                 return -ENOMEM;
184
185         drvdata->hdmi_rd_dmactl = rd_dmactl;
186
187         return devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->bursten,
188                                             &v->hdmi_rdma_bursten, 8);
189 }
190
191 static int lpass_platform_pcmops_open(struct snd_soc_component *component,
192                                       struct snd_pcm_substream *substream)
193 {
194         struct snd_pcm_runtime *runtime = substream->runtime;
195         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
196         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
197         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
198         struct lpass_variant *v = drvdata->variant;
199         int ret, dma_ch, dir = substream->stream;
200         struct lpass_pcm_data *data;
201         struct regmap *map;
202         unsigned int dai_id = cpu_dai->driver->id;
203
204         component->id = dai_id;
205         data = kzalloc(sizeof(*data), GFP_KERNEL);
206         if (!data)
207                 return -ENOMEM;
208
209         data->i2s_port = cpu_dai->driver->id;
210         runtime->private_data = data;
211
212         if (v->alloc_dma_channel)
213                 dma_ch = v->alloc_dma_channel(drvdata, dir, dai_id);
214         else
215                 dma_ch = 0;
216
217         if (dma_ch < 0) {
218                 kfree(data);
219                 return dma_ch;
220         }
221
222         switch (dai_id) {
223         case MI2S_PRIMARY ... MI2S_QUINARY:
224                 map = drvdata->lpaif_map;
225                 drvdata->substream[dma_ch] = substream;
226                 break;
227         case LPASS_DP_RX:
228                 map = drvdata->hdmiif_map;
229                 drvdata->hdmi_substream[dma_ch] = substream;
230                 break;
231         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
232         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
233                 map = drvdata->rxtx_lpaif_map;
234                 drvdata->rxtx_substream[dma_ch] = substream;
235                 break;
236         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
237                 map = drvdata->va_lpaif_map;
238                 drvdata->va_substream[dma_ch] = substream;
239                 break;
240         default:
241                 break;
242         }
243
244         data->dma_ch = dma_ch;
245         switch (dai_id) {
246         case MI2S_PRIMARY ... MI2S_QUINARY:
247         case LPASS_DP_RX:
248                 ret = regmap_write(map, LPAIF_DMACTL_REG(v, dma_ch, dir, data->i2s_port), 0);
249                 if (ret) {
250                         kfree(data);
251                         dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret);
252                         return ret;
253                 }
254                 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
255                 runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
256                 break;
257         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
258         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
259                 snd_soc_set_runtime_hwparams(substream, &lpass_platform_rxtx_hardware);
260                 runtime->dma_bytes = lpass_platform_rxtx_hardware.buffer_bytes_max;
261                 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
262                 break;
263         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
264                 snd_soc_set_runtime_hwparams(substream, &lpass_platform_va_hardware);
265                 runtime->dma_bytes = lpass_platform_va_hardware.buffer_bytes_max;
266                 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
267                 break;
268         default:
269                 break;
270         }
271         ret = snd_pcm_hw_constraint_integer(runtime,
272                         SNDRV_PCM_HW_PARAM_PERIODS);
273         if (ret < 0) {
274                 kfree(data);
275                 dev_err(soc_runtime->dev, "setting constraints failed: %d\n",
276                         ret);
277                 return -EINVAL;
278         }
279
280         return 0;
281 }
282
283 static int lpass_platform_pcmops_close(struct snd_soc_component *component,
284                                        struct snd_pcm_substream *substream)
285 {
286         struct snd_pcm_runtime *runtime = substream->runtime;
287         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
288         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
289         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
290         struct lpass_variant *v = drvdata->variant;
291         struct lpass_pcm_data *data;
292         unsigned int dai_id = cpu_dai->driver->id;
293
294         data = runtime->private_data;
295
296         switch (dai_id) {
297         case MI2S_PRIMARY ... MI2S_QUINARY:
298                 drvdata->substream[data->dma_ch] = NULL;
299                 break;
300         case LPASS_DP_RX:
301                 drvdata->hdmi_substream[data->dma_ch] = NULL;
302                 break;
303         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
304         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
305                 drvdata->rxtx_substream[data->dma_ch] = NULL;
306                 break;
307         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
308                 drvdata->va_substream[data->dma_ch] = NULL;
309                 break;
310         default:
311                 break;
312         }
313
314         if (v->free_dma_channel)
315                 v->free_dma_channel(drvdata, data->dma_ch, dai_id);
316
317         kfree(data);
318         return 0;
319 }
320
321 static struct lpaif_dmactl *__lpass_get_dmactl_handle(const struct snd_pcm_substream *substream,
322                                      struct snd_soc_component *component)
323 {
324         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
325         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
326         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
327         struct lpaif_dmactl *dmactl = NULL;
328
329         switch (cpu_dai->driver->id) {
330         case MI2S_PRIMARY ... MI2S_QUINARY:
331                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
332                         dmactl = drvdata->rd_dmactl;
333                 else
334                         dmactl = drvdata->wr_dmactl;
335                 break;
336         case LPASS_DP_RX:
337                 dmactl = drvdata->hdmi_rd_dmactl;
338                 break;
339         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
340                 dmactl = drvdata->rxtx_rd_dmactl;
341                 break;
342         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
343                 dmactl = drvdata->rxtx_wr_dmactl;
344                 break;
345         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
346                 dmactl = drvdata->va_wr_dmactl;
347                 break;
348         }
349
350         return dmactl;
351 }
352
353 static int __lpass_get_id(const struct snd_pcm_substream *substream,
354                                      struct snd_soc_component *component)
355 {
356         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
357         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
358         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
359         struct snd_pcm_runtime *rt = substream->runtime;
360         struct lpass_pcm_data *pcm_data = rt->private_data;
361         struct lpass_variant *v = drvdata->variant;
362         int id;
363
364         switch (cpu_dai->driver->id) {
365         case MI2S_PRIMARY ... MI2S_QUINARY:
366                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
367                         id = pcm_data->dma_ch;
368                 else
369                         id = pcm_data->dma_ch - v->wrdma_channel_start;
370                 break;
371         case LPASS_DP_RX:
372                 id = pcm_data->dma_ch;
373                 break;
374         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
375                 id = pcm_data->dma_ch;
376                 break;
377         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
378                 id = pcm_data->dma_ch - v->rxtx_wrdma_channel_start;
379                 break;
380         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
381                 id = pcm_data->dma_ch - v->va_wrdma_channel_start;
382                 break;
383         }
384
385         return id;
386 }
387
388 static struct regmap *__lpass_get_regmap_handle(const struct snd_pcm_substream *substream,
389                                      struct snd_soc_component *component)
390 {
391         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
392         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
393         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
394         struct regmap *map = NULL;
395
396         switch (cpu_dai->driver->id) {
397         case MI2S_PRIMARY ... MI2S_QUINARY:
398                 map = drvdata->lpaif_map;
399                 break;
400         case LPASS_DP_RX:
401                 map = drvdata->hdmiif_map;
402                 break;
403         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
404         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
405                 map = drvdata->rxtx_lpaif_map;
406                 break;
407         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
408                 map = drvdata->va_lpaif_map;
409                 break;
410         }
411
412         return map;
413 }
414
415 static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
416                                            struct snd_pcm_substream *substream,
417                                            struct snd_pcm_hw_params *params)
418 {
419         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
420         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
421         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
422         struct snd_pcm_runtime *rt = substream->runtime;
423         struct lpass_pcm_data *pcm_data = rt->private_data;
424         struct lpass_variant *v = drvdata->variant;
425         snd_pcm_format_t format = params_format(params);
426         unsigned int channels = params_channels(params);
427         unsigned int regval;
428         struct lpaif_dmactl *dmactl;
429         int id;
430         int bitwidth;
431         int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
432         unsigned int dai_id = cpu_dai->driver->id;
433
434         dmactl = __lpass_get_dmactl_handle(substream, component);
435         id = __lpass_get_id(substream, component);
436
437         bitwidth = snd_pcm_format_width(format);
438         if (bitwidth < 0) {
439                 dev_err(soc_runtime->dev, "invalid bit width given: %d\n",
440                                 bitwidth);
441                 return bitwidth;
442         }
443
444         ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
445         if (ret) {
446                 dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret);
447                 return ret;
448         }
449
450         ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
451         if (ret) {
452                 dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret);
453                 return ret;
454         }
455
456         switch (dai_id) {
457         case LPASS_DP_RX:
458                 ret = regmap_fields_write(dmactl->burst8, id,
459                                                         LPAIF_DMACTL_BURSTEN_INCR4);
460                 if (ret) {
461                         dev_err(soc_runtime->dev, "error updating burst8en field: %d\n", ret);
462                         return ret;
463                 }
464                 ret = regmap_fields_write(dmactl->burst16, id,
465                                                         LPAIF_DMACTL_BURSTEN_INCR4);
466                 if (ret) {
467                         dev_err(soc_runtime->dev, "error updating burst16en field: %d\n", ret);
468                         return ret;
469                 }
470                 ret = regmap_fields_write(dmactl->dynburst, id,
471                                                         LPAIF_DMACTL_BURSTEN_INCR4);
472                 if (ret) {
473                         dev_err(soc_runtime->dev, "error updating dynbursten field: %d\n", ret);
474                         return ret;
475                 }
476                 break;
477         case MI2S_PRIMARY:
478         case MI2S_SECONDARY:
479         case MI2S_TERTIARY:
480         case MI2S_QUATERNARY:
481         case MI2S_QUINARY:
482                 ret = regmap_fields_write(dmactl->intf, id,
483                                                 LPAIF_DMACTL_AUDINTF(dma_port));
484                 if (ret) {
485                         dev_err(soc_runtime->dev, "error updating audio interface field: %d\n",
486                                         ret);
487                         return ret;
488                 }
489
490                 break;
491         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
492         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
493         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX0:
494                 break;
495         default:
496                 dev_err(soc_runtime->dev, "%s: invalid  interface: %d\n", __func__, dai_id);
497                 break;
498         }
499         switch (bitwidth) {
500         case 16:
501                 switch (channels) {
502                 case 1:
503                 case 2:
504                         regval = LPAIF_DMACTL_WPSCNT_ONE;
505                         break;
506                 case 4:
507                         regval = LPAIF_DMACTL_WPSCNT_TWO;
508                         break;
509                 case 6:
510                         regval = LPAIF_DMACTL_WPSCNT_THREE;
511                         break;
512                 case 8:
513                         regval = LPAIF_DMACTL_WPSCNT_FOUR;
514                         break;
515                 default:
516                         dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
517                                 bitwidth, channels);
518                         return -EINVAL;
519                 }
520                 break;
521         case 24:
522         case 32:
523                 switch (channels) {
524                 case 1:
525                         regval = LPAIF_DMACTL_WPSCNT_ONE;
526                         break;
527                 case 2:
528                         regval = (dai_id == LPASS_DP_RX ?
529                         LPAIF_DMACTL_WPSCNT_ONE :
530                         LPAIF_DMACTL_WPSCNT_TWO);
531                         break;
532                 case 4:
533                         regval = (dai_id == LPASS_DP_RX ?
534                         LPAIF_DMACTL_WPSCNT_TWO :
535                         LPAIF_DMACTL_WPSCNT_FOUR);
536                         break;
537                 case 6:
538                         regval = (dai_id == LPASS_DP_RX ?
539                         LPAIF_DMACTL_WPSCNT_THREE :
540                         LPAIF_DMACTL_WPSCNT_SIX);
541                         break;
542                 case 8:
543                         regval = (dai_id == LPASS_DP_RX ?
544                         LPAIF_DMACTL_WPSCNT_FOUR :
545                         LPAIF_DMACTL_WPSCNT_EIGHT);
546                         break;
547                 default:
548                         dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
549                                 bitwidth, channels);
550                         return -EINVAL;
551                 }
552                 break;
553         default:
554                 dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
555                         bitwidth, channels);
556                 return -EINVAL;
557         }
558
559         ret = regmap_fields_write(dmactl->wpscnt, id, regval);
560         if (ret) {
561                 dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n",
562                         ret);
563                 return ret;
564         }
565
566         return 0;
567 }
568
569 static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component,
570                                          struct snd_pcm_substream *substream)
571 {
572         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
573         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
574         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
575         struct snd_pcm_runtime *rt = substream->runtime;
576         struct lpass_pcm_data *pcm_data = rt->private_data;
577         struct lpass_variant *v = drvdata->variant;
578         unsigned int reg;
579         int ret;
580         struct regmap *map;
581         unsigned int dai_id = cpu_dai->driver->id;
582
583         if (is_cdc_dma_port(dai_id))
584                 return 0;
585         map = __lpass_get_regmap_handle(substream, component);
586
587         reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream, dai_id);
588         ret = regmap_write(map, reg, 0);
589         if (ret)
590                 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
591                         ret);
592
593         return ret;
594 }
595
596 static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
597                                          struct snd_pcm_substream *substream)
598 {
599         struct snd_pcm_runtime *runtime = substream->runtime;
600         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
601         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
602         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
603         struct snd_pcm_runtime *rt = substream->runtime;
604         struct lpass_pcm_data *pcm_data = rt->private_data;
605         struct lpass_variant *v = drvdata->variant;
606         struct lpaif_dmactl *dmactl;
607         struct regmap *map;
608         int ret, id, ch, dir = substream->stream;
609         unsigned int dai_id = cpu_dai->driver->id;
610
611         ch = pcm_data->dma_ch;
612
613         dmactl = __lpass_get_dmactl_handle(substream, component);
614         id = __lpass_get_id(substream, component);
615         map = __lpass_get_regmap_handle(substream, component);
616
617         ret = regmap_write(map, LPAIF_DMABASE_REG(v, ch, dir, dai_id),
618                                 runtime->dma_addr);
619         if (ret) {
620                 dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n",
621                         ret);
622                 return ret;
623         }
624
625         ret = regmap_write(map, LPAIF_DMABUFF_REG(v, ch, dir, dai_id),
626                         (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
627         if (ret) {
628                 dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n",
629                         ret);
630                 return ret;
631         }
632
633         ret = regmap_write(map, LPAIF_DMAPER_REG(v, ch, dir, dai_id),
634                         (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
635         if (ret) {
636                 dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n",
637                         ret);
638                 return ret;
639         }
640
641         if (is_cdc_dma_port(dai_id)) {
642                 ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
643                 if (ret) {
644                         dev_err(soc_runtime->dev, "error writing fifowm field to dmactl reg: %d, id: %d\n",
645                                 ret, id);
646                         return ret;
647                 }
648         }
649         ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
650         if (ret) {
651                 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
652                         ret);
653                 return ret;
654         }
655
656         return 0;
657 }
658
659 static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
660                                          struct snd_pcm_substream *substream,
661                                          int cmd)
662 {
663         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
664         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
665         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
666         struct snd_pcm_runtime *rt = substream->runtime;
667         struct lpass_pcm_data *pcm_data = rt->private_data;
668         struct lpass_variant *v = drvdata->variant;
669         struct lpaif_dmactl *dmactl;
670         struct regmap *map;
671         int ret, ch, id;
672         unsigned int reg_irqclr = 0, val_irqclr = 0;
673         unsigned int  reg_irqen = 0, val_irqen = 0, val_mask = 0;
674         unsigned int dai_id = cpu_dai->driver->id;
675
676         ch = pcm_data->dma_ch;
677         dmactl = __lpass_get_dmactl_handle(substream, component);
678         id = __lpass_get_id(substream, component);
679         map = __lpass_get_regmap_handle(substream, component);
680
681         switch (cmd) {
682         case SNDRV_PCM_TRIGGER_START:
683         case SNDRV_PCM_TRIGGER_RESUME:
684         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
685                 ret = regmap_fields_write(dmactl->enable, id,
686                                                  LPAIF_DMACTL_ENABLE_ON);
687                 if (ret) {
688                         dev_err(soc_runtime->dev,
689                                 "error writing to rdmactl reg: %d\n", ret);
690                         return ret;
691                 }
692                 switch (dai_id) {
693                 case LPASS_DP_RX:
694                         ret = regmap_fields_write(dmactl->dyncclk, id,
695                                          LPAIF_DMACTL_DYNCLK_ON);
696                         if (ret) {
697                                 dev_err(soc_runtime->dev,
698                                         "error writing to rdmactl reg: %d\n", ret);
699                                 return ret;
700                         }
701                         reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v);
702                         val_irqclr = (LPAIF_IRQ_ALL(ch) |
703                                         LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
704                                         LPAIF_IRQ_HDMI_METADONE |
705                                         LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
706
707                         reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v);
708                         val_mask = (LPAIF_IRQ_ALL(ch) |
709                                         LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
710                                         LPAIF_IRQ_HDMI_METADONE |
711                                         LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
712                         val_irqen = (LPAIF_IRQ_ALL(ch) |
713                                         LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
714                                         LPAIF_IRQ_HDMI_METADONE |
715                                         LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
716                         break;
717                 case MI2S_PRIMARY:
718                 case MI2S_SECONDARY:
719                 case MI2S_TERTIARY:
720                 case MI2S_QUATERNARY:
721                 case MI2S_QUINARY:
722                         reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
723                         val_irqclr = LPAIF_IRQ_ALL(ch);
724
725
726                         reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
727                         val_mask = LPAIF_IRQ_ALL(ch);
728                         val_irqen = LPAIF_IRQ_ALL(ch);
729                         break;
730                 case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
731                 case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
732                         ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_ON);
733                         if (ret) {
734                                 dev_err(soc_runtime->dev,
735                                         "error writing to rdmactl reg field: %d\n", ret);
736                                 return ret;
737                         }
738                         reg_irqclr = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
739                         val_irqclr = LPAIF_IRQ_ALL(ch);
740
741                         reg_irqen = LPAIF_RXTX_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
742                         val_mask = LPAIF_IRQ_ALL(ch);
743                         val_irqen = LPAIF_IRQ_ALL(ch);
744                         break;
745                 case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
746                         ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_ON);
747                         if (ret) {
748                                 dev_err(soc_runtime->dev,
749                                         "error writing to rdmactl reg field: %d\n", ret);
750                                 return ret;
751                         }
752                         reg_irqclr = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
753                         val_irqclr = LPAIF_IRQ_ALL(ch);
754
755                         reg_irqen = LPAIF_VA_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
756                         val_mask = LPAIF_IRQ_ALL(ch);
757                         val_irqen = LPAIF_IRQ_ALL(ch);
758                         break;
759                 default:
760                         dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
761                         return -EINVAL;
762                 }
763
764                 ret = regmap_write_bits(map, reg_irqclr, val_irqclr, val_irqclr);
765                 if (ret) {
766                         dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret);
767                         return ret;
768                 }
769                 ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
770                 if (ret) {
771                         dev_err(soc_runtime->dev, "error writing to irqen reg: %d\n", ret);
772                         return ret;
773                 }
774                 break;
775         case SNDRV_PCM_TRIGGER_STOP:
776         case SNDRV_PCM_TRIGGER_SUSPEND:
777         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
778                 ret = regmap_fields_write(dmactl->enable, id,
779                                          LPAIF_DMACTL_ENABLE_OFF);
780                 if (ret) {
781                         dev_err(soc_runtime->dev,
782                                 "error writing to rdmactl reg: %d\n", ret);
783                         return ret;
784                 }
785                 switch (dai_id) {
786                 case LPASS_DP_RX:
787                         ret = regmap_fields_write(dmactl->dyncclk, id,
788                                          LPAIF_DMACTL_DYNCLK_OFF);
789                         if (ret) {
790                                 dev_err(soc_runtime->dev,
791                                         "error writing to rdmactl reg: %d\n", ret);
792                                 return ret;
793                         }
794                         reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v);
795                         val_mask = (LPAIF_IRQ_ALL(ch) |
796                                         LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) |
797                                         LPAIF_IRQ_HDMI_METADONE |
798                                         LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch));
799                         val_irqen = 0;
800                         break;
801                 case MI2S_PRIMARY:
802                 case MI2S_SECONDARY:
803                 case MI2S_TERTIARY:
804                 case MI2S_QUATERNARY:
805                 case MI2S_QUINARY:
806                         reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
807                         val_mask = LPAIF_IRQ_ALL(ch);
808                         val_irqen = 0;
809                         break;
810                 case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
811                 case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
812                         ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_OFF);
813                         if (ret) {
814                                 dev_err(soc_runtime->dev,
815                                         "error writing to rdmactl reg field: %d\n", ret);
816                                 return ret;
817                         }
818
819                         reg_irqclr = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
820                         val_irqclr = LPAIF_IRQ_ALL(ch);
821
822                         reg_irqen = LPAIF_RXTX_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
823                         val_mask = LPAIF_IRQ_ALL(ch);
824                         val_irqen = LPAIF_IRQ_ALL(ch);
825                         break;
826                 case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
827                         ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_OFF);
828                         if (ret) {
829                                 dev_err(soc_runtime->dev,
830                                         "error writing to rdmactl reg field: %d\n", ret);
831                                 return ret;
832                         }
833
834                         reg_irqclr = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
835                         val_irqclr = LPAIF_IRQ_ALL(ch);
836
837                         reg_irqen = LPAIF_VA_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
838                         val_mask = LPAIF_IRQ_ALL(ch);
839                         val_irqen = LPAIF_IRQ_ALL(ch);
840                         break;
841                 default:
842                         dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
843                         return -EINVAL;
844                 }
845
846                 ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
847                 if (ret) {
848                         dev_err(soc_runtime->dev,
849                                 "error writing to irqen reg: %d\n", ret);
850                         return ret;
851                 }
852                 break;
853         }
854
855         return 0;
856 }
857
858 static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
859                 struct snd_soc_component *component,
860                 struct snd_pcm_substream *substream)
861 {
862         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
863         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
864         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
865         struct snd_pcm_runtime *rt = substream->runtime;
866         struct lpass_pcm_data *pcm_data = rt->private_data;
867         struct lpass_variant *v = drvdata->variant;
868         unsigned int base_addr, curr_addr;
869         int ret, ch, dir = substream->stream;
870         struct regmap *map;
871         unsigned int dai_id = cpu_dai->driver->id;
872
873         map = __lpass_get_regmap_handle(substream, component);
874         ch = pcm_data->dma_ch;
875
876         ret = regmap_read(map,
877                         LPAIF_DMABASE_REG(v, ch, dir, dai_id), &base_addr);
878         if (ret) {
879                 dev_err(soc_runtime->dev,
880                         "error reading from rdmabase reg: %d\n", ret);
881                 return ret;
882         }
883
884         ret = regmap_read(map,
885                         LPAIF_DMACURR_REG(v, ch, dir, dai_id), &curr_addr);
886         if (ret) {
887                 dev_err(soc_runtime->dev,
888                         "error reading from rdmacurr reg: %d\n", ret);
889                 return ret;
890         }
891
892         return bytes_to_frames(substream->runtime, curr_addr - base_addr);
893 }
894
895 static int lpass_platform_cdc_dma_mmap(struct snd_pcm_substream *substream,
896                                        struct vm_area_struct *vma)
897 {
898         struct snd_pcm_runtime *runtime = substream->runtime;
899         unsigned long size, offset;
900
901         vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
902         size = vma->vm_end - vma->vm_start;
903         offset = vma->vm_pgoff << PAGE_SHIFT;
904         return io_remap_pfn_range(vma, vma->vm_start,
905                         (runtime->dma_addr + offset) >> PAGE_SHIFT,
906                         size, vma->vm_page_prot);
907
908 }
909
910 static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
911                                       struct snd_pcm_substream *substream,
912                                       struct vm_area_struct *vma)
913 {
914         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
915         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
916         unsigned int dai_id = cpu_dai->driver->id;
917
918         if (is_cdc_dma_port(dai_id))
919                 return lpass_platform_cdc_dma_mmap(substream, vma);
920
921         return snd_pcm_lib_default_mmap(substream, vma);
922 }
923
924 static irqreturn_t lpass_dma_interrupt_handler(
925                         struct snd_pcm_substream *substream,
926                         struct lpass_data *drvdata,
927                         int chan, u32 interrupts)
928 {
929         struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream);
930         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
931         struct lpass_variant *v = drvdata->variant;
932         irqreturn_t ret = IRQ_NONE;
933         int rv;
934         unsigned int reg, val, mask;
935         struct regmap *map;
936         unsigned int dai_id = cpu_dai->driver->id;
937
938         mask = LPAIF_IRQ_ALL(chan);
939         switch (dai_id) {
940         case LPASS_DP_RX:
941                 map = drvdata->hdmiif_map;
942                 reg = LPASS_HDMITX_APP_IRQCLEAR_REG(v);
943                 val = (LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
944                 LPAIF_IRQ_HDMI_METADONE |
945                 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan));
946         break;
947         case MI2S_PRIMARY:
948         case MI2S_SECONDARY:
949         case MI2S_TERTIARY:
950         case MI2S_QUATERNARY:
951         case MI2S_QUINARY:
952                 map = drvdata->lpaif_map;
953                 reg = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
954                 val = 0;
955         break;
956         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
957         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
958                 map = drvdata->rxtx_lpaif_map;
959                 reg = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
960                 val = 0;
961         break;
962         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
963                 map = drvdata->va_lpaif_map;
964                 reg = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
965                 val = 0;
966         break;
967         default:
968         dev_err(soc_runtime->dev, "%s: invalid  %d interface\n", __func__, dai_id);
969         return -EINVAL;
970         }
971         if (interrupts & LPAIF_IRQ_PER(chan)) {
972                 rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val));
973                 if (rv) {
974                         dev_err(soc_runtime->dev,
975                                 "error writing to irqclear reg: %d\n", rv);
976                         return IRQ_NONE;
977                 }
978                 snd_pcm_period_elapsed(substream);
979                 ret = IRQ_HANDLED;
980         }
981
982         if (interrupts & LPAIF_IRQ_XRUN(chan)) {
983                 rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val));
984                 if (rv) {
985                         dev_err(soc_runtime->dev,
986                                 "error writing to irqclear reg: %d\n", rv);
987                         return IRQ_NONE;
988                 }
989                 dev_warn_ratelimited(soc_runtime->dev, "xrun warning\n");
990
991                 snd_pcm_stop_xrun(substream);
992                 ret = IRQ_HANDLED;
993         }
994
995         if (interrupts & LPAIF_IRQ_ERR(chan)) {
996                 rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val));
997                 if (rv) {
998                         dev_err(soc_runtime->dev,
999                                 "error writing to irqclear reg: %d\n", rv);
1000                         return IRQ_NONE;
1001                 }
1002                 dev_err(soc_runtime->dev, "bus access error\n");
1003                 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
1004                 ret = IRQ_HANDLED;
1005         }
1006
1007         if (interrupts & val) {
1008                 rv = regmap_write(map, reg, val);
1009                 if (rv) {
1010                         dev_err(soc_runtime->dev,
1011                         "error writing to irqclear reg: %d\n", rv);
1012                         return IRQ_NONE;
1013                 }
1014                 ret = IRQ_HANDLED;
1015         }
1016
1017         return ret;
1018 }
1019
1020 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
1021 {
1022         struct lpass_data *drvdata = data;
1023         struct lpass_variant *v = drvdata->variant;
1024         unsigned int irqs;
1025         int rv, chan;
1026
1027         rv = regmap_read(drvdata->lpaif_map,
1028                         LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1029         if (rv) {
1030                 pr_err("error reading from irqstat reg: %d\n", rv);
1031                 return IRQ_NONE;
1032         }
1033
1034         /* Handle per channel interrupts */
1035         for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) {
1036                 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) {
1037                         rv = lpass_dma_interrupt_handler(
1038                                                 drvdata->substream[chan],
1039                                                 drvdata, chan, irqs);
1040                         if (rv != IRQ_HANDLED)
1041                                 return rv;
1042                 }
1043         }
1044
1045         return IRQ_HANDLED;
1046 }
1047
1048 static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data)
1049 {
1050         struct lpass_data *drvdata = data;
1051         struct lpass_variant *v = drvdata->variant;
1052         unsigned int irqs;
1053         int rv, chan;
1054
1055         rv = regmap_read(drvdata->hdmiif_map,
1056                         LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs);
1057         if (rv) {
1058                 pr_err("error reading from irqstat reg: %d\n", rv);
1059                 return IRQ_NONE;
1060         }
1061
1062         /* Handle per channel interrupts */
1063         for (chan = 0; chan < LPASS_MAX_HDMI_DMA_CHANNELS; chan++) {
1064                 if (irqs & (LPAIF_IRQ_ALL(chan) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) |
1065                                 LPAIF_IRQ_HDMI_METADONE |
1066                                 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan))
1067                         && drvdata->hdmi_substream[chan]) {
1068                         rv = lpass_dma_interrupt_handler(
1069                                                 drvdata->hdmi_substream[chan],
1070                                                 drvdata, chan, irqs);
1071                         if (rv != IRQ_HANDLED)
1072                                 return rv;
1073                 }
1074         }
1075         return IRQ_HANDLED;
1076 }
1077
1078 static irqreturn_t lpass_platform_rxtxif_irq(int irq, void *data)
1079 {
1080         struct lpass_data *drvdata = data;
1081         struct lpass_variant *v = drvdata->variant;
1082         unsigned int irqs;
1083         irqreturn_t rv;
1084         int chan;
1085
1086         rv = regmap_read(drvdata->rxtx_lpaif_map,
1087                         LPAIF_RXTX_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1088
1089         /* Handle per channel interrupts */
1090         for (chan = 0; chan < LPASS_MAX_CDC_DMA_CHANNELS; chan++) {
1091                 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->rxtx_substream[chan]) {
1092                         rv = lpass_dma_interrupt_handler(
1093                                                 drvdata->rxtx_substream[chan],
1094                                                 drvdata, chan, irqs);
1095                         if (rv != IRQ_HANDLED)
1096                                 return rv;
1097                 }
1098         }
1099
1100         return IRQ_HANDLED;
1101 }
1102
1103 static irqreturn_t lpass_platform_vaif_irq(int irq, void *data)
1104 {
1105         struct lpass_data *drvdata = data;
1106         struct lpass_variant *v = drvdata->variant;
1107         unsigned int irqs;
1108         irqreturn_t rv;
1109         int chan;
1110
1111         rv = regmap_read(drvdata->va_lpaif_map,
1112                         LPAIF_VA_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1113
1114         /* Handle per channel interrupts */
1115         for (chan = 0; chan < LPASS_MAX_VA_CDC_DMA_CHANNELS; chan++) {
1116                 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->va_substream[chan]) {
1117                         rv = lpass_dma_interrupt_handler(
1118                                                 drvdata->va_substream[chan],
1119                                                 drvdata, chan, irqs);
1120                         if (rv != IRQ_HANDLED)
1121                                 return rv;
1122                 }
1123         }
1124         return IRQ_HANDLED;
1125 }
1126
1127 static int lpass_platform_prealloc_cdc_dma_buffer(struct snd_soc_component *component,
1128                                                   struct snd_pcm *pcm, int dai_id)
1129 {
1130         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1131         struct snd_pcm_substream *substream;
1132         struct snd_dma_buffer *buf;
1133
1134         if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
1135                 substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1136         else
1137                 substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1138
1139         buf = &substream->dma_buffer;
1140         buf->dev.dev = pcm->card->dev;
1141         buf->private_data = NULL;
1142
1143         /* Assign Codec DMA buffer pointers */
1144         buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
1145
1146         switch (dai_id) {
1147         case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
1148                 buf->bytes = lpass_platform_rxtx_hardware.buffer_bytes_max;
1149                 buf->addr = drvdata->rxtx_cdc_dma_lpm_buf;
1150                 break;
1151         case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
1152                 buf->bytes = lpass_platform_rxtx_hardware.buffer_bytes_max;
1153                 buf->addr = drvdata->rxtx_cdc_dma_lpm_buf + LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE;
1154                 break;
1155         case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
1156                 buf->bytes = lpass_platform_va_hardware.buffer_bytes_max;
1157                 buf->addr = drvdata->va_cdc_dma_lpm_buf;
1158                 break;
1159         default:
1160                 break;
1161         }
1162
1163         buf->area = (unsigned char * __force)memremap(buf->addr, buf->bytes, MEMREMAP_WC);
1164
1165         return 0;
1166 }
1167
1168 static int lpass_platform_pcm_new(struct snd_soc_component *component,
1169                                   struct snd_soc_pcm_runtime *soc_runtime)
1170 {
1171         struct snd_pcm *pcm = soc_runtime->pcm;
1172         struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0);
1173         unsigned int dai_id = cpu_dai->driver->id;
1174
1175         size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
1176
1177         /*
1178          * Lpass codec dma can access only lpass lpm hardware memory.
1179          * ioremap is for HLOS to access hardware memory.
1180          */
1181         if (is_cdc_dma_port(dai_id))
1182                 return lpass_platform_prealloc_cdc_dma_buffer(component, pcm, dai_id);
1183
1184         return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
1185                                             component->dev, size);
1186 }
1187
1188 static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
1189 {
1190         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1191         struct regmap *map;
1192         unsigned int dai_id = component->id;
1193
1194         if (dai_id == LPASS_DP_RX)
1195                 map = drvdata->hdmiif_map;
1196         else
1197                 map = drvdata->lpaif_map;
1198
1199         regcache_cache_only(map, true);
1200         regcache_mark_dirty(map);
1201
1202         return 0;
1203 }
1204
1205 static int lpass_platform_pcmops_resume(struct snd_soc_component *component)
1206 {
1207         struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1208         struct regmap *map;
1209         unsigned int dai_id = component->id;
1210
1211         if (dai_id == LPASS_DP_RX)
1212                 map = drvdata->hdmiif_map;
1213         else
1214                 map = drvdata->lpaif_map;
1215
1216         regcache_cache_only(map, false);
1217         return regcache_sync(map);
1218 }
1219
1220 static int lpass_platform_copy(struct snd_soc_component *component,
1221                                struct snd_pcm_substream *substream, int channel,
1222                                unsigned long pos, void __user *buf, unsigned long bytes)
1223 {
1224         struct snd_pcm_runtime *rt = substream->runtime;
1225         unsigned int dai_id = component->id;
1226         int ret = 0;
1227
1228         void __iomem *dma_buf = (void __iomem *) (rt->dma_area + pos +
1229                                 channel * (rt->dma_bytes / rt->channels));
1230
1231         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1232                 if (is_cdc_dma_port(dai_id)) {
1233                         ret = copy_from_user_toio(dma_buf, buf, bytes);
1234                 } else {
1235                         if (copy_from_user((void __force *)dma_buf, buf, bytes))
1236                                 ret = -EFAULT;
1237                 }
1238         } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1239                 if (is_cdc_dma_port(dai_id)) {
1240                         ret = copy_to_user_fromio(buf, dma_buf, bytes);
1241                 } else {
1242                         if (copy_to_user(buf, (void __force *)dma_buf, bytes))
1243                                 ret = -EFAULT;
1244                 }
1245         }
1246
1247         return ret;
1248 }
1249
1250 static const struct snd_soc_component_driver lpass_component_driver = {
1251         .name           = DRV_NAME,
1252         .open           = lpass_platform_pcmops_open,
1253         .close          = lpass_platform_pcmops_close,
1254         .hw_params      = lpass_platform_pcmops_hw_params,
1255         .hw_free        = lpass_platform_pcmops_hw_free,
1256         .prepare        = lpass_platform_pcmops_prepare,
1257         .trigger        = lpass_platform_pcmops_trigger,
1258         .pointer        = lpass_platform_pcmops_pointer,
1259         .mmap           = lpass_platform_pcmops_mmap,
1260         .pcm_construct  = lpass_platform_pcm_new,
1261         .suspend                = lpass_platform_pcmops_suspend,
1262         .resume                 = lpass_platform_pcmops_resume,
1263         .copy_user              = lpass_platform_copy,
1264
1265 };
1266
1267 int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
1268 {
1269         struct lpass_data *drvdata = platform_get_drvdata(pdev);
1270         struct lpass_variant *v = drvdata->variant;
1271         int ret;
1272
1273         drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
1274         if (drvdata->lpaif_irq < 0)
1275                 return -ENODEV;
1276
1277         /* ensure audio hardware is disabled */
1278         ret = regmap_write(drvdata->lpaif_map,
1279                         LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
1280         if (ret) {
1281                 dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret);
1282                 return ret;
1283         }
1284
1285         ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq,
1286                         lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
1287                         "lpass-irq-lpaif", drvdata);
1288         if (ret) {
1289                 dev_err(&pdev->dev, "irq request failed: %d\n", ret);
1290                 return ret;
1291         }
1292
1293         ret = lpass_platform_alloc_dmactl_fields(&pdev->dev,
1294                                                  drvdata->lpaif_map);
1295         if (ret) {
1296                 dev_err(&pdev->dev,
1297                         "error initializing dmactl fields: %d\n", ret);
1298                 return ret;
1299         }
1300
1301         if (drvdata->codec_dma_enable) {
1302                 ret = regmap_write(drvdata->rxtx_lpaif_map,
1303                         LPAIF_RXTX_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0x0);
1304                 if (ret) {
1305                         dev_err(&pdev->dev, "error writing to rxtx irqen reg: %d\n", ret);
1306                         return ret;
1307                 }
1308                 ret = regmap_write(drvdata->va_lpaif_map,
1309                         LPAIF_VA_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0x0);
1310                 if (ret) {
1311                         dev_err(&pdev->dev, "error writing to rxtx irqen reg: %d\n", ret);
1312                         return ret;
1313                 }
1314                 drvdata->rxtxif_irq = platform_get_irq_byname(pdev, "lpass-irq-rxtxif");
1315                 if (drvdata->rxtxif_irq < 0)
1316                         return -ENODEV;
1317
1318                 ret = devm_request_irq(&pdev->dev, drvdata->rxtxif_irq,
1319                                 lpass_platform_rxtxif_irq, 0, "lpass-irq-rxtxif", drvdata);
1320                 if (ret) {
1321                         dev_err(&pdev->dev, "rxtx irq request failed: %d\n", ret);
1322                         return ret;
1323                 }
1324
1325                 ret = lpass_platform_alloc_rxtx_dmactl_fields(&pdev->dev,
1326                                                  drvdata->rxtx_lpaif_map);
1327                 if (ret) {
1328                         dev_err(&pdev->dev,
1329                                 "error initializing rxtx dmactl fields: %d\n", ret);
1330                         return ret;
1331                 }
1332
1333                 drvdata->vaif_irq = platform_get_irq_byname(pdev, "lpass-irq-vaif");
1334                 if (drvdata->vaif_irq < 0)
1335                         return -ENODEV;
1336
1337                 ret = devm_request_irq(&pdev->dev, drvdata->vaif_irq,
1338                                 lpass_platform_vaif_irq, 0, "lpass-irq-vaif", drvdata);
1339                 if (ret) {
1340                         dev_err(&pdev->dev, "va irq request failed: %d\n", ret);
1341                         return ret;
1342                 }
1343
1344                 ret = lpass_platform_alloc_va_dmactl_fields(&pdev->dev,
1345                                                  drvdata->va_lpaif_map);
1346                 if (ret) {
1347                         dev_err(&pdev->dev,
1348                                 "error initializing va dmactl fields: %d\n", ret);
1349                         return ret;
1350                 }
1351         }
1352
1353         if (drvdata->hdmi_port_enable) {
1354                 drvdata->hdmiif_irq = platform_get_irq_byname(pdev, "lpass-irq-hdmi");
1355                 if (drvdata->hdmiif_irq < 0)
1356                         return -ENODEV;
1357
1358                 ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq,
1359                                 lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", drvdata);
1360                 if (ret) {
1361                         dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret);
1362                         return ret;
1363                 }
1364                 ret = regmap_write(drvdata->hdmiif_map,
1365                                 LPASS_HDMITX_APP_IRQEN_REG(v), 0);
1366                 if (ret) {
1367                         dev_err(&pdev->dev, "error writing to hdmi irqen reg: %d\n", ret);
1368                         return ret;
1369                 }
1370
1371                 ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev,
1372                                                          drvdata->hdmiif_map);
1373                 if (ret) {
1374                         dev_err(&pdev->dev,
1375                                 "error initializing hdmidmactl fields: %d\n", ret);
1376                         return ret;
1377                 }
1378         }
1379         return devm_snd_soc_register_component(&pdev->dev,
1380                         &lpass_component_driver, NULL, 0);
1381 }
1382 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
1383
1384 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
1385 MODULE_LICENSE("GPL v2");