1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de> 4 */ 5 6 #include <linux/init.h> 7 #include <linux/io.h> 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/mod_devicetable.h> 11 #include <linux/platform_device.h> 12 #include <linux/regmap.h> 13 #include <linux/slab.h> 14 15 #include <linux/clk.h> 16 #include <linux/delay.h> 17 18 #include <linux/dma-mapping.h> 19 20 #include <sound/core.h> 21 #include <sound/pcm.h> 22 #include <sound/pcm_params.h> 23 #include <sound/soc.h> 24 #include <sound/initval.h> 25 #include <sound/dmaengine_pcm.h> 26 27 #include "jz4740-i2s.h" 28 29 #define JZ_REG_AIC_CONF 0x00 30 #define JZ_REG_AIC_CTRL 0x04 31 #define JZ_REG_AIC_I2S_FMT 0x10 32 #define JZ_REG_AIC_FIFO_STATUS 0x14 33 #define JZ_REG_AIC_I2S_STATUS 0x1c 34 #define JZ_REG_AIC_CLK_DIV 0x30 35 #define JZ_REG_AIC_FIFO 0x34 36 37 #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_MASK (0xf << 12) 38 #define JZ_AIC_CONF_FIFO_TX_THRESHOLD_MASK (0xf << 8) 39 #define JZ_AIC_CONF_OVERFLOW_PLAY_LAST BIT(6) 40 #define JZ_AIC_CONF_INTERNAL_CODEC BIT(5) 41 #define JZ_AIC_CONF_I2S BIT(4) 42 #define JZ_AIC_CONF_RESET BIT(3) 43 #define JZ_AIC_CONF_BIT_CLK_MASTER BIT(2) 44 #define JZ_AIC_CONF_SYNC_CLK_MASTER BIT(1) 45 #define JZ_AIC_CONF_ENABLE BIT(0) 46 47 #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 48 #define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 49 #define JZ4760_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 24 50 #define JZ4760_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 16 51 52 #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) 53 #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) 54 #define JZ_AIC_CTRL_ENABLE_RX_DMA BIT(15) 55 #define JZ_AIC_CTRL_ENABLE_TX_DMA BIT(14) 56 #define JZ_AIC_CTRL_MONO_TO_STEREO BIT(11) 57 #define JZ_AIC_CTRL_SWITCH_ENDIANNESS BIT(10) 58 #define JZ_AIC_CTRL_SIGNED_TO_UNSIGNED BIT(9) 59 #define JZ_AIC_CTRL_TFLUSH BIT(8) 60 #define JZ_AIC_CTRL_RFLUSH BIT(7) 61 #define JZ_AIC_CTRL_ENABLE_ROR_INT BIT(6) 62 #define JZ_AIC_CTRL_ENABLE_TUR_INT BIT(5) 63 #define JZ_AIC_CTRL_ENABLE_RFS_INT BIT(4) 64 #define JZ_AIC_CTRL_ENABLE_TFS_INT BIT(3) 65 #define JZ_AIC_CTRL_ENABLE_LOOPBACK BIT(2) 66 #define JZ_AIC_CTRL_ENABLE_PLAYBACK BIT(1) 67 #define JZ_AIC_CTRL_ENABLE_CAPTURE BIT(0) 68 69 #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET 19 70 #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 71 72 #define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) 73 #define JZ_AIC_I2S_FMT_DISABLE_BIT_ICLK BIT(13) 74 #define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) 75 #define JZ_AIC_I2S_FMT_MSB BIT(0) 76 77 #define JZ_AIC_I2S_STATUS_BUSY BIT(2) 78 79 #define JZ_AIC_CLK_DIV_MASK 0xf 80 #define I2SDIV_DV_SHIFT 0 81 #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) 82 #define I2SDIV_IDV_SHIFT 8 83 #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) 84 85 enum jz47xx_i2s_version { 86 JZ_I2S_JZ4740, 87 JZ_I2S_JZ4760, 88 JZ_I2S_JZ4770, 89 JZ_I2S_JZ4780, 90 }; 91 92 struct i2s_soc_info { 93 enum jz47xx_i2s_version version; 94 struct snd_soc_dai_driver *dai; 95 96 bool shared_fifo_flush; 97 }; 98 99 struct jz4740_i2s { 100 struct regmap *regmap; 101 102 struct clk *clk_aic; 103 struct clk *clk_i2s; 104 105 struct snd_dmaengine_dai_dma_data playback_dma_data; 106 struct snd_dmaengine_dai_dma_data capture_dma_data; 107 108 const struct i2s_soc_info *soc_info; 109 }; 110 111 static int jz4740_i2s_startup(struct snd_pcm_substream *substream, 112 struct snd_soc_dai *dai) 113 { 114 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 115 int ret; 116 117 /* 118 * When we can flush FIFOs independently, only flush the FIFO 119 * that is starting up. We can do this when the DAI is active 120 * because it does not disturb other active substreams. 121 */ 122 if (!i2s->soc_info->shared_fifo_flush) { 123 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 124 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CTRL, JZ_AIC_CTRL_TFLUSH); 125 else 126 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CTRL, JZ_AIC_CTRL_RFLUSH); 127 } 128 129 if (snd_soc_dai_active(dai)) 130 return 0; 131 132 /* 133 * When there is a shared flush bit for both FIFOs, the TFLUSH 134 * bit flushes both FIFOs. Flushing while the DAI is active would 135 * cause FIFO underruns in other active substreams so we have to 136 * guard this behind the snd_soc_dai_active() check. 137 */ 138 if (i2s->soc_info->shared_fifo_flush) 139 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CTRL, JZ_AIC_CTRL_TFLUSH); 140 141 ret = clk_prepare_enable(i2s->clk_i2s); 142 if (ret) 143 return ret; 144 145 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CONF, JZ_AIC_CONF_ENABLE); 146 return 0; 147 } 148 149 static void jz4740_i2s_shutdown(struct snd_pcm_substream *substream, 150 struct snd_soc_dai *dai) 151 { 152 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 153 154 if (snd_soc_dai_active(dai)) 155 return; 156 157 regmap_clear_bits(i2s->regmap, JZ_REG_AIC_CONF, JZ_AIC_CONF_ENABLE); 158 159 clk_disable_unprepare(i2s->clk_i2s); 160 } 161 162 static int jz4740_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 163 struct snd_soc_dai *dai) 164 { 165 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 166 uint32_t mask; 167 168 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 169 mask = JZ_AIC_CTRL_ENABLE_PLAYBACK | JZ_AIC_CTRL_ENABLE_TX_DMA; 170 else 171 mask = JZ_AIC_CTRL_ENABLE_CAPTURE | JZ_AIC_CTRL_ENABLE_RX_DMA; 172 173 switch (cmd) { 174 case SNDRV_PCM_TRIGGER_START: 175 case SNDRV_PCM_TRIGGER_RESUME: 176 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 177 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CTRL, mask); 178 break; 179 case SNDRV_PCM_TRIGGER_STOP: 180 case SNDRV_PCM_TRIGGER_SUSPEND: 181 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 182 regmap_clear_bits(i2s->regmap, JZ_REG_AIC_CTRL, mask); 183 break; 184 default: 185 return -EINVAL; 186 } 187 188 return 0; 189 } 190 191 static int jz4740_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 192 { 193 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 194 const unsigned int conf_mask = JZ_AIC_CONF_BIT_CLK_MASTER | 195 JZ_AIC_CONF_SYNC_CLK_MASTER; 196 unsigned int conf = 0, format = 0; 197 198 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 199 case SND_SOC_DAIFMT_BP_FP: 200 conf |= JZ_AIC_CONF_BIT_CLK_MASTER | JZ_AIC_CONF_SYNC_CLK_MASTER; 201 format |= JZ_AIC_I2S_FMT_ENABLE_SYS_CLK; 202 break; 203 case SND_SOC_DAIFMT_BC_FP: 204 conf |= JZ_AIC_CONF_SYNC_CLK_MASTER; 205 break; 206 case SND_SOC_DAIFMT_BP_FC: 207 conf |= JZ_AIC_CONF_BIT_CLK_MASTER; 208 break; 209 case SND_SOC_DAIFMT_BC_FC: 210 break; 211 default: 212 return -EINVAL; 213 } 214 215 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 216 case SND_SOC_DAIFMT_MSB: 217 format |= JZ_AIC_I2S_FMT_MSB; 218 break; 219 case SND_SOC_DAIFMT_I2S: 220 break; 221 default: 222 return -EINVAL; 223 } 224 225 switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 226 case SND_SOC_DAIFMT_NB_NF: 227 break; 228 default: 229 return -EINVAL; 230 } 231 232 regmap_update_bits(i2s->regmap, JZ_REG_AIC_CONF, conf_mask, conf); 233 regmap_write(i2s->regmap, JZ_REG_AIC_I2S_FMT, format); 234 235 return 0; 236 } 237 238 static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, 239 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 240 { 241 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 242 unsigned int sample_size; 243 uint32_t ctrl, div_reg; 244 int div; 245 246 regmap_read(i2s->regmap, JZ_REG_AIC_CTRL, &ctrl); 247 regmap_read(i2s->regmap, JZ_REG_AIC_CLK_DIV, &div_reg); 248 249 div = clk_get_rate(i2s->clk_i2s) / (64 * params_rate(params)); 250 251 switch (params_format(params)) { 252 case SNDRV_PCM_FORMAT_S8: 253 sample_size = 0; 254 break; 255 case SNDRV_PCM_FORMAT_S16: 256 sample_size = 1; 257 break; 258 default: 259 return -EINVAL; 260 } 261 262 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 263 ctrl &= ~JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK; 264 ctrl |= sample_size << JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_OFFSET; 265 if (params_channels(params) == 1) 266 ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; 267 else 268 ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; 269 270 div_reg &= ~I2SDIV_DV_MASK; 271 div_reg |= (div - 1) << I2SDIV_DV_SHIFT; 272 } else { 273 ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; 274 ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; 275 276 if (i2s->soc_info->version >= JZ_I2S_JZ4770) { 277 div_reg &= ~I2SDIV_IDV_MASK; 278 div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; 279 } else { 280 div_reg &= ~I2SDIV_DV_MASK; 281 div_reg |= (div - 1) << I2SDIV_DV_SHIFT; 282 } 283 } 284 285 regmap_write(i2s->regmap, JZ_REG_AIC_CTRL, ctrl); 286 regmap_write(i2s->regmap, JZ_REG_AIC_CLK_DIV, div_reg); 287 288 return 0; 289 } 290 291 static int jz4740_i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, 292 unsigned int freq, int dir) 293 { 294 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 295 struct clk *parent; 296 int ret = 0; 297 298 switch (clk_id) { 299 case JZ4740_I2S_CLKSRC_EXT: 300 parent = clk_get(NULL, "ext"); 301 if (IS_ERR(parent)) 302 return PTR_ERR(parent); 303 clk_set_parent(i2s->clk_i2s, parent); 304 break; 305 case JZ4740_I2S_CLKSRC_PLL: 306 parent = clk_get(NULL, "pll half"); 307 if (IS_ERR(parent)) 308 return PTR_ERR(parent); 309 clk_set_parent(i2s->clk_i2s, parent); 310 ret = clk_set_rate(i2s->clk_i2s, freq); 311 break; 312 default: 313 return -EINVAL; 314 } 315 clk_put(parent); 316 317 return ret; 318 } 319 320 static int jz4740_i2s_suspend(struct snd_soc_component *component) 321 { 322 struct jz4740_i2s *i2s = snd_soc_component_get_drvdata(component); 323 324 if (snd_soc_component_active(component)) { 325 regmap_clear_bits(i2s->regmap, JZ_REG_AIC_CONF, JZ_AIC_CONF_ENABLE); 326 clk_disable_unprepare(i2s->clk_i2s); 327 } 328 329 clk_disable_unprepare(i2s->clk_aic); 330 331 return 0; 332 } 333 334 static int jz4740_i2s_resume(struct snd_soc_component *component) 335 { 336 struct jz4740_i2s *i2s = snd_soc_component_get_drvdata(component); 337 int ret; 338 339 ret = clk_prepare_enable(i2s->clk_aic); 340 if (ret) 341 return ret; 342 343 if (snd_soc_component_active(component)) { 344 ret = clk_prepare_enable(i2s->clk_i2s); 345 if (ret) { 346 clk_disable_unprepare(i2s->clk_aic); 347 return ret; 348 } 349 350 regmap_set_bits(i2s->regmap, JZ_REG_AIC_CONF, JZ_AIC_CONF_ENABLE); 351 } 352 353 return 0; 354 } 355 356 static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) 357 { 358 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 359 uint32_t conf; 360 int ret; 361 362 ret = clk_prepare_enable(i2s->clk_aic); 363 if (ret) 364 return ret; 365 366 snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, 367 &i2s->capture_dma_data); 368 369 if (i2s->soc_info->version >= JZ_I2S_JZ4760) { 370 conf = (7 << JZ4760_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 371 (8 << JZ4760_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 372 JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 373 JZ_AIC_CONF_I2S | 374 JZ_AIC_CONF_INTERNAL_CODEC; 375 } else { 376 conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 377 (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 378 JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 379 JZ_AIC_CONF_I2S | 380 JZ_AIC_CONF_INTERNAL_CODEC; 381 } 382 383 regmap_write(i2s->regmap, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); 384 regmap_write(i2s->regmap, JZ_REG_AIC_CONF, conf); 385 386 return 0; 387 } 388 389 static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai) 390 { 391 struct jz4740_i2s *i2s = snd_soc_dai_get_drvdata(dai); 392 393 clk_disable_unprepare(i2s->clk_aic); 394 return 0; 395 } 396 397 static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = { 398 .startup = jz4740_i2s_startup, 399 .shutdown = jz4740_i2s_shutdown, 400 .trigger = jz4740_i2s_trigger, 401 .hw_params = jz4740_i2s_hw_params, 402 .set_fmt = jz4740_i2s_set_fmt, 403 .set_sysclk = jz4740_i2s_set_sysclk, 404 }; 405 406 #define JZ4740_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \ 407 SNDRV_PCM_FMTBIT_S16_LE) 408 409 static struct snd_soc_dai_driver jz4740_i2s_dai = { 410 .probe = jz4740_i2s_dai_probe, 411 .remove = jz4740_i2s_dai_remove, 412 .playback = { 413 .channels_min = 1, 414 .channels_max = 2, 415 .rates = SNDRV_PCM_RATE_8000_48000, 416 .formats = JZ4740_I2S_FMTS, 417 }, 418 .capture = { 419 .channels_min = 2, 420 .channels_max = 2, 421 .rates = SNDRV_PCM_RATE_8000_48000, 422 .formats = JZ4740_I2S_FMTS, 423 }, 424 .symmetric_rate = 1, 425 .ops = &jz4740_i2s_dai_ops, 426 }; 427 428 static const struct i2s_soc_info jz4740_i2s_soc_info = { 429 .version = JZ_I2S_JZ4740, 430 .dai = &jz4740_i2s_dai, 431 .shared_fifo_flush = true, 432 }; 433 434 static const struct i2s_soc_info jz4760_i2s_soc_info = { 435 .version = JZ_I2S_JZ4760, 436 .dai = &jz4740_i2s_dai, 437 }; 438 439 static struct snd_soc_dai_driver jz4770_i2s_dai = { 440 .probe = jz4740_i2s_dai_probe, 441 .remove = jz4740_i2s_dai_remove, 442 .playback = { 443 .channels_min = 1, 444 .channels_max = 2, 445 .rates = SNDRV_PCM_RATE_8000_48000, 446 .formats = JZ4740_I2S_FMTS, 447 }, 448 .capture = { 449 .channels_min = 2, 450 .channels_max = 2, 451 .rates = SNDRV_PCM_RATE_8000_48000, 452 .formats = JZ4740_I2S_FMTS, 453 }, 454 .ops = &jz4740_i2s_dai_ops, 455 }; 456 457 static const struct i2s_soc_info jz4770_i2s_soc_info = { 458 .version = JZ_I2S_JZ4770, 459 .dai = &jz4770_i2s_dai, 460 }; 461 462 static const struct i2s_soc_info jz4780_i2s_soc_info = { 463 .version = JZ_I2S_JZ4780, 464 .dai = &jz4770_i2s_dai, 465 }; 466 467 static const struct snd_soc_component_driver jz4740_i2s_component = { 468 .name = "jz4740-i2s", 469 .suspend = jz4740_i2s_suspend, 470 .resume = jz4740_i2s_resume, 471 .legacy_dai_naming = 1, 472 }; 473 474 static const struct of_device_id jz4740_of_matches[] = { 475 { .compatible = "ingenic,jz4740-i2s", .data = &jz4740_i2s_soc_info }, 476 { .compatible = "ingenic,jz4760-i2s", .data = &jz4760_i2s_soc_info }, 477 { .compatible = "ingenic,jz4770-i2s", .data = &jz4770_i2s_soc_info }, 478 { .compatible = "ingenic,jz4780-i2s", .data = &jz4780_i2s_soc_info }, 479 { /* sentinel */ } 480 }; 481 MODULE_DEVICE_TABLE(of, jz4740_of_matches); 482 483 static const struct regmap_config jz4740_i2s_regmap_config = { 484 .reg_bits = 32, 485 .reg_stride = 4, 486 .val_bits = 32, 487 .max_register = JZ_REG_AIC_FIFO, 488 }; 489 490 static int jz4740_i2s_dev_probe(struct platform_device *pdev) 491 { 492 struct device *dev = &pdev->dev; 493 struct jz4740_i2s *i2s; 494 struct resource *mem; 495 void __iomem *regs; 496 int ret; 497 498 i2s = devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); 499 if (!i2s) 500 return -ENOMEM; 501 502 i2s->soc_info = device_get_match_data(dev); 503 504 regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); 505 if (IS_ERR(regs)) 506 return PTR_ERR(regs); 507 508 i2s->playback_dma_data.maxburst = 16; 509 i2s->playback_dma_data.addr = mem->start + JZ_REG_AIC_FIFO; 510 511 i2s->capture_dma_data.maxburst = 16; 512 i2s->capture_dma_data.addr = mem->start + JZ_REG_AIC_FIFO; 513 514 i2s->clk_aic = devm_clk_get(dev, "aic"); 515 if (IS_ERR(i2s->clk_aic)) 516 return PTR_ERR(i2s->clk_aic); 517 518 i2s->clk_i2s = devm_clk_get(dev, "i2s"); 519 if (IS_ERR(i2s->clk_i2s)) 520 return PTR_ERR(i2s->clk_i2s); 521 522 i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, 523 &jz4740_i2s_regmap_config); 524 if (IS_ERR(i2s->regmap)) 525 return PTR_ERR(i2s->regmap); 526 527 platform_set_drvdata(pdev, i2s); 528 529 ret = devm_snd_soc_register_component(dev, &jz4740_i2s_component, 530 i2s->soc_info->dai, 1); 531 if (ret) 532 return ret; 533 534 return devm_snd_dmaengine_pcm_register(dev, NULL, 535 SND_DMAENGINE_PCM_FLAG_COMPAT); 536 } 537 538 static struct platform_driver jz4740_i2s_driver = { 539 .probe = jz4740_i2s_dev_probe, 540 .driver = { 541 .name = "jz4740-i2s", 542 .of_match_table = jz4740_of_matches, 543 }, 544 }; 545 546 module_platform_driver(jz4740_i2s_driver); 547 548 MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>"); 549 MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver"); 550 MODULE_LICENSE("GPL"); 551 MODULE_ALIAS("platform:jz4740-i2s"); 552