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