diff options
| -rw-r--r-- | sound/soc/qcom/lpass-ipq806x.c | 12 | ||||
| -rw-r--r-- | sound/soc/qcom/lpass-platform.c | 93 | ||||
| -rw-r--r-- | sound/soc/qcom/lpass.h | 2 |
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 | ||
| 66 | int ipq806x_lpass_alloc_dma_channel(struct lpass_data *drvdata) | ||
| 67 | { | ||
| 68 | return IPQ806X_LPAIF_RDMA_CHAN_MI2S; | ||
| 69 | } | ||
| 70 | |||
| 71 | int ipq806x_lpass_free_dma_channel(struct lpass_data *drvdata, int chan) | ||
| 72 | { | ||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 66 | struct lpass_variant ipq806x_data = { | 76 | struct 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 | ||
| 80 | static const struct of_device_id ipq806x_lpass_cpu_device_id[] = { | 92 | static 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 | ||
| 27 | struct 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, | |||
| 164 | static int lpass_platform_pcmops_hw_free(struct snd_pcm_substream *substream) | 170 | static 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; |
