1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved.
4 *
5 * lpass-platform.c -- ALSA SoC platform driver for QTi LPASS
6 */
7
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"
18#include "lpass.h"
19
20#define DRV_NAME "lpass-platform"
21
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
27
28static 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 |
36					SNDRV_PCM_FMTBIT_S32,
37	.rates			=	SNDRV_PCM_RATE_8000_192000,
38	.rate_min		=	8000,
39	.rate_max		=	192000,
40	.channels_min		=	1,
41	.channels_max		=	8,
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,
49	.fifo_size		=	0,
50};
51
52static 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 |
60					SNDRV_PCM_FMTBIT_S32,
61	.rates			=	SNDRV_PCM_RATE_8000_192000,
62	.rate_min		=	8000,
63	.rate_max		=	192000,
64	.channels_min		=	1,
65	.channels_max		=	8,
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,
73	.fifo_size		=	0,
74};
75
76static 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 |
84					SNDRV_PCM_FMTBIT_S32,
85	.rates			=	SNDRV_PCM_RATE_8000_192000,
86	.rate_min		=	8000,
87	.rate_max		=	192000,
88	.channels_min		=	1,
89	.channels_max		=	8,
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,
97	.fifo_size		=	0,
98};
99
100static int lpass_platform_alloc_rxtx_dmactl_fields(struct device *dev,
101					 struct regmap *map)
102{
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;
106	int rval;
107
108	rd_dmactl = devm_kzalloc(dev, sizeof(*rd_dmactl), GFP_KERNEL);
109	if (!rd_dmactl)
110		return -ENOMEM;
111
112	wr_dmactl = devm_kzalloc(dev, sizeof(*wr_dmactl), GFP_KERNEL);
113	if (!wr_dmactl)
114		return -ENOMEM;
115
116	drvdata->rxtx_rd_dmactl = rd_dmactl;
117	drvdata->rxtx_wr_dmactl = wr_dmactl;
118
119	rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
120					    &v->rxtx_rdma_intf, LPASS_CDC_DMA_REGISTER_FIELDS_MAX);
121	if (rval)
122		return rval;
123
124	return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
125					    &v->rxtx_wrdma_intf, LPASS_CDC_DMA_REGISTER_FIELDS_MAX);
126}
127
128static int lpass_platform_alloc_va_dmactl_fields(struct device *dev,
129					 struct regmap *map)
130{
131	struct lpass_data *drvdata = dev_get_drvdata(dev);
132	const struct lpass_variant *v = drvdata->variant;
133	struct lpaif_dmactl *wr_dmactl;
134
135	wr_dmactl = devm_kzalloc(dev, sizeof(*wr_dmactl), GFP_KERNEL);
136	if (!wr_dmactl)
137		return -ENOMEM;
138
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);
142}
143
144
145static int lpass_platform_alloc_dmactl_fields(struct device *dev,
146					 struct regmap *map)
147{
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;
151	int rval;
152
153	drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
154					  GFP_KERNEL);
155	if (drvdata->rd_dmactl == NULL)
156		return -ENOMEM;
157
158	drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl),
159					  GFP_KERNEL);
160	if (drvdata->wr_dmactl == NULL)
161		return -ENOMEM;
162
163	rd_dmactl = drvdata->rd_dmactl;
164	wr_dmactl = drvdata->wr_dmactl;
165
166	rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf,
167					    &v->rdma_intf, 6);
168	if (rval)
169		return rval;
170
171	return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf,
172					    &v->wrdma_intf, 6);
173}
174
175static int lpass_platform_alloc_hdmidmactl_fields(struct device *dev,
176					 struct regmap *map)
177{
178	struct lpass_data *drvdata = dev_get_drvdata(dev);
179	const struct lpass_variant *v = drvdata->variant;
180	struct lpaif_dmactl *rd_dmactl;
181
182	rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), GFP_KERNEL);
183	if (rd_dmactl == NULL)
184		return -ENOMEM;
185
186	drvdata->hdmi_rd_dmactl = rd_dmactl;
187
188	return devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->bursten,
189					    &v->hdmi_rdma_bursten, 8);
190}
191
192static int lpass_platform_pcmops_open(struct snd_soc_component *component,
193				      struct snd_pcm_substream *substream)
194{
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;
202	struct regmap *map;
203	unsigned int dai_id = cpu_dai->driver->id;
204
205	component->id = dai_id;
206	data = kzalloc(sizeof(*data), GFP_KERNEL);
207	if (!data)
208		return -ENOMEM;
209
210	data->i2s_port = cpu_dai->driver->id;
211	runtime->private_data = data;
212
213	if (v->alloc_dma_channel)
214		dma_ch = v->alloc_dma_channel(drvdata, dir, dai_id);
215	else
216		dma_ch = 0;
217
218	if (dma_ch < 0) {
219		kfree(data);
220		return dma_ch;
221	}
222
223	switch (dai_id) {
224	case MI2S_PRIMARY ... MI2S_QUINARY:
225		map = drvdata->lpaif_map;
226		drvdata->substream[dma_ch] = substream;
227		break;
228	case LPASS_DP_RX:
229		map = drvdata->hdmiif_map;
230		drvdata->hdmi_substream[dma_ch] = substream;
231		break;
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;
236		break;
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;
240		break;
241	default:
242		break;
243	}
244
245	data->dma_ch = dma_ch;
246	switch (dai_id) {
247	case MI2S_PRIMARY ... MI2S_QUINARY:
248	case LPASS_DP_RX:
249		ret = regmap_write(map, LPAIF_DMACTL_REG(v, dma_ch, dir, data->i2s_port), 0);
250		if (ret) {
251			kfree(data);
252			dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", ret);
253			return ret;
254		}
255		snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware);
256		runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max;
257		break;
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);
263		break;
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);
268		break;
269	default:
270		break;
271	}
272	ret = snd_pcm_hw_constraint_integer(runtime,
273			SNDRV_PCM_HW_PARAM_PERIODS);
274	if (ret < 0) {
275		kfree(data);
276		dev_err(soc_runtime->dev, "setting constraints failed: %d\n",
277			ret);
278		return -EINVAL;
279	}
280
281	return 0;
282}
283
284static int lpass_platform_pcmops_close(struct snd_soc_component *component,
285				       struct snd_pcm_substream *substream)
286{
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;
294
295	data = runtime->private_data;
296
297	switch (dai_id) {
298	case MI2S_PRIMARY ... MI2S_QUINARY:
299		drvdata->substream[data->dma_ch] = NULL;
300		break;
301	case LPASS_DP_RX:
302		drvdata->hdmi_substream[data->dma_ch] = NULL;
303		break;
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;
307		break;
308	case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
309		drvdata->va_substream[data->dma_ch] = NULL;
310		break;
311	default:
312		break;
313	}
314
315	if (v->free_dma_channel)
316		v->free_dma_channel(drvdata, data->dma_ch, dai_id);
317
318	kfree(data);
319	return 0;
320}
321
322static struct lpaif_dmactl *__lpass_get_dmactl_handle(const struct snd_pcm_substream *substream,
323				     struct snd_soc_component *component)
324{
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;
329
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;
334		else
335			dmactl = drvdata->wr_dmactl;
336		break;
337	case LPASS_DP_RX:
338		dmactl = drvdata->hdmi_rd_dmactl;
339		break;
340	case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
341		dmactl = drvdata->rxtx_rd_dmactl;
342		break;
343	case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
344		dmactl = drvdata->rxtx_wr_dmactl;
345		break;
346	case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
347		dmactl = drvdata->va_wr_dmactl;
348		break;
349	}
350
351	return dmactl;
352}
353
354static int __lpass_get_id(const struct snd_pcm_substream *substream,
355				     struct snd_soc_component *component)
356{
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;
363	int id;
364
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;
369		else
370			id = pcm_data->dma_ch - v->wrdma_channel_start;
371		break;
372	case LPASS_DP_RX:
373		id = pcm_data->dma_ch;
374		break;
375	case LPASS_CDC_DMA_RX0 ... LPASS_CDC_DMA_RX9:
376		id = pcm_data->dma_ch;
377		break;
378	case LPASS_CDC_DMA_TX0 ... LPASS_CDC_DMA_TX8:
379		id = pcm_data->dma_ch - v->rxtx_wrdma_channel_start;
380		break;
381	case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
382		id = pcm_data->dma_ch - v->va_wrdma_channel_start;
383		break;
384	}
385
386	return id;
387}
388
389static struct regmap *__lpass_get_regmap_handle(const struct snd_pcm_substream *substream,
390				     struct snd_soc_component *component)
391{
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;
396
397	switch (cpu_dai->driver->id) {
398	case MI2S_PRIMARY ... MI2S_QUINARY:
399		map = drvdata->lpaif_map;
400		break;
401	case LPASS_DP_RX:
402		map = drvdata->hdmiif_map;
403		break;
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;
407		break;
408	case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
409		map = drvdata->va_lpaif_map;
410		break;
411	}
412
413	return map;
414}
415
416static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component,
417					   struct snd_pcm_substream *substream,
418					   struct snd_pcm_hw_params *params)
419{
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);
428	unsigned int regval;
429	struct lpaif_dmactl *dmactl;
430	int id;
431	int bitwidth;
432	int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start;
433	unsigned int dai_id = cpu_dai->driver->id;
434
435	dmactl = __lpass_get_dmactl_handle(substream, component);
436	id = __lpass_get_id(substream, component);
437
438	bitwidth = snd_pcm_format_width(format);
439	if (bitwidth < 0) {
440		dev_err(soc_runtime->dev, "invalid bit width given: %d\n",
441				bitwidth);
442		return bitwidth;
443	}
444
445	ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4);
446	if (ret) {
447		dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret);
448		return ret;
449	}
450
451	ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
452	if (ret) {
453		dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret);
454		return ret;
455	}
456
457	switch (dai_id) {
458	case LPASS_DP_RX:
459		ret = regmap_fields_write(dmactl->burst8, id,
460							LPAIF_DMACTL_BURSTEN_INCR4);
461		if (ret) {
462			dev_err(soc_runtime->dev, "error updating burst8en field: %d\n", ret);
463			return ret;
464		}
465		ret = regmap_fields_write(dmactl->burst16, id,
466							LPAIF_DMACTL_BURSTEN_INCR4);
467		if (ret) {
468			dev_err(soc_runtime->dev, "error updating burst16en field: %d\n", ret);
469			return ret;
470		}
471		ret = regmap_fields_write(dmactl->dynburst, id,
472							LPAIF_DMACTL_BURSTEN_INCR4);
473		if (ret) {
474			dev_err(soc_runtime->dev, "error updating dynbursten field: %d\n", ret);
475			return ret;
476		}
477		break;
478	case MI2S_PRIMARY:
479	case MI2S_SECONDARY:
480	case MI2S_TERTIARY:
481	case MI2S_QUATERNARY:
482	case MI2S_QUINARY:
483		ret = regmap_fields_write(dmactl->intf, id,
484						LPAIF_DMACTL_AUDINTF(dma_port));
485		if (ret) {
486			dev_err(soc_runtime->dev, "error updating audio interface field: %d\n",
487					ret);
488			return ret;
489		}
490
491		break;
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:
495		break;
496	default:
497		dev_err(soc_runtime->dev, "%s: invalid  interface: %d\n", __func__, dai_id);
498		break;
499	}
500	switch (bitwidth) {
501	case 16:
502		switch (channels) {
503		case 1:
504		case 2:
505			regval = LPAIF_DMACTL_WPSCNT_ONE;
506			break;
507		case 4:
508			regval = LPAIF_DMACTL_WPSCNT_TWO;
509			break;
510		case 6:
511			regval = LPAIF_DMACTL_WPSCNT_THREE;
512			break;
513		case 8:
514			regval = LPAIF_DMACTL_WPSCNT_FOUR;
515			break;
516		default:
517			dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
518				bitwidth, channels);
519			return -EINVAL;
520		}
521		break;
522	case 24:
523	case 32:
524		switch (channels) {
525		case 1:
526			regval = LPAIF_DMACTL_WPSCNT_ONE;
527			break;
528		case 2:
529			regval = (dai_id == LPASS_DP_RX ?
530			LPAIF_DMACTL_WPSCNT_ONE :
531			LPAIF_DMACTL_WPSCNT_TWO);
532			break;
533		case 4:
534			regval = (dai_id == LPASS_DP_RX ?
535			LPAIF_DMACTL_WPSCNT_TWO :
536			LPAIF_DMACTL_WPSCNT_FOUR);
537			break;
538		case 6:
539			regval = (dai_id == LPASS_DP_RX ?
540			LPAIF_DMACTL_WPSCNT_THREE :
541			LPAIF_DMACTL_WPSCNT_SIX);
542			break;
543		case 8:
544			regval = (dai_id == LPASS_DP_RX ?
545			LPAIF_DMACTL_WPSCNT_FOUR :
546			LPAIF_DMACTL_WPSCNT_EIGHT);
547			break;
548		default:
549			dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
550				bitwidth, channels);
551			return -EINVAL;
552		}
553		break;
554	default:
555		dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n",
556			bitwidth, channels);
557		return -EINVAL;
558	}
559
560	ret = regmap_fields_write(dmactl->wpscnt, id, regval);
561	if (ret) {
562		dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n",
563			ret);
564		return ret;
565	}
566
567	return 0;
568}
569
570static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component,
571					 struct snd_pcm_substream *substream)
572{
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;
579	unsigned int reg;
580	int ret;
581	struct regmap *map;
582	unsigned int dai_id = cpu_dai->driver->id;
583
584	if (is_cdc_dma_port(dai_id))
585		return 0;
586	map = __lpass_get_regmap_handle(substream, component);
587
588	reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream, dai_id);
589	ret = regmap_write(map, reg, 0);
590	if (ret)
591		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
592			ret);
593
594	return ret;
595}
596
597static int lpass_platform_pcmops_prepare(struct snd_soc_component *component,
598					 struct snd_pcm_substream *substream)
599{
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;
608	struct regmap *map;
609	int ret, id, ch, dir = substream->stream;
610	unsigned int dai_id = cpu_dai->driver->id;
611
612	ch = pcm_data->dma_ch;
613
614	dmactl = __lpass_get_dmactl_handle(substream, component);
615	id = __lpass_get_id(substream, component);
616	map = __lpass_get_regmap_handle(substream, component);
617
618	ret = regmap_write(map, LPAIF_DMABASE_REG(v, ch, dir, dai_id),
619				runtime->dma_addr);
620	if (ret) {
621		dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n",
622			ret);
623		return ret;
624	}
625
626	ret = regmap_write(map, LPAIF_DMABUFF_REG(v, ch, dir, dai_id),
627			(snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
628	if (ret) {
629		dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n",
630			ret);
631		return ret;
632	}
633
634	ret = regmap_write(map, LPAIF_DMAPER_REG(v, ch, dir, dai_id),
635			(snd_pcm_lib_period_bytes(substream) >> 2) - 1);
636	if (ret) {
637		dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n",
638			ret);
639		return ret;
640	}
641
642	if (is_cdc_dma_port(dai_id)) {
643		ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8);
644		if (ret) {
645			dev_err(soc_runtime->dev, "error writing fifowm field to dmactl reg: %d, id: %d\n",
646				ret, id);
647			return ret;
648		}
649	}
650	ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON);
651	if (ret) {
652		dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n",
653			ret);
654		return ret;
655	}
656
657	return 0;
658}
659
660static int lpass_platform_pcmops_trigger(struct snd_soc_component *component,
661					 struct snd_pcm_substream *substream,
662					 int cmd)
663{
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;
671	struct regmap *map;
672	int ret, ch, id;
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;
676
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);
681
682	switch (cmd) {
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);
688		if (ret) {
689			dev_err(soc_runtime->dev,
690				"error writing to rdmactl reg: %d\n", ret);
691			return ret;
692		}
693		switch (dai_id) {
694		case LPASS_DP_RX:
695			ret = regmap_fields_write(dmactl->dyncclk, id,
696					 LPAIF_DMACTL_DYNCLK_ON);
697			if (ret) {
698				dev_err(soc_runtime->dev,
699					"error writing to rdmactl reg: %d\n", ret);
700				return ret;
701			}
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));
707
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));
717			break;
718		case MI2S_PRIMARY:
719		case MI2S_SECONDARY:
720		case MI2S_TERTIARY:
721		case MI2S_QUATERNARY:
722		case MI2S_QUINARY:
723			reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
724			val_irqclr = LPAIF_IRQ_ALL(ch);
725
726
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);
730			break;
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);
734			if (ret) {
735				dev_err(soc_runtime->dev,
736					"error writing to rdmactl reg field: %d\n", ret);
737				return ret;
738			}
739			reg_irqclr = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
740			val_irqclr = LPAIF_IRQ_ALL(ch);
741
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);
745			break;
746		case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
747			ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_ON);
748			if (ret) {
749				dev_err(soc_runtime->dev,
750					"error writing to rdmactl reg field: %d\n", ret);
751				return ret;
752			}
753			reg_irqclr = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
754			val_irqclr = LPAIF_IRQ_ALL(ch);
755
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);
759			break;
760		default:
761			dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
762			return -EINVAL;
763		}
764
765		ret = regmap_write_bits(map, reg_irqclr, val_irqclr, val_irqclr);
766		if (ret) {
767			dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret);
768			return ret;
769		}
770		ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
771		if (ret) {
772			dev_err(soc_runtime->dev, "error writing to irqen reg: %d\n", ret);
773			return ret;
774		}
775		break;
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);
781		if (ret) {
782			dev_err(soc_runtime->dev,
783				"error writing to rdmactl reg: %d\n", ret);
784			return ret;
785		}
786		switch (dai_id) {
787		case LPASS_DP_RX:
788			ret = regmap_fields_write(dmactl->dyncclk, id,
789					 LPAIF_DMACTL_DYNCLK_OFF);
790			if (ret) {
791				dev_err(soc_runtime->dev,
792					"error writing to rdmactl reg: %d\n", ret);
793				return ret;
794			}
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));
800			val_irqen = 0;
801			break;
802		case MI2S_PRIMARY:
803		case MI2S_SECONDARY:
804		case MI2S_TERTIARY:
805		case MI2S_QUATERNARY:
806		case MI2S_QUINARY:
807			reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST);
808			val_mask = LPAIF_IRQ_ALL(ch);
809			val_irqen = 0;
810			break;
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);
814			if (ret) {
815				dev_err(soc_runtime->dev,
816					"error writing to rdmactl reg field: %d\n", ret);
817				return ret;
818			}
819
820			reg_irqclr = LPAIF_RXTX_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
821			val_irqclr = LPAIF_IRQ_ALL(ch);
822
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);
826			break;
827		case LPASS_CDC_DMA_VA_TX0 ... LPASS_CDC_DMA_VA_TX8:
828			ret = regmap_fields_write(dmactl->dyncclk, id, LPAIF_DMACTL_DYNCLK_OFF);
829			if (ret) {
830				dev_err(soc_runtime->dev,
831					"error writing to rdmactl reg field: %d\n", ret);
832				return ret;
833			}
834
835			reg_irqclr = LPAIF_VA_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
836			val_irqclr = LPAIF_IRQ_ALL(ch);
837
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);
841			break;
842		default:
843			dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id);
844			return -EINVAL;
845		}
846
847		ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen);
848		if (ret) {
849			dev_err(soc_runtime->dev,
850				"error writing to irqen reg: %d\n", ret);
851			return ret;
852		}
853		break;
854	}
855
856	return 0;
857}
858
859static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
860		struct snd_soc_component *component,
861		struct snd_pcm_substream *substream)
862{
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;
871	struct regmap *map;
872	unsigned int dai_id = cpu_dai->driver->id;
873
874	map = __lpass_get_regmap_handle(substream, component);
875	ch = pcm_data->dma_ch;
876
877	ret = regmap_read(map,
878			LPAIF_DMABASE_REG(v, ch, dir, dai_id), &base_addr);
879	if (ret) {
880		dev_err(soc_runtime->dev,
881			"error reading from rdmabase reg: %d\n", ret);
882		return ret;
883	}
884
885	ret = regmap_read(map,
886			LPAIF_DMACURR_REG(v, ch, dir, dai_id), &curr_addr);
887	if (ret) {
888		dev_err(soc_runtime->dev,
889			"error reading from rdmacurr reg: %d\n", ret);
890		return ret;
891	}
892
893	return bytes_to_frames(substream->runtime, curr_addr - base_addr);
894}
895
896static int lpass_platform_cdc_dma_mmap(struct snd_pcm_substream *substream,
897				       struct vm_area_struct *vma)
898{
899	struct snd_pcm_runtime *runtime = substream->runtime;
900	unsigned long size, offset;
901
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);
908
909}
910
911static int lpass_platform_pcmops_mmap(struct snd_soc_component *component,
912				      struct snd_pcm_substream *substream,
913				      struct vm_area_struct *vma)
914{
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;
918
919	if (is_cdc_dma_port(dai_id))
920		return lpass_platform_cdc_dma_mmap(substream, vma);
921
922	return snd_pcm_lib_default_mmap(substream, vma);
923}
924
925static irqreturn_t lpass_dma_interrupt_handler(
926			struct snd_pcm_substream *substream,
927			struct lpass_data *drvdata,
928			int chan, u32 interrupts)
929{
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;
934	int rv;
935	unsigned int reg, val, mask;
936	struct regmap *map;
937	unsigned int dai_id = cpu_dai->driver->id;
938
939	mask = LPAIF_IRQ_ALL(chan);
940	switch (dai_id) {
941	case LPASS_DP_RX:
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));
947	break;
948	case MI2S_PRIMARY:
949	case MI2S_SECONDARY:
950	case MI2S_TERTIARY:
951	case MI2S_QUATERNARY:
952	case MI2S_QUINARY:
953		map = drvdata->lpaif_map;
954		reg = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST);
955		val = 0;
956	break;
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);
961		val = 0;
962	break;
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);
966		val = 0;
967	break;
968	default:
969	dev_err(soc_runtime->dev, "%s: invalid  %d interface\n", __func__, dai_id);
970	return -EINVAL;
971	}
972	if (interrupts & LPAIF_IRQ_PER(chan)) {
973		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_PER(chan) | val));
974		if (rv) {
975			dev_err(soc_runtime->dev,
976				"error writing to irqclear reg: %d\n", rv);
977			return IRQ_NONE;
978		}
979		snd_pcm_period_elapsed(substream);
980		ret = IRQ_HANDLED;
981	}
982
983	if (interrupts & LPAIF_IRQ_XRUN(chan)) {
984		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_XRUN(chan) | val));
985		if (rv) {
986			dev_err(soc_runtime->dev,
987				"error writing to irqclear reg: %d\n", rv);
988			return IRQ_NONE;
989		}
990		dev_warn_ratelimited(soc_runtime->dev, "xrun warning\n");
991
992		snd_pcm_stop_xrun(substream);
993		ret = IRQ_HANDLED;
994	}
995
996	if (interrupts & LPAIF_IRQ_ERR(chan)) {
997		rv = regmap_write_bits(map, reg, mask, (LPAIF_IRQ_ERR(chan) | val));
998		if (rv) {
999			dev_err(soc_runtime->dev,
1000				"error writing to irqclear reg: %d\n", rv);
1001			return IRQ_NONE;
1002		}
1003		dev_err(soc_runtime->dev, "bus access error\n");
1004		snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED);
1005		ret = IRQ_HANDLED;
1006	}
1007
1008	if (interrupts & val) {
1009		rv = regmap_write(map, reg, val);
1010		if (rv) {
1011			dev_err(soc_runtime->dev,
1012			"error writing to irqclear reg: %d\n", rv);
1013			return IRQ_NONE;
1014		}
1015		ret = IRQ_HANDLED;
1016	}
1017
1018	return ret;
1019}
1020
1021static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
1022{
1023	struct lpass_data *drvdata = data;
1024	const struct lpass_variant *v = drvdata->variant;
1025	unsigned int irqs;
1026	int rv, chan;
1027
1028	rv = regmap_read(drvdata->lpaif_map,
1029			LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1030	if (rv) {
1031		pr_err("error reading from irqstat reg: %d\n", rv);
1032		return IRQ_NONE;
1033	}
1034
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)
1042				return rv;
1043		}
1044	}
1045
1046	return IRQ_HANDLED;
1047}
1048
1049static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data)
1050{
1051	struct lpass_data *drvdata = data;
1052	const struct lpass_variant *v = drvdata->variant;
1053	unsigned int irqs;
1054	int rv, chan;
1055
1056	rv = regmap_read(drvdata->hdmiif_map,
1057			LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs);
1058	if (rv) {
1059		pr_err("error reading from irqstat reg: %d\n", rv);
1060		return IRQ_NONE;
1061	}
1062
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)
1073				return rv;
1074		}
1075	}
1076	return IRQ_HANDLED;
1077}
1078
1079static irqreturn_t lpass_platform_rxtxif_irq(int irq, void *data)
1080{
1081	struct lpass_data *drvdata = data;
1082	const struct lpass_variant *v = drvdata->variant;
1083	unsigned int irqs;
1084	irqreturn_t rv;
1085	int chan;
1086
1087	rv = regmap_read(drvdata->rxtx_lpaif_map,
1088			LPAIF_RXTX_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1089
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)
1097				return rv;
1098		}
1099	}
1100
1101	return IRQ_HANDLED;
1102}
1103
1104static irqreturn_t lpass_platform_vaif_irq(int irq, void *data)
1105{
1106	struct lpass_data *drvdata = data;
1107	const struct lpass_variant *v = drvdata->variant;
1108	unsigned int irqs;
1109	irqreturn_t rv;
1110	int chan;
1111
1112	rv = regmap_read(drvdata->va_lpaif_map,
1113			LPAIF_VA_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs);
1114
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)
1122				return rv;
1123		}
1124	}
1125	return IRQ_HANDLED;
1126}
1127
1128static int lpass_platform_prealloc_cdc_dma_buffer(struct snd_soc_component *component,
1129						  struct snd_pcm *pcm, int dai_id)
1130{
1131	struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1132	struct snd_pcm_substream *substream;
1133	struct snd_dma_buffer *buf;
1134
1135	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
1136		substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
1137	else
1138		substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
1139
1140	buf = &substream->dma_buffer;
1141	buf->dev.dev = pcm->card->dev;
1142	buf->private_data = NULL;
1143
1144	/* Assign Codec DMA buffer pointers */
1145	buf->dev.type = SNDRV_DMA_TYPE_CONTINUOUS;
1146
1147	switch (dai_id) {
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;
1151		break;
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;
1155		break;
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;
1159		break;
1160	default:
1161		break;
1162	}
1163
1164	buf->area = (unsigned char * __force)memremap(buf->addr, buf->bytes, MEMREMAP_WC);
1165
1166	return 0;
1167}
1168
1169static int lpass_platform_pcm_new(struct snd_soc_component *component,
1170				  struct snd_soc_pcm_runtime *soc_runtime)
1171{
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;
1175
1176	size_t size = lpass_platform_pcm_hardware.buffer_bytes_max;
1177
1178	/*
1179	 * Lpass codec dma can access only lpass lpm hardware memory.
1180	 * ioremap is for HLOS to access hardware memory.
1181	 */
1182	if (is_cdc_dma_port(dai_id))
1183		return lpass_platform_prealloc_cdc_dma_buffer(component, pcm, dai_id);
1184
1185	return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_NONCOHERENT,
1186					    component->dev, size);
1187}
1188
1189static int lpass_platform_pcmops_suspend(struct snd_soc_component *component)
1190{
1191	struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1192	struct regmap *map;
1193	unsigned int dai_id = component->id;
1194
1195	if (dai_id == LPASS_DP_RX)
1196		map = drvdata->hdmiif_map;
1197	else
1198		map = drvdata->lpaif_map;
1199
1200	regcache_cache_only(map, true);
1201	regcache_mark_dirty(map);
1202
1203	return 0;
1204}
1205
1206static int lpass_platform_pcmops_resume(struct snd_soc_component *component)
1207{
1208	struct lpass_data *drvdata = snd_soc_component_get_drvdata(component);
1209	struct regmap *map;
1210	unsigned int dai_id = component->id;
1211
1212	if (dai_id == LPASS_DP_RX)
1213		map = drvdata->hdmiif_map;
1214	else
1215		map = drvdata->lpaif_map;
1216
1217	regcache_cache_only(map, false);
1218	return regcache_sync(map);
1219}
1220
1221static 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)
1225{
1226	struct snd_pcm_runtime *rt = substream->runtime;
1227	unsigned int dai_id = component->id;
1228	int ret = 0;
1229
1230	void __iomem *dma_buf = (void __iomem *) (rt->dma_area + pos +
1231				channel * (rt->dma_bytes / rt->channels));
1232
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);
1236		} else {
1237			if (copy_from_iter((void __force *)dma_buf, bytes, buf) != bytes)
1238				ret = -EFAULT;
1239		}
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);
1243		} else {
1244			if (copy_to_iter((void __force *)dma_buf, bytes, buf) != bytes)
1245				ret = -EFAULT;
1246		}
1247	}
1248
1249	return ret;
1250}
1251
1252static const struct snd_soc_component_driver lpass_component_driver = {
1253	.name		= DRV_NAME,
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,
1266
1267};
1268
1269int asoc_qcom_lpass_platform_register(struct platform_device *pdev)
1270{
1271	struct lpass_data *drvdata = platform_get_drvdata(pdev);
1272	const struct lpass_variant *v = drvdata->variant;
1273	int ret;
1274
1275	drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif");
1276	if (drvdata->lpaif_irq < 0)
1277		return -ENODEV;
1278
1279	/* ensure audio hardware is disabled */
1280	ret = regmap_write(drvdata->lpaif_map,
1281			LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0);
1282	if (ret) {
1283		dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret);
1284		return ret;
1285	}
1286
1287	ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq,
1288			lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING,
1289			"lpass-irq-lpaif", drvdata);
1290	if (ret) {
1291		dev_err(&pdev->dev, "irq request failed: %d\n", ret);
1292		return ret;
1293	}
1294
1295	ret = lpass_platform_alloc_dmactl_fields(&pdev->dev,
1296						 drvdata->lpaif_map);
1297	if (ret) {
1298		dev_err(&pdev->dev,
1299			"error initializing dmactl fields: %d\n", ret);
1300		return ret;
1301	}
1302
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);
1306		if (ret) {
1307			dev_err(&pdev->dev, "error writing to rxtx irqen reg: %d\n", ret);
1308			return ret;
1309		}
1310		ret = regmap_write(drvdata->va_lpaif_map,
1311			LPAIF_VA_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0x0);
1312		if (ret) {
1313			dev_err(&pdev->dev, "error writing to rxtx irqen reg: %d\n", ret);
1314			return ret;
1315		}
1316		drvdata->rxtxif_irq = platform_get_irq_byname(pdev, "lpass-irq-rxtxif");
1317		if (drvdata->rxtxif_irq < 0)
1318			return -ENODEV;
1319
1320		ret = devm_request_irq(&pdev->dev, drvdata->rxtxif_irq,
1321				lpass_platform_rxtxif_irq, 0, "lpass-irq-rxtxif", drvdata);
1322		if (ret) {
1323			dev_err(&pdev->dev, "rxtx irq request failed: %d\n", ret);
1324			return ret;
1325		}
1326
1327		ret = lpass_platform_alloc_rxtx_dmactl_fields(&pdev->dev,
1328						 drvdata->rxtx_lpaif_map);
1329		if (ret) {
1330			dev_err(&pdev->dev,
1331				"error initializing rxtx dmactl fields: %d\n", ret);
1332			return ret;
1333		}
1334
1335		drvdata->vaif_irq = platform_get_irq_byname(pdev, "lpass-irq-vaif");
1336		if (drvdata->vaif_irq < 0)
1337			return -ENODEV;
1338
1339		ret = devm_request_irq(&pdev->dev, drvdata->vaif_irq,
1340				lpass_platform_vaif_irq, 0, "lpass-irq-vaif", drvdata);
1341		if (ret) {
1342			dev_err(&pdev->dev, "va irq request failed: %d\n", ret);
1343			return ret;
1344		}
1345
1346		ret = lpass_platform_alloc_va_dmactl_fields(&pdev->dev,
1347						 drvdata->va_lpaif_map);
1348		if (ret) {
1349			dev_err(&pdev->dev,
1350				"error initializing va dmactl fields: %d\n", ret);
1351			return ret;
1352		}
1353	}
1354
1355	if (drvdata->hdmi_port_enable) {
1356		drvdata->hdmiif_irq = platform_get_irq_byname(pdev, "lpass-irq-hdmi");
1357		if (drvdata->hdmiif_irq < 0)
1358			return -ENODEV;
1359
1360		ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq,
1361				lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", drvdata);
1362		if (ret) {
1363			dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret);
1364			return ret;
1365		}
1366		ret = regmap_write(drvdata->hdmiif_map,
1367				LPASS_HDMITX_APP_IRQEN_REG(v), 0);
1368		if (ret) {
1369			dev_err(&pdev->dev, "error writing to hdmi irqen reg: %d\n", ret);
1370			return ret;
1371		}
1372
1373		ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev,
1374							 drvdata->hdmiif_map);
1375		if (ret) {
1376			dev_err(&pdev->dev,
1377				"error initializing hdmidmactl fields: %d\n", ret);
1378			return ret;
1379		}
1380	}
1381	return devm_snd_soc_register_component(&pdev->dev,
1382			&lpass_component_driver, NULL, 0);
1383}
1384EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register);
1385
1386MODULE_DESCRIPTION("QTi LPASS Platform Driver");
1387MODULE_LICENSE("GPL");
1388