ASoC: qcom: move ipq806x specific bits out of lpass driver.
[firefly-linux-kernel-4.4.55.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 #define LPASS_PLATFORM_BUFFER_SIZE      (16 * 1024)
28 #define LPASS_PLATFORM_PERIODS          2
29
30 static struct snd_pcm_hardware lpass_platform_pcm_hardware = {
31         .info                   =       SNDRV_PCM_INFO_MMAP |
32                                         SNDRV_PCM_INFO_MMAP_VALID |
33                                         SNDRV_PCM_INFO_INTERLEAVED |
34                                         SNDRV_PCM_INFO_PAUSE |
35                                         SNDRV_PCM_INFO_RESUME,
36         .formats                =       SNDRV_PCM_FMTBIT_S16 |
37                                         SNDRV_PCM_FMTBIT_S24 |
38                                         SNDRV_PCM_FMTBIT_S32,
39         .rates                  =       SNDRV_PCM_RATE_8000_192000,
40         .rate_min               =       8000,
41         .rate_max               =       192000,
42         .channels_min           =       1,
43         .channels_max           =       8,
44         .buffer_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE,
45         .period_bytes_max       =       LPASS_PLATFORM_BUFFER_SIZE /
46                                                 LPASS_PLATFORM_PERIODS,
47         .period_bytes_min       =       LPASS_PLATFORM_BUFFER_SIZE /
48                                                 LPASS_PLATFORM_PERIODS,
49         .periods_min            =       LPASS_PLATFORM_PERIODS,
50         .periods_max            =       LPASS_PLATFORM_PERIODS,
51         .fifo_size              =       0,
52 };
53
54 static int lpass_platform_pcmops_open(struct snd_pcm_substream *substream)
55 {
56         struct snd_pcm_runtime *runtime = substream->runtime;
57         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
58         int ret;
59
60         snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
61
62         runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
63
64         ret = snd_pcm_hw_constraint_integer(runtime,
65                         SNDRV_PCM_HW_PARAM_PERIODS);
66         if (ret < 0) {
67                 dev_err(soc_runtime->dev, "%s() setting constraints failed: %d\n",
68                                 __func__, ret);
69                 return -EINVAL;
70         }
71
72         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
73
74         return 0;
75 }
76
77 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
78                 struct snd_pcm_hw_params *params)
79 {
80         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
81         struct lpass_data *drvdata =
82                 snd_soc_platform_get_drvdata(soc_runtime->platform);
83         struct lpass_variant *v = drvdata->variant;
84         snd_pcm_format_t format = params_format(params);
85         unsigned int channels = params_channels(params);
86         unsigned int regval;
87         int bitwidth;
88         int ret;
89
90         bitwidth = snd_pcm_format_width(format);
91         if (bitwidth < 0) {
92                 dev_err(soc_runtime->dev, "%s() invalid bit width given: %d\n",
93                                 __func__, bitwidth);
94                 return bitwidth;
95         }
96
97         regval = LPAIF_RDMACTL_BURSTEN_INCR4 |
98                         LPAIF_RDMACTL_AUDINTF_MI2S |
99                         LPAIF_RDMACTL_FIFOWM_8;
100
101         switch (bitwidth) {
102         case 16:
103                 switch (channels) {
104                 case 1:
105                 case 2:
106                         regval |= LPAIF_RDMACTL_WPSCNT_ONE;
107                         break;
108                 case 4:
109                         regval |= LPAIF_RDMACTL_WPSCNT_TWO;
110                         break;
111                 case 6:
112                         regval |= LPAIF_RDMACTL_WPSCNT_THREE;
113                         break;
114                 case 8:
115                         regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
116                         break;
117                 default:
118                         dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
119                                         __func__, bitwidth, channels);
120                         return -EINVAL;
121                 }
122                 break;
123         case 24:
124         case 32:
125                 switch (channels) {
126                 case 1:
127                         regval |= LPAIF_RDMACTL_WPSCNT_ONE;
128                         break;
129                 case 2:
130                         regval |= LPAIF_RDMACTL_WPSCNT_TWO;
131                         break;
132                 case 4:
133                         regval |= LPAIF_RDMACTL_WPSCNT_FOUR;
134                         break;
135                 case 6:
136                         regval |= LPAIF_RDMACTL_WPSCNT_SIX;
137                         break;
138                 case 8:
139                         regval |= LPAIF_RDMACTL_WPSCNT_EIGHT;
140                         break;
141                 default:
142                         dev_err(soc_runtime->dev, "%s() invalid PCM config given: bw=%d, ch=%u\n",
143                                         __func__, bitwidth, channels);
144                         return -EINVAL;
145                 }
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
153         ret = regmap_write(drvdata->lpaif_map,
154                         LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), regval);
155         if (ret) {
156                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
157                                 __func__, ret);
158                 return ret;
159         }
160
161         return 0;
162 }
163
164 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
165 {
166         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
167         struct lpass_data *drvdata =
168                 snd_soc_platform_get_drvdata(soc_runtime->platform);
169         struct lpass_variant *v = drvdata->variant;
170         int ret;
171
172         ret = regmap_write(drvdata->lpaif_map,
173                         LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0);
174         if (ret)
175                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
176                                 __func__, ret);
177
178         return ret;
179 }
180
181 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
182 {
183         struct snd_pcm_runtime *runtime = substream->runtime;
184         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
185         struct lpass_data *drvdata =
186                 snd_soc_platform_get_drvdata(soc_runtime->platform);
187         struct lpass_variant *v = drvdata->variant;
188         int ret;
189
190         ret = regmap_write(drvdata->lpaif_map,
191                         LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S),
192                         runtime->dma_addr);
193         if (ret) {
194                 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
195                                 __func__, ret);
196                 return ret;
197         }
198
199         ret = regmap_write(drvdata->lpaif_map,
200                         LPAIF_RDMABUFF_REG(v, LPAIF_RDMA_CHAN_MI2S),
201                         (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
202         if (ret) {
203                 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
204                                 __func__, ret);
205                 return ret;
206         }
207
208         ret = regmap_write(drvdata->lpaif_map,
209                         LPAIF_RDMAPER_REG(v, LPAIF_RDMA_CHAN_MI2S),
210                         (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
211         if (ret) {
212                 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
213                                 __func__, ret);
214                 return ret;
215         }
216
217         ret = regmap_update_bits(drvdata->lpaif_map,
218                         LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
219                         LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON);
220         if (ret) {
221                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
222                                 __func__, ret);
223                 return ret;
224         }
225
226         return 0;
227 }
228
229 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
230                 int cmd)
231 {
232         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
233         struct lpass_data *drvdata =
234                 snd_soc_platform_get_drvdata(soc_runtime->platform);
235         struct lpass_variant *v = drvdata->variant;
236         int ret;
237
238         switch (cmd) {
239         case SNDRV_PCM_TRIGGER_START:
240         case SNDRV_PCM_TRIGGER_RESUME:
241         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
242                 /* clear status before enabling interrupts */
243                 ret = regmap_write(drvdata->lpaif_map,
244                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
245                                 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S));
246                 if (ret) {
247                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
248                                         __func__, ret);
249                         return ret;
250                 }
251
252                 ret = regmap_update_bits(drvdata->lpaif_map,
253                                 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
254                                 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S),
255                                 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S));
256                 if (ret) {
257                         dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
258                                         __func__, ret);
259                         return ret;
260                 }
261
262                 ret = regmap_update_bits(drvdata->lpaif_map,
263                                 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
264                                 LPAIF_RDMACTL_ENABLE_MASK,
265                                 LPAIF_RDMACTL_ENABLE_ON);
266                 if (ret) {
267                         dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
268                                         __func__, ret);
269                         return ret;
270                 }
271                 break;
272         case SNDRV_PCM_TRIGGER_STOP:
273         case SNDRV_PCM_TRIGGER_SUSPEND:
274         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
275                 ret = regmap_update_bits(drvdata->lpaif_map,
276                                 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S),
277                                 LPAIF_RDMACTL_ENABLE_MASK,
278                                 LPAIF_RDMACTL_ENABLE_OFF);
279                 if (ret) {
280                         dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
281                                         __func__, ret);
282                         return ret;
283                 }
284
285                 ret = regmap_update_bits(drvdata->lpaif_map,
286                                 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
287                                 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0);
288                 if (ret) {
289                         dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
290                                         __func__, ret);
291                         return ret;
292                 }
293                 break;
294         }
295
296         return 0;
297 }
298
299 static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
300                 struct snd_pcm_substream *substream)
301 {
302         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
303         struct lpass_data *drvdata =
304                         snd_soc_platform_get_drvdata(soc_runtime->platform);
305         struct lpass_variant *v = drvdata->variant;
306         unsigned int base_addr, curr_addr;
307         int ret;
308
309         ret = regmap_read(drvdata->lpaif_map,
310                          LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S),
311                          &base_addr);
312         if (ret) {
313                 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
314                                 __func__, ret);
315                 return ret;
316         }
317
318         ret = regmap_read(drvdata->lpaif_map,
319                          LPAIF_RDMACURR_REG(v, LPAIF_RDMA_CHAN_MI2S),
320                          &curr_addr);
321         if (ret) {
322                 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
323                                 __func__, ret);
324                 return ret;
325         }
326
327         return bytes_to_frames(substream->runtime, curr_addr - base_addr);
328 }
329
330 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream *substream,
331                 struct vm_area_struct *vma)
332 {
333         struct snd_pcm_runtime *runtime = substream->runtime;
334
335         return dma_mmap_coherent(substream->pcm->card->dev, vma,
336                         runtime->dma_area, runtime->dma_addr,
337                         runtime->dma_bytes);
338 }
339
340 static struct snd_pcm_ops lpass_platform_pcm_ops = {
341         .open           = lpass_platform_pcmops_open,
342         .ioctl          = snd_pcm_lib_ioctl,
343         .hw_params      = lpass_platform_pcmops_hw_params,
344         .hw_free        = lpass_platform_pcmops_hw_free,
345         .prepare        = lpass_platform_pcmops_prepare,
346         .trigger        = lpass_platform_pcmops_trigger,
347         .pointer        = lpass_platform_pcmops_pointer,
348         .mmap           = lpass_platform_pcmops_mmap,
349 };
350
351 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
352 {
353         struct snd_pcm_substream *substream = data;
354         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
355         struct lpass_data *drvdata =
356                 snd_soc_platform_get_drvdata(soc_runtime->platform);
357         struct lpass_variant *v = drvdata->variant;
358         unsigned int interrupts;
359         irqreturn_t ret = IRQ_NONE;
360         int rv;
361
362         rv = regmap_read(drvdata->lpaif_map,
363                         LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts);
364         if (rv) {
365                 dev_err(soc_runtime->dev, "%s() error reading from irqstat reg: %d\n",
366                                 __func__, rv);
367                 return IRQ_NONE;
368         }
369         interrupts &= LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
370
371         if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) {
372                 rv = regmap_write(drvdata->lpaif_map,
373                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
374                                 LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S));
375                 if (rv) {
376                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
377                                         __func__, rv);
378                         return IRQ_NONE;
379                 }
380                 snd_pcm_period_elapsed(substream);
381                 ret = IRQ_HANDLED;
382         }
383
384         if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) {
385                 rv = regmap_write(drvdata->lpaif_map,
386                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
387                                 LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S));
388                 if (rv) {
389                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
390                                         __func__, rv);
391                         return IRQ_NONE;
392                 }
393                 dev_warn(soc_runtime->dev, "%s() xrun warning\n", __func__);
394                 snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
395                 ret = IRQ_HANDLED;
396         }
397
398         if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) {
399                 rv = regmap_write(drvdata->lpaif_map,
400                                 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
401                                 LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S));
402                 if (rv) {
403                         dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
404                                         __func__, rv);
405                         return IRQ_NONE;
406                 }
407                 dev_err(soc_runtime->dev, "%s() bus access error\n", __func__);
408                 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
409                 ret = IRQ_HANDLED;
410         }
411
412         return ret;
413 }
414
415 static int lpass_platform_alloc_buffer(struct snd_pcm_substream *substream,
416                 struct snd_soc_pcm_runtime *soc_runtime)
417 {
418         struct snd_dma_buffer *buf = &substream->dma_buffer;
419         size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
420
421         buf->dev.type = SNDRV_DMA_TYPE_DEV;
422         buf->dev.dev = soc_runtime->dev;
423         buf->private_data = NULL;
424         buf->area = dma_alloc_coherent(soc_runtime->dev, size, &buf->addr,
425                         GFP_KERNEL);
426         if (!buf->area) {
427                 dev_err(soc_runtime->dev, "%s: Could not allocate DMA buffer\n",
428                                 __func__);
429                 return -ENOMEM;
430         }
431         buf->bytes = size;
432
433         return 0;
434 }
435
436 static void lpass_platform_free_buffer(struct snd_pcm_substream *substream,
437                 struct snd_soc_pcm_runtime *soc_runtime)
438 {
439         struct snd_dma_buffer *buf = &substream->dma_buffer;
440
441         if (buf->area) {
442                 dma_free_coherent(soc_runtime->dev, buf->bytes, buf->area,
443                                 buf->addr);
444         }
445         buf->area = NULL;
446 }
447
448 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
449 {
450         struct snd_pcm *pcm = soc_runtime->pcm;
451         struct snd_pcm_substream *substream =
452                 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
453         struct lpass_data *drvdata =
454                 snd_soc_platform_get_drvdata(soc_runtime->platform);
455         struct lpass_variant *v = drvdata->variant;
456         int ret;
457
458         soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32);
459         soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask;
460
461         ret = lpass_platform_alloc_buffer(substream, soc_runtime);
462         if (ret)
463                 return ret;
464
465         ret = devm_request_irq(soc_runtime->dev, drvdata->lpaif_irq,
466                         lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
467                         "lpass-irq-lpaif", substream);
468         if (ret) {
469                 dev_err(soc_runtime->dev, "%s() irq request failed: %d\n",
470                                 __func__, ret);
471                 goto err_buf;
472         }
473
474         /* ensure audio hardware is disabled */
475         ret = regmap_write(drvdata->lpaif_map,
476                         LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
477         if (ret) {
478                 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
479                                 __func__, ret);
480                 return ret;
481         }
482         ret = regmap_write(drvdata->lpaif_map,
483                         LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0);
484         if (ret) {
485                 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
486                                 __func__, ret);
487                 return ret;
488         }
489
490         return 0;
491
492 err_buf:
493         lpass_platform_free_buffer(substream, soc_runtime);
494         return ret;
495 }
496
497 static void lpass_platform_pcm_free(struct snd_pcm *pcm)
498 {
499         struct snd_pcm_substream *substream =
500                 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
501         struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
502
503         lpass_platform_free_buffer(substream, soc_runtime);
504 }
505
506 static struct snd_soc_platform_driver lpass_platform_driver = {
507         .pcm_new        = lpass_platform_pcm_new,
508         .pcm_free       = lpass_platform_pcm_free,
509         .ops            = &lpass_platform_pcm_ops,
510 };
511
512 int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
513 {
514         struct lpass_data *drvdata = platform_get_drvdata(pdev);
515
516         drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
517         if (drvdata->lpaif_irq < 0) {
518                 dev_err(&pdev->dev, "%s() error getting irq handle: %d\n",
519                                 __func__, drvdata->lpaif_irq);
520                 return -ENODEV;
521         }
522
523         return devm_snd_soc_register_platform(&pdev->dev,
524                         &lpass_platform_driver);
525 }
526 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
527
528 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
529 MODULE_LICENSE("GPL v2");