1 /* 2 * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License version 2 and 6 * only version 2 as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it will be useful, 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * GNU General Public License for more details. 12 * 13 * lpass-cpu.c -- ALSA SoC CPU DAI driver for QTi LPASS 14 */ 15 16 #include <linux/clk.h> 17 #include <linux/compiler.h> 18 #include <linux/device.h> 19 #include <linux/err.h> 20 #include <linux/ioport.h> 21 #include <linux/kernel.h> 22 #include <linux/mod_devicetable.h> 23 #include <linux/module.h> 24 #include <linux/of.h> 25 #include <linux/platform_device.h> 26 #include <sound/pcm.h> 27 #include <sound/pcm_params.h> 28 #include <linux/regmap.h> 29 #include <sound/soc.h> 30 #include <sound/soc-dai.h> 31 #include "lpass-lpaif-ipq806x.h" 32 #include "lpass.h" 33 34 static int lpass_cpu_daiops_set_sysclk(struct snd_soc_dai *dai, int clk_id, 35 unsigned int freq, int dir) 36 { 37 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 38 int ret; 39 40 ret = clk_set_rate(drvdata->mi2s_osr_clk, freq); 41 if (ret) 42 dev_err(dai->dev, "%s() error setting mi2s osrclk to %u: %d\n", 43 __func__, freq, ret); 44 45 return ret; 46 } 47 48 static int lpass_cpu_daiops_startup(struct snd_pcm_substream *substream, 49 struct snd_soc_dai *dai) 50 { 51 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 52 int ret; 53 54 ret = clk_prepare_enable(drvdata->mi2s_osr_clk); 55 if (ret) { 56 dev_err(dai->dev, "%s() error in enabling mi2s osr clk: %d\n", 57 __func__, ret); 58 return ret; 59 } 60 61 ret = clk_prepare_enable(drvdata->mi2s_bit_clk); 62 if (ret) { 63 dev_err(dai->dev, "%s() error in enabling mi2s bit clk: %d\n", 64 __func__, ret); 65 clk_disable_unprepare(drvdata->mi2s_osr_clk); 66 return ret; 67 } 68 69 return 0; 70 } 71 72 static void lpass_cpu_daiops_shutdown(struct snd_pcm_substream *substream, 73 struct snd_soc_dai *dai) 74 { 75 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 76 77 clk_disable_unprepare(drvdata->mi2s_bit_clk); 78 clk_disable_unprepare(drvdata->mi2s_osr_clk); 79 } 80 81 static int lpass_cpu_daiops_hw_params(struct snd_pcm_substream *substream, 82 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 83 { 84 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 85 snd_pcm_format_t format = params_format(params); 86 unsigned int channels = params_channels(params); 87 unsigned int rate = params_rate(params); 88 unsigned int regval; 89 int bitwidth, ret; 90 91 bitwidth = snd_pcm_format_width(format); 92 if (bitwidth < 0) { 93 dev_err(dai->dev, "%s() invalid bit width given: %d\n", 94 __func__, bitwidth); 95 return bitwidth; 96 } 97 98 regval = LPAIF_I2SCTL_LOOPBACK_DISABLE | 99 LPAIF_I2SCTL_WSSRC_INTERNAL; 100 101 switch (bitwidth) { 102 case 16: 103 regval |= LPAIF_I2SCTL_BITWIDTH_16; 104 break; 105 case 24: 106 regval |= LPAIF_I2SCTL_BITWIDTH_24; 107 break; 108 case 32: 109 regval |= LPAIF_I2SCTL_BITWIDTH_32; 110 break; 111 default: 112 dev_err(dai->dev, "%s() invalid bitwidth given: %d\n", 113 __func__, bitwidth); 114 return -EINVAL; 115 } 116 117 switch (channels) { 118 case 1: 119 regval |= LPAIF_I2SCTL_SPKMODE_SD0; 120 regval |= LPAIF_I2SCTL_SPKMONO_MONO; 121 break; 122 case 2: 123 regval |= LPAIF_I2SCTL_SPKMODE_SD0; 124 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 125 break; 126 case 4: 127 regval |= LPAIF_I2SCTL_SPKMODE_QUAD01; 128 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 129 break; 130 case 6: 131 regval |= LPAIF_I2SCTL_SPKMODE_6CH; 132 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 133 break; 134 case 8: 135 regval |= LPAIF_I2SCTL_SPKMODE_8CH; 136 regval |= LPAIF_I2SCTL_SPKMONO_STEREO; 137 break; 138 default: 139 dev_err(dai->dev, "%s() invalid channels given: %u\n", 140 __func__, channels); 141 return -EINVAL; 142 } 143 144 ret = regmap_write(drvdata->lpaif_map, 145 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), regval); 146 if (ret) { 147 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 148 __func__, ret); 149 return ret; 150 } 151 152 ret = clk_set_rate(drvdata->mi2s_bit_clk, rate * bitwidth * 2); 153 if (ret) { 154 dev_err(dai->dev, "%s() error setting mi2s bitclk to %u: %d\n", 155 __func__, rate * bitwidth * 2, ret); 156 return ret; 157 } 158 159 return 0; 160 } 161 162 static int lpass_cpu_daiops_hw_free(struct snd_pcm_substream *substream, 163 struct snd_soc_dai *dai) 164 { 165 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 166 int ret; 167 168 ret = regmap_write(drvdata->lpaif_map, 169 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); 170 if (ret) 171 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 172 __func__, ret); 173 174 return ret; 175 } 176 177 static int lpass_cpu_daiops_prepare(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_update_bits(drvdata->lpaif_map, 184 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 185 LPAIF_I2SCTL_SPKEN_MASK, LPAIF_I2SCTL_SPKEN_ENABLE); 186 if (ret) 187 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 188 __func__, ret); 189 190 return ret; 191 } 192 193 static int lpass_cpu_daiops_trigger(struct snd_pcm_substream *substream, 194 int cmd, struct snd_soc_dai *dai) 195 { 196 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 197 int ret = -EINVAL; 198 199 switch (cmd) { 200 case SNDRV_PCM_TRIGGER_START: 201 case SNDRV_PCM_TRIGGER_RESUME: 202 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 203 ret = regmap_update_bits(drvdata->lpaif_map, 204 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 205 LPAIF_I2SCTL_SPKEN_MASK, 206 LPAIF_I2SCTL_SPKEN_ENABLE); 207 if (ret) 208 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 209 __func__, ret); 210 break; 211 case SNDRV_PCM_TRIGGER_STOP: 212 case SNDRV_PCM_TRIGGER_SUSPEND: 213 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 214 ret = regmap_update_bits(drvdata->lpaif_map, 215 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 216 LPAIF_I2SCTL_SPKEN_MASK, 217 LPAIF_I2SCTL_SPKEN_DISABLE); 218 if (ret) 219 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 220 __func__, ret); 221 break; 222 } 223 224 return ret; 225 } 226 227 static struct snd_soc_dai_ops lpass_cpu_dai_ops = { 228 .set_sysclk = lpass_cpu_daiops_set_sysclk, 229 .startup = lpass_cpu_daiops_startup, 230 .shutdown = lpass_cpu_daiops_shutdown, 231 .hw_params = lpass_cpu_daiops_hw_params, 232 .hw_free = lpass_cpu_daiops_hw_free, 233 .prepare = lpass_cpu_daiops_prepare, 234 .trigger = lpass_cpu_daiops_trigger, 235 }; 236 237 static int lpass_cpu_dai_probe(struct snd_soc_dai *dai) 238 { 239 struct lpass_data *drvdata = snd_soc_dai_get_drvdata(dai); 240 int ret; 241 242 /* ensure audio hardware is disabled */ 243 ret = regmap_write(drvdata->lpaif_map, 244 LPAIF_I2SCTL_REG(LPAIF_I2S_PORT_MI2S), 0); 245 if (ret) 246 dev_err(dai->dev, "%s() error writing to i2sctl reg: %d\n", 247 __func__, ret); 248 249 return ret; 250 } 251 252 static struct snd_soc_dai_driver lpass_cpu_dai_driver = { 253 .playback = { 254 .stream_name = "lpass-cpu-playback", 255 .formats = SNDRV_PCM_FMTBIT_S16 | 256 SNDRV_PCM_FMTBIT_S24 | 257 SNDRV_PCM_FMTBIT_S32, 258 .rates = SNDRV_PCM_RATE_8000 | 259 SNDRV_PCM_RATE_16000 | 260 SNDRV_PCM_RATE_32000 | 261 SNDRV_PCM_RATE_48000 | 262 SNDRV_PCM_RATE_96000, 263 .rate_min = 8000, 264 .rate_max = 96000, 265 .channels_min = 1, 266 .channels_max = 8, 267 }, 268 .probe = &lpass_cpu_dai_probe, 269 .ops = &lpass_cpu_dai_ops, 270 }; 271 272 static const struct snd_soc_component_driver lpass_cpu_comp_driver = { 273 .name = "lpass-cpu", 274 }; 275 276 static bool lpass_cpu_regmap_writeable(struct device *dev, unsigned int reg) 277 { 278 int i; 279 280 for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) 281 if (reg == LPAIF_I2SCTL_REG(i)) 282 return true; 283 284 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { 285 if (reg == LPAIF_IRQEN_REG(i)) 286 return true; 287 if (reg == LPAIF_IRQCLEAR_REG(i)) 288 return true; 289 } 290 291 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { 292 if (reg == LPAIF_RDMACTL_REG(i)) 293 return true; 294 if (reg == LPAIF_RDMABASE_REG(i)) 295 return true; 296 if (reg == LPAIF_RDMABUFF_REG(i)) 297 return true; 298 if (reg == LPAIF_RDMAPER_REG(i)) 299 return true; 300 } 301 302 return false; 303 } 304 305 static bool lpass_cpu_regmap_readable(struct device *dev, unsigned int reg) 306 { 307 int i; 308 309 for (i = 0; i < LPAIF_I2S_PORT_NUM; ++i) 310 if (reg == LPAIF_I2SCTL_REG(i)) 311 return true; 312 313 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) { 314 if (reg == LPAIF_IRQEN_REG(i)) 315 return true; 316 if (reg == LPAIF_IRQSTAT_REG(i)) 317 return true; 318 } 319 320 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) { 321 if (reg == LPAIF_RDMACTL_REG(i)) 322 return true; 323 if (reg == LPAIF_RDMABASE_REG(i)) 324 return true; 325 if (reg == LPAIF_RDMABUFF_REG(i)) 326 return true; 327 if (reg == LPAIF_RDMACURR_REG(i)) 328 return true; 329 if (reg == LPAIF_RDMAPER_REG(i)) 330 return true; 331 } 332 333 return false; 334 } 335 336 static bool lpass_cpu_regmap_volatile(struct device *dev, unsigned int reg) 337 { 338 int i; 339 340 for (i = 0; i < LPAIF_IRQ_PORT_NUM; ++i) 341 if (reg == LPAIF_IRQSTAT_REG(i)) 342 return true; 343 344 for (i = 0; i < LPAIF_RDMA_CHAN_NUM; ++i) 345 if (reg == LPAIF_RDMACURR_REG(i)) 346 return true; 347 348 return false; 349 } 350 351 static const struct regmap_config lpass_cpu_regmap_config = { 352 .reg_bits = 32, 353 .reg_stride = 4, 354 .val_bits = 32, 355 .max_register = LPAIF_RDMAPER_REG(LPAIF_RDMA_CHAN_MAX), 356 .writeable_reg = lpass_cpu_regmap_writeable, 357 .readable_reg = lpass_cpu_regmap_readable, 358 .volatile_reg = lpass_cpu_regmap_volatile, 359 .cache_type = REGCACHE_FLAT, 360 }; 361 362 static int lpass_cpu_platform_probe(struct platform_device *pdev) 363 { 364 struct lpass_data *drvdata; 365 struct device_node *dsp_of_node; 366 struct resource *res; 367 int ret; 368 369 dsp_of_node = of_parse_phandle(pdev->dev.of_node, "qcom,adsp", 0); 370 if (dsp_of_node) { 371 dev_err(&pdev->dev, "%s() DSP exists and holds audio resources\n", 372 __func__); 373 return -EBUSY; 374 } 375 376 drvdata = devm_kzalloc(&pdev->dev, sizeof(struct lpass_data), 377 GFP_KERNEL); 378 if (!drvdata) 379 return -ENOMEM; 380 platform_set_drvdata(pdev, drvdata); 381 382 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpass-lpaif"); 383 if (!res) { 384 dev_err(&pdev->dev, "%s() error getting resource\n", __func__); 385 return -ENODEV; 386 } 387 388 drvdata->lpaif = devm_ioremap_resource(&pdev->dev, res); 389 if (IS_ERR((void const __force *)drvdata->lpaif)) { 390 dev_err(&pdev->dev, "%s() error mapping reg resource: %ld\n", 391 __func__, 392 PTR_ERR((void const __force *)drvdata->lpaif)); 393 return PTR_ERR((void const __force *)drvdata->lpaif); 394 } 395 396 drvdata->lpaif_map = devm_regmap_init_mmio(&pdev->dev, drvdata->lpaif, 397 &lpass_cpu_regmap_config); 398 if (IS_ERR(drvdata->lpaif_map)) { 399 dev_err(&pdev->dev, "%s() error initializing regmap: %ld\n", 400 __func__, PTR_ERR(drvdata->lpaif_map)); 401 return PTR_ERR(drvdata->lpaif_map); 402 } 403 404 drvdata->mi2s_osr_clk = devm_clk_get(&pdev->dev, "mi2s-osr-clk"); 405 if (IS_ERR(drvdata->mi2s_osr_clk)) { 406 dev_err(&pdev->dev, "%s() error getting mi2s-osr-clk: %ld\n", 407 __func__, PTR_ERR(drvdata->mi2s_osr_clk)); 408 return PTR_ERR(drvdata->mi2s_osr_clk); 409 } 410 411 drvdata->mi2s_bit_clk = devm_clk_get(&pdev->dev, "mi2s-bit-clk"); 412 if (IS_ERR(drvdata->mi2s_bit_clk)) { 413 dev_err(&pdev->dev, "%s() error getting mi2s-bit-clk: %ld\n", 414 __func__, PTR_ERR(drvdata->mi2s_bit_clk)); 415 return PTR_ERR(drvdata->mi2s_bit_clk); 416 } 417 418 drvdata->ahbix_clk = devm_clk_get(&pdev->dev, "ahbix-clk"); 419 if (IS_ERR(drvdata->ahbix_clk)) { 420 dev_err(&pdev->dev, "%s() error getting ahbix-clk: %ld\n", 421 __func__, PTR_ERR(drvdata->ahbix_clk)); 422 return PTR_ERR(drvdata->ahbix_clk); 423 } 424 425 ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); 426 if (ret) { 427 dev_err(&pdev->dev, "%s() error setting rate on ahbix_clk: %d\n", 428 __func__, ret); 429 return ret; 430 } 431 dev_dbg(&pdev->dev, "%s() set ahbix_clk rate to %lu\n", __func__, 432 clk_get_rate(drvdata->ahbix_clk)); 433 434 ret = clk_prepare_enable(drvdata->ahbix_clk); 435 if (ret) { 436 dev_err(&pdev->dev, "%s() error enabling ahbix_clk: %d\n", 437 __func__, ret); 438 return ret; 439 } 440 441 ret = devm_snd_soc_register_component(&pdev->dev, 442 &lpass_cpu_comp_driver, &lpass_cpu_dai_driver, 1); 443 if (ret) { 444 dev_err(&pdev->dev, "%s() error registering cpu driver: %d\n", 445 __func__, ret); 446 goto err_clk; 447 } 448 449 ret = asoc_qcom_lpass_platform_register(pdev); 450 if (ret) { 451 dev_err(&pdev->dev, "%s() error registering platform driver: %d\n", 452 __func__, ret); 453 goto err_clk; 454 } 455 456 return 0; 457 458 err_clk: 459 clk_disable_unprepare(drvdata->ahbix_clk); 460 return ret; 461 } 462 463 static int lpass_cpu_platform_remove(struct platform_device *pdev) 464 { 465 struct lpass_data *drvdata = platform_get_drvdata(pdev); 466 467 clk_disable_unprepare(drvdata->ahbix_clk); 468 469 return 0; 470 } 471 472 #ifdef CONFIG_OF 473 static const struct of_device_id lpass_cpu_device_id[] = { 474 { .compatible = "qcom,lpass-cpu" }, 475 {} 476 }; 477 MODULE_DEVICE_TABLE(of, lpass_cpu_device_id); 478 #endif 479 480 static struct platform_driver lpass_cpu_platform_driver = { 481 .driver = { 482 .name = "lpass-cpu", 483 .of_match_table = of_match_ptr(lpass_cpu_device_id), 484 }, 485 .probe = lpass_cpu_platform_probe, 486 .remove = lpass_cpu_platform_remove, 487 }; 488 module_platform_driver(lpass_cpu_platform_driver); 489 490 MODULE_DESCRIPTION("QTi LPASS CPU Driver"); 491 MODULE_LICENSE("GPL v2"); 492