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-cpu.c -- ALSA SoC CPU DAI driver for QTi LPASS 6 */ 7 8 #include <linux/clk.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/of.h> 12 #include <linux/of_device.h> 13 #include <linux/platform_device.h> 14 #include <sound/pcm.h> 15 #include <sound/pcm_params.h> 16 #include <linux/regmap.h> 17 #include <sound/soc.h> 18 #include <sound/soc-dai.h> 19 #include "lpass-lpaif-reg.h" 20 #include "lpass.h" 21 22 static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, 23 unsigned int freq, int dir) 24 { 25 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 26 int ret; 27 28 ret = clk_set_rate(drvdata->mi2s_osr_clk[dai->driver->id], freq); 29 if (ret) 30 dev_err(dai->dev, "error setting mi2s osrclk to %u: %d\n", 31 freq, ret); 32 33 return ret; 34 } 35 36 static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, 37 struct snd_soc_dai *dai) 38 { 39 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 40 int ret; 41 42 ret = clk_prepare_enable(drvdata->mi2s_osr_clk[dai->driver->id]); 43 if (ret) { 44 dev_err(dai->dev, "error in enabling mi2s osr clk: %d\n", ret); 45 return ret; 46 } 47 48 ret = clk_prepare_enable(drvdata->mi2s_bit_clk[dai->driver->id]); 49 if (ret) { 50 dev_err(dai->dev, "error in enabling mi2s bit clk: %d\n", ret); 51 clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); 52 return ret; 53 } 54 55 return 0; 56 } 57 58 static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, 59 struct snd_soc_dai *dai) 60 { 61 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 62 63 clk_disable_unprepare(drvdata->mi2s_bit_clk[dai->driver->id]); 64 65 clk_disable_unprepare(drvdata->mi2s_osr_clk[dai->driver->id]); 66 } 67 68 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, 69 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 70 { 71 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 72 snd_pcm_format_t format = params_format(params); 73 unsigned int channels = params_channels(params); 74 unsigned int rate = params_rate(params); 75 unsigned int regval; 76 int bitwidth, ret; 77 78 bitwidth = snd_pcm_format_width(format); 79 if (bitwidth < 0) { 80 dev_err(dai->dev, "invalid bit width given: %d\n", bitwidth); 81 return bitwidth; 82 } 83 84 regval = LPAIF_I2SCTL_LOOPBACK_DISABLE | 85 LPAIF_I2SCTL_WSSRC_INTERNAL; 86 87 switch (bitwidth) { 88 case 16: 89 regval |= LPAIF_I2SCTL_BITWIDTH_16; 90 break; 91 case 24: 92 regval |= LPAIF_I2SCTL_BITWIDTH_24; 93 break; 94 case 32: 95 regval |= LPAIF_I2SCTL_BITWIDTH_32; 96 break; 97 default: 98 dev_err(dai->dev, "invalid bitwidth given: %d\n", bitwidth); 99 return -EINVAL; 100 } 101 102 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 103 switch (channels) { 104 case 1: 105 regval |= LPAIF_I2SCTL_SPKMODE_SD0; 106 regval |= LPAIF_I2SCTL_SPKMONO_MONO; 107 break; 108 case 2: 109 regval |= LPAIF_I2SCTL_SPKMODE_SD0; 110 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 111 break; 112 case 4: 113 regval |= LPAIF_I2SCTL_SPKMODE_QUAD01; 114 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 115 break; 116 case 6: 117 regval |= LPAIF_I2SCTL_SPKMODE_6CH; 118 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 119 break; 120 case 8: 121 regval |= LPAIF_I2SCTL_SPKMODE_8CH; 122 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 123 break; 124 default: 125 dev_err(dai->dev, "invalid channels given: %u\n", 126 channels); 127 return -EINVAL; 128 } 129 } else { 130 switch (channels) { 131 case 1: 132 regval |= LPAIF_I2SCTL_MICMODE_SD0; 133 regval |= LPAIF_I2SCTL_MICMONO_MONO; 134 break; 135 case 2: 136 regval |= LPAIF_I2SCTL_MICMODE_SD0; 137 regval |= LPAIF_I2SCTL_MICMONO_STEREO; 138 break; 139 case 4: 140 regval |= LPAIF_I2SCTL_MICMODE_QUAD01; 141 regval |= LPAIF_I2SCTL_MICMONO_STEREO; 142 break; 143 case 6: 144 regval |= LPAIF_I2SCTL_MICMODE_6CH; 145 regval |= LPAIF_I2SCTL_MICMONO_STEREO; 146 break; 147 case 8: 148 regval |= LPAIF_I2SCTL_MICMODE_8CH; 149 regval |= LPAIF_I2SCTL_MICMONO_STEREO; 150 break; 151 default: 152 dev_err(dai->dev, "invalid channels given: %u\n", 153 channels); 154 return -EINVAL; 155 } 156 } 157 158 ret = regmap_write(drvdata->lpaif_map, 159 LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 160 regval); 161 if (ret) { 162 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); 163 return ret; 164 } 165 166 ret = clk_set_rate(drvdata->mi2s_bit_clk[dai->driver->id], 167 rate * bitwidth * 2); 168 if (ret) { 169 dev_err(dai->dev, "error setting mi2s bitclk to %u: %d\n", 170 rate * bitwidth * 2, ret); 171 return ret; 172 } 173 174 return 0; 175 } 176 177 static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, 178 struct snd_soc_dai *dai) 179 { 180 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 181 int ret; 182 183 ret = regmap_write(drvdata->lpaif_map, 184 LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 185 0); 186 if (ret) 187 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); 188 189 return ret; 190 } 191 192 static int lpass_cpu_daiops_prepare(struct snd_pcm_substream *substream, 193 struct snd_soc_dai *dai) 194 { 195 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 196 int ret; 197 unsigned int val, mask; 198 199 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 200 val = LPAIF_I2SCTL_SPKEN_ENABLE; 201 mask = LPAIF_I2SCTL_SPKEN_MASK; 202 } else { 203 val = LPAIF_I2SCTL_MICEN_ENABLE; 204 mask = LPAIF_I2SCTL_MICEN_MASK; 205 } 206 207 ret = regmap_update_bits(drvdata->lpaif_map, 208 LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 209 mask, val); 210 if (ret) 211 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); 212 213 return ret; 214 } 215 216 static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, 217 int cmd, struct snd_soc_dai *dai) 218 { 219 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 220 int ret = -EINVAL; 221 unsigned int val, mask; 222 223 switch (cmd) { 224 case SNDRV_PCM_TRIGGER_START: 225 case SNDRV_PCM_TRIGGER_RESUME: 226 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 227 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 228 val = LPAIF_I2SCTL_SPKEN_ENABLE; 229 mask = LPAIF_I2SCTL_SPKEN_MASK; 230 } else { 231 val = LPAIF_I2SCTL_MICEN_ENABLE; 232 mask = LPAIF_I2SCTL_MICEN_MASK; 233 } 234 235 ret = regmap_update_bits(drvdata->lpaif_map, 236 LPAIF_I2SCTL_REG(drvdata->variant, 237 dai->driver->id), 238 mask, val); 239 if (ret) 240 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", 241 ret); 242 break; 243 case SNDRV_PCM_TRIGGER_STOP: 244 case SNDRV_PCM_TRIGGER_SUSPEND: 245 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 246 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 247 val = LPAIF_I2SCTL_SPKEN_DISABLE; 248 mask = LPAIF_I2SCTL_SPKEN_MASK; 249 } else { 250 val = LPAIF_I2SCTL_MICEN_DISABLE; 251 mask = LPAIF_I2SCTL_MICEN_MASK; 252 } 253 254 ret = regmap_update_bits(drvdata->lpaif_map, 255 LPAIF_I2SCTL_REG(drvdata->variant, 256 dai->driver->id), 257 mask, val); 258 if (ret) 259 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", 260 ret); 261 break; 262 } 263 264 return ret; 265 } 266 267 const struct snd_soc_dai_ops asoc_qcom_lpass_cpu_dai_ops = { 268 .set_sysclk = lpass_cpu_daiops_set_sysclk, 269 .startup = lpass_cpu_daiops_startup, 270 .shutdown = lpass_cpu_daiops_shutdown, 271 .hw_params = lpass_cpu_daiops_hw_params, 272 .hw_free = lpass_cpu_daiops_hw_free, 273 .prepare = lpass_cpu_daiops_prepare, 274 .trigger = lpass_cpu_daiops_trigger, 275 }; 276 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_ops); 277 278 int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) 279 { 280 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 281 int ret; 282 283 /* ensure audio hardware is disabled */ 284 ret = regmap_write(drvdata->lpaif_map, 285 LPAIF_I2SCTL_REG(drvdata->variant, dai->driver->id), 0); 286 if (ret) 287 dev_err(dai->dev, "error writing to i2sctl reg: %d\n", ret); 288 289 return ret; 290 } 291 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe); 292 293 static const struct snd_soc_component_driver lpass_cpu_comp_driver = { 294 .name = "lpass-cpu", 295 }; 296 297 static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) 298 { 299 struct lpass_data *drvdata = dev_get_drvdata(dev); 300 struct lpass_variant *v = drvdata->variant; 301 int i; 302 303 for (i = 0; i < v->i2s_ports; ++i) 304 if (reg == LPAIF_I2SCTL_REG(v, i)) 305 return true; 306 307 for (i = 0; i < v->irq_ports; ++i) { 308 if (reg == LPAIF_IRQEN_REG(v, i)) 309 return true; 310 if (reg == LPAIF_IRQCLEAR_REG(v, i)) 311 return true; 312 } 313 314 for (i = 0; i < v->rdma_channels; ++i) { 315 if (reg == LPAIF_RDMACTL_REG(v, i)) 316 return true; 317 if (reg == LPAIF_RDMABASE_REG(v, i)) 318 return true; 319 if (reg == LPAIF_RDMABUFF_REG(v, i)) 320 return true; 321 if (reg == LPAIF_RDMAPER_REG(v, i)) 322 return true; 323 } 324 325 for (i = 0; i < v->wrdma_channels; ++i) { 326 if (reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start)) 327 return true; 328 if (reg == LPAIF_WRDMABASE_REG(v, i + v->wrdma_channel_start)) 329 return true; 330 if (reg == LPAIF_WRDMABUFF_REG(v, i + v->wrdma_channel_start)) 331 return true; 332 if (reg == LPAIF_WRDMAPER_REG(v, i + v->wrdma_channel_start)) 333 return true; 334 } 335 336 return false; 337 } 338 339 static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) 340 { 341 struct lpass_data *drvdata = dev_get_drvdata(dev); 342 struct lpass_variant *v = drvdata->variant; 343 int i; 344 345 for (i = 0; i < v->i2s_ports; ++i) 346 if (reg == LPAIF_I2SCTL_REG(v, i)) 347 return true; 348 349 for (i = 0; i < v->irq_ports; ++i) { 350 if (reg == LPAIF_IRQEN_REG(v, i)) 351 return true; 352 if (reg == LPAIF_IRQSTAT_REG(v, i)) 353 return true; 354 } 355 356 for (i = 0; i < v->rdma_channels; ++i) { 357 if (reg == LPAIF_RDMACTL_REG(v, i)) 358 return true; 359 if (reg == LPAIF_RDMABASE_REG(v, i)) 360 return true; 361 if (reg == LPAIF_RDMABUFF_REG(v, i)) 362 return true; 363 if (reg == LPAIF_RDMACURR_REG(v, i)) 364 return true; 365 if (reg == LPAIF_RDMAPER_REG(v, i)) 366 return true; 367 } 368 369 for (i = 0; i < v->wrdma_channels; ++i) { 370 if (reg == LPAIF_WRDMACTL_REG(v, i + v->wrdma_channel_start)) 371 return true; 372 if (reg == LPAIF_WRDMABASE_REG(v, i + v->wrdma_channel_start)) 373 return true; 374 if (reg == LPAIF_WRDMABUFF_REG(v, i + v->wrdma_channel_start)) 375 return true; 376 if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start)) 377 return true; 378 if (reg == LPAIF_WRDMAPER_REG(v, i + v->wrdma_channel_start)) 379 return true; 380 } 381 382 return false; 383 } 384 385 static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) 386 { 387 struct lpass_data *drvdata = dev_get_drvdata(dev); 388 struct lpass_variant *v = drvdata->variant; 389 int i; 390 391 for (i = 0; i < v->irq_ports; ++i) 392 if (reg == LPAIF_IRQSTAT_REG(v, i)) 393 return true; 394 395 for (i = 0; i < v->rdma_channels; ++i) 396 if (reg == LPAIF_RDMACURR_REG(v, i)) 397 return true; 398 399 for (i = 0; i < v->wrdma_channels; ++i) 400 if (reg == LPAIF_WRDMACURR_REG(v, i + v->wrdma_channel_start)) 401 return true; 402 403 return false; 404 } 405 406 static struct regmap_config lpass_cpu_regmap_config = { 407 .reg_bits = 32, 408 .reg_stride = 4, 409 .val_bits = 32, 410 .writeable_reg = lpass_cpu_regmap_writeable, 411 .readable_reg = lpass_cpu_regmap_readable, 412 .volatile_reg = lpass_cpu_regmap_volatile, 413 .cache_type = REGCACHE_FLAT, 414 }; 415 416 int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev) 417 { 418 struct lpass_data *drvdata; 419 struct device_node *dsp_of_node; 420 struct resource *res; 421 struct lpass_variant *variant; 422 struct device *dev = &pdev->dev; 423 const struct of_device_id *match; 424 int ret, i, dai_id; 425 426 dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); 427 if (dsp_of_node) { 428 dev_err(&pdev->dev, "DSP exists and holds audio resources\n"); 429 return -EBUSY; 430 } 431 432 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct lpass_data), 433 GFP_KERNEL); 434 if (!drvdata) 435 return -ENOMEM; 436 platform_set_drvdata(pdev, drvdata); 437 438 match = of_match_device(dev->driver->of_match_table, dev); 439 if (!match || !match->data) 440 return -EINVAL; 441 442 drvdata->variant = (struct lpass_variant *)match->data; 443 variant = drvdata->variant; 444 445 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); 446 447 drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); 448 if (IS_ERR((void const __force *)drvdata->lpaif)) { 449 dev_err(&pdev->dev, "error mapping reg resource: %ld\n", 450 PTR_ERR((void const __force *)drvdata->lpaif)); 451 return PTR_ERR((void const __force *)drvdata->lpaif); 452 } 453 454 lpass_cpu_regmap_config.max_register = LPAIF_WRDMAPER_REG(variant, 455 variant->wrdma_channels + 456 variant->wrdma_channel_start); 457 458 drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, 459 &lpass_cpu_regmap_config); 460 if (IS_ERR(drvdata->lpaif_map)) { 461 dev_err(&pdev->dev, "error initializing regmap: %ld\n", 462 PTR_ERR(drvdata->lpaif_map)); 463 return PTR_ERR(drvdata->lpaif_map); 464 } 465 466 if (variant->init) 467 variant->init(pdev); 468 469 for (i = 0; i < variant->num_dai; i++) { 470 dai_id = variant->dai_driver[i].id; 471 drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(&pdev->dev, 472 variant->dai_osr_clk_names[i]); 473 if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) { 474 dev_warn(&pdev->dev, 475 "%s() error getting optional %s: %ld\n", 476 __func__, 477 variant->dai_osr_clk_names[i], 478 PTR_ERR(drvdata->mi2s_osr_clk[dai_id])); 479 480 drvdata->mi2s_osr_clk[dai_id] = NULL; 481 } 482 483 drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(&pdev->dev, 484 variant->dai_bit_clk_names[i]); 485 if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) { 486 dev_err(&pdev->dev, 487 "error getting %s: %ld\n", 488 variant->dai_bit_clk_names[i], 489 PTR_ERR(drvdata->mi2s_bit_clk[dai_id])); 490 return PTR_ERR(drvdata->mi2s_bit_clk[dai_id]); 491 } 492 } 493 494 drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); 495 if (IS_ERR(drvdata->ahbix_clk)) { 496 dev_err(&pdev->dev, "error getting ahbix-clk: %ld\n", 497 PTR_ERR(drvdata->ahbix_clk)); 498 return PTR_ERR(drvdata->ahbix_clk); 499 } 500 501 ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); 502 if (ret) { 503 dev_err(&pdev->dev, "error setting rate on ahbix_clk: %d\n", 504 ret); 505 return ret; 506 } 507 dev_dbg(&pdev->dev, "set ahbix_clk rate to %lu\n", 508 clk_get_rate(drvdata->ahbix_clk)); 509 510 ret = clk_prepare_enable(drvdata->ahbix_clk); 511 if (ret) { 512 dev_err(&pdev->dev, "error enabling ahbix_clk: %d\n", ret); 513 return ret; 514 } 515 516 ret = devm_snd_soc_register_component(&pdev->dev, 517 &lpass_cpu_comp_driver, 518 variant->dai_driver, 519 variant->num_dai); 520 if (ret) { 521 dev_err(&pdev->dev, "error registering cpu driver: %d\n", ret); 522 goto err_clk; 523 } 524 525 ret = asoc_qcom_lpass_platform_register(pdev); 526 if (ret) { 527 dev_err(&pdev->dev, "error registering platform driver: %d\n", 528 ret); 529 goto err_clk; 530 } 531 532 return 0; 533 534 err_clk: 535 clk_disable_unprepare(drvdata->ahbix_clk); 536 return ret; 537 } 538 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_probe); 539 540 int asoc_qcom_lpass_cpu_platform_remove(struct platform_device *pdev) 541 { 542 struct lpass_data *drvdata = platform_get_drvdata(pdev); 543 544 if (drvdata->variant->exit) 545 drvdata->variant->exit(pdev); 546 547 clk_disable_unprepare(drvdata->ahbix_clk); 548 549 return 0; 550 } 551 EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_platform_remove); 552 553 MODULE_DESCRIPTION("QTi LPASS CPU Driver"); 554 MODULE_LICENSE("GPL v2"); 555