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 28 static const struct snd_pcm_hardware lpass_platform_pcm_hardware = { 29 .info = SNDRV_PCM_INFO_MMAP | 30 SNDRV_PCM_INFO_MMAP_VALID | 31 SNDRV_PCM_INFO_INTERLEAVED | 32 SNDRV_PCM_INFO_PAUSE | 33 SNDRV_PCM_INFO_RESUME, 34 .formats = SNDRV_PCM_FMTBIT_S16 | 35 SNDRV_PCM_FMTBIT_S24 | 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 52 static const struct snd_pcm_hardware lpass_platform_rxtx_hardware = { 53 .info = SNDRV_PCM_INFO_MMAP | 54 SNDRV_PCM_INFO_MMAP_VALID | 55 SNDRV_PCM_INFO_INTERLEAVED | 56 SNDRV_PCM_INFO_PAUSE | 57 SNDRV_PCM_INFO_RESUME, 58 .formats = SNDRV_PCM_FMTBIT_S16 | 59 SNDRV_PCM_FMTBIT_S24 | 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 76 static const struct snd_pcm_hardware lpass_platform_va_hardware = { 77 .info = SNDRV_PCM_INFO_MMAP | 78 SNDRV_PCM_INFO_MMAP_VALID | 79 SNDRV_PCM_INFO_INTERLEAVED | 80 SNDRV_PCM_INFO_PAUSE | 81 SNDRV_PCM_INFO_RESUME, 82 .formats = SNDRV_PCM_FMTBIT_S16 | 83 SNDRV_PCM_FMTBIT_S24 | 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 100 static 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 128 static 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 145 static 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 175 static 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 192 static 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 284 static 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 322 static 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 354 static 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 389 static 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 416 static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, 417 struct snd_pcm_substream *substream, 418 struct snd_pcm_hw_params *params) 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 570 static 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 597 static 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 660 static 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 859 static 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 896 static 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 911 static 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 925 static 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 1021 static 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 1049 static 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 1079 static 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 1104 static 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 1128 static 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 1169 static 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 1189 static 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 1206 static 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 1221 static int lpass_platform_copy(struct snd_soc_component *component, 1222 struct snd_pcm_substream *substream, int channel, 1223 unsigned long pos, struct iov_iter *buf, 1224 unsigned long bytes) 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 1252 static 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 1269 int 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 } 1384 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register); 1385 1386 MODULE_DESCRIPTION("QTi LPASS Platform Driver"); 1387 MODULE_LICENSE("GPL"); 1388
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.