Merge tag 'edac_for_4.6' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
[cascardo/linux.git] / sound / soc / qcom / lpass-platform.c
1 /*
2  * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 and
6  * only version 2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
14  */
15
16 #include <linux/dma-mapping.h>
17 #include <linux/export.h>
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/platform_device.h>
21 #include <sound/pcm_params.h>
22 #include <linux/regmap.h>
23 #include <sound/soc.h>
24 #include "lpass-lpaif-reg.h"
25 #include "lpass.h"
26
27 struct lpass_pcm_data {
28         int rdma_ch;
29         int i2s_port;
30 };
31
32 #define LPASS_PLATFORM_BUFFER_SIZE      (16 * 1024)
33 #define LPASS_PLATFORM_PERIODS          2
34
35 static struct snd_pcm_hardware lpass_platform_pcm_hardware = {
36         .info                   =       SNDRV_PCM_INFO_MMAP |
37                                         SNDRV_PCM_INFO_MMAP_VALID |
38                                         SNDRV_PCM_INFO_INTERLEAVED |
39                                         SNDRV_PCM_INFO_PAUSE |
40                                         SNDRV_PCM_INFO_RESUME,
41         .formats                =       SNDRV_PCM_FMTBIT_S16 |
42                                         SNDRV_PCM_FMTBIT_S24 |
43                                         SNDRV_PCM_FMTBIT_S32,
44         .rates                  =       SNDRV_PCM_RATE_8000_192000,
45         .rate_min               =       8000,
46         .rate_max               =       192000,
47         .channels_min           =       1,
48         .channels_max           =       8,
49         .buffer_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE,
50         .period_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE /
51                                                 LPASS_PLATFORM_PERIODS,
52         .period_bytes_min       =       LPASS_PLATFORM_BUFFER_SIZE /
53                                                 LPASS_PLATFORM_PERIODS,
54         .periods_min            =       LPASS_PLATFORM_PERIODS,
55         .periods_max            =       LPASS_PLATFORM_PERIODS,
56         .fifo_size              =       0,
57 };
58
59 static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
60 {
61         struct snd_pcm_runtime *runtime = substream->runtime;
62         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
63         int ret;
64
65         snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
66
67         runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
68
69         ret = snd_pcm_hw_constraint_integer(runtime,
70                         SNDRV_PCM_HW_PARAM_PERIODS);
71         if (ret < 0) {
72                 dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n",
73                                 __func__, ret);
74                 return -EINVAL;
75         }
76
77         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
78
79         return 0;
80 }
81
82 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
83                 struct snd_pcm_hw_params *params)
84 {
85         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
86         struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
87         struct lpass_data *drvdata =
88                 snd_soc_platform_get_drvdata(soc_runtime->platform);
89         struct lpass_variant *v = drvdata->variant;
90         snd_pcm_format_t format = params_format(params);
91         unsigned int channels = params_channels(params);
92         unsigned int regval;
93         int bitwidth;
94         int ret, rdma_port = pcm_data->i2s_port + v->rdmactl_audif_start;
95
96         bitwidth = snd_pcm_format_width(format);
97         if (bitwidth < 0) {
98                 dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n",
99                                 __func__, bitwidth);
100                 return bitwidth;
101         }
102
103         regval = LPAIF_RDMACTL_BURSTEN_INCR4 |
104                         LPAIF_RDMACTL_AUDINTF(rdma_port) |
105                         LPAIF_RDMACTL_FIFOWM_8;
106
107         switch (bitwidth) {
108         case 16:
109                 switch (channels) {
110                 case 1:
111                 case 2:
112                         regval |= LPAIF_RDMACTL_WPSCNT_ONE;
113                         break;
114                 case 4:
115                         regval |= LPAIF_RDMACTL_WPSCNT_TWO;
116                         break;
117                 case 6:
118                         regval |= LPAIF_RDMACTL_WPSCNT_THREE;
119                         break;
120                 case 8:
121                         regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
122                         break;
123                 default:
124                         dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
125                                         __func__, bitwidth, channels);
126                         return -EINVAL;
127                 }
128                 break;
129         case 24:
130         case 32:
131                 switch (channels) {
132                 case 1:
133                         regval |= LPAIF_RDMACTL_WPSCNT_ONE;
134                         break;
135                 case 2:
136                         regval |= LPAIF_RDMACTL_WPSCNT_TWO;
137                         break;
138                 case 4:
139                         regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
140                         break;
141                 case 6:
142                         regval |= LPAIF_RDMACTL_WPSCNT_SIX;
143                         break;
144                 case 8:
145                         regval |= LPAIF_RDMACTL_WPSCNT_EIGHT;
146                         break;
147                 default:
148                         dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
149                                         __func__, bitwidth, channels);
150                         return -EINVAL;
151                 }
152                 break;
153         default:
154                 dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
155                                 __func__, bitwidth, channels);
156                 return -EINVAL;
157         }
158
159         ret = regmap_write(drvdata->lpaif_map,
160                         LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), regval);
161         if (ret) {
162                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
163                                 __func__, ret);
164                 return ret;
165         }
166
167         return 0;
168 }
169
170 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
171 {
172         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
173         struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
174         struct lpass_data *drvdata =
175                 snd_soc_platform_get_drvdata(soc_runtime->platform);
176         struct lpass_variant *v = drvdata->variant;
177         int ret;
178
179         ret = regmap_write(drvdata->lpaif_map,
180                         LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), 0);
181         if (ret)
182                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
183                                 __func__, ret);
184
185         return ret;
186 }
187
188 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
189 {
190         struct snd_pcm_runtime *runtime = substream->runtime;
191         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
192         struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
193         struct lpass_data *drvdata =
194                 snd_soc_platform_get_drvdata(soc_runtime->platform);
195         struct lpass_variant *v = drvdata->variant;
196         int ret, ch = pcm_data->rdma_ch;
197
198         ret = regmap_write(drvdata->lpaif_map,
199                         LPAIF_RDMABASE_REG(v, ch),
200                         runtime->dma_addr);
201         if (ret) {
202                 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
203                                 __func__, ret);
204                 return ret;
205         }
206
207         ret = regmap_write(drvdata->lpaif_map,
208                         LPAIF_RDMABUFF_REG(v, ch),
209                         (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
210         if (ret) {
211                 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
212                                 __func__, ret);
213                 return ret;
214         }
215
216         ret = regmap_write(drvdata->lpaif_map,
217                         LPAIF_RDMAPER_REG(v, ch),
218                         (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
219         if (ret) {
220                 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
221                                 __func__, ret);
222                 return ret;
223         }
224
225         ret = regmap_update_bits(drvdata->lpaif_map,
226                         LPAIF_RDMACTL_REG(v, ch),
227                         LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON);
228         if (ret) {
229                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
230                                 __func__, ret);
231                 return ret;
232         }
233
234         return 0;
235 }
236
237 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
238                 int cmd)
239 {
240         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
241         struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
242         struct lpass_data *drvdata =
243                 snd_soc_platform_get_drvdata(soc_runtime->platform);
244         struct lpass_variant *v = drvdata->variant;
245         int ret, ch = pcm_data->rdma_ch;
246
247         switch (cmd) {
248         case SNDRV_PCM_TRIGGER_START:
249         case SNDRV_PCM_TRIGGER_RESUME:
250         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
251                 /* clear status before enabling interrupts */
252                 ret = regmap_write(drvdata->lpaif_map,
253                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
254                                 LPAIF_IRQ_ALL(ch));
255                 if (ret) {
256                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
257                                         __func__, ret);
258                         return ret;
259                 }
260
261                 ret = regmap_update_bits(drvdata->lpaif_map,
262                                 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
263                                 LPAIF_IRQ_ALL(ch),
264                                 LPAIF_IRQ_ALL(ch));
265                 if (ret) {
266                         dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
267                                         __func__, ret);
268                         return ret;
269                 }
270
271                 ret = regmap_update_bits(drvdata->lpaif_map,
272                                 LPAIF_RDMACTL_REG(v, ch),
273                                 LPAIF_RDMACTL_ENABLE_MASK,
274                                 LPAIF_RDMACTL_ENABLE_ON);
275                 if (ret) {
276                         dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
277                                         __func__, ret);
278                         return ret;
279                 }
280                 break;
281         case SNDRV_PCM_TRIGGER_STOP:
282         case SNDRV_PCM_TRIGGER_SUSPEND:
283         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
284                 ret = regmap_update_bits(drvdata->lpaif_map,
285                                 LPAIF_RDMACTL_REG(v, ch),
286                                 LPAIF_RDMACTL_ENABLE_MASK,
287                                 LPAIF_RDMACTL_ENABLE_OFF);
288                 if (ret) {
289                         dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
290                                         __func__, ret);
291                         return ret;
292                 }
293
294                 ret = regmap_update_bits(drvdata->lpaif_map,
295                                 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
296                                 LPAIF_IRQ_ALL(ch), 0);
297                 if (ret) {
298                         dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
299                                         __func__, ret);
300                         return ret;
301                 }
302                 break;
303         }
304
305         return 0;
306 }
307
308 static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
309                 struct snd_pcm_substream *substream)
310 {
311         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
312         struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
313         struct lpass_data *drvdata =
314                         snd_soc_platform_get_drvdata(soc_runtime->platform);
315         struct lpass_variant *v = drvdata->variant;
316         unsigned int base_addr, curr_addr;
317         int ret, ch = pcm_data->rdma_ch;
318
319         ret = regmap_read(drvdata->lpaif_map,
320                         LPAIF_RDMABASE_REG(v, ch), &base_addr);
321         if (ret) {
322                 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
323                                 __func__, ret);
324                 return ret;
325         }
326
327         ret = regmap_read(drvdata->lpaif_map,
328                         LPAIF_RDMACURR_REG(v, ch), &curr_addr);
329         if (ret) {
330                 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
331                                 __func__, ret);
332                 return ret;
333         }
334
335         return bytes_to_frames(substream->runtime, curr_addr - base_addr);
336 }
337
338 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
339                 struct vm_area_struct *vma)
340 {
341         struct snd_pcm_runtime *runtime = substream->runtime;
342
343         return dma_mmap_coherent(substream->pcm->card->dev, vma,
344                         runtime->dma_area, runtime->dma_addr,
345                         runtime->dma_bytes);
346 }
347
348 static struct snd_pcm_ops lpass_platform_pcm_ops = {
349         .open           = lpass_platform_pcmops_open,
350         .ioctl          = snd_pcm_lib_ioctl,
351         .hw_params      = lpass_platform_pcmops_hw_params,
352         .hw_free        = lpass_platform_pcmops_hw_free,
353         .prepare        = lpass_platform_pcmops_prepare,
354         .trigger        = lpass_platform_pcmops_trigger,
355         .pointer        = lpass_platform_pcmops_pointer,
356         .mmap           = lpass_platform_pcmops_mmap,
357 };
358
359 static irqreturn_t lpass_dma_interrupt_handler(
360                         struct snd_pcm_substream *substream,
361                         struct lpass_data *drvdata,
362                         int chan, u32 interrupts)
363 {
364         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
365         struct lpass_variant *v = drvdata->variant;
366         irqreturn_t ret = IRQ_NONE;
367         int rv;
368
369         if (interrupts & LPAIF_IRQ_PER(chan)) {
370                 rv = regmap_write(drvdata->lpaif_map,
371                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
372                                 LPAIF_IRQ_PER(chan));
373                 if (rv) {
374                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
375                                         __func__, rv);
376                         return IRQ_NONE;
377                 }
378                 snd_pcm_period_elapsed(substream);
379                 ret = IRQ_HANDLED;
380         }
381
382         if (interrupts & LPAIF_IRQ_XRUN(chan)) {
383                 rv = regmap_write(drvdata->lpaif_map,
384                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
385                                 LPAIF_IRQ_XRUN(chan));
386                 if (rv) {
387                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
388                                         __func__, rv);
389                         return IRQ_NONE;
390                 }
391                 dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__);
392                 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
393                 ret = IRQ_HANDLED;
394         }
395
396         if (interrupts & LPAIF_IRQ_ERR(chan)) {
397                 rv = regmap_write(drvdata->lpaif_map,
398                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
399                                 LPAIF_IRQ_ERR(chan));
400                 if (rv) {
401                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
402                                         __func__, rv);
403                         return IRQ_NONE;
404                 }
405                 dev_err(soc_runtime->dev, "%s() bus access error\n", __func__);
406                 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
407                 ret = IRQ_HANDLED;
408         }
409
410         return ret;
411 }
412
413 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
414 {
415         struct lpass_data *drvdata = data;
416         struct lpass_variant *v = drvdata->variant;
417         unsigned int irqs;
418         int rv, chan;
419
420         rv = regmap_read(drvdata->lpaif_map,
421                         LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
422         if (rv) {
423                 pr_err("%s() error reading from irqstat reg: %d\n",
424                                 __func__, rv);
425                 return IRQ_NONE;
426         }
427
428         /* Handle per channel interrupts */
429         for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) {
430                 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) {
431                         rv = lpass_dma_interrupt_handler(
432                                                 drvdata->substream[chan],
433                                                 drvdata, chan, irqs);
434                         if (rv != IRQ_HANDLED)
435                                 return rv;
436                 }
437         }
438
439         return IRQ_HANDLED;
440 }
441
442 static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream,
443                 struct snd_soc_pcm_runtime *rt)
444 {
445         struct snd_dma_buffer *buf = &substream->dma_buffer;
446         size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
447
448         buf->dev.type = SNDRV_DMA_TYPE_DEV;
449         buf->dev.dev = rt->platform->dev;
450         buf->private_data = NULL;
451         buf->area = dma_alloc_coherent(rt->platform->dev, size, &buf->addr,
452                         GFP_KERNEL);
453         if (!buf->area) {
454                 dev_err(rt->platform->dev, "%s: Could not allocate DMA buffer\n",
455                                 __func__);
456                 return -ENOMEM;
457         }
458         buf->bytes = size;
459
460         return 0;
461 }
462
463 static void lpass_platform_free_buffer(struct snd_pcm_substream *substream,
464                 struct snd_soc_pcm_runtime *rt)
465 {
466         struct snd_dma_buffer *buf = &substream->dma_buffer;
467
468         if (buf->area) {
469                 dma_free_coherent(rt->dev, buf->bytes, buf->area,
470                                 buf->addr);
471         }
472         buf->area = NULL;
473 }
474
475 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
476 {
477         struct snd_pcm *pcm = soc_runtime->pcm;
478         struct snd_pcm_substream *substream =
479                 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
480         struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
481         struct lpass_data *drvdata =
482                 snd_soc_platform_get_drvdata(soc_runtime->platform);
483         struct lpass_variant *v = drvdata->variant;
484         int ret;
485         struct lpass_pcm_data *data;
486
487         data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
488         if (!data)
489                 return -ENOMEM;
490
491         if (v->alloc_dma_channel)
492                 data->rdma_ch = v->alloc_dma_channel(drvdata);
493
494         if (IS_ERR_VALUE(data->rdma_ch))
495                 return data->rdma_ch;
496
497         drvdata->substream[data->rdma_ch] = substream;
498         data->i2s_port = cpu_dai->driver->id;
499
500         snd_soc_pcm_set_drvdata(soc_runtime, data);
501
502         ret = lpass_platform_alloc_buffer(substream, soc_runtime);
503         if (ret)
504                 return ret;
505
506         ret = regmap_write(drvdata->lpaif_map,
507                         LPAIF_RDMACTL_REG(v, data->rdma_ch), 0);
508         if (ret) {
509                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
510                                 __func__, ret);
511                 goto err_buf;
512         }
513
514         return 0;
515
516 err_buf:
517         lpass_platform_free_buffer(substream, soc_runtime);
518         return ret;
519 }
520
521 static void lpass_platform_pcm_free(struct snd_pcm *pcm)
522 {
523         struct snd_pcm_substream *substream =
524                 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
525         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
526         struct lpass_data *drvdata =
527                 snd_soc_platform_get_drvdata(soc_runtime->platform);
528         struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime);
529         struct lpass_variant *v = drvdata->variant;
530
531         drvdata->substream[data->rdma_ch] = NULL;
532
533         if (v->free_dma_channel)
534                 v->free_dma_channel(drvdata, data->rdma_ch);
535
536         lpass_platform_free_buffer(substream, soc_runtime);
537 }
538
539 static struct snd_soc_platform_driver lpass_platform_driver = {
540         .pcm_new        = lpass_platform_pcm_new,
541         .pcm_free       = lpass_platform_pcm_free,
542         .ops            = &lpass_platform_pcm_ops,
543 };
544
545 int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
546 {
547         struct lpass_data *drvdata = platform_get_drvdata(pdev);
548         struct lpass_variant *v = drvdata->variant;
549         int ret;
550
551         drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
552         if (drvdata->lpaif_irq < 0) {
553                 dev_err(&pdev->dev, "%s() error getting irq handle: %d\n",
554                                 __func__, drvdata->lpaif_irq);
555                 return -ENODEV;
556         }
557
558         /* ensure audio hardware is disabled */
559         ret = regmap_write(drvdata->lpaif_map,
560                         LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
561         if (ret) {
562                 dev_err(&pdev->dev, "%s() error writing to irqen reg: %d\n",
563                                 __func__, ret);
564                 return ret;
565         }
566
567         ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq,
568                         lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
569                         "lpass-irq-lpaif", drvdata);
570         if (ret) {
571                 dev_err(&pdev->dev, "%s() irq request failed: %d\n",
572                                 __func__, ret);
573                 return ret;
574         }
575
576
577         return devm_snd_soc_register_platform(&pdev->dev,
578                         &lpass_platform_driver);
579 }
580 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
581
582 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
583 MODULE_LICENSE("GPL v2");