1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
5 * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
8 #include <dt-bindings/sound/qcom,lpass.h>
9 #include <linux/dma-mapping.h>
10 #include <linux/export.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/platform_device.h>
14 #include <sound/pcm_params.h>
15 #include <linux/regmap.h>
16 #include <sound/soc.h>
17 #include "lpass-lpaif-reg.h"
20 #define DRV_NAME "lpass-platform"
22 #define LPASS_PLATFORM_BUFFER_SIZE (24 * 2 * 1024)
23 #define LPASS_PLATFORM_PERIODS 2
24 #define LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE (8 * 1024)
25 #define LPASS_VA_CDC_DMA_LPM_BUFF_SIZE (12 * 1024)
26 #define LPASS_CDC_DMA_REGISTER_FIELDS_MAX 15
28 static const struct snd_pcm_hardware lpass_platform_pcm_hardware
= {
29 .info
= SNDRV_PCM_INFO_MMAP
|
30 SNDRV_PCM_INFO_MMAP_VALID
|
31 SNDRV_PCM_INFO_INTERLEAVED
|
32 SNDRV_PCM_INFO_PAUSE
|
33 SNDRV_PCM_INFO_RESUME
,
34 .formats
= SNDRV_PCM_FMTBIT_S16
|
35 SNDRV_PCM_FMTBIT_S24
|
37 .rates
= SNDRV_PCM_RATE_8000_192000
,
42 .buffer_bytes_max
= LPASS_PLATFORM_BUFFER_SIZE
,
43 .period_bytes_max
= LPASS_PLATFORM_BUFFER_SIZE
/
44 LPASS_PLATFORM_PERIODS
,
45 .period_bytes_min
= LPASS_PLATFORM_BUFFER_SIZE
/
46 LPASS_PLATFORM_PERIODS
,
47 .periods_min
= LPASS_PLATFORM_PERIODS
,
48 .periods_max
= LPASS_PLATFORM_PERIODS
,
52 static const struct snd_pcm_hardware lpass_platform_rxtx_hardware
= {
53 .info
= SNDRV_PCM_INFO_MMAP
|
54 SNDRV_PCM_INFO_MMAP_VALID
|
55 SNDRV_PCM_INFO_INTERLEAVED
|
56 SNDRV_PCM_INFO_PAUSE
|
57 SNDRV_PCM_INFO_RESUME
,
58 .formats
= SNDRV_PCM_FMTBIT_S16
|
59 SNDRV_PCM_FMTBIT_S24
|
61 .rates
= SNDRV_PCM_RATE_8000_192000
,
66 .buffer_bytes_max
= LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE
,
67 .period_bytes_max
= LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE
/
68 LPASS_PLATFORM_PERIODS
,
69 .period_bytes_min
= LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE
/
70 LPASS_PLATFORM_PERIODS
,
71 .periods_min
= LPASS_PLATFORM_PERIODS
,
72 .periods_max
= LPASS_PLATFORM_PERIODS
,
76 static const struct snd_pcm_hardware lpass_platform_va_hardware
= {
77 .info
= SNDRV_PCM_INFO_MMAP
|
78 SNDRV_PCM_INFO_MMAP_VALID
|
79 SNDRV_PCM_INFO_INTERLEAVED
|
80 SNDRV_PCM_INFO_PAUSE
|
81 SNDRV_PCM_INFO_RESUME
,
82 .formats
= SNDRV_PCM_FMTBIT_S16
|
83 SNDRV_PCM_FMTBIT_S24
|
85 .rates
= SNDRV_PCM_RATE_8000_192000
,
90 .buffer_bytes_max
= LPASS_VA_CDC_DMA_LPM_BUFF_SIZE
,
91 .period_bytes_max
= LPASS_VA_CDC_DMA_LPM_BUFF_SIZE
/
92 LPASS_PLATFORM_PERIODS
,
93 .period_bytes_min
= LPASS_VA_CDC_DMA_LPM_BUFF_SIZE
/
94 LPASS_PLATFORM_PERIODS
,
95 .periods_min
= LPASS_PLATFORM_PERIODS
,
96 .periods_max
= LPASS_PLATFORM_PERIODS
,
100 static int lpass_platform_alloc_rxtx_dmactl_fields(struct device
*dev
,
103 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
104 const struct lpass_variant
*v
= drvdata
->variant
;
105 struct lpaif_dmactl
*rd_dmactl
, *wr_dmactl
;
108 rd_dmactl
= devm_kzalloc(dev
, sizeof(*rd_dmactl
), GFP_KERNEL
);
112 wr_dmactl
= devm_kzalloc(dev
, sizeof(*wr_dmactl
), GFP_KERNEL
);
116 drvdata
->rxtx_rd_dmactl
= rd_dmactl
;
117 drvdata
->rxtx_wr_dmactl
= wr_dmactl
;
119 rval
= devm_regmap_field_bulk_alloc(dev
, map
, &rd_dmactl
->intf
,
120 &v
->rxtx_rdma_intf
, LPASS_CDC_DMA_REGISTER_FIELDS_MAX
);
124 return devm_regmap_field_bulk_alloc(dev
, map
, &wr_dmactl
->intf
,
125 &v
->rxtx_wrdma_intf
, LPASS_CDC_DMA_REGISTER_FIELDS_MAX
);
128 static int lpass_platform_alloc_va_dmactl_fields(struct device
*dev
,
131 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
132 const struct lpass_variant
*v
= drvdata
->variant
;
133 struct lpaif_dmactl
*wr_dmactl
;
135 wr_dmactl
= devm_kzalloc(dev
, sizeof(*wr_dmactl
), GFP_KERNEL
);
139 drvdata
->va_wr_dmactl
= wr_dmactl
;
140 return devm_regmap_field_bulk_alloc(dev
, map
, &wr_dmactl
->intf
,
141 &v
->va_wrdma_intf
, LPASS_CDC_DMA_REGISTER_FIELDS_MAX
);
145 static int lpass_platform_alloc_dmactl_fields(struct device
*dev
,
148 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
149 const struct lpass_variant
*v
= drvdata
->variant
;
150 struct lpaif_dmactl
*rd_dmactl
, *wr_dmactl
;
153 drvdata
->rd_dmactl
= devm_kzalloc(dev
, sizeof(struct lpaif_dmactl
),
155 if (drvdata
->rd_dmactl
== NULL
)
158 drvdata
->wr_dmactl
= devm_kzalloc(dev
, sizeof(struct lpaif_dmactl
),
160 if (drvdata
->wr_dmactl
== NULL
)
163 rd_dmactl
= drvdata
->rd_dmactl
;
164 wr_dmactl
= drvdata
->wr_dmactl
;
166 rval
= devm_regmap_field_bulk_alloc(dev
, map
, &rd_dmactl
->intf
,
171 return devm_regmap_field_bulk_alloc(dev
, map
, &wr_dmactl
->intf
,
175 static int lpass_platform_alloc_hdmidmactl_fields(struct device
*dev
,
178 struct lpass_data
*drvdata
= dev_get_drvdata(dev
);
179 const struct lpass_variant
*v
= drvdata
->variant
;
180 struct lpaif_dmactl
*rd_dmactl
;
182 rd_dmactl
= devm_kzalloc(dev
, sizeof(struct lpaif_dmactl
), GFP_KERNEL
);
183 if (rd_dmactl
== NULL
)
186 drvdata
->hdmi_rd_dmactl
= rd_dmactl
;
188 return devm_regmap_field_bulk_alloc(dev
, map
, &rd_dmactl
->bursten
,
189 &v
->hdmi_rdma_bursten
, 8);
192 static int lpass_platform_pcmops_open(struct snd_soc_component
*component
,
193 struct snd_pcm_substream
*substream
)
195 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
196 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
197 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
198 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
199 const struct lpass_variant
*v
= drvdata
->variant
;
200 int ret
, dma_ch
, dir
= substream
->stream
;
201 struct lpass_pcm_data
*data
;
203 unsigned int dai_id
= cpu_dai
->driver
->id
;
205 component
->id
= dai_id
;
206 data
= kzalloc(sizeof(*data
), GFP_KERNEL
);
210 data
->i2s_port
= cpu_dai
->driver
->id
;
211 runtime
->private_data
= data
;
213 if (v
->alloc_dma_channel
)
214 dma_ch
= v
->alloc_dma_channel(drvdata
, dir
, dai_id
);
224 case MI2S_PRIMARY
... MI2S_QUINARY
:
225 map
= drvdata
->lpaif_map
;
226 drvdata
->substream
[dma_ch
] = substream
;
229 map
= drvdata
->hdmiif_map
;
230 drvdata
->hdmi_substream
[dma_ch
] = substream
;
232 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
233 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
234 map
= drvdata
->rxtx_lpaif_map
;
235 drvdata
->rxtx_substream
[dma_ch
] = substream
;
237 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
238 map
= drvdata
->va_lpaif_map
;
239 drvdata
->va_substream
[dma_ch
] = substream
;
245 data
->dma_ch
= dma_ch
;
247 case MI2S_PRIMARY
... MI2S_QUINARY
:
249 ret
= regmap_write(map
, LPAIF_DMACTL_REG(v
, dma_ch
, dir
, data
->i2s_port
), 0);
252 dev_err(soc_runtime
->dev
, "error writing to rdmactl reg: %d\n", ret
);
255 snd_soc_set_runtime_hwparams(substream
, &lpass_platform_pcm_hardware
);
256 runtime
->dma_bytes
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
258 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
259 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
260 snd_soc_set_runtime_hwparams(substream
, &lpass_platform_rxtx_hardware
);
261 runtime
->dma_bytes
= lpass_platform_rxtx_hardware
.buffer_bytes_max
;
262 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
264 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
265 snd_soc_set_runtime_hwparams(substream
, &lpass_platform_va_hardware
);
266 runtime
->dma_bytes
= lpass_platform_va_hardware
.buffer_bytes_max
;
267 snd_pcm_set_runtime_buffer(substream
, &substream
->dma_buffer
);
272 ret
= snd_pcm_hw_constraint_integer(runtime
,
273 SNDRV_PCM_HW_PARAM_PERIODS
);
276 dev_err(soc_runtime
->dev
, "setting constraints failed: %d\n",
284 static int lpass_platform_pcmops_close(struct snd_soc_component
*component
,
285 struct snd_pcm_substream
*substream
)
287 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
288 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
289 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
290 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
291 const struct lpass_variant
*v
= drvdata
->variant
;
292 struct lpass_pcm_data
*data
;
293 unsigned int dai_id
= cpu_dai
->driver
->id
;
295 data
= runtime
->private_data
;
298 case MI2S_PRIMARY
... MI2S_QUINARY
:
299 drvdata
->substream
[data
->dma_ch
] = NULL
;
302 drvdata
->hdmi_substream
[data
->dma_ch
] = NULL
;
304 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
305 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
306 drvdata
->rxtx_substream
[data
->dma_ch
] = NULL
;
308 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
309 drvdata
->va_substream
[data
->dma_ch
] = NULL
;
315 if (v
->free_dma_channel
)
316 v
->free_dma_channel(drvdata
, data
->dma_ch
, dai_id
);
322 static struct lpaif_dmactl
*__lpass_get_dmactl_handle(const struct snd_pcm_substream
*substream
,
323 struct snd_soc_component
*component
)
325 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
326 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
327 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
328 struct lpaif_dmactl
*dmactl
= NULL
;
330 switch (cpu_dai
->driver
->id
) {
331 case MI2S_PRIMARY
... MI2S_QUINARY
:
332 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
333 dmactl
= drvdata
->rd_dmactl
;
335 dmactl
= drvdata
->wr_dmactl
;
338 dmactl
= drvdata
->hdmi_rd_dmactl
;
340 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
341 dmactl
= drvdata
->rxtx_rd_dmactl
;
343 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
344 dmactl
= drvdata
->rxtx_wr_dmactl
;
346 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
347 dmactl
= drvdata
->va_wr_dmactl
;
354 static int __lpass_get_id(const struct snd_pcm_substream
*substream
,
355 struct snd_soc_component
*component
)
357 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
358 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
359 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
360 struct snd_pcm_runtime
*rt
= substream
->runtime
;
361 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
362 const struct lpass_variant
*v
= drvdata
->variant
;
365 switch (cpu_dai
->driver
->id
) {
366 case MI2S_PRIMARY
... MI2S_QUINARY
:
367 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
368 id
= pcm_data
->dma_ch
;
370 id
= pcm_data
->dma_ch
- v
->wrdma_channel_start
;
373 id
= pcm_data
->dma_ch
;
375 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
376 id
= pcm_data
->dma_ch
;
378 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
379 id
= pcm_data
->dma_ch
- v
->rxtx_wrdma_channel_start
;
381 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
382 id
= pcm_data
->dma_ch
- v
->va_wrdma_channel_start
;
389 static struct regmap
*__lpass_get_regmap_handle(const struct snd_pcm_substream
*substream
,
390 struct snd_soc_component
*component
)
392 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
393 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
394 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
395 struct regmap
*map
= NULL
;
397 switch (cpu_dai
->driver
->id
) {
398 case MI2S_PRIMARY
... MI2S_QUINARY
:
399 map
= drvdata
->lpaif_map
;
402 map
= drvdata
->hdmiif_map
;
404 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
405 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
406 map
= drvdata
->rxtx_lpaif_map
;
408 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
409 map
= drvdata
->va_lpaif_map
;
416 static int lpass_platform_pcmops_hw_params(struct snd_soc_component
*component
,
417 struct snd_pcm_substream
*substream
,
418 struct snd_pcm_hw_params
*params
)
420 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
421 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
422 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
423 struct snd_pcm_runtime
*rt
= substream
->runtime
;
424 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
425 const struct lpass_variant
*v
= drvdata
->variant
;
426 snd_pcm_format_t format
= params_format(params
);
427 unsigned int channels
= params_channels(params
);
429 struct lpaif_dmactl
*dmactl
;
432 int ret
, dma_port
= pcm_data
->i2s_port
+ v
->dmactl_audif_start
;
433 unsigned int dai_id
= cpu_dai
->driver
->id
;
435 dmactl
= __lpass_get_dmactl_handle(substream
, component
);
436 id
= __lpass_get_id(substream
, component
);
438 bitwidth
= snd_pcm_format_width(format
);
440 dev_err(soc_runtime
->dev
, "invalid bit width given: %d\n",
445 ret
= regmap_fields_write(dmactl
->bursten
, id
, LPAIF_DMACTL_BURSTEN_INCR4
);
447 dev_err(soc_runtime
->dev
, "error updating bursten field: %d\n", ret
);
451 ret
= regmap_fields_write(dmactl
->fifowm
, id
, LPAIF_DMACTL_FIFOWM_8
);
453 dev_err(soc_runtime
->dev
, "error updating fifowm field: %d\n", ret
);
459 ret
= regmap_fields_write(dmactl
->burst8
, id
,
460 LPAIF_DMACTL_BURSTEN_INCR4
);
462 dev_err(soc_runtime
->dev
, "error updating burst8en field: %d\n", ret
);
465 ret
= regmap_fields_write(dmactl
->burst16
, id
,
466 LPAIF_DMACTL_BURSTEN_INCR4
);
468 dev_err(soc_runtime
->dev
, "error updating burst16en field: %d\n", ret
);
471 ret
= regmap_fields_write(dmactl
->dynburst
, id
,
472 LPAIF_DMACTL_BURSTEN_INCR4
);
474 dev_err(soc_runtime
->dev
, "error updating dynbursten field: %d\n", ret
);
481 case MI2S_QUATERNARY
:
483 ret
= regmap_fields_write(dmactl
->intf
, id
,
484 LPAIF_DMACTL_AUDINTF(dma_port
));
486 dev_err(soc_runtime
->dev
, "error updating audio interface field: %d\n",
492 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
493 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
494 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX0
:
497 dev_err(soc_runtime
->dev
, "%s: invalid interface: %d\n", __func__
, dai_id
);
505 regval
= LPAIF_DMACTL_WPSCNT_ONE
;
508 regval
= LPAIF_DMACTL_WPSCNT_TWO
;
511 regval
= LPAIF_DMACTL_WPSCNT_THREE
;
514 regval
= LPAIF_DMACTL_WPSCNT_FOUR
;
517 dev_err(soc_runtime
->dev
, "invalid PCM config given: bw=%d, ch=%u\n",
526 regval
= LPAIF_DMACTL_WPSCNT_ONE
;
529 regval
= (dai_id
== LPASS_DP_RX
?
530 LPAIF_DMACTL_WPSCNT_ONE
:
531 LPAIF_DMACTL_WPSCNT_TWO
);
534 regval
= (dai_id
== LPASS_DP_RX
?
535 LPAIF_DMACTL_WPSCNT_TWO
:
536 LPAIF_DMACTL_WPSCNT_FOUR
);
539 regval
= (dai_id
== LPASS_DP_RX
?
540 LPAIF_DMACTL_WPSCNT_THREE
:
541 LPAIF_DMACTL_WPSCNT_SIX
);
544 regval
= (dai_id
== LPASS_DP_RX
?
545 LPAIF_DMACTL_WPSCNT_FOUR
:
546 LPAIF_DMACTL_WPSCNT_EIGHT
);
549 dev_err(soc_runtime
->dev
, "invalid PCM config given: bw=%d, ch=%u\n",
555 dev_err(soc_runtime
->dev
, "invalid PCM config given: bw=%d, ch=%u\n",
560 ret
= regmap_fields_write(dmactl
->wpscnt
, id
, regval
);
562 dev_err(soc_runtime
->dev
, "error writing to dmactl reg: %d\n",
570 static int lpass_platform_pcmops_hw_free(struct snd_soc_component
*component
,
571 struct snd_pcm_substream
*substream
)
573 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
574 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
575 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
576 struct snd_pcm_runtime
*rt
= substream
->runtime
;
577 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
578 const struct lpass_variant
*v
= drvdata
->variant
;
582 unsigned int dai_id
= cpu_dai
->driver
->id
;
584 if (is_cdc_dma_port(dai_id
))
586 map
= __lpass_get_regmap_handle(substream
, component
);
588 reg
= LPAIF_DMACTL_REG(v
, pcm_data
->dma_ch
, substream
->stream
, dai_id
);
589 ret
= regmap_write(map
, reg
, 0);
591 dev_err(soc_runtime
->dev
, "error writing to rdmactl reg: %d\n",
597 static int lpass_platform_pcmops_prepare(struct snd_soc_component
*component
,
598 struct snd_pcm_substream
*substream
)
600 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
601 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
602 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
603 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
604 struct snd_pcm_runtime
*rt
= substream
->runtime
;
605 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
606 const struct lpass_variant
*v
= drvdata
->variant
;
607 struct lpaif_dmactl
*dmactl
;
609 int ret
, id
, ch
, dir
= substream
->stream
;
610 unsigned int dai_id
= cpu_dai
->driver
->id
;
612 ch
= pcm_data
->dma_ch
;
614 dmactl
= __lpass_get_dmactl_handle(substream
, component
);
615 id
= __lpass_get_id(substream
, component
);
616 map
= __lpass_get_regmap_handle(substream
, component
);
618 ret
= regmap_write(map
, LPAIF_DMABASE_REG(v
, ch
, dir
, dai_id
),
621 dev_err(soc_runtime
->dev
, "error writing to rdmabase reg: %d\n",
626 ret
= regmap_write(map
, LPAIF_DMABUFF_REG(v
, ch
, dir
, dai_id
),
627 (snd_pcm_lib_buffer_bytes(substream
) >> 2) - 1);
629 dev_err(soc_runtime
->dev
, "error writing to rdmabuff reg: %d\n",
634 ret
= regmap_write(map
, LPAIF_DMAPER_REG(v
, ch
, dir
, dai_id
),
635 (snd_pcm_lib_period_bytes(substream
) >> 2) - 1);
637 dev_err(soc_runtime
->dev
, "error writing to rdmaper reg: %d\n",
642 if (is_cdc_dma_port(dai_id
)) {
643 ret
= regmap_fields_write(dmactl
->fifowm
, id
, LPAIF_DMACTL_FIFOWM_8
);
645 dev_err(soc_runtime
->dev
, "error writing fifowm field to dmactl reg: %d, id: %d\n",
650 ret
= regmap_fields_write(dmactl
->enable
, id
, LPAIF_DMACTL_ENABLE_ON
);
652 dev_err(soc_runtime
->dev
, "error writing to rdmactl reg: %d\n",
660 static int lpass_platform_pcmops_trigger(struct snd_soc_component
*component
,
661 struct snd_pcm_substream
*substream
,
664 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
665 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
666 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
667 struct snd_pcm_runtime
*rt
= substream
->runtime
;
668 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
669 const struct lpass_variant
*v
= drvdata
->variant
;
670 struct lpaif_dmactl
*dmactl
;
673 unsigned int reg_irqclr
= 0, val_irqclr
= 0;
674 unsigned int reg_irqen
= 0, val_irqen
= 0, val_mask
= 0;
675 unsigned int dai_id
= cpu_dai
->driver
->id
;
677 ch
= pcm_data
->dma_ch
;
678 dmactl
= __lpass_get_dmactl_handle(substream
, component
);
679 id
= __lpass_get_id(substream
, component
);
680 map
= __lpass_get_regmap_handle(substream
, component
);
683 case SNDRV_PCM_TRIGGER_START
:
684 case SNDRV_PCM_TRIGGER_RESUME
:
685 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
686 ret
= regmap_fields_write(dmactl
->enable
, id
,
687 LPAIF_DMACTL_ENABLE_ON
);
689 dev_err(soc_runtime
->dev
,
690 "error writing to rdmactl reg: %d\n", ret
);
695 ret
= regmap_fields_write(dmactl
->dyncclk
, id
,
696 LPAIF_DMACTL_DYNCLK_ON
);
698 dev_err(soc_runtime
->dev
,
699 "error writing to rdmactl reg: %d\n", ret
);
702 reg_irqclr
= LPASS_HDMITX_APP_IRQCLEAR_REG(v
);
703 val_irqclr
= (LPAIF_IRQ_ALL(ch
) |
704 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch
) |
705 LPAIF_IRQ_HDMI_METADONE
|
706 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch
));
708 reg_irqen
= LPASS_HDMITX_APP_IRQEN_REG(v
);
709 val_mask
= (LPAIF_IRQ_ALL(ch
) |
710 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch
) |
711 LPAIF_IRQ_HDMI_METADONE
|
712 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch
));
713 val_irqen
= (LPAIF_IRQ_ALL(ch
) |
714 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch
) |
715 LPAIF_IRQ_HDMI_METADONE
|
716 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch
));
721 case MI2S_QUATERNARY
:
723 reg_irqclr
= LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
724 val_irqclr
= LPAIF_IRQ_ALL(ch
);
727 reg_irqen
= LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
728 val_mask
= LPAIF_IRQ_ALL(ch
);
729 val_irqen
= LPAIF_IRQ_ALL(ch
);
731 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
732 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
733 ret
= regmap_fields_write(dmactl
->dyncclk
, id
, LPAIF_DMACTL_DYNCLK_ON
);
735 dev_err(soc_runtime
->dev
,
736 "error writing to rdmactl reg field: %d\n", ret
);
739 reg_irqclr
= LPAIF_RXTX_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
740 val_irqclr
= LPAIF_IRQ_ALL(ch
);
742 reg_irqen
= LPAIF_RXTX_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
743 val_mask
= LPAIF_IRQ_ALL(ch
);
744 val_irqen
= LPAIF_IRQ_ALL(ch
);
746 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
747 ret
= regmap_fields_write(dmactl
->dyncclk
, id
, LPAIF_DMACTL_DYNCLK_ON
);
749 dev_err(soc_runtime
->dev
,
750 "error writing to rdmactl reg field: %d\n", ret
);
753 reg_irqclr
= LPAIF_VA_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
754 val_irqclr
= LPAIF_IRQ_ALL(ch
);
756 reg_irqen
= LPAIF_VA_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
757 val_mask
= LPAIF_IRQ_ALL(ch
);
758 val_irqen
= LPAIF_IRQ_ALL(ch
);
761 dev_err(soc_runtime
->dev
, "%s: invalid %d interface\n", __func__
, dai_id
);
765 ret
= regmap_write_bits(map
, reg_irqclr
, val_irqclr
, val_irqclr
);
767 dev_err(soc_runtime
->dev
, "error writing to irqclear reg: %d\n", ret
);
770 ret
= regmap_update_bits(map
, reg_irqen
, val_mask
, val_irqen
);
772 dev_err(soc_runtime
->dev
, "error writing to irqen reg: %d\n", ret
);
776 case SNDRV_PCM_TRIGGER_STOP
:
777 case SNDRV_PCM_TRIGGER_SUSPEND
:
778 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
779 ret
= regmap_fields_write(dmactl
->enable
, id
,
780 LPAIF_DMACTL_ENABLE_OFF
);
782 dev_err(soc_runtime
->dev
,
783 "error writing to rdmactl reg: %d\n", ret
);
788 ret
= regmap_fields_write(dmactl
->dyncclk
, id
,
789 LPAIF_DMACTL_DYNCLK_OFF
);
791 dev_err(soc_runtime
->dev
,
792 "error writing to rdmactl reg: %d\n", ret
);
795 reg_irqen
= LPASS_HDMITX_APP_IRQEN_REG(v
);
796 val_mask
= (LPAIF_IRQ_ALL(ch
) |
797 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch
) |
798 LPAIF_IRQ_HDMI_METADONE
|
799 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch
));
805 case MI2S_QUATERNARY
:
807 reg_irqen
= LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
808 val_mask
= LPAIF_IRQ_ALL(ch
);
811 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
812 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
813 ret
= regmap_fields_write(dmactl
->dyncclk
, id
, LPAIF_DMACTL_DYNCLK_OFF
);
815 dev_err(soc_runtime
->dev
,
816 "error writing to rdmactl reg field: %d\n", ret
);
820 reg_irqclr
= LPAIF_RXTX_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
821 val_irqclr
= LPAIF_IRQ_ALL(ch
);
823 reg_irqen
= LPAIF_RXTX_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
824 val_mask
= LPAIF_IRQ_ALL(ch
);
825 val_irqen
= LPAIF_IRQ_ALL(ch
);
827 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
828 ret
= regmap_fields_write(dmactl
->dyncclk
, id
, LPAIF_DMACTL_DYNCLK_OFF
);
830 dev_err(soc_runtime
->dev
,
831 "error writing to rdmactl reg field: %d\n", ret
);
835 reg_irqclr
= LPAIF_VA_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
836 val_irqclr
= LPAIF_IRQ_ALL(ch
);
838 reg_irqen
= LPAIF_VA_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
);
839 val_mask
= LPAIF_IRQ_ALL(ch
);
840 val_irqen
= LPAIF_IRQ_ALL(ch
);
843 dev_err(soc_runtime
->dev
, "%s: invalid %d interface\n", __func__
, dai_id
);
847 ret
= regmap_update_bits(map
, reg_irqen
, val_mask
, val_irqen
);
849 dev_err(soc_runtime
->dev
,
850 "error writing to irqen reg: %d\n", ret
);
859 static snd_pcm_uframes_t
lpass_platform_pcmops_pointer(
860 struct snd_soc_component
*component
,
861 struct snd_pcm_substream
*substream
)
863 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
864 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
865 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
866 struct snd_pcm_runtime
*rt
= substream
->runtime
;
867 struct lpass_pcm_data
*pcm_data
= rt
->private_data
;
868 const struct lpass_variant
*v
= drvdata
->variant
;
869 unsigned int base_addr
, curr_addr
;
870 int ret
, ch
, dir
= substream
->stream
;
872 unsigned int dai_id
= cpu_dai
->driver
->id
;
874 map
= __lpass_get_regmap_handle(substream
, component
);
875 ch
= pcm_data
->dma_ch
;
877 ret
= regmap_read(map
,
878 LPAIF_DMABASE_REG(v
, ch
, dir
, dai_id
), &base_addr
);
880 dev_err(soc_runtime
->dev
,
881 "error reading from rdmabase reg: %d\n", ret
);
885 ret
= regmap_read(map
,
886 LPAIF_DMACURR_REG(v
, ch
, dir
, dai_id
), &curr_addr
);
888 dev_err(soc_runtime
->dev
,
889 "error reading from rdmacurr reg: %d\n", ret
);
893 return bytes_to_frames(substream
->runtime
, curr_addr
- base_addr
);
896 static int lpass_platform_cdc_dma_mmap(struct snd_pcm_substream
*substream
,
897 struct vm_area_struct
*vma
)
899 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
900 unsigned long size
, offset
;
902 vma
->vm_page_prot
= pgprot_writecombine(vma
->vm_page_prot
);
903 size
= vma
->vm_end
- vma
->vm_start
;
904 offset
= vma
->vm_pgoff
<< PAGE_SHIFT
;
905 return io_remap_pfn_range(vma
, vma
->vm_start
,
906 (runtime
->dma_addr
+ offset
) >> PAGE_SHIFT
,
907 size
, vma
->vm_page_prot
);
911 static int lpass_platform_pcmops_mmap(struct snd_soc_component
*component
,
912 struct snd_pcm_substream
*substream
,
913 struct vm_area_struct
*vma
)
915 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
916 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
917 unsigned int dai_id
= cpu_dai
->driver
->id
;
919 if (is_cdc_dma_port(dai_id
))
920 return lpass_platform_cdc_dma_mmap(substream
, vma
);
922 return snd_pcm_lib_default_mmap(substream
, vma
);
925 static irqreturn_t
lpass_dma_interrupt_handler(
926 struct snd_pcm_substream
*substream
,
927 struct lpass_data
*drvdata
,
928 int chan
, u32 interrupts
)
930 struct snd_soc_pcm_runtime
*soc_runtime
= snd_soc_substream_to_rtd(substream
);
931 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
932 const struct lpass_variant
*v
= drvdata
->variant
;
933 irqreturn_t ret
= IRQ_NONE
;
935 unsigned int reg
, val
, mask
;
937 unsigned int dai_id
= cpu_dai
->driver
->id
;
939 mask
= LPAIF_IRQ_ALL(chan
);
942 map
= drvdata
->hdmiif_map
;
943 reg
= LPASS_HDMITX_APP_IRQCLEAR_REG(v
);
944 val
= (LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan
) |
945 LPAIF_IRQ_HDMI_METADONE
|
946 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan
));
951 case MI2S_QUATERNARY
:
953 map
= drvdata
->lpaif_map
;
954 reg
= LPAIF_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
957 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
958 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
959 map
= drvdata
->rxtx_lpaif_map
;
960 reg
= LPAIF_RXTX_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
963 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
964 map
= drvdata
->va_lpaif_map
;
965 reg
= LPAIF_VA_IRQCLEAR_REG(v
, LPAIF_IRQ_PORT_HOST
);
969 dev_err(soc_runtime
->dev
, "%s: invalid %d interface\n", __func__
, dai_id
);
972 if (interrupts
& LPAIF_IRQ_PER(chan
)) {
973 rv
= regmap_write_bits(map
, reg
, mask
, (LPAIF_IRQ_PER(chan
) | val
));
975 dev_err(soc_runtime
->dev
,
976 "error writing to irqclear reg: %d\n", rv
);
979 snd_pcm_period_elapsed(substream
);
983 if (interrupts
& LPAIF_IRQ_XRUN(chan
)) {
984 rv
= regmap_write_bits(map
, reg
, mask
, (LPAIF_IRQ_XRUN(chan
) | val
));
986 dev_err(soc_runtime
->dev
,
987 "error writing to irqclear reg: %d\n", rv
);
990 dev_warn_ratelimited(soc_runtime
->dev
, "xrun warning\n");
992 snd_pcm_stop_xrun(substream
);
996 if (interrupts
& LPAIF_IRQ_ERR(chan
)) {
997 rv
= regmap_write_bits(map
, reg
, mask
, (LPAIF_IRQ_ERR(chan
) | val
));
999 dev_err(soc_runtime
->dev
,
1000 "error writing to irqclear reg: %d\n", rv
);
1003 dev_err(soc_runtime
->dev
, "bus access error\n");
1004 snd_pcm_stop(substream
, SNDRV_PCM_STATE_DISCONNECTED
);
1008 if (interrupts
& val
) {
1009 rv
= regmap_write(map
, reg
, val
);
1011 dev_err(soc_runtime
->dev
,
1012 "error writing to irqclear reg: %d\n", rv
);
1021 static irqreturn_t
lpass_platform_lpaif_irq(int irq
, void *data
)
1023 struct lpass_data
*drvdata
= data
;
1024 const struct lpass_variant
*v
= drvdata
->variant
;
1028 rv
= regmap_read(drvdata
->lpaif_map
,
1029 LPAIF_IRQSTAT_REG(v
, LPAIF_IRQ_PORT_HOST
), &irqs
);
1031 pr_err("error reading from irqstat reg: %d\n", rv
);
1035 /* Handle per channel interrupts */
1036 for (chan
= 0; chan
< LPASS_MAX_DMA_CHANNELS
; chan
++) {
1037 if (irqs
& LPAIF_IRQ_ALL(chan
) && drvdata
->substream
[chan
]) {
1038 rv
= lpass_dma_interrupt_handler(
1039 drvdata
->substream
[chan
],
1040 drvdata
, chan
, irqs
);
1041 if (rv
!= IRQ_HANDLED
)
1049 static irqreturn_t
lpass_platform_hdmiif_irq(int irq
, void *data
)
1051 struct lpass_data
*drvdata
= data
;
1052 const struct lpass_variant
*v
= drvdata
->variant
;
1056 rv
= regmap_read(drvdata
->hdmiif_map
,
1057 LPASS_HDMITX_APP_IRQSTAT_REG(v
), &irqs
);
1059 pr_err("error reading from irqstat reg: %d\n", rv
);
1063 /* Handle per channel interrupts */
1064 for (chan
= 0; chan
< LPASS_MAX_HDMI_DMA_CHANNELS
; chan
++) {
1065 if (irqs
& (LPAIF_IRQ_ALL(chan
) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan
) |
1066 LPAIF_IRQ_HDMI_METADONE
|
1067 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan
))
1068 && drvdata
->hdmi_substream
[chan
]) {
1069 rv
= lpass_dma_interrupt_handler(
1070 drvdata
->hdmi_substream
[chan
],
1071 drvdata
, chan
, irqs
);
1072 if (rv
!= IRQ_HANDLED
)
1079 static irqreturn_t
lpass_platform_rxtxif_irq(int irq
, void *data
)
1081 struct lpass_data
*drvdata
= data
;
1082 const struct lpass_variant
*v
= drvdata
->variant
;
1087 rv
= regmap_read(drvdata
->rxtx_lpaif_map
,
1088 LPAIF_RXTX_IRQSTAT_REG(v
, LPAIF_IRQ_PORT_HOST
), &irqs
);
1090 /* Handle per channel interrupts */
1091 for (chan
= 0; chan
< LPASS_MAX_CDC_DMA_CHANNELS
; chan
++) {
1092 if (irqs
& LPAIF_IRQ_ALL(chan
) && drvdata
->rxtx_substream
[chan
]) {
1093 rv
= lpass_dma_interrupt_handler(
1094 drvdata
->rxtx_substream
[chan
],
1095 drvdata
, chan
, irqs
);
1096 if (rv
!= IRQ_HANDLED
)
1104 static irqreturn_t
lpass_platform_vaif_irq(int irq
, void *data
)
1106 struct lpass_data
*drvdata
= data
;
1107 const struct lpass_variant
*v
= drvdata
->variant
;
1112 rv
= regmap_read(drvdata
->va_lpaif_map
,
1113 LPAIF_VA_IRQSTAT_REG(v
, LPAIF_IRQ_PORT_HOST
), &irqs
);
1115 /* Handle per channel interrupts */
1116 for (chan
= 0; chan
< LPASS_MAX_VA_CDC_DMA_CHANNELS
; chan
++) {
1117 if (irqs
& LPAIF_IRQ_ALL(chan
) && drvdata
->va_substream
[chan
]) {
1118 rv
= lpass_dma_interrupt_handler(
1119 drvdata
->va_substream
[chan
],
1120 drvdata
, chan
, irqs
);
1121 if (rv
!= IRQ_HANDLED
)
1128 static int lpass_platform_prealloc_cdc_dma_buffer(struct snd_soc_component
*component
,
1129 struct snd_pcm
*pcm
, int dai_id
)
1131 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
1132 struct snd_pcm_substream
*substream
;
1133 struct snd_dma_buffer
*buf
;
1135 if (pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
)
1136 substream
= pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
;
1138 substream
= pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
;
1140 buf
= &substream
->dma_buffer
;
1141 buf
->dev
.dev
= pcm
->card
->dev
;
1142 buf
->private_data
= NULL
;
1144 /* Assign Codec DMA buffer pointers */
1145 buf
->dev
.type
= SNDRV_DMA_TYPE_CONTINUOUS
;
1148 case LPASS_CDC_DMA_RX0
... LPASS_CDC_DMA_RX9
:
1149 buf
->bytes
= lpass_platform_rxtx_hardware
.buffer_bytes_max
;
1150 buf
->addr
= drvdata
->rxtx_cdc_dma_lpm_buf
;
1152 case LPASS_CDC_DMA_TX0
... LPASS_CDC_DMA_TX8
:
1153 buf
->bytes
= lpass_platform_rxtx_hardware
.buffer_bytes_max
;
1154 buf
->addr
= drvdata
->rxtx_cdc_dma_lpm_buf
+ LPASS_RXTX_CDC_DMA_LPM_BUFF_SIZE
;
1156 case LPASS_CDC_DMA_VA_TX0
... LPASS_CDC_DMA_VA_TX8
:
1157 buf
->bytes
= lpass_platform_va_hardware
.buffer_bytes_max
;
1158 buf
->addr
= drvdata
->va_cdc_dma_lpm_buf
;
1164 buf
->area
= (unsigned char * __force
)memremap(buf
->addr
, buf
->bytes
, MEMREMAP_WC
);
1169 static int lpass_platform_pcm_new(struct snd_soc_component
*component
,
1170 struct snd_soc_pcm_runtime
*soc_runtime
)
1172 struct snd_pcm
*pcm
= soc_runtime
->pcm
;
1173 struct snd_soc_dai
*cpu_dai
= snd_soc_rtd_to_cpu(soc_runtime
, 0);
1174 unsigned int dai_id
= cpu_dai
->driver
->id
;
1176 size_t size
= lpass_platform_pcm_hardware
.buffer_bytes_max
;
1179 * Lpass codec dma can access only lpass lpm hardware memory.
1180 * ioremap is for HLOS to access hardware memory.
1182 if (is_cdc_dma_port(dai_id
))
1183 return lpass_platform_prealloc_cdc_dma_buffer(component
, pcm
, dai_id
);
1185 return snd_pcm_set_fixed_buffer_all(pcm
, SNDRV_DMA_TYPE_NONCOHERENT
,
1186 component
->dev
, size
);
1189 static int lpass_platform_pcmops_suspend(struct snd_soc_component
*component
)
1191 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
1193 unsigned int dai_id
= component
->id
;
1195 if (dai_id
== LPASS_DP_RX
)
1196 map
= drvdata
->hdmiif_map
;
1198 map
= drvdata
->lpaif_map
;
1200 regcache_cache_only(map
, true);
1201 regcache_mark_dirty(map
);
1206 static int lpass_platform_pcmops_resume(struct snd_soc_component
*component
)
1208 struct lpass_data
*drvdata
= snd_soc_component_get_drvdata(component
);
1210 unsigned int dai_id
= component
->id
;
1212 if (dai_id
== LPASS_DP_RX
)
1213 map
= drvdata
->hdmiif_map
;
1215 map
= drvdata
->lpaif_map
;
1217 regcache_cache_only(map
, false);
1218 return regcache_sync(map
);
1221 static int lpass_platform_copy(struct snd_soc_component
*component
,
1222 struct snd_pcm_substream
*substream
, int channel
,
1223 unsigned long pos
, struct iov_iter
*buf
,
1224 unsigned long bytes
)
1226 struct snd_pcm_runtime
*rt
= substream
->runtime
;
1227 unsigned int dai_id
= component
->id
;
1230 void __iomem
*dma_buf
= (void __iomem
*) (rt
->dma_area
+ pos
+
1231 channel
* (rt
->dma_bytes
/ rt
->channels
));
1233 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
1234 if (is_cdc_dma_port(dai_id
)) {
1235 ret
= copy_from_iter_toio(dma_buf
, buf
, bytes
);
1237 if (copy_from_iter((void __force
*)dma_buf
, bytes
, buf
) != bytes
)
1240 } else if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
) {
1241 if (is_cdc_dma_port(dai_id
)) {
1242 ret
= copy_to_iter_fromio(buf
, dma_buf
, bytes
);
1244 if (copy_to_iter((void __force
*)dma_buf
, bytes
, buf
) != bytes
)
1252 static const struct snd_soc_component_driver lpass_component_driver
= {
1254 .open
= lpass_platform_pcmops_open
,
1255 .close
= lpass_platform_pcmops_close
,
1256 .hw_params
= lpass_platform_pcmops_hw_params
,
1257 .hw_free
= lpass_platform_pcmops_hw_free
,
1258 .prepare
= lpass_platform_pcmops_prepare
,
1259 .trigger
= lpass_platform_pcmops_trigger
,
1260 .pointer
= lpass_platform_pcmops_pointer
,
1261 .mmap
= lpass_platform_pcmops_mmap
,
1262 .pcm_construct
= lpass_platform_pcm_new
,
1263 .suspend
= lpass_platform_pcmops_suspend
,
1264 .resume
= lpass_platform_pcmops_resume
,
1265 .copy
= lpass_platform_copy
,
1269 int asoc_qcom_lpass_platform_register(struct platform_device
*pdev
)
1271 struct lpass_data
*drvdata
= platform_get_drvdata(pdev
);
1272 const struct lpass_variant
*v
= drvdata
->variant
;
1275 drvdata
->lpaif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-lpaif");
1276 if (drvdata
->lpaif_irq
< 0)
1279 /* ensure audio hardware is disabled */
1280 ret
= regmap_write(drvdata
->lpaif_map
,
1281 LPAIF_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
), 0);
1283 dev_err(&pdev
->dev
, "error writing to irqen reg: %d\n", ret
);
1287 ret
= devm_request_irq(&pdev
->dev
, drvdata
->lpaif_irq
,
1288 lpass_platform_lpaif_irq
, IRQF_TRIGGER_RISING
,
1289 "lpass-irq-lpaif", drvdata
);
1291 dev_err(&pdev
->dev
, "irq request failed: %d\n", ret
);
1295 ret
= lpass_platform_alloc_dmactl_fields(&pdev
->dev
,
1296 drvdata
->lpaif_map
);
1299 "error initializing dmactl fields: %d\n", ret
);
1303 if (drvdata
->codec_dma_enable
) {
1304 ret
= regmap_write(drvdata
->rxtx_lpaif_map
,
1305 LPAIF_RXTX_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
), 0x0);
1307 dev_err(&pdev
->dev
, "error writing to rxtx irqen reg: %d\n", ret
);
1310 ret
= regmap_write(drvdata
->va_lpaif_map
,
1311 LPAIF_VA_IRQEN_REG(v
, LPAIF_IRQ_PORT_HOST
), 0x0);
1313 dev_err(&pdev
->dev
, "error writing to rxtx irqen reg: %d\n", ret
);
1316 drvdata
->rxtxif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-rxtxif");
1317 if (drvdata
->rxtxif_irq
< 0)
1320 ret
= devm_request_irq(&pdev
->dev
, drvdata
->rxtxif_irq
,
1321 lpass_platform_rxtxif_irq
, 0, "lpass-irq-rxtxif", drvdata
);
1323 dev_err(&pdev
->dev
, "rxtx irq request failed: %d\n", ret
);
1327 ret
= lpass_platform_alloc_rxtx_dmactl_fields(&pdev
->dev
,
1328 drvdata
->rxtx_lpaif_map
);
1331 "error initializing rxtx dmactl fields: %d\n", ret
);
1335 drvdata
->vaif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-vaif");
1336 if (drvdata
->vaif_irq
< 0)
1339 ret
= devm_request_irq(&pdev
->dev
, drvdata
->vaif_irq
,
1340 lpass_platform_vaif_irq
, 0, "lpass-irq-vaif", drvdata
);
1342 dev_err(&pdev
->dev
, "va irq request failed: %d\n", ret
);
1346 ret
= lpass_platform_alloc_va_dmactl_fields(&pdev
->dev
,
1347 drvdata
->va_lpaif_map
);
1350 "error initializing va dmactl fields: %d\n", ret
);
1355 if (drvdata
->hdmi_port_enable
) {
1356 drvdata
->hdmiif_irq
= platform_get_irq_byname(pdev
, "lpass-irq-hdmi");
1357 if (drvdata
->hdmiif_irq
< 0)
1360 ret
= devm_request_irq(&pdev
->dev
, drvdata
->hdmiif_irq
,
1361 lpass_platform_hdmiif_irq
, 0, "lpass-irq-hdmi", drvdata
);
1363 dev_err(&pdev
->dev
, "irq hdmi request failed: %d\n", ret
);
1366 ret
= regmap_write(drvdata
->hdmiif_map
,
1367 LPASS_HDMITX_APP_IRQEN_REG(v
), 0);
1369 dev_err(&pdev
->dev
, "error writing to hdmi irqen reg: %d\n", ret
);
1373 ret
= lpass_platform_alloc_hdmidmactl_fields(&pdev
->dev
,
1374 drvdata
->hdmiif_map
);
1377 "error initializing hdmidmactl fields: %d\n", ret
);
1381 return devm_snd_soc_register_component(&pdev
->dev
,
1382 &lpass_component_driver
, NULL
, 0);
1384 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register
);
1386 MODULE_DESCRIPTION("QTi LPASS Platform Driver");
1387 MODULE_LICENSE("GPL");