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