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
{
32 #define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024)
33 #define LPASS_PLATFORM_PERIODS 2
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
|
44 .rates
= SNDRV_PCM_RATE_8000_192000
,
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
,
59 static int lpass_platform_pcmops_open(struct snd_pcm_substream
*substream
)
61 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
62 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
65 snd_soc_set_runtime_hwparams(substream
, &lpass_platform_pcm_hardware
);
67 runtime
->dma_bytes
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
69 ret
= snd_pcm_hw_constraint_integer(runtime
,
70 SNDRV_PCM_HW_PARAM_PERIODS
);
72 dev_err(soc_runtime
->dev
, "%s() setting constraints failed: %d\n",
77 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
82 static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream
*substream
,
83 struct snd_pcm_hw_params
*params
)
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
);
94 int ret
, rdma_port
= pcm_data
->i2s_port
+ v
->rdmactl_audif_start
;
96 bitwidth
= snd_pcm_format_width(format
);
98 dev_err(soc_runtime
->dev
, "%s() invalid bit width given: %d\n",
103 regval
= LPAIF_RDMACTL_BURSTEN_INCR4
|
104 LPAIF_RDMACTL_AUDINTF(rdma_port
) |
105 LPAIF_RDMACTL_FIFOWM_8
;
112 regval
|= LPAIF_RDMACTL_WPSCNT_ONE
;
115 regval
|= LPAIF_RDMACTL_WPSCNT_TWO
;
118 regval
|= LPAIF_RDMACTL_WPSCNT_THREE
;
121 regval
|= LPAIF_RDMACTL_WPSCNT_FOUR
;
124 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
125 __func__
, bitwidth
, channels
);
133 regval
|= LPAIF_RDMACTL_WPSCNT_ONE
;
136 regval
|= LPAIF_RDMACTL_WPSCNT_TWO
;
139 regval
|= LPAIF_RDMACTL_WPSCNT_FOUR
;
142 regval
|= LPAIF_RDMACTL_WPSCNT_SIX
;
145 regval
|= LPAIF_RDMACTL_WPSCNT_EIGHT
;
148 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
149 __func__
, bitwidth
, channels
);
154 dev_err(soc_runtime
->dev
, "%s() invalid PCM config given: bw=%d, ch=%u\n",
155 __func__
, bitwidth
, channels
);
159 ret
= regmap_write(drvdata
->lpaif_map
,
160 LPAIF_RDMACTL_REG(v
, pcm_data
->rdma_ch
), regval
);
162 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
170 static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream
*substream
)
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
;
179 ret
= regmap_write(drvdata
->lpaif_map
,
180 LPAIF_RDMACTL_REG(v
, pcm_data
->rdma_ch
), 0);
182 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
188 static int lpass_platform_pcmops_prepare(struct snd_pcm_substream
*substream
)
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
;
198 ret
= regmap_write(drvdata
->lpaif_map
,
199 LPAIF_RDMABASE_REG(v
, ch
),
202 dev_err(soc_runtime
->dev
, "%s() error writing to rdmabase reg: %d\n",
207 ret
= regmap_write(drvdata
->lpaif_map
,
208 LPAIF_RDMABUFF_REG(v
, ch
),
209 (snd_pcm_lib_buffer_bytes(substream
) >> 2) - 1);
211 dev_err(soc_runtime
->dev
, "%s() error writing to rdmabuff reg: %d\n",
216 ret
= regmap_write(drvdata
->lpaif_map
,
217 LPAIF_RDMAPER_REG(v
, ch
),
218 (snd_pcm_lib_period_bytes(substream
) >> 2) - 1);
220 dev_err(soc_runtime
->dev
, "%s() error writing to rdmaper reg: %d\n",
225 ret
= regmap_update_bits(drvdata
->lpaif_map
,
226 LPAIF_RDMACTL_REG(v
, ch
),
227 LPAIF_RDMACTL_ENABLE_MASK
, LPAIF_RDMACTL_ENABLE_ON
);
229 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
237 static int lpass_platform_pcmops_trigger(struct snd_pcm_substream
*substream
,
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
;
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
),
256 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
261 ret
= regmap_update_bits(drvdata
->lpaif_map
,
262 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
),
266 dev_err(soc_runtime
->dev
, "%s() error writing to irqen reg: %d\n",
271 ret
= regmap_update_bits(drvdata
->lpaif_map
,
272 LPAIF_RDMACTL_REG(v
, ch
),
273 LPAIF_RDMACTL_ENABLE_MASK
,
274 LPAIF_RDMACTL_ENABLE_ON
);
276 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
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
);
289 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
294 ret
= regmap_update_bits(drvdata
->lpaif_map
,
295 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
),
296 LPAIF_IRQ_ALL(ch
), 0);
298 dev_err(soc_runtime
->dev
, "%s() error writing to irqen reg: %d\n",
308 static snd_pcm_uframes_t
lpass_platform_pcmops_pointer(
309 struct snd_pcm_substream
*substream
)
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
;
319 ret
= regmap_read(drvdata
->lpaif_map
,
320 LPAIF_RDMABASE_REG(v
, ch
), &base_addr
);
322 dev_err(soc_runtime
->dev
, "%s() error reading from rdmabase reg: %d\n",
327 ret
= regmap_read(drvdata
->lpaif_map
,
328 LPAIF_RDMACURR_REG(v
, ch
), &curr_addr
);
330 dev_err(soc_runtime
->dev
, "%s() error reading from rdmacurr reg: %d\n",
335 return bytes_to_frames(substream
->runtime
, curr_addr
- base_addr
);
338 static int lpass_platform_pcmops_mmap(struct snd_pcm_substream
*substream
,
339 struct vm_area_struct
*vma
)
341 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
343 return dma_mmap_coherent(substream
->pcm
->card
->dev
, vma
,
344 runtime
->dma_area
, runtime
->dma_addr
,
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
,
359 static irqreturn_t
lpass_dma_interrupt_handler(
360 struct snd_pcm_substream
*substream
,
361 struct lpass_data
*drvdata
,
362 int chan
, u32 interrupts
)
364 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
365 struct lpass_variant
*v
= drvdata
->variant
;
366 irqreturn_t ret
= IRQ_NONE
;
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
));
374 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
378 snd_pcm_period_elapsed(substream
);
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
));
387 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
391 dev_warn(soc_runtime
->dev
, "%s() xrun warning\n", __func__
);
392 snd_pcm_stop(substream
, SNDRV_PCM_STATE_XRUN
);
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
));
401 dev_err(soc_runtime
->dev
, "%s() error writing to irqclear reg: %d\n",
405 dev_err(soc_runtime
->dev
, "%s() bus access error\n", __func__
);
406 snd_pcm_stop(substream
, SNDRV_PCM_STATE_DISCONNECTED
);
413 static irqreturn_t
lpass_platform_lpaif_irq(int irq
, void *data
)
415 struct lpass_data
*drvdata
= data
;
416 struct lpass_variant
*v
= drvdata
->variant
;
420 rv
= regmap_read(drvdata
->lpaif_map
,
421 LPAIF_IRQSTAT_REG(v
, LPAIF_IRQ_PORT_HOST
), &irqs
);
423 pr_err("%s() error reading from irqstat reg: %d\n",
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
)
442 static int lpass_platform_alloc_buffer(struct snd_pcm_substream
*substream
,
443 struct snd_soc_pcm_runtime
*soc_runtime
)
445 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
446 size_t size
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
448 buf
->dev
.type
= SNDRV_DMA_TYPE_DEV
;
449 buf
->dev
.dev
= soc_runtime
->dev
;
450 buf
->private_data
= NULL
;
451 buf
->area
= dma_alloc_coherent(soc_runtime
->dev
, size
, &buf
->addr
,
454 dev_err(soc_runtime
->dev
, "%s: Could not allocate DMA buffer\n",
463 static void lpass_platform_free_buffer(struct snd_pcm_substream
*substream
,
464 struct snd_soc_pcm_runtime
*soc_runtime
)
466 struct snd_dma_buffer
*buf
= &substream
->dma_buffer
;
469 dma_free_coherent(soc_runtime
->dev
, buf
->bytes
, buf
->area
,
475 static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime
*soc_runtime
)
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
;
485 struct lpass_pcm_data
*data
;
487 data
= devm_kzalloc(soc_runtime
->dev
, sizeof(*data
), GFP_KERNEL
);
491 if (v
->alloc_dma_channel
)
492 data
->rdma_ch
= v
->alloc_dma_channel(drvdata
);
494 if (IS_ERR_VALUE(data
->rdma_ch
))
495 return data
->rdma_ch
;
497 drvdata
->substream
[data
->rdma_ch
] = substream
;
498 data
->i2s_port
= cpu_dai
->driver
->id
;
500 snd_soc_pcm_set_drvdata(soc_runtime
, data
);
502 soc_runtime
->dev
->coherent_dma_mask
= DMA_BIT_MASK(32);
503 soc_runtime
->dev
->dma_mask
= &soc_runtime
->dev
->coherent_dma_mask
;
505 ret
= lpass_platform_alloc_buffer(substream
, soc_runtime
);
509 ret
= regmap_write(drvdata
->lpaif_map
,
510 LPAIF_RDMACTL_REG(v
, data
->rdma_ch
), 0);
512 dev_err(soc_runtime
->dev
, "%s() error writing to rdmactl reg: %d\n",
520 lpass_platform_free_buffer(substream
, soc_runtime
);
524 static void lpass_platform_pcm_free(struct snd_pcm
*pcm
)
526 struct snd_pcm_substream
*substream
=
527 pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
;
528 struct snd_soc_pcm_runtime
*soc_runtime
= substream
->private_data
;
529 struct lpass_data
*drvdata
=
530 snd_soc_platform_get_drvdata(soc_runtime
->platform
);
531 struct lpass_pcm_data
*data
= snd_soc_pcm_get_drvdata(soc_runtime
);
532 struct lpass_variant
*v
= drvdata
->variant
;
534 drvdata
->substream
[data
->rdma_ch
] = NULL
;
536 if (v
->free_dma_channel
)
537 v
->free_dma_channel(drvdata
, data
->rdma_ch
);
539 lpass_platform_free_buffer(substream
, soc_runtime
);
542 static struct snd_soc_platform_driver lpass_platform_driver
= {
543 .pcm_new
= lpass_platform_pcm_new
,
544 .pcm_free
= lpass_platform_pcm_free
,
545 .ops
= &lpass_platform_pcm_ops
,
548 int asoc_qcom_lpass_platform_register(struct platform_device
*pdev
)
550 struct lpass_data
*drvdata
= platform_get_drvdata(pdev
);
551 struct lpass_variant
*v
= drvdata
->variant
;
554 drvdata
->lpaif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-lpaif");
555 if (drvdata
->lpaif_irq
< 0) {
556 dev_err(&pdev
->dev
, "%s() error getting irq handle: %d\n",
557 __func__
, drvdata
->lpaif_irq
);
561 /* ensure audio hardware is disabled */
562 ret
= regmap_write(drvdata
->lpaif_map
,
563 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
), 0);
565 dev_err(&pdev
->dev
, "%s() error writing to irqen reg: %d\n",
570 ret
= devm_request_irq(&pdev
->dev
, drvdata
->lpaif_irq
,
571 lpass_platform_lpaif_irq
, IRQF_TRIGGER_RISING
,
572 "lpass-irq-lpaif", drvdata
);
574 dev_err(&pdev
->dev
, "%s() irq request failed: %d\n",
580 return devm_snd_soc_register_platform(&pdev
->dev
,
581 &lpass_platform_driver
);
583 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register
);
585 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
586 MODULE_LICENSE("GPL v2");