Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: jz4740: Add jz4780 support

The jz4780 and jz4740 have very similar i2s blocks.

The slight difference is in Rx/Tx fifos.
And the bitclocks for input/output are different.

This patch adds jz4780 support to the driver

Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
Acked-by: Lars-Peter Clausen <lars@metafoo.de>
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Zubair Lutfullah Kakakhel and committed by
Mark Brown
967beb2e c517d838

+75 -11
+1 -1
Documentation/devicetree/bindings/sound/ingenic,jz4740-i2s.txt
··· 1 1 Ingenic JZ4740 I2S controller 2 2 3 3 Required properties: 4 - - compatible : "ingenic,jz4740-i2s" 4 + - compatible : "ingenic,jz4740-i2s" or "ingenic,jz4780-i2s" 5 5 - reg : I2S registers location and length 6 6 - clocks : AIC and I2S PLL clock specifiers. 7 7 - clock-names: "aic" and "i2s"
+74 -10
sound/soc/jz4740/jz4740-i2s.c
··· 58 58 59 59 #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 60 60 #define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 61 + #define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 24 62 + #define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 16 63 + #define JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_MASK \ 64 + (0xf << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) 65 + #define JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_MASK \ 66 + (0x1f << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) 61 67 62 68 #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) 63 69 #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) ··· 85 79 #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 86 80 87 81 #define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) 82 + #define JZ_AIC_I2S_FMT_DISABLE_BIT_ICLK BIT(13) 88 83 #define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) 89 84 #define JZ_AIC_I2S_FMT_MSB BIT(0) 90 85 ··· 94 87 #define JZ_AIC_CLK_DIV_MASK 0xf 95 88 #define I2SDIV_DV_SHIFT 8 96 89 #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) 90 + #define I2SDIV_IDV_SHIFT 8 91 + #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) 92 + 93 + enum jz47xx_i2s_version { 94 + JZ_I2S_JZ4740, 95 + JZ_I2S_JZ4780, 96 + }; 97 97 98 98 struct jz4740_i2s { 99 99 struct resource *mem; ··· 112 98 113 99 struct snd_dmaengine_dai_dma_data playback_dma_data; 114 100 struct snd_dmaengine_dai_dma_data capture_dma_data; 101 + 102 + enum jz47xx_i2s_version version; 115 103 }; 116 104 117 105 static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, ··· 283 267 ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; 284 268 else 285 269 ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; 270 + 271 + div_reg &= ~I2SDIV_DV_MASK; 272 + div_reg |= (div - 1) << I2SDIV_DV_SHIFT; 286 273 } else { 287 274 ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; 288 275 ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; 276 + 277 + if (i2s->version >= JZ_I2S_JZ4780) { 278 + div_reg &= ~I2SDIV_IDV_MASK; 279 + div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; 280 + } else { 281 + div_reg &= ~I2SDIV_DV_MASK; 282 + div_reg |= (div - 1) << I2SDIV_DV_SHIFT; 283 + } 289 284 } 290 285 291 - div_reg &= ~I2SDIV_DV_MASK; 292 - div_reg |= (div - 1) << I2SDIV_DV_SHIFT; 293 286 jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); 294 287 jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); 295 288 ··· 394 369 snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, 395 370 &i2s->capture_dma_data); 396 371 397 - conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 398 - (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 399 - JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 400 - JZ_AIC_CONF_I2S | 401 - JZ_AIC_CONF_INTERNAL_CODEC; 372 + if (i2s->version >= JZ_I2S_JZ4780) { 373 + conf = (7 << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 374 + (8 << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 375 + JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 376 + JZ_AIC_CONF_I2S | 377 + JZ_AIC_CONF_INTERNAL_CODEC; 378 + } else { 379 + conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | 380 + (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | 381 + JZ_AIC_CONF_OVERFLOW_PLAY_LAST | 382 + JZ_AIC_CONF_I2S | 383 + JZ_AIC_CONF_INTERNAL_CODEC; 384 + } 402 385 403 386 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); 404 387 jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); ··· 455 422 .resume = jz4740_i2s_resume, 456 423 }; 457 424 425 + static struct snd_soc_dai_driver jz4780_i2s_dai = { 426 + .probe = jz4740_i2s_dai_probe, 427 + .remove = jz4740_i2s_dai_remove, 428 + .playback = { 429 + .channels_min = 1, 430 + .channels_max = 2, 431 + .rates = SNDRV_PCM_RATE_8000_48000, 432 + .formats = JZ4740_I2S_FMTS, 433 + }, 434 + .capture = { 435 + .channels_min = 2, 436 + .channels_max = 2, 437 + .rates = SNDRV_PCM_RATE_8000_48000, 438 + .formats = JZ4740_I2S_FMTS, 439 + }, 440 + .ops = &jz4740_i2s_dai_ops, 441 + .suspend = jz4740_i2s_suspend, 442 + .resume = jz4740_i2s_resume, 443 + }; 444 + 458 445 static const struct snd_soc_component_driver jz4740_i2s_component = { 459 446 .name = "jz4740-i2s", 460 447 }; 461 448 462 449 #ifdef CONFIG_OF 463 450 static const struct of_device_id jz4740_of_matches[] = { 464 - { .compatible = "ingenic,jz4740-i2s" }, 451 + { .compatible = "ingenic,jz4740-i2s", .data = (void *)JZ_I2S_JZ4740 }, 452 + { .compatible = "ingenic,jz4780-i2s", .data = (void *)JZ_I2S_JZ4780 }, 465 453 { /* sentinel */ } 466 454 }; 467 455 #endif ··· 492 438 struct jz4740_i2s *i2s; 493 439 struct resource *mem; 494 440 int ret; 441 + const struct of_device_id *match; 495 442 496 443 i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); 497 444 if (!i2s) 498 445 return -ENOMEM; 446 + 447 + match = of_match_device(jz4740_of_matches, &pdev->dev); 448 + if (match) 449 + i2s->version = (enum jz47xx_i2s_version)match->data; 499 450 500 451 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 501 452 i2s->base = devm_ioremap_resource(&pdev->dev, mem); ··· 519 460 520 461 platform_set_drvdata(pdev, i2s); 521 462 522 - ret = devm_snd_soc_register_component(&pdev->dev, 523 - &jz4740_i2s_component, &jz4740_i2s_dai, 1); 463 + if (i2s->version == JZ_I2S_JZ4780) 464 + ret = devm_snd_soc_register_component(&pdev->dev, 465 + &jz4740_i2s_component, &jz4780_i2s_dai, 1); 466 + else 467 + ret = devm_snd_soc_register_component(&pdev->dev, 468 + &jz4740_i2s_component, &jz4740_i2s_dai, 1); 469 + 524 470 if (ret) 525 471 return ret; 526 472