aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/qcom/lpass-ipq806x.c12
-rw-r--r--sound/soc/qcom/lpass-platform.c93
-rw-r--r--sound/soc/qcom/lpass.h2
3 files changed, 77 insertions, 30 deletions
diff --git a/sound/soc/qcom/lpass-ipq806x.c b/sound/soc/qcom/lpass-ipq806x.c
index cc5f3b4857eb..2eab828644e8 100644
--- a/sound/soc/qcom/lpass-ipq806x.c
+++ b/sound/soc/qcom/lpass-ipq806x.c
@@ -63,6 +63,16 @@ static struct snd_soc_dai_driver ipq806x_lpass_cpu_dai_driver = {
63 .ops = &asoc_qcom_lpass_cpu_dai_ops, 63 .ops = &asoc_qcom_lpass_cpu_dai_ops,
64}; 64};
65 65
66int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata)
67{
68 return IPQ806X_LPAIF_RDMA_CHAN_MI2S;
69}
70
71int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan)
72{
73 return 0;
74}
75
66struct lpass_variant ipq806x_data = { 76struct lpass_variant ipq806x_data = {
67 .i2sctrl_reg_base = 0x0010, 77 .i2sctrl_reg_base = 0x0010,
68 .i2sctrl_reg_stride = 0x04, 78 .i2sctrl_reg_stride = 0x04,
@@ -75,6 +85,8 @@ struct lpass_variant ipq806x_data = {
75 .rdma_channels = 4, 85 .rdma_channels = 4,
76 .dai_driver = &ipq806x_lpass_cpu_dai_driver, 86 .dai_driver = &ipq806x_lpass_cpu_dai_driver,
77 .num_dai = 1, 87 .num_dai = 1,
88 .alloc_dma_channel = ipq806x_lpass_alloc_dma_channel,
89 .free_dma_channel = ipq806x_lpass_free_dma_channel,
78}; 90};
79 91
80static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { 92static const struct of_device_id ipq806x_lpass_cpu_device_id[] = {
diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c
index a38e7ecf244f..fc0889196e7a 100644
--- a/sound/soc/qcom/lpass-platform.c
+++ b/sound/soc/qcom/lpass-platform.c
@@ -24,6 +24,11 @@
24#include "lpass-lpaif-reg.h" 24#include "lpass-lpaif-reg.h"
25#include "lpass.h" 25#include "lpass.h"
26 26
27struct lpass_pcm_data {
28 int rdma_ch;
29 int i2s_port;
30};
31
27#define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024) 32#define LPASS_PLATFORM_BUFFER_SIZE (16 * 1024)
28#define LPASS_PLATFORM_PERIODS 2 33#define LPASS_PLATFORM_PERIODS 2
29 34
@@ -78,6 +83,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
78 struct snd_pcm_hw_params *params) 83 struct snd_pcm_hw_params *params)
79{ 84{
80 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 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);
81 struct lpass_data *drvdata = 87 struct lpass_data *drvdata =
82 snd_soc_platform_get_drvdata(soc_runtime->platform); 88 snd_soc_platform_get_drvdata(soc_runtime->platform);
83 struct lpass_variant *v = drvdata->variant; 89 struct lpass_variant *v = drvdata->variant;
@@ -85,7 +91,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
85 unsigned int channels = params_channels(params); 91 unsigned int channels = params_channels(params);
86 unsigned int regval; 92 unsigned int regval;
87 int bitwidth; 93 int bitwidth;
88 int ret; 94 int ret, rdma_port = pcm_data->i2s_port;
89 95
90 bitwidth = snd_pcm_format_width(format); 96 bitwidth = snd_pcm_format_width(format);
91 if (bitwidth < 0) { 97 if (bitwidth < 0) {
@@ -95,7 +101,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
95 } 101 }
96 102
97 regval = LPAIF_RDMACTL_BURSTEN_INCR4 | 103 regval = LPAIF_RDMACTL_BURSTEN_INCR4 |
98 LPAIF_RDMACTL_AUDINTF_MI2S | 104 LPAIF_RDMACTL_AUDINTF(rdma_port) |
99 LPAIF_RDMACTL_FIFOWM_8; 105 LPAIF_RDMACTL_FIFOWM_8;
100 106
101 switch (bitwidth) { 107 switch (bitwidth) {
@@ -151,7 +157,7 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
151 } 157 }
152 158
153 ret = regmap_write(drvdata->lpaif_map, 159 ret = regmap_write(drvdata->lpaif_map,
154 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), regval); 160 LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), regval);
155 if (ret) { 161 if (ret) {
156 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 162 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
157 __func__, ret); 163 __func__, ret);
@@ -164,13 +170,14 @@ static int lpass_platform_pcmops_hw_params(struct snd_pcm_substream *substream,
164static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) 170static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream)
165{ 171{
166 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 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);
167 struct lpass_data *drvdata = 174 struct lpass_data *drvdata =
168 snd_soc_platform_get_drvdata(soc_runtime->platform); 175 snd_soc_platform_get_drvdata(soc_runtime->platform);
169 struct lpass_variant *v = drvdata->variant; 176 struct lpass_variant *v = drvdata->variant;
170 int ret; 177 int ret;
171 178
172 ret = regmap_write(drvdata->lpaif_map, 179 ret = regmap_write(drvdata->lpaif_map,
173 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); 180 LPAIF_RDMACTL_REG(v, pcm_data->rdma_ch), 0);
174 if (ret) 181 if (ret)
175 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 182 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
176 __func__, ret); 183 __func__, ret);
@@ -182,13 +189,14 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
182{ 189{
183 struct snd_pcm_runtime *runtime = substream->runtime; 190 struct snd_pcm_runtime *runtime = substream->runtime;
184 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 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);
185 struct lpass_data *drvdata = 193 struct lpass_data *drvdata =
186 snd_soc_platform_get_drvdata(soc_runtime->platform); 194 snd_soc_platform_get_drvdata(soc_runtime->platform);
187 struct lpass_variant *v = drvdata->variant; 195 struct lpass_variant *v = drvdata->variant;
188 int ret; 196 int ret, ch = pcm_data->rdma_ch;
189 197
190 ret = regmap_write(drvdata->lpaif_map, 198 ret = regmap_write(drvdata->lpaif_map,
191 LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), 199 LPAIF_RDMABASE_REG(v, ch),
192 runtime->dma_addr); 200 runtime->dma_addr);
193 if (ret) { 201 if (ret) {
194 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n", 202 dev_err(soc_runtime->dev, "%s() error writing to rdmabase reg: %d\n",
@@ -197,7 +205,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
197 } 205 }
198 206
199 ret = regmap_write(drvdata->lpaif_map, 207 ret = regmap_write(drvdata->lpaif_map,
200 LPAIF_RDMABUFF_REG(v, LPAIF_RDMA_CHAN_MI2S), 208 LPAIF_RDMABUFF_REG(v, ch),
201 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); 209 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1);
202 if (ret) { 210 if (ret) {
203 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n", 211 dev_err(soc_runtime->dev, "%s() error writing to rdmabuff reg: %d\n",
@@ -206,7 +214,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
206 } 214 }
207 215
208 ret = regmap_write(drvdata->lpaif_map, 216 ret = regmap_write(drvdata->lpaif_map,
209 LPAIF_RDMAPER_REG(v, LPAIF_RDMA_CHAN_MI2S), 217 LPAIF_RDMAPER_REG(v, ch),
210 (snd_pcm_lib_period_bytes(substream) >> 2) - 1); 218 (snd_pcm_lib_period_bytes(substream) >> 2) - 1);
211 if (ret) { 219 if (ret) {
212 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n", 220 dev_err(soc_runtime->dev, "%s() error writing to rdmaper reg: %d\n",
@@ -215,7 +223,7 @@ static int lpass_platform_pcmops_prepare(struct snd_pcm_substream *substream)
215 } 223 }
216 224
217 ret = regmap_update_bits(drvdata->lpaif_map, 225 ret = regmap_update_bits(drvdata->lpaif_map,
218 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 226 LPAIF_RDMACTL_REG(v, ch),
219 LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON); 227 LPAIF_RDMACTL_ENABLE_MASK, LPAIF_RDMACTL_ENABLE_ON);
220 if (ret) { 228 if (ret) {
221 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 229 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
@@ -230,10 +238,11 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
230 int cmd) 238 int cmd)
231{ 239{
232 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 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);
233 struct lpass_data *drvdata = 242 struct lpass_data *drvdata =
234 snd_soc_platform_get_drvdata(soc_runtime->platform); 243 snd_soc_platform_get_drvdata(soc_runtime->platform);
235 struct lpass_variant *v = drvdata->variant; 244 struct lpass_variant *v = drvdata->variant;
236 int ret; 245 int ret, ch = pcm_data->rdma_ch;
237 246
238 switch (cmd) { 247 switch (cmd) {
239 case SNDRV_PCM_TRIGGER_START: 248 case SNDRV_PCM_TRIGGER_START:
@@ -242,7 +251,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
242 /* clear status before enabling interrupts */ 251 /* clear status before enabling interrupts */
243 ret = regmap_write(drvdata->lpaif_map, 252 ret = regmap_write(drvdata->lpaif_map,
244 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 253 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
245 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); 254 LPAIF_IRQ_ALL(ch));
246 if (ret) { 255 if (ret) {
247 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 256 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
248 __func__, ret); 257 __func__, ret);
@@ -251,8 +260,8 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
251 260
252 ret = regmap_update_bits(drvdata->lpaif_map, 261 ret = regmap_update_bits(drvdata->lpaif_map,
253 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 262 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
254 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 263 LPAIF_IRQ_ALL(ch),
255 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S)); 264 LPAIF_IRQ_ALL(ch));
256 if (ret) { 265 if (ret) {
257 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 266 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
258 __func__, ret); 267 __func__, ret);
@@ -260,7 +269,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
260 } 269 }
261 270
262 ret = regmap_update_bits(drvdata->lpaif_map, 271 ret = regmap_update_bits(drvdata->lpaif_map,
263 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 272 LPAIF_RDMACTL_REG(v, ch),
264 LPAIF_RDMACTL_ENABLE_MASK, 273 LPAIF_RDMACTL_ENABLE_MASK,
265 LPAIF_RDMACTL_ENABLE_ON); 274 LPAIF_RDMACTL_ENABLE_ON);
266 if (ret) { 275 if (ret) {
@@ -273,7 +282,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
273 case SNDRV_PCM_TRIGGER_SUSPEND: 282 case SNDRV_PCM_TRIGGER_SUSPEND:
274 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 283 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
275 ret = regmap_update_bits(drvdata->lpaif_map, 284 ret = regmap_update_bits(drvdata->lpaif_map,
276 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 285 LPAIF_RDMACTL_REG(v, ch),
277 LPAIF_RDMACTL_ENABLE_MASK, 286 LPAIF_RDMACTL_ENABLE_MASK,
278 LPAIF_RDMACTL_ENABLE_OFF); 287 LPAIF_RDMACTL_ENABLE_OFF);
279 if (ret) { 288 if (ret) {
@@ -284,7 +293,7 @@ static int lpass_platform_pcmops_trigger(struct snd_pcm_substream *substream,
284 293
285 ret = regmap_update_bits(drvdata->lpaif_map, 294 ret = regmap_update_bits(drvdata->lpaif_map,
286 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 295 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST),
287 LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S), 0); 296 LPAIF_IRQ_ALL(ch), 0);
288 if (ret) { 297 if (ret) {
289 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n", 298 dev_err(soc_runtime->dev, "%s() error writing to irqen reg: %d\n",
290 __func__, ret); 299 __func__, ret);
@@ -300,15 +309,15 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
300 struct snd_pcm_substream *substream) 309 struct snd_pcm_substream *substream)
301{ 310{
302 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 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);
303 struct lpass_data *drvdata = 313 struct lpass_data *drvdata =
304 snd_soc_platform_get_drvdata(soc_runtime->platform); 314 snd_soc_platform_get_drvdata(soc_runtime->platform);
305 struct lpass_variant *v = drvdata->variant; 315 struct lpass_variant *v = drvdata->variant;
306 unsigned int base_addr, curr_addr; 316 unsigned int base_addr, curr_addr;
307 int ret; 317 int ret, ch = pcm_data->rdma_ch;
308 318
309 ret = regmap_read(drvdata->lpaif_map, 319 ret = regmap_read(drvdata->lpaif_map,
310 LPAIF_RDMABASE_REG(v, LPAIF_RDMA_CHAN_MI2S), 320 LPAIF_RDMABASE_REG(v, ch), &base_addr);
311 &base_addr);
312 if (ret) { 321 if (ret) {
313 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n", 322 dev_err(soc_runtime->dev, "%s() error reading from rdmabase reg: %d\n",
314 __func__, ret); 323 __func__, ret);
@@ -316,8 +325,7 @@ static snd_pcm_uframes_t lpass_platform_pcmops_pointer(
316 } 325 }
317 326
318 ret = regmap_read(drvdata->lpaif_map, 327 ret = regmap_read(drvdata->lpaif_map,
319 LPAIF_RDMACURR_REG(v, LPAIF_RDMA_CHAN_MI2S), 328 LPAIF_RDMACURR_REG(v, ch), &curr_addr);
320 &curr_addr);
321 if (ret) { 329 if (ret) {
322 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n", 330 dev_err(soc_runtime->dev, "%s() error reading from rdmacurr reg: %d\n",
323 __func__, ret); 331 __func__, ret);
@@ -355,9 +363,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
355 struct lpass_data *drvdata = 363 struct lpass_data *drvdata =
356 snd_soc_platform_get_drvdata(soc_runtime->platform); 364 snd_soc_platform_get_drvdata(soc_runtime->platform);
357 struct lpass_variant *v = drvdata->variant; 365 struct lpass_variant *v = drvdata->variant;
366 struct lpass_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(soc_runtime);
358 unsigned int interrupts; 367 unsigned int interrupts;
359 irqreturn_t ret = IRQ_NONE; 368 irqreturn_t ret = IRQ_NONE;
360 int rv; 369 int rv, chan = pcm_data->rdma_ch;
361 370
362 rv = regmap_read(drvdata->lpaif_map, 371 rv = regmap_read(drvdata->lpaif_map,
363 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts); 372 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &interrupts);
@@ -366,12 +375,13 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
366 __func__, rv); 375 __func__, rv);
367 return IRQ_NONE; 376 return IRQ_NONE;
368 } 377 }
369 interrupts &= LPAIF_IRQ_ALL(LPAIF_RDMA_CHAN_MI2S);
370 378
371 if (interrupts & LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)) { 379 interrupts &= LPAIF_IRQ_ALL(chan);
380
381 if (interrupts & LPAIF_IRQ_PER(chan)) {
372 rv = regmap_write(drvdata->lpaif_map, 382 rv = regmap_write(drvdata->lpaif_map,
373 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 383 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
374 LPAIF_IRQ_PER(LPAIF_RDMA_CHAN_MI2S)); 384 LPAIF_IRQ_PER(chan));
375 if (rv) { 385 if (rv) {
376 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 386 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
377 __func__, rv); 387 __func__, rv);
@@ -381,10 +391,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
381 ret = IRQ_HANDLED; 391 ret = IRQ_HANDLED;
382 } 392 }
383 393
384 if (interrupts & LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)) { 394 if (interrupts & LPAIF_IRQ_XRUN(chan)) {
385 rv = regmap_write(drvdata->lpaif_map, 395 rv = regmap_write(drvdata->lpaif_map,
386 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 396 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
387 LPAIF_IRQ_XRUN(LPAIF_RDMA_CHAN_MI2S)); 397 LPAIF_IRQ_XRUN(chan));
388 if (rv) { 398 if (rv) {
389 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 399 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
390 __func__, rv); 400 __func__, rv);
@@ -395,10 +405,10 @@ static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data)
395 ret = IRQ_HANDLED; 405 ret = IRQ_HANDLED;
396 } 406 }
397 407
398 if (interrupts & LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)) { 408 if (interrupts & LPAIF_IRQ_ERR(chan)) {
399 rv = regmap_write(drvdata->lpaif_map, 409 rv = regmap_write(drvdata->lpaif_map,
400 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST), 410 LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST),
401 LPAIF_IRQ_ERR(LPAIF_RDMA_CHAN_MI2S)); 411 LPAIF_IRQ_ERR(chan));
402 if (rv) { 412 if (rv) {
403 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n", 413 dev_err(soc_runtime->dev, "%s() error writing to irqclear reg: %d\n",
404 __func__, rv); 414 __func__, rv);
@@ -450,10 +460,26 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
450 struct snd_pcm *pcm = soc_runtime->pcm; 460 struct snd_pcm *pcm = soc_runtime->pcm;
451 struct snd_pcm_substream *substream = 461 struct snd_pcm_substream *substream =
452 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 462 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
463 struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
453 struct lpass_data *drvdata = 464 struct lpass_data *drvdata =
454 snd_soc_platform_get_drvdata(soc_runtime->platform); 465 snd_soc_platform_get_drvdata(soc_runtime->platform);
455 struct lpass_variant *v = drvdata->variant; 466 struct lpass_variant *v = drvdata->variant;
456 int ret; 467 int ret;
468 struct lpass_pcm_data *data;
469
470 data = devm_kzalloc(soc_runtime->dev, sizeof(*data), GFP_KERNEL);
471 if (!data)
472 return -ENOMEM;
473
474 if (v->alloc_dma_channel)
475 data->rdma_ch = v->alloc_dma_channel(drvdata);
476
477 if (IS_ERR_VALUE(data->rdma_ch))
478 return data->rdma_ch;
479
480 data->i2s_port = cpu_dai->driver->id;
481
482 snd_soc_pcm_set_drvdata(soc_runtime, data);
457 483
458 soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32); 484 soc_runtime->dev->coherent_dma_mask = DMA_BIT_MASK(32);
459 soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask; 485 soc_runtime->dev->dma_mask = &soc_runtime->dev->coherent_dma_mask;
@@ -480,7 +506,7 @@ static int lpass_platform_pcm_new(struct snd_soc_pcm_runtime *soc_runtime)
480 return ret; 506 return ret;
481 } 507 }
482 ret = regmap_write(drvdata->lpaif_map, 508 ret = regmap_write(drvdata->lpaif_map,
483 LPAIF_RDMACTL_REG(v, LPAIF_RDMA_CHAN_MI2S), 0); 509 LPAIF_RDMACTL_REG(v, data->rdma_ch), 0);
484 if (ret) { 510 if (ret) {
485 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n", 511 dev_err(soc_runtime->dev, "%s() error writing to rdmactl reg: %d\n",
486 __func__, ret); 512 __func__, ret);
@@ -499,6 +525,13 @@ static void lpass_platform_pcm_free(struct snd_pcm *pcm)
499 struct snd_pcm_substream *substream = 525 struct snd_pcm_substream *substream =
500 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 526 pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
501 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data; 527 struct snd_soc_pcm_runtime *soc_runtime = substream->private_data;
528 struct lpass_data *drvdata =
529 snd_soc_platform_get_drvdata(soc_runtime->platform);
530 struct lpass_pcm_data *data = snd_soc_pcm_get_drvdata(soc_runtime);
531 struct lpass_variant *v = drvdata->variant;
532
533 if (v->free_dma_channel)
534 v->free_dma_channel(drvdata, data->rdma_ch);
502 535
503 lpass_platform_free_buffer(substream, soc_runtime); 536 lpass_platform_free_buffer(substream, soc_runtime);
504} 537}
diff --git a/sound/soc/qcom/lpass.h b/sound/soc/qcom/lpass.h
index fa00be43e923..caaf17fb0015 100644
--- a/sound/soc/qcom/lpass.h
+++ b/sound/soc/qcom/lpass.h
@@ -63,6 +63,8 @@ struct lpass_variant {
63 /* SOC specific intialization like clocks */ 63 /* SOC specific intialization like clocks */
64 int (*init)(struct platform_device *pdev); 64 int (*init)(struct platform_device *pdev);
65 int (*exit)(struct platform_device *pdev); 65 int (*exit)(struct platform_device *pdev);
66 int (*alloc_dma_channel)(struct lpass_data *data);
67 int (*free_dma_channel)(struct lpass_data *data, int ch);
66 68
67 /* SOC specific dais */ 69 /* SOC specific dais */
68 struct snd_soc_dai_driver *dai_driver; 70 struct snd_soc_dai_driver *dai_driver;