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