aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/qcom
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2015-05-16 08:32:34 -0400
committerMark Brown <broonie@kernel.org>2015-05-21 16:12:39 -0400
commit6db1c6ba9544e99778e0fdebe2d62c917fe1811c (patch)
tree05958b19c51dffdc04e0b5be1b05d298a6160daf /sound/soc/qcom
parent0ae9fd3b2c99099d5a800057b4092fdaa0e973a7 (diff)
ASoC: qcom: remove hardcoded dma channel
This patch removes hardcoded dma channel value in lpass driver, Now the dma channel allocation happens in the SOC specific layer. This will allow different LPASS integrations to use the lpass driver in more generic way. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Tested-by: Kenneth Westfield <kwestfie@codeaurora.org> Acked-by: Kenneth Westfield <kwestfie@codeaurora.org> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/qcom')
-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;