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 <linux/dma-mapping.h> 9 #include <linux/export.h> 10 #include <linux/kernel.h> 11 #include <linux/module.h> 12 #include <linux/platform_device.h> 13 #include <sound/pcm_params.h> 14 #include <linux/regmap.h> 15 #include <sound/soc.h> 16 #include "lpass-lpaif-reg.h" 17 #include "lpass.h" 18 19 #define DRV_NAME "lpass-platform" 20 21 struct lpass_pcm_data { 22 int dma_ch; 23 int i2s_port; 24 }; 25 26 #define LPASS_PLATFORM_BUFFER_SIZE (24 * 2 * 1024) 27 #define LPASS_PLATFORM_PERIODS 2 28 29 static const struct snd_pcm_hardware lpass_platform_pcm_hardware = { 30 .info = SNDRV_PCM_INFO_MMAP | 31 SNDRV_PCM_INFO_MMAP_VALID | 32 SNDRV_PCM_INFO_INTERLEAVED | 33 SNDRV_PCM_INFO_PAUSE | 34 SNDRV_PCM_INFO_RESUME, 35 .formats = SNDRV_PCM_FMTBIT_S16 | 36 SNDRV_PCM_FMTBIT_S24 | 37 SNDRV_PCM_FMTBIT_S32, 38 .rates = SNDRV_PCM_RATE_8000_192000, 39 .rate_min = 8000, 40 .rate_max = 192000, 41 .channels_min = 1, 42 .channels_max = 8, 43 .buffer_bytes_max = LPASS_PLATFORM_BUFFER_SIZE, 44 .period_bytes_max = LPASS_PLATFORM_BUFFER_SIZE / 45 LPASS_PLATFORM_PERIODS, 46 .period_bytes_min = LPASS_PLATFORM_BUFFER_SIZE / 47 LPASS_PLATFORM_PERIODS, 48 .periods_min = LPASS_PLATFORM_PERIODS, 49 .periods_max = LPASS_PLATFORM_PERIODS, 50 .fifo_size = 0, 51 }; 52 53 static int lpass_platform_alloc_dmactl_fields(struct device *dev, 54 struct regmap *map) 55 { 56 struct lpass_data *drvdata = dev_get_drvdata(dev); 57 struct lpass_variant *v = drvdata->variant; 58 struct lpaif_dmactl *rd_dmactl, *wr_dmactl; 59 int rval; 60 61 drvdata->rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), 62 GFP_KERNEL); 63 if (drvdata->rd_dmactl == NULL) 64 return -ENOMEM; 65 66 drvdata->wr_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), 67 GFP_KERNEL); 68 if (drvdata->wr_dmactl == NULL) 69 return -ENOMEM; 70 71 rd_dmactl = drvdata->rd_dmactl; 72 wr_dmactl = drvdata->wr_dmactl; 73 74 rval = devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->intf, 75 &v->rdma_intf, 6); 76 if (rval) 77 return rval; 78 79 return devm_regmap_field_bulk_alloc(dev, map, &wr_dmactl->intf, 80 &v->wrdma_intf, 6); 81 } 82 83 static int lpass_platform_alloc_hdmidmactl_fields(struct device *dev, 84 struct regmap *map) 85 { 86 struct lpass_data *drvdata = dev_get_drvdata(dev); 87 struct lpass_variant *v = drvdata->variant; 88 struct lpaif_dmactl *rd_dmactl; 89 90 rd_dmactl = devm_kzalloc(dev, sizeof(struct lpaif_dmactl), GFP_KERNEL); 91 if (rd_dmactl == NULL) 92 return -ENOMEM; 93 94 drvdata->hdmi_rd_dmactl = rd_dmactl; 95 96 return devm_regmap_field_bulk_alloc(dev, map, &rd_dmactl->bursten, 97 &v->hdmi_rdma_bursten, 8); 98 } 99 100 static int lpass_platform_pcmops_open(struct snd_soc_component *component, 101 struct snd_pcm_substream *substream) 102 { 103 struct snd_pcm_runtime *runtime = substream->runtime; 104 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 105 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 106 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 107 struct lpass_variant *v = drvdata->variant; 108 int ret, dma_ch, dir = substream->stream; 109 struct lpass_pcm_data *data; 110 struct regmap *map; 111 unsigned int dai_id = cpu_dai->driver->id; 112 113 data = kzalloc(sizeof(*data), GFP_KERNEL); 114 if (!data) 115 return -ENOMEM; 116 117 data->i2s_port = cpu_dai->driver->id; 118 runtime->private_data = data; 119 120 if (v->alloc_dma_channel) 121 dma_ch = v->alloc_dma_channel(drvdata, dir, dai_id); 122 else 123 dma_ch = 0; 124 125 if (dma_ch < 0) { 126 kfree(data); 127 return dma_ch; 128 } 129 130 if (cpu_dai->driver->id == LPASS_DP_RX) { 131 map = drvdata->hdmiif_map; 132 drvdata->hdmi_substream[dma_ch] = substream; 133 } else { 134 map = drvdata->lpaif_map; 135 drvdata->substream[dma_ch] = substream; 136 } 137 data->dma_ch = dma_ch; 138 ret = regmap_write(map, 139 LPAIF_DMACTL_REG(v, dma_ch, dir, data->i2s_port), 0); 140 if (ret) { 141 dev_err(soc_runtime->dev, 142 "error writing to rdmactl reg: %d\n", ret); 143 return ret; 144 } 145 snd_soc_set_runtime_hwparams(substream, &lpass_platform_pcm_hardware); 146 147 runtime->dma_bytes = lpass_platform_pcm_hardware.buffer_bytes_max; 148 149 ret = snd_pcm_hw_constraint_integer(runtime, 150 SNDRV_PCM_HW_PARAM_PERIODS); 151 if (ret < 0) { 152 kfree(data); 153 dev_err(soc_runtime->dev, "setting constraints failed: %d\n", 154 ret); 155 return -EINVAL; 156 } 157 158 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); 159 160 return 0; 161 } 162 163 static int lpass_platform_pcmops_close(struct snd_soc_component *component, 164 struct snd_pcm_substream *substream) 165 { 166 struct snd_pcm_runtime *runtime = substream->runtime; 167 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 168 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 169 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 170 struct lpass_variant *v = drvdata->variant; 171 struct lpass_pcm_data *data; 172 unsigned int dai_id = cpu_dai->driver->id; 173 174 data = runtime->private_data; 175 if (dai_id == LPASS_DP_RX) 176 drvdata->hdmi_substream[data->dma_ch] = NULL; 177 else 178 drvdata->substream[data->dma_ch] = NULL; 179 if (v->free_dma_channel) 180 v->free_dma_channel(drvdata, data->dma_ch, dai_id); 181 182 kfree(data); 183 return 0; 184 } 185 186 static int lpass_platform_pcmops_hw_params(struct snd_soc_component *component, 187 struct snd_pcm_substream *substream, 188 struct snd_pcm_hw_params *params) 189 { 190 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 191 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 192 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 193 struct snd_pcm_runtime *rt = substream->runtime; 194 struct lpass_pcm_data *pcm_data = rt->private_data; 195 struct lpass_variant *v = drvdata->variant; 196 snd_pcm_format_t format = params_format(params); 197 unsigned int channels = params_channels(params); 198 unsigned int regval; 199 struct lpaif_dmactl *dmactl; 200 int id, dir = substream->stream; 201 int bitwidth; 202 int ret, dma_port = pcm_data->i2s_port + v->dmactl_audif_start; 203 unsigned int dai_id = cpu_dai->driver->id; 204 205 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 206 id = pcm_data->dma_ch; 207 if (dai_id == LPASS_DP_RX) 208 dmactl = drvdata->hdmi_rd_dmactl; 209 else 210 dmactl = drvdata->rd_dmactl; 211 212 } else { 213 dmactl = drvdata->wr_dmactl; 214 id = pcm_data->dma_ch - v->wrdma_channel_start; 215 } 216 217 bitwidth = snd_pcm_format_width(format); 218 if (bitwidth < 0) { 219 dev_err(soc_runtime->dev, "invalid bit width given: %d\n", 220 bitwidth); 221 return bitwidth; 222 } 223 224 ret = regmap_fields_write(dmactl->bursten, id, LPAIF_DMACTL_BURSTEN_INCR4); 225 if (ret) { 226 dev_err(soc_runtime->dev, "error updating bursten field: %d\n", ret); 227 return ret; 228 } 229 230 ret = regmap_fields_write(dmactl->fifowm, id, LPAIF_DMACTL_FIFOWM_8); 231 if (ret) { 232 dev_err(soc_runtime->dev, "error updating fifowm field: %d\n", ret); 233 return ret; 234 } 235 236 switch (dai_id) { 237 case LPASS_DP_RX: 238 ret = regmap_fields_write(dmactl->burst8, id, 239 LPAIF_DMACTL_BURSTEN_INCR4); 240 if (ret) { 241 dev_err(soc_runtime->dev, "error updating burst8en field: %d\n", ret); 242 return ret; 243 } 244 ret = regmap_fields_write(dmactl->burst16, id, 245 LPAIF_DMACTL_BURSTEN_INCR4); 246 if (ret) { 247 dev_err(soc_runtime->dev, "error updating burst16en field: %d\n", ret); 248 return ret; 249 } 250 ret = regmap_fields_write(dmactl->dynburst, id, 251 LPAIF_DMACTL_BURSTEN_INCR4); 252 if (ret) { 253 dev_err(soc_runtime->dev, "error updating dynbursten field: %d\n", ret); 254 return ret; 255 } 256 break; 257 case MI2S_PRIMARY: 258 case MI2S_SECONDARY: 259 ret = regmap_fields_write(dmactl->intf, id, 260 LPAIF_DMACTL_AUDINTF(dma_port)); 261 if (ret) { 262 dev_err(soc_runtime->dev, "error updating audio interface field: %d\n", 263 ret); 264 return ret; 265 } 266 267 break; 268 default: 269 dev_err(soc_runtime->dev, "%s: invalid interface: %d\n", __func__, dai_id); 270 break; 271 } 272 switch (bitwidth) { 273 case 16: 274 switch (channels) { 275 case 1: 276 case 2: 277 regval = LPAIF_DMACTL_WPSCNT_ONE; 278 break; 279 case 4: 280 regval = LPAIF_DMACTL_WPSCNT_TWO; 281 break; 282 case 6: 283 regval = LPAIF_DMACTL_WPSCNT_THREE; 284 break; 285 case 8: 286 regval = LPAIF_DMACTL_WPSCNT_FOUR; 287 break; 288 default: 289 dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", 290 bitwidth, channels); 291 return -EINVAL; 292 } 293 break; 294 case 24: 295 case 32: 296 switch (channels) { 297 case 1: 298 regval = LPAIF_DMACTL_WPSCNT_ONE; 299 break; 300 case 2: 301 regval = (dai_id == LPASS_DP_RX ? 302 LPAIF_DMACTL_WPSCNT_ONE : 303 LPAIF_DMACTL_WPSCNT_TWO); 304 break; 305 case 4: 306 regval = (dai_id == LPASS_DP_RX ? 307 LPAIF_DMACTL_WPSCNT_TWO : 308 LPAIF_DMACTL_WPSCNT_FOUR); 309 break; 310 case 6: 311 regval = (dai_id == LPASS_DP_RX ? 312 LPAIF_DMACTL_WPSCNT_THREE : 313 LPAIF_DMACTL_WPSCNT_SIX); 314 break; 315 case 8: 316 regval = (dai_id == LPASS_DP_RX ? 317 LPAIF_DMACTL_WPSCNT_FOUR : 318 LPAIF_DMACTL_WPSCNT_EIGHT); 319 break; 320 default: 321 dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", 322 bitwidth, channels); 323 return -EINVAL; 324 } 325 break; 326 default: 327 dev_err(soc_runtime->dev, "invalid PCM config given: bw=%d, ch=%u\n", 328 bitwidth, channels); 329 return -EINVAL; 330 } 331 332 ret = regmap_fields_write(dmactl->wpscnt, id, regval); 333 if (ret) { 334 dev_err(soc_runtime->dev, "error writing to dmactl reg: %d\n", 335 ret); 336 return ret; 337 } 338 339 return 0; 340 } 341 342 static int lpass_platform_pcmops_hw_free(struct snd_soc_component *component, 343 struct snd_pcm_substream *substream) 344 { 345 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 346 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 347 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 348 struct snd_pcm_runtime *rt = substream->runtime; 349 struct lpass_pcm_data *pcm_data = rt->private_data; 350 struct lpass_variant *v = drvdata->variant; 351 unsigned int reg; 352 int ret; 353 struct regmap *map; 354 unsigned int dai_id = cpu_dai->driver->id; 355 356 if (dai_id == LPASS_DP_RX) 357 map = drvdata->hdmiif_map; 358 else 359 map = drvdata->lpaif_map; 360 361 reg = LPAIF_DMACTL_REG(v, pcm_data->dma_ch, substream->stream, dai_id); 362 ret = regmap_write(map, reg, 0); 363 if (ret) 364 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", 365 ret); 366 367 return ret; 368 } 369 370 static int lpass_platform_pcmops_prepare(struct snd_soc_component *component, 371 struct snd_pcm_substream *substream) 372 { 373 struct snd_pcm_runtime *runtime = substream->runtime; 374 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 375 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 376 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 377 struct snd_pcm_runtime *rt = substream->runtime; 378 struct lpass_pcm_data *pcm_data = rt->private_data; 379 struct lpass_variant *v = drvdata->variant; 380 struct lpaif_dmactl *dmactl; 381 struct regmap *map; 382 int ret, id, ch, dir = substream->stream; 383 unsigned int dai_id = cpu_dai->driver->id; 384 385 386 ch = pcm_data->dma_ch; 387 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 388 if (dai_id == LPASS_DP_RX) { 389 dmactl = drvdata->hdmi_rd_dmactl; 390 map = drvdata->hdmiif_map; 391 } else { 392 dmactl = drvdata->rd_dmactl; 393 map = drvdata->lpaif_map; 394 } 395 396 id = pcm_data->dma_ch; 397 } else { 398 dmactl = drvdata->wr_dmactl; 399 id = pcm_data->dma_ch - v->wrdma_channel_start; 400 map = drvdata->lpaif_map; 401 } 402 403 ret = regmap_write(map, LPAIF_DMABASE_REG(v, ch, dir, dai_id), 404 runtime->dma_addr); 405 if (ret) { 406 dev_err(soc_runtime->dev, "error writing to rdmabase reg: %d\n", 407 ret); 408 return ret; 409 } 410 411 ret = regmap_write(map, LPAIF_DMABUFF_REG(v, ch, dir, dai_id), 412 (snd_pcm_lib_buffer_bytes(substream) >> 2) - 1); 413 if (ret) { 414 dev_err(soc_runtime->dev, "error writing to rdmabuff reg: %d\n", 415 ret); 416 return ret; 417 } 418 419 ret = regmap_write(map, LPAIF_DMAPER_REG(v, ch, dir, dai_id), 420 (snd_pcm_lib_period_bytes(substream) >> 2) - 1); 421 if (ret) { 422 dev_err(soc_runtime->dev, "error writing to rdmaper reg: %d\n", 423 ret); 424 return ret; 425 } 426 427 ret = regmap_fields_write(dmactl->enable, id, LPAIF_DMACTL_ENABLE_ON); 428 if (ret) { 429 dev_err(soc_runtime->dev, "error writing to rdmactl reg: %d\n", 430 ret); 431 return ret; 432 } 433 434 return 0; 435 } 436 437 static int lpass_platform_pcmops_trigger(struct snd_soc_component *component, 438 struct snd_pcm_substream *substream, 439 int cmd) 440 { 441 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 442 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 443 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 444 struct snd_pcm_runtime *rt = substream->runtime; 445 struct lpass_pcm_data *pcm_data = rt->private_data; 446 struct lpass_variant *v = drvdata->variant; 447 struct lpaif_dmactl *dmactl; 448 struct regmap *map; 449 int ret, ch, id; 450 int dir = substream->stream; 451 unsigned int reg_irqclr = 0, val_irqclr = 0; 452 unsigned int reg_irqen = 0, val_irqen = 0, val_mask = 0; 453 unsigned int dai_id = cpu_dai->driver->id; 454 455 ch = pcm_data->dma_ch; 456 if (dir == SNDRV_PCM_STREAM_PLAYBACK) { 457 id = pcm_data->dma_ch; 458 if (dai_id == LPASS_DP_RX) 459 dmactl = drvdata->hdmi_rd_dmactl; 460 else 461 dmactl = drvdata->rd_dmactl; 462 } else { 463 dmactl = drvdata->wr_dmactl; 464 id = pcm_data->dma_ch - v->wrdma_channel_start; 465 } 466 467 switch (cmd) { 468 case SNDRV_PCM_TRIGGER_START: 469 case SNDRV_PCM_TRIGGER_RESUME: 470 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 471 ret = regmap_fields_write(dmactl->enable, id, 472 LPAIF_DMACTL_ENABLE_ON); 473 if (ret) { 474 dev_err(soc_runtime->dev, 475 "error writing to rdmactl reg: %d\n", ret); 476 return ret; 477 } 478 switch (dai_id) { 479 case LPASS_DP_RX: 480 ret = regmap_fields_write(dmactl->dyncclk, id, 481 LPAIF_DMACTL_DYNCLK_ON); 482 if (ret) { 483 dev_err(soc_runtime->dev, 484 "error writing to rdmactl reg: %d\n", ret); 485 return ret; 486 } 487 map = drvdata->hdmiif_map; 488 reg_irqclr = LPASS_HDMITX_APP_IRQCLEAR_REG(v); 489 val_irqclr = (LPAIF_IRQ_ALL(ch) | 490 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | 491 LPAIF_IRQ_HDMI_METADONE | 492 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch)); 493 494 reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v); 495 val_mask = (LPAIF_IRQ_ALL(ch) | 496 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | 497 LPAIF_IRQ_HDMI_METADONE | 498 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch)); 499 val_irqen = (LPAIF_IRQ_ALL(ch) | 500 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | 501 LPAIF_IRQ_HDMI_METADONE | 502 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch)); 503 break; 504 case MI2S_PRIMARY: 505 case MI2S_SECONDARY: 506 map = drvdata->lpaif_map; 507 reg_irqclr = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); 508 val_irqclr = LPAIF_IRQ_ALL(ch); 509 510 511 reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST); 512 val_mask = LPAIF_IRQ_ALL(ch); 513 val_irqen = LPAIF_IRQ_ALL(ch); 514 break; 515 default: 516 dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); 517 return -EINVAL; 518 } 519 520 ret = regmap_write(map, reg_irqclr, val_irqclr); 521 if (ret) { 522 dev_err(soc_runtime->dev, "error writing to irqclear reg: %d\n", ret); 523 return ret; 524 } 525 ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen); 526 if (ret) { 527 dev_err(soc_runtime->dev, "error writing to irqen reg: %d\n", ret); 528 return ret; 529 } 530 break; 531 case SNDRV_PCM_TRIGGER_STOP: 532 case SNDRV_PCM_TRIGGER_SUSPEND: 533 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 534 ret = regmap_fields_write(dmactl->enable, id, 535 LPAIF_DMACTL_ENABLE_OFF); 536 if (ret) { 537 dev_err(soc_runtime->dev, 538 "error writing to rdmactl reg: %d\n", ret); 539 return ret; 540 } 541 switch (dai_id) { 542 case LPASS_DP_RX: 543 ret = regmap_fields_write(dmactl->dyncclk, id, 544 LPAIF_DMACTL_DYNCLK_OFF); 545 if (ret) { 546 dev_err(soc_runtime->dev, 547 "error writing to rdmactl reg: %d\n", ret); 548 return ret; 549 } 550 map = drvdata->hdmiif_map; 551 reg_irqen = LPASS_HDMITX_APP_IRQEN_REG(v); 552 val_mask = (LPAIF_IRQ_ALL(ch) | 553 LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(ch) | 554 LPAIF_IRQ_HDMI_METADONE | 555 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(ch)); 556 val_irqen = 0; 557 break; 558 case MI2S_PRIMARY: 559 case MI2S_SECONDARY: 560 map = drvdata->lpaif_map; 561 reg_irqen = LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST); 562 val_mask = LPAIF_IRQ_ALL(ch); 563 val_irqen = 0; 564 break; 565 default: 566 dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); 567 return -EINVAL; 568 } 569 570 ret = regmap_update_bits(map, reg_irqen, val_mask, val_irqen); 571 if (ret) { 572 dev_err(soc_runtime->dev, 573 "error writing to irqen reg: %d\n", ret); 574 return ret; 575 } 576 break; 577 } 578 579 return 0; 580 } 581 582 static snd_pcm_uframes_t lpass_platform_pcmops_pointer( 583 struct snd_soc_component *component, 584 struct snd_pcm_substream *substream) 585 { 586 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 587 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 588 struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); 589 struct snd_pcm_runtime *rt = substream->runtime; 590 struct lpass_pcm_data *pcm_data = rt->private_data; 591 struct lpass_variant *v = drvdata->variant; 592 unsigned int base_addr, curr_addr; 593 int ret, ch, dir = substream->stream; 594 struct regmap *map; 595 unsigned int dai_id = cpu_dai->driver->id; 596 597 if (dai_id == LPASS_DP_RX) 598 map = drvdata->hdmiif_map; 599 else 600 map = drvdata->lpaif_map; 601 602 ch = pcm_data->dma_ch; 603 604 ret = regmap_read(map, 605 LPAIF_DMABASE_REG(v, ch, dir, dai_id), &base_addr); 606 if (ret) { 607 dev_err(soc_runtime->dev, 608 "error reading from rdmabase reg: %d\n", ret); 609 return ret; 610 } 611 612 ret = regmap_read(map, 613 LPAIF_DMACURR_REG(v, ch, dir, dai_id), &curr_addr); 614 if (ret) { 615 dev_err(soc_runtime->dev, 616 "error reading from rdmacurr reg: %d\n", ret); 617 return ret; 618 } 619 620 return bytes_to_frames(substream->runtime, curr_addr - base_addr); 621 } 622 623 static int lpass_platform_pcmops_mmap(struct snd_soc_component *component, 624 struct snd_pcm_substream *substream, 625 struct vm_area_struct *vma) 626 { 627 struct snd_pcm_runtime *runtime = substream->runtime; 628 629 return dma_mmap_coherent(component->dev, vma, runtime->dma_area, 630 runtime->dma_addr, runtime->dma_bytes); 631 } 632 633 static irqreturn_t lpass_dma_interrupt_handler( 634 struct snd_pcm_substream *substream, 635 struct lpass_data *drvdata, 636 int chan, u32 interrupts) 637 { 638 struct snd_soc_pcm_runtime *soc_runtime = asoc_substream_to_rtd(substream); 639 struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(soc_runtime, 0); 640 struct lpass_variant *v = drvdata->variant; 641 irqreturn_t ret = IRQ_NONE; 642 int rv; 643 unsigned int reg = 0, val = 0; 644 struct regmap *map; 645 unsigned int dai_id = cpu_dai->driver->id; 646 647 switch (dai_id) { 648 case LPASS_DP_RX: 649 map = drvdata->hdmiif_map; 650 reg = LPASS_HDMITX_APP_IRQCLEAR_REG(v); 651 val = (LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) | 652 LPAIF_IRQ_HDMI_METADONE | 653 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan)); 654 break; 655 case MI2S_PRIMARY: 656 case MI2S_SECONDARY: 657 map = drvdata->lpaif_map; 658 reg = LPAIF_IRQCLEAR_REG(v, LPAIF_IRQ_PORT_HOST); 659 val = 0; 660 break; 661 default: 662 dev_err(soc_runtime->dev, "%s: invalid %d interface\n", __func__, dai_id); 663 return -EINVAL; 664 } 665 if (interrupts & LPAIF_IRQ_PER(chan)) { 666 667 rv = regmap_write(map, reg, LPAIF_IRQ_PER(chan) | val); 668 if (rv) { 669 dev_err(soc_runtime->dev, 670 "error writing to irqclear reg: %d\n", rv); 671 return IRQ_NONE; 672 } 673 snd_pcm_period_elapsed(substream); 674 ret = IRQ_HANDLED; 675 } 676 677 if (interrupts & LPAIF_IRQ_XRUN(chan)) { 678 rv = regmap_write(map, reg, LPAIF_IRQ_XRUN(chan) | val); 679 if (rv) { 680 dev_err(soc_runtime->dev, 681 "error writing to irqclear reg: %d\n", rv); 682 return IRQ_NONE; 683 } 684 dev_warn(soc_runtime->dev, "xrun warning\n"); 685 snd_pcm_stop_xrun(substream); 686 ret = IRQ_HANDLED; 687 } 688 689 if (interrupts & LPAIF_IRQ_ERR(chan)) { 690 rv = regmap_write(map, reg, LPAIF_IRQ_ERR(chan) | val); 691 if (rv) { 692 dev_err(soc_runtime->dev, 693 "error writing to irqclear reg: %d\n", rv); 694 return IRQ_NONE; 695 } 696 dev_err(soc_runtime->dev, "bus access error\n"); 697 snd_pcm_stop(substream, SNDRV_PCM_STATE_DISCONNECTED); 698 ret = IRQ_HANDLED; 699 } 700 701 if (interrupts & val) { 702 rv = regmap_write(map, reg, val); 703 if (rv) { 704 dev_err(soc_runtime->dev, 705 "error writing to irqclear reg: %d\n", rv); 706 return IRQ_NONE; 707 } 708 ret = IRQ_HANDLED; 709 } 710 711 return ret; 712 } 713 714 static irqreturn_t lpass_platform_lpaif_irq(int irq, void *data) 715 { 716 struct lpass_data *drvdata = data; 717 struct lpass_variant *v = drvdata->variant; 718 unsigned int irqs; 719 int rv, chan; 720 721 rv = regmap_read(drvdata->lpaif_map, 722 LPAIF_IRQSTAT_REG(v, LPAIF_IRQ_PORT_HOST), &irqs); 723 if (rv) { 724 pr_err("error reading from irqstat reg: %d\n", rv); 725 return IRQ_NONE; 726 } 727 728 /* Handle per channel interrupts */ 729 for (chan = 0; chan < LPASS_MAX_DMA_CHANNELS; chan++) { 730 if (irqs & LPAIF_IRQ_ALL(chan) && drvdata->substream[chan]) { 731 rv = lpass_dma_interrupt_handler( 732 drvdata->substream[chan], 733 drvdata, chan, irqs); 734 if (rv != IRQ_HANDLED) 735 return rv; 736 } 737 } 738 739 return IRQ_HANDLED; 740 } 741 742 static irqreturn_t lpass_platform_hdmiif_irq(int irq, void *data) 743 { 744 struct lpass_data *drvdata = data; 745 struct lpass_variant *v = drvdata->variant; 746 unsigned int irqs; 747 int rv, chan; 748 749 rv = regmap_read(drvdata->hdmiif_map, 750 LPASS_HDMITX_APP_IRQSTAT_REG(v), &irqs); 751 if (rv) { 752 pr_err("error reading from irqstat reg: %d\n", rv); 753 return IRQ_NONE; 754 } 755 756 /* Handle per channel interrupts */ 757 for (chan = 0; chan < LPASS_MAX_HDMI_DMA_CHANNELS; chan++) { 758 if (irqs & (LPAIF_IRQ_ALL(chan) | LPAIF_IRQ_HDMI_REQ_ON_PRELOAD(chan) | 759 LPAIF_IRQ_HDMI_METADONE | 760 LPAIF_IRQ_HDMI_SDEEP_AUD_DIS(chan)) 761 && drvdata->hdmi_substream[chan]) { 762 rv = lpass_dma_interrupt_handler( 763 drvdata->hdmi_substream[chan], 764 drvdata, chan, irqs); 765 if (rv != IRQ_HANDLED) 766 return rv; 767 } 768 } 769 770 return IRQ_HANDLED; 771 } 772 773 static int lpass_platform_pcm_new(struct snd_soc_component *component, 774 struct snd_soc_pcm_runtime *soc_runtime) 775 { 776 struct snd_pcm *pcm = soc_runtime->pcm; 777 struct snd_pcm_substream *psubstream, *csubstream; 778 int ret = -EINVAL; 779 size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; 780 781 psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 782 if (psubstream) { 783 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 784 component->dev, 785 size, &psubstream->dma_buffer); 786 if (ret) { 787 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 788 return ret; 789 } 790 } 791 792 csubstream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 793 if (csubstream) { 794 ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, 795 component->dev, 796 size, &csubstream->dma_buffer); 797 if (ret) { 798 dev_err(soc_runtime->dev, "Cannot allocate buffer(s)\n"); 799 if (psubstream) 800 snd_dma_free_pages(&psubstream->dma_buffer); 801 return ret; 802 } 803 804 } 805 806 return 0; 807 } 808 809 static void lpass_platform_pcm_free(struct snd_soc_component *component, 810 struct snd_pcm *pcm) 811 { 812 struct snd_pcm_substream *substream; 813 int i; 814 815 for_each_pcm_streams(i) { 816 substream = pcm->streams[i].substream; 817 if (substream) { 818 snd_dma_free_pages(&substream->dma_buffer); 819 substream->dma_buffer.area = NULL; 820 substream->dma_buffer.addr = 0; 821 } 822 } 823 } 824 825 static const struct snd_soc_component_driver lpass_component_driver = { 826 .name = DRV_NAME, 827 .open = lpass_platform_pcmops_open, 828 .close = lpass_platform_pcmops_close, 829 .hw_params = lpass_platform_pcmops_hw_params, 830 .hw_free = lpass_platform_pcmops_hw_free, 831 .prepare = lpass_platform_pcmops_prepare, 832 .trigger = lpass_platform_pcmops_trigger, 833 .pointer = lpass_platform_pcmops_pointer, 834 .mmap = lpass_platform_pcmops_mmap, 835 .pcm_construct = lpass_platform_pcm_new, 836 .pcm_destruct = lpass_platform_pcm_free, 837 838 }; 839 840 int asoc_qcom_lpass_platform_register(struct platform_device *pdev) 841 { 842 struct lpass_data *drvdata = platform_get_drvdata(pdev); 843 struct lpass_variant *v = drvdata->variant; 844 int ret; 845 846 drvdata->lpaif_irq = platform_get_irq_byname(pdev, "lpass-irq-lpaif"); 847 if (drvdata->lpaif_irq < 0) 848 return -ENODEV; 849 850 /* ensure audio hardware is disabled */ 851 ret = regmap_write(drvdata->lpaif_map, 852 LPAIF_IRQEN_REG(v, LPAIF_IRQ_PORT_HOST), 0); 853 if (ret) { 854 dev_err(&pdev->dev, "error writing to irqen reg: %d\n", ret); 855 return ret; 856 } 857 858 ret = devm_request_irq(&pdev->dev, drvdata->lpaif_irq, 859 lpass_platform_lpaif_irq, IRQF_TRIGGER_RISING, 860 "lpass-irq-lpaif", drvdata); 861 if (ret) { 862 dev_err(&pdev->dev, "irq request failed: %d\n", ret); 863 return ret; 864 } 865 866 ret = lpass_platform_alloc_dmactl_fields(&pdev->dev, 867 drvdata->lpaif_map); 868 if (ret) { 869 dev_err(&pdev->dev, 870 "error initializing dmactl fields: %d\n", ret); 871 return ret; 872 } 873 874 if (drvdata->hdmi_port_enable) { 875 drvdata->hdmiif_irq = platform_get_irq_byname(pdev, "lpass-irq-hdmi"); 876 if (drvdata->hdmiif_irq < 0) 877 return -ENODEV; 878 879 ret = devm_request_irq(&pdev->dev, drvdata->hdmiif_irq, 880 lpass_platform_hdmiif_irq, 0, "lpass-irq-hdmi", drvdata); 881 if (ret) { 882 dev_err(&pdev->dev, "irq hdmi request failed: %d\n", ret); 883 return ret; 884 } 885 ret = regmap_write(drvdata->hdmiif_map, 886 LPASS_HDMITX_APP_IRQEN_REG(v), 0); 887 if (ret) { 888 dev_err(&pdev->dev, "error writing to hdmi irqen reg: %d\n", ret); 889 return ret; 890 } 891 892 ret = lpass_platform_alloc_hdmidmactl_fields(&pdev->dev, 893 drvdata->hdmiif_map); 894 if (ret) { 895 dev_err(&pdev->dev, 896 "error initializing hdmidmactl fields: %d\n", ret); 897 return ret; 898 } 899 } 900 return devm_snd_soc_register_component(&pdev->dev, 901 &lpass_component_driver, NULL, 0); 902 } 903 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_platform_register); 904 905 MODULE_DESCRIPTION("QTi LPASS Platform Driver"); 906 MODULE_LICENSE("GPL v2"); 907