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