diff options
author | Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com> | 2015-03-09 08:11:08 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-03-09 14:10:17 -0400 |
commit | 967beb2e87771411e08467152e3d9f1c3ae73a67 (patch) | |
tree | 9960e9024c97dfc5539fb480bdcdcb476e89637f /sound/soc/jz4740 | |
parent | c517d838eb7d07bbe9507871fab3931deccff539 (diff) |
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>
Diffstat (limited to 'sound/soc/jz4740')
-rw-r--r-- | sound/soc/jz4740/jz4740-i2s.c | 84 |
1 files changed, 74 insertions, 10 deletions
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c index 07f77815a586..b05fb1c1a848 100644 --- a/sound/soc/jz4740/jz4740-i2s.c +++ b/sound/soc/jz4740/jz4740-i2s.c | |||
@@ -58,6 +58,12 @@ | |||
58 | 58 | ||
59 | #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 | 59 | #define JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET 12 |
60 | #define JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET 8 | 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 | #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) | 68 | #define JZ_AIC_CTRL_OUTPUT_SAMPLE_SIZE_MASK (0x7 << 19) |
63 | #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) | 69 | #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK (0x7 << 16) |
@@ -79,6 +85,7 @@ | |||
79 | #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 | 85 | #define JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET 16 |
80 | 86 | ||
81 | #define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) | 87 | #define JZ_AIC_I2S_FMT_DISABLE_BIT_CLK BIT(12) |
88 | #define JZ_AIC_I2S_FMT_DISABLE_BIT_ICLK BIT(13) | ||
82 | #define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) | 89 | #define JZ_AIC_I2S_FMT_ENABLE_SYS_CLK BIT(4) |
83 | #define JZ_AIC_I2S_FMT_MSB BIT(0) | 90 | #define JZ_AIC_I2S_FMT_MSB BIT(0) |
84 | 91 | ||
@@ -87,6 +94,13 @@ | |||
87 | #define JZ_AIC_CLK_DIV_MASK 0xf | 94 | #define JZ_AIC_CLK_DIV_MASK 0xf |
88 | #define I2SDIV_DV_SHIFT 8 | 95 | #define I2SDIV_DV_SHIFT 8 |
89 | #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) | 96 | #define I2SDIV_DV_MASK (0xf << I2SDIV_DV_SHIFT) |
97 | #define I2SDIV_IDV_SHIFT 8 | ||
98 | #define I2SDIV_IDV_MASK (0xf << I2SDIV_IDV_SHIFT) | ||
99 | |||
100 | enum jz47xx_i2s_version { | ||
101 | JZ_I2S_JZ4740, | ||
102 | JZ_I2S_JZ4780, | ||
103 | }; | ||
90 | 104 | ||
91 | struct jz4740_i2s { | 105 | struct jz4740_i2s { |
92 | struct resource *mem; | 106 | struct resource *mem; |
@@ -98,6 +112,8 @@ struct jz4740_i2s { | |||
98 | 112 | ||
99 | struct snd_dmaengine_dai_dma_data playback_dma_data; | 113 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
100 | struct snd_dmaengine_dai_dma_data capture_dma_data; | 114 | struct snd_dmaengine_dai_dma_data capture_dma_data; |
115 | |||
116 | enum jz47xx_i2s_version version; | ||
101 | }; | 117 | }; |
102 | 118 | ||
103 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, | 119 | static inline uint32_t jz4740_i2s_read(const struct jz4740_i2s *i2s, |
@@ -267,13 +283,22 @@ static int jz4740_i2s_hw_params(struct snd_pcm_substream *substream, | |||
267 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; | 283 | ctrl |= JZ_AIC_CTRL_MONO_TO_STEREO; |
268 | else | 284 | else |
269 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; | 285 | ctrl &= ~JZ_AIC_CTRL_MONO_TO_STEREO; |
286 | |||
287 | div_reg &= ~I2SDIV_DV_MASK; | ||
288 | div_reg |= (div - 1) << I2SDIV_DV_SHIFT; | ||
270 | } else { | 289 | } else { |
271 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; | 290 | ctrl &= ~JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_MASK; |
272 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; | 291 | ctrl |= sample_size << JZ_AIC_CTRL_INPUT_SAMPLE_SIZE_OFFSET; |
292 | |||
293 | if (i2s->version >= JZ_I2S_JZ4780) { | ||
294 | div_reg &= ~I2SDIV_IDV_MASK; | ||
295 | div_reg |= (div - 1) << I2SDIV_IDV_SHIFT; | ||
296 | } else { | ||
297 | div_reg &= ~I2SDIV_DV_MASK; | ||
298 | div_reg |= (div - 1) << I2SDIV_DV_SHIFT; | ||
299 | } | ||
273 | } | 300 | } |
274 | 301 | ||
275 | div_reg &= ~I2SDIV_DV_MASK; | ||
276 | div_reg |= (div - 1) << I2SDIV_DV_SHIFT; | ||
277 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); | 302 | jz4740_i2s_write(i2s, JZ_REG_AIC_CTRL, ctrl); |
278 | jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); | 303 | jz4740_i2s_write(i2s, JZ_REG_AIC_CLK_DIV, div_reg); |
279 | 304 | ||
@@ -369,11 +394,19 @@ static int jz4740_i2s_dai_probe(struct snd_soc_dai *dai) | |||
369 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, | 394 | snd_soc_dai_init_dma_data(dai, &i2s->playback_dma_data, |
370 | &i2s->capture_dma_data); | 395 | &i2s->capture_dma_data); |
371 | 396 | ||
372 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | | 397 | if (i2s->version >= JZ_I2S_JZ4780) { |
373 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | | 398 | conf = (7 << JZ4780_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | |
374 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | | 399 | (8 << JZ4780_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | |
375 | JZ_AIC_CONF_I2S | | 400 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | |
376 | JZ_AIC_CONF_INTERNAL_CODEC; | 401 | JZ_AIC_CONF_I2S | |
402 | JZ_AIC_CONF_INTERNAL_CODEC; | ||
403 | } else { | ||
404 | conf = (7 << JZ_AIC_CONF_FIFO_RX_THRESHOLD_OFFSET) | | ||
405 | (8 << JZ_AIC_CONF_FIFO_TX_THRESHOLD_OFFSET) | | ||
406 | JZ_AIC_CONF_OVERFLOW_PLAY_LAST | | ||
407 | JZ_AIC_CONF_I2S | | ||
408 | JZ_AIC_CONF_INTERNAL_CODEC; | ||
409 | } | ||
377 | 410 | ||
378 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); | 411 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, JZ_AIC_CONF_RESET); |
379 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); | 412 | jz4740_i2s_write(i2s, JZ_REG_AIC_CONF, conf); |
@@ -422,13 +455,34 @@ static struct snd_soc_dai_driver jz4740_i2s_dai = { | |||
422 | .resume = jz4740_i2s_resume, | 455 | .resume = jz4740_i2s_resume, |
423 | }; | 456 | }; |
424 | 457 | ||
458 | static struct snd_soc_dai_driver jz4780_i2s_dai = { | ||
459 | .probe = jz4740_i2s_dai_probe, | ||
460 | .remove = jz4740_i2s_dai_remove, | ||
461 | .playback = { | ||
462 | .channels_min = 1, | ||
463 | .channels_max = 2, | ||
464 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
465 | .formats = JZ4740_I2S_FMTS, | ||
466 | }, | ||
467 | .capture = { | ||
468 | .channels_min = 2, | ||
469 | .channels_max = 2, | ||
470 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
471 | .formats = JZ4740_I2S_FMTS, | ||
472 | }, | ||
473 | .ops = &jz4740_i2s_dai_ops, | ||
474 | .suspend = jz4740_i2s_suspend, | ||
475 | .resume = jz4740_i2s_resume, | ||
476 | }; | ||
477 | |||
425 | static const struct snd_soc_component_driver jz4740_i2s_component = { | 478 | static const struct snd_soc_component_driver jz4740_i2s_component = { |
426 | .name = "jz4740-i2s", | 479 | .name = "jz4740-i2s", |
427 | }; | 480 | }; |
428 | 481 | ||
429 | #ifdef CONFIG_OF | 482 | #ifdef CONFIG_OF |
430 | static const struct of_device_id jz4740_of_matches[] = { | 483 | static const struct of_device_id jz4740_of_matches[] = { |
431 | { .compatible = "ingenic,jz4740-i2s" }, | 484 | { .compatible = "ingenic,jz4740-i2s", .data = (void *)JZ_I2S_JZ4740 }, |
485 | { .compatible = "ingenic,jz4780-i2s", .data = (void *)JZ_I2S_JZ4780 }, | ||
432 | { /* sentinel */ } | 486 | { /* sentinel */ } |
433 | }; | 487 | }; |
434 | #endif | 488 | #endif |
@@ -438,11 +492,16 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) | |||
438 | struct jz4740_i2s *i2s; | 492 | struct jz4740_i2s *i2s; |
439 | struct resource *mem; | 493 | struct resource *mem; |
440 | int ret; | 494 | int ret; |
495 | const struct of_device_id *match; | ||
441 | 496 | ||
442 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); | 497 | i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL); |
443 | if (!i2s) | 498 | if (!i2s) |
444 | return -ENOMEM; | 499 | return -ENOMEM; |
445 | 500 | ||
501 | match = of_match_device(jz4740_of_matches, &pdev->dev); | ||
502 | if (match) | ||
503 | i2s->version = (enum jz47xx_i2s_version)match->data; | ||
504 | |||
446 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 505 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
447 | i2s->base = devm_ioremap_resource(&pdev->dev, mem); | 506 | i2s->base = devm_ioremap_resource(&pdev->dev, mem); |
448 | if (IS_ERR(i2s->base)) | 507 | if (IS_ERR(i2s->base)) |
@@ -460,8 +519,13 @@ static int jz4740_i2s_dev_probe(struct platform_device *pdev) | |||
460 | 519 | ||
461 | platform_set_drvdata(pdev, i2s); | 520 | platform_set_drvdata(pdev, i2s); |
462 | 521 | ||
463 | ret = devm_snd_soc_register_component(&pdev->dev, | 522 | if (i2s->version == JZ_I2S_JZ4780) |
464 | &jz4740_i2s_component, &jz4740_i2s_dai, 1); | 523 | ret = devm_snd_soc_register_component(&pdev->dev, |
524 | &jz4740_i2s_component, &jz4780_i2s_dai, 1); | ||
525 | else | ||
526 | ret = devm_snd_soc_register_component(&pdev->dev, | ||
527 | &jz4740_i2s_component, &jz4740_i2s_dai, 1); | ||
528 | |||
465 | if (ret) | 529 | if (ret) |
466 | return ret; | 530 | return ret; |
467 | 531 | ||