2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
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.
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.
13 * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
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"
27 struct lpass_pcm_data
{
33 #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024)
34 #define LPASS_PLATFORM_PERIODS 2
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
|
45 .rates
= SNDRV_PCM_RATE_8000_192000
,
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
,
60 static int lpass_platform_pcmops_open(struct snd_pcm_substream
*substream
)
62 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
63 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
64 struct snd_soc_dai
*cpu_dai
= soc_runtime
->cpu_dai
;
65 struct lpass_data
*drvdata
=
66 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
67 struct lpass_variant
*v
= drvdata
->variant
;
68 int ret
, dma_ch
, dir
= substream
->stream
;
69 struct lpass_pcm_data
*data
;
71 data
= devm_kzalloc(soc_runtime
->dev
, sizeof(*data
), GFP_KERNEL
);
75 data
->i2s_port
= cpu_dai
->driver
->id
;
76 runtime
->private_data
= data
;
79 if (v
->alloc_dma_channel
)
80 dma_ch
= v
->alloc_dma_channel(drvdata
, dir
);
87 drvdata
->substream
[dma_ch
] = substream
;
89 ret
= regmap_write(drvdata
->lpaif_map
,
90 LPAIF_DMACTL_REG(v
, dma_ch
, dir
), 0);
92 dev_err(soc_runtime
->dev
,
93 "%s() error writing to rdmactl reg: %d\n",
98 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
99 data
->rdma_ch
= dma_ch
;
101 data
->wrdma_ch
= dma_ch
;
103 snd_soc_set_runtime_hwparams(substream
, &lpass_platform_pcm_hardware
);
105 runtime
->dma_bytes
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
107 ret
= snd_pcm_hw_constraint_integer(runtime
,
108 SNDRV_PCM_HW_PARAM_PERIODS
);
110 dev_err(soc_runtime
->dev
, "%s() setting constraints failed: %d\n",
115 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
120 static int lpass_platform_pcmops_close(struct snd_pcm_substream
*substream
)
122 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
123 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
124 struct lpass_data
*drvdata
=
125 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
126 struct lpass_variant
*v
= drvdata
->variant
;
127 struct lpass_pcm_data
*data
;
128 int dma_ch
, dir
= substream
->stream
;
130 data
= runtime
->private_data
;
131 v
= drvdata
->variant
;
133 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
134 dma_ch
= data
->rdma_ch
;
136 dma_ch
= data
->wrdma_ch
;
138 drvdata
->substream
[dma_ch
] = NULL
;
140 if (v
->free_dma_channel
)
141 v
->free_dma_channel(drvdata
, dma_ch
);
146 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream
*substream
,
147 struct snd_pcm_hw_params
*params
)
149 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
150 struct lpass_data
*drvdata
=
151 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
152 struct snd_pcm_runtime
*rt
= substream
->runtime
;
153 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
154 struct lpass_variant
*v
= drvdata
->variant
;
155 snd_pcm_format_t format
= params_format(params
);
156 unsigned int channels
= params_channels(params
);
158 int ch
, dir
= substream
->stream
;
160 int ret
, dma_port
= pcm_data
->i2s_port
+ v
->dmactl_audif_start
;
162 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
163 ch
= pcm_data
->rdma_ch
;
165 ch
= pcm_data
->wrdma_ch
;
167 bitwidth
= snd_pcm_format_width(format
);
169 dev_err(soc_runtime
->dev
, "%s() invalid bit width given: %d\n",
174 regval
= LPAIF_DMACTL_BURSTEN_INCR4
|
175 LPAIF_DMACTL_AUDINTF(dma_port
) |
176 LPAIF_DMACTL_FIFOWM_8
;
183 regval
|= LPAIF_DMACTL_WPSCNT_ONE
;
186 regval
|= LPAIF_DMACTL_WPSCNT_TWO
;
189 regval
|= LPAIF_DMACTL_WPSCNT_THREE
;
192 regval
|= LPAIF_DMACTL_WPSCNT_FOUR
;
195 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
196 __func__
, bitwidth
, channels
);
204 regval
|= LPAIF_DMACTL_WPSCNT_ONE
;
207 regval
|= LPAIF_DMACTL_WPSCNT_TWO
;
210 regval
|= LPAIF_DMACTL_WPSCNT_FOUR
;
213 regval
|= LPAIF_DMACTL_WPSCNT_SIX
;
216 regval
|= LPAIF_DMACTL_WPSCNT_EIGHT
;
219 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
220 __func__
, bitwidth
, channels
);
225 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
226 __func__
, bitwidth
, channels
);
230 ret
= regmap_write(drvdata
->lpaif_map
,
231 LPAIF_DMACTL_REG(v
, ch
, dir
), regval
);
233 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
241 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream
*substream
)
243 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
244 struct lpass_data
*drvdata
=
245 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
246 struct snd_pcm_runtime
*rt
= substream
->runtime
;
247 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
248 struct lpass_variant
*v
= drvdata
->variant
;
252 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
253 reg
= LPAIF_RDMACTL_REG(v
, pcm_data
->rdma_ch
);
255 reg
= LPAIF_WRDMACTL_REG(v
, pcm_data
->wrdma_ch
);
257 ret
= regmap_write(drvdata
->lpaif_map
, reg
, 0);
259 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
265 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream
*substream
)
267 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
268 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
269 struct lpass_data
*drvdata
=
270 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
271 struct snd_pcm_runtime
*rt
= substream
->runtime
;
272 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
273 struct lpass_variant
*v
= drvdata
->variant
;
274 int ret
, ch
, dir
= substream
->stream
;
276 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
277 ch
= pcm_data
->rdma_ch
;
279 ch
= pcm_data
->wrdma_ch
;
281 ret
= regmap_write(drvdata
->lpaif_map
,
282 LPAIF_DMABASE_REG(v
, ch
, dir
),
285 dev_err(soc_runtime
->dev
, "%s() error writing to rdmabase reg: %d\n",
290 ret
= regmap_write(drvdata
->lpaif_map
,
291 LPAIF_DMABUFF_REG(v
, ch
, dir
),
292 (snd_pcm_lib_buffer_bytes(substream
) >> 2) - 1);
294 dev_err(soc_runtime
->dev
, "%s() error writing to rdmabuff reg: %d\n",
299 ret
= regmap_write(drvdata
->lpaif_map
,
300 LPAIF_DMAPER_REG(v
, ch
, dir
),
301 (snd_pcm_lib_period_bytes(substream
) >> 2) - 1);
303 dev_err(soc_runtime
->dev
, "%s() error writing to rdmaper reg: %d\n",
308 ret
= regmap_update_bits(drvdata
->lpaif_map
,
309 LPAIF_DMACTL_REG(v
, ch
, dir
),
310 LPAIF_DMACTL_ENABLE_MASK
, LPAIF_DMACTL_ENABLE_ON
);
312 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
320 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream
*substream
,
323 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
324 struct lpass_data
*drvdata
=
325 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
326 struct snd_pcm_runtime
*rt
= substream
->runtime
;
327 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
328 struct lpass_variant
*v
= drvdata
->variant
;
329 int ret
, ch
, dir
= substream
->stream
;
331 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
332 ch
= pcm_data
->rdma_ch
;
334 ch
= pcm_data
->wrdma_ch
;
337 case SNDRV_PCM_TRIGGER_START
:
338 case SNDRV_PCM_TRIGGER_RESUME
:
339 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
340 /* clear status before enabling interrupts */
341 ret
= regmap_write(drvdata
->lpaif_map
,
342 LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
),
345 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
350 ret
= regmap_update_bits(drvdata
->lpaif_map
,
351 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
),
355 dev_err(soc_runtime
->dev
, "%s() error writing to irqen reg: %d\n",
360 ret
= regmap_update_bits(drvdata
->lpaif_map
,
361 LPAIF_DMACTL_REG(v
, ch
, dir
),
362 LPAIF_DMACTL_ENABLE_MASK
,
363 LPAIF_DMACTL_ENABLE_ON
);
365 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
370 case SNDRV_PCM_TRIGGER_STOP
:
371 case SNDRV_PCM_TRIGGER_SUSPEND
:
372 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
373 ret
= regmap_update_bits(drvdata
->lpaif_map
,
374 LPAIF_DMACTL_REG(v
, ch
, dir
),
375 LPAIF_DMACTL_ENABLE_MASK
,
376 LPAIF_DMACTL_ENABLE_OFF
);
378 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
383 ret
= regmap_update_bits(drvdata
->lpaif_map
,
384 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
),
385 LPAIF_IRQ_ALL(ch
), 0);
387 dev_err(soc_runtime
->dev
, "%s() error writing to irqen reg: %d\n",
397 static snd_pcm_uframes_t
lpass_platform_pcmops_pointer(
398 struct snd_pcm_substream
*substream
)
400 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
401 struct lpass_data
*drvdata
=
402 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
403 struct snd_pcm_runtime
*rt
= substream
->runtime
;
404 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
405 struct lpass_variant
*v
= drvdata
->variant
;
406 unsigned int base_addr
, curr_addr
;
407 int ret
, ch
, dir
= substream
->stream
;
409 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
)
410 ch
= pcm_data
->rdma_ch
;
412 ch
= pcm_data
->wrdma_ch
;
414 ret
= regmap_read(drvdata
->lpaif_map
,
415 LPAIF_DMABASE_REG(v
, ch
, dir
), &base_addr
);
417 dev_err(soc_runtime
->dev
, "%s() error reading from rdmabase reg: %d\n",
422 ret
= regmap_read(drvdata
->lpaif_map
,
423 LPAIF_DMACURR_REG(v
, ch
, dir
), &curr_addr
);
425 dev_err(soc_runtime
->dev
, "%s() error reading from rdmacurr reg: %d\n",
430 return bytes_to_frames(substream
->runtime
, curr_addr
- base_addr
);
433 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream
*substream
,
434 struct vm_area_struct
*vma
)
436 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
438 return dma_mmap_coherent(substream
->pcm
->card
->dev
, vma
,
439 runtime
->dma_area
, runtime
->dma_addr
,
443 static const struct snd_pcm_ops lpass_platform_pcm_ops
= {
444 .open
= lpass_platform_pcmops_open
,
445 .close
= lpass_platform_pcmops_close
,
446 .ioctl
= snd_pcm_lib_ioctl
,
447 .hw_params
= lpass_platform_pcmops_hw_params
,
448 .hw_free
= lpass_platform_pcmops_hw_free
,
449 .prepare
= lpass_platform_pcmops_prepare
,
450 .trigger
= lpass_platform_pcmops_trigger
,
451 .pointer
= lpass_platform_pcmops_pointer
,
452 .mmap
= lpass_platform_pcmops_mmap
,
455 static irqreturn_t
lpass_dma_interrupt_handler(
456 struct snd_pcm_substream
*substream
,
457 struct lpass_data
*drvdata
,
458 int chan
, u32 interrupts
)
460 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
461 struct lpass_variant
*v
= drvdata
->variant
;
462 irqreturn_t ret
= IRQ_NONE
;
465 if (interrupts
& LPAIF_IRQ_PER(chan
)) {
466 rv
= regmap_write(drvdata
->lpaif_map
,
467 LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
),
468 LPAIF_IRQ_PER(chan
));
470 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
474 snd_pcm_period_elapsed(substream
);
478 if (interrupts
& LPAIF_IRQ_XRUN(chan
)) {
479 rv
= regmap_write(drvdata
->lpaif_map
,
480 LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
),
481 LPAIF_IRQ_XRUN(chan
));
483 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
487 dev_warn(soc_runtime
->dev
, "%s() xrun warning\n", __func__
);
488 snd_pcm_stop(substream
, SNDRV_PCM_STATE_XRUN
);
492 if (interrupts
& LPAIF_IRQ_ERR(chan
)) {
493 rv
= regmap_write(drvdata
->lpaif_map
,
494 LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
),
495 LPAIF_IRQ_ERR(chan
));
497 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
501 dev_err(soc_runtime
->dev
, "%s() bus access error\n", __func__
);
502 snd_pcm_stop(substream
, SNDRV_PCM_STATE_DISCONNECTED
);
509 static irqreturn_t
lpass_platform_lpaif_irq(int irq
, void *data
)
511 struct lpass_data
*drvdata
= data
;
512 struct lpass_variant
*v
= drvdata
->variant
;
516 rv
= regmap_read(drvdata
->lpaif_map
,
517 LPAIF_IRQSTAT_REG(v
, LPAIF_IRQ_PORT_HOST
), &irqs
);
519 pr_err("%s() error reading from irqstat reg: %d\n",
524 /* Handle per channel interrupts */
525 for (chan
= 0; chan
< LPASS_MAX_DMA_CHANNELS
; chan
++) {
526 if (irqs
& LPAIF_IRQ_ALL(chan
) && drvdata
->substream
[chan
]) {
527 rv
= lpass_dma_interrupt_handler(
528 drvdata
->substream
[chan
],
529 drvdata
, chan
, irqs
);
530 if (rv
!= IRQ_HANDLED
)
538 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime
*soc_runtime
)
540 struct snd_pcm
*pcm
= soc_runtime
->pcm
;
541 struct snd_pcm_substream
*psubstream
, *csubstream
;
543 size_t size
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
545 psubstream
= pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
;
547 ret
= snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
,
548 soc_runtime
->platform
->dev
,
549 size
, &psubstream
->dma_buffer
);
551 dev_err(soc_runtime
->dev
, "Cannot allocate buffer(s)\n");
556 csubstream
= pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
;
558 ret
= snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV
,
559 soc_runtime
->platform
->dev
,
560 size
, &csubstream
->dma_buffer
);
562 dev_err(soc_runtime
->dev
, "Cannot allocate buffer(s)\n");
564 snd_dma_free_pages(&psubstream
->dma_buffer
);
573 static void lpass_platform_pcm_free(struct snd_pcm
*pcm
)
575 struct snd_pcm_substream
*substream
;
578 for (i
= 0; i
< ARRAY_SIZE(pcm
->streams
); i
++) {
579 substream
= pcm
->streams
[i
].substream
;
581 snd_dma_free_pages(&substream
->dma_buffer
);
582 substream
->dma_buffer
.area
= NULL
;
583 substream
->dma_buffer
.addr
= 0;
588 static struct snd_soc_platform_driver lpass_platform_driver
= {
589 .pcm_new
= lpass_platform_pcm_new
,
590 .pcm_free
= lpass_platform_pcm_free
,
591 .ops
= &lpass_platform_pcm_ops
,
594 int asoc_qcom_lpass_platform_register(struct platform_device
*pdev
)
596 struct lpass_data
*drvdata
= platform_get_drvdata(pdev
);
597 struct lpass_variant
*v
= drvdata
->variant
;
600 drvdata
->lpaif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-lpaif");
601 if (drvdata
->lpaif_irq
< 0) {
602 dev_err(&pdev
->dev
, "%s() error getting irq handle: %d\n",
603 __func__
, drvdata
->lpaif_irq
);
607 /* ensure audio hardware is disabled */
608 ret
= regmap_write(drvdata
->lpaif_map
,
609 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
), 0);
611 dev_err(&pdev
->dev
, "%s() error writing to irqen reg: %d\n",
616 ret
= devm_request_irq(&pdev
->dev
, drvdata
->lpaif_irq
,
617 lpass_platform_lpaif_irq
, IRQF_TRIGGER_RISING
,
618 "lpass-irq-lpaif", drvdata
);
620 dev_err(&pdev
->dev
, "%s() irq request failed: %d\n",
626 return devm_snd_soc_register_platform(&pdev
->dev
,
627 &lpass_platform_driver
);
629 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register
);
631 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
632 MODULE_LICENSE("GPL v2");