diff options
author | Sugar Zhang <sugar.zhang@rock-chips.com> | 2016-04-11 05:26:03 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-05-30 11:19:41 -0400 |
commit | 170abcaae8bec0a53f2f7708a83119ec42fb09e2 (patch) | |
tree | 81e39509d076707f6ac8c433686088003b07d46c | |
parent | 1a695a905c18548062509178b98bc91e67510864 (diff) |
ASoC: rockchip: i2s: configure the sdio pins' iomux mode
There are 3 i2s sdio pins, which iomux mode is as follows:
- sdi3_sdo1
- sdi2_sdo2
- sdi1_sdo3
we need to configure these pins' iomux mode via the GRF register
when use multi channel playback/capture.
Signed-off-by: Sugar Zhang <sugar.zhang@rock-chips.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/rockchip-i2s.txt | 5 | ||||
-rw-r--r-- | sound/soc/rockchip/rockchip_i2s.c | 67 | ||||
-rw-r--r-- | sound/soc/rockchip/rockchip_i2s.h | 7 |
3 files changed, 70 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt index 6e86d8aa29b4..4ea29aa9af59 100644 --- a/Documentation/devicetree/bindings/sound/rockchip-i2s.txt +++ b/Documentation/devicetree/bindings/sound/rockchip-i2s.txt | |||
@@ -23,6 +23,11 @@ Required properties: | |||
23 | - rockchip,playback-channels: max playback channels, if not set, 8 channels default. | 23 | - rockchip,playback-channels: max playback channels, if not set, 8 channels default. |
24 | - rockchip,capture-channels: max capture channels, if not set, 2 channels default. | 24 | - rockchip,capture-channels: max capture channels, if not set, 2 channels default. |
25 | 25 | ||
26 | Required properties for controller which support multi channels | ||
27 | playback/capture: | ||
28 | |||
29 | - rockchip,grf: the phandle of the syscon node for GRF register. | ||
30 | |||
26 | Example for rk3288 I2S controller: | 31 | Example for rk3288 I2S controller: |
27 | 32 | ||
28 | i2s@ff890000 { | 33 | i2s@ff890000 { |
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c index 574c6af28c06..2f290f3a0ac7 100644 --- a/sound/soc/rockchip/rockchip_i2s.c +++ b/sound/soc/rockchip/rockchip_i2s.c | |||
@@ -11,8 +11,10 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/mfd/syscon.h> | ||
14 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
15 | #include <linux/of_gpio.h> | 16 | #include <linux/of_gpio.h> |
17 | #include <linux/of_device.h> | ||
16 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
17 | #include <linux/pm_runtime.h> | 19 | #include <linux/pm_runtime.h> |
18 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
@@ -23,6 +25,11 @@ | |||
23 | 25 | ||
24 | #define DRV_NAME "rockchip-i2s" | 26 | #define DRV_NAME "rockchip-i2s" |
25 | 27 | ||
28 | struct rk_i2s_pins { | ||
29 | u32 reg_offset; | ||
30 | u32 shift; | ||
31 | }; | ||
32 | |||
26 | struct rk_i2s_dev { | 33 | struct rk_i2s_dev { |
27 | struct device *dev; | 34 | struct device *dev; |
28 | 35 | ||
@@ -33,6 +40,7 @@ struct rk_i2s_dev { | |||
33 | struct snd_dmaengine_dai_dma_data playback_dma_data; | 40 | struct snd_dmaengine_dai_dma_data playback_dma_data; |
34 | 41 | ||
35 | struct regmap *regmap; | 42 | struct regmap *regmap; |
43 | struct regmap *grf; | ||
36 | 44 | ||
37 | /* | 45 | /* |
38 | * Used to indicate the tx/rx status. | 46 | * Used to indicate the tx/rx status. |
@@ -42,6 +50,7 @@ struct rk_i2s_dev { | |||
42 | bool tx_start; | 50 | bool tx_start; |
43 | bool rx_start; | 51 | bool rx_start; |
44 | bool is_master_mode; | 52 | bool is_master_mode; |
53 | const struct rk_i2s_pins *pins; | ||
45 | }; | 54 | }; |
46 | 55 | ||
47 | static int i2s_runtime_suspend(struct device *dev) | 56 | static int i2s_runtime_suspend(struct device *dev) |
@@ -300,6 +309,30 @@ static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream, | |||
300 | I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, | 309 | I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK, |
301 | val); | 310 | val); |
302 | 311 | ||
312 | if (!IS_ERR(i2s->grf) && i2s->pins) { | ||
313 | regmap_read(i2s->regmap, I2S_TXCR, &val); | ||
314 | val &= I2S_TXCR_CSR_MASK; | ||
315 | |||
316 | switch (val) { | ||
317 | case I2S_CHN_4: | ||
318 | val = I2S_IO_4CH_OUT_6CH_IN; | ||
319 | break; | ||
320 | case I2S_CHN_6: | ||
321 | val = I2S_IO_6CH_OUT_4CH_IN; | ||
322 | break; | ||
323 | case I2S_CHN_8: | ||
324 | val = I2S_IO_8CH_OUT_2CH_IN; | ||
325 | break; | ||
326 | default: | ||
327 | val = I2S_IO_2CH_OUT_8CH_IN; | ||
328 | break; | ||
329 | } | ||
330 | |||
331 | val <<= i2s->pins->shift; | ||
332 | val |= (I2S_IO_DIRECTION_MASK << i2s->pins->shift) << 16; | ||
333 | regmap_write(i2s->grf, i2s->pins->reg_offset, val); | ||
334 | } | ||
335 | |||
303 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, | 336 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK, |
304 | I2S_DMACR_TDL(16)); | 337 | I2S_DMACR_TDL(16)); |
305 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, | 338 | regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK, |
@@ -485,9 +518,23 @@ static const struct regmap_config rockchip_i2s_regmap_config = { | |||
485 | .cache_type = REGCACHE_FLAT, | 518 | .cache_type = REGCACHE_FLAT, |
486 | }; | 519 | }; |
487 | 520 | ||
521 | static const struct rk_i2s_pins rk3399_i2s_pins = { | ||
522 | .reg_offset = 0xe220, | ||
523 | .shift = 11, | ||
524 | }; | ||
525 | |||
526 | static const struct of_device_id rockchip_i2s_match[] = { | ||
527 | { .compatible = "rockchip,rk3066-i2s", }, | ||
528 | { .compatible = "rockchip,rk3188-i2s", }, | ||
529 | { .compatible = "rockchip,rk3288-i2s", }, | ||
530 | { .compatible = "rockchip,rk3399-i2s", .data = &rk3399_i2s_pins }, | ||
531 | {}, | ||
532 | }; | ||
533 | |||
488 | static int rockchip_i2s_probe(struct platform_device *pdev) | 534 | static int rockchip_i2s_probe(struct platform_device *pdev) |
489 | { | 535 | { |
490 | struct device_node *node = pdev->dev.of_node; | 536 | struct device_node *node = pdev->dev.of_node; |
537 | const struct of_device_id *of_id; | ||
491 | struct rk_i2s_dev *i2s; | 538 | struct rk_i2s_dev *i2s; |
492 | struct snd_soc_dai_driver *soc_dai; | 539 | struct snd_soc_dai_driver *soc_dai; |
493 | struct resource *res; | 540 | struct resource *res; |
@@ -501,6 +548,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
501 | return -ENOMEM; | 548 | return -ENOMEM; |
502 | } | 549 | } |
503 | 550 | ||
551 | i2s->dev = &pdev->dev; | ||
552 | |||
553 | i2s->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf"); | ||
554 | if (!IS_ERR(i2s->grf)) { | ||
555 | of_id = of_match_device(rockchip_i2s_match, &pdev->dev); | ||
556 | if (!of_id || !of_id->data) | ||
557 | return -EINVAL; | ||
558 | |||
559 | i2s->pins = of_id->data; | ||
560 | } | ||
561 | |||
504 | /* try to prepare related clocks */ | 562 | /* try to prepare related clocks */ |
505 | i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); | 563 | i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk"); |
506 | if (IS_ERR(i2s->hclk)) { | 564 | if (IS_ERR(i2s->hclk)) { |
@@ -540,7 +598,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev) | |||
540 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; | 598 | i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
541 | i2s->capture_dma_data.maxburst = 4; | 599 | i2s->capture_dma_data.maxburst = 4; |
542 | 600 | ||
543 | i2s->dev = &pdev->dev; | ||
544 | dev_set_drvdata(&pdev->dev, i2s); | 601 | dev_set_drvdata(&pdev->dev, i2s); |
545 | 602 | ||
546 | pm_runtime_enable(&pdev->dev); | 603 | pm_runtime_enable(&pdev->dev); |
@@ -606,14 +663,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev) | |||
606 | return 0; | 663 | return 0; |
607 | } | 664 | } |
608 | 665 | ||
609 | static const struct of_device_id rockchip_i2s_match[] = { | ||
610 | { .compatible = "rockchip,rk3066-i2s", }, | ||
611 | { .compatible = "rockchip,rk3188-i2s", }, | ||
612 | { .compatible = "rockchip,rk3288-i2s", }, | ||
613 | { .compatible = "rockchip,rk3399-i2s", }, | ||
614 | {}, | ||
615 | }; | ||
616 | |||
617 | static const struct dev_pm_ops rockchip_i2s_pm_ops = { | 666 | static const struct dev_pm_ops rockchip_i2s_pm_ops = { |
618 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, | 667 | SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume, |
619 | NULL) | 668 | NULL) |
diff --git a/sound/soc/rockchip/rockchip_i2s.h b/sound/soc/rockchip/rockchip_i2s.h index dc6e2c74d088..8e239d301bc7 100644 --- a/sound/soc/rockchip/rockchip_i2s.h +++ b/sound/soc/rockchip/rockchip_i2s.h | |||
@@ -236,4 +236,11 @@ enum { | |||
236 | #define I2S_TXDR (0x0024) | 236 | #define I2S_TXDR (0x0024) |
237 | #define I2S_RXDR (0x0028) | 237 | #define I2S_RXDR (0x0028) |
238 | 238 | ||
239 | /* io direction cfg register */ | ||
240 | #define I2S_IO_DIRECTION_MASK (7) | ||
241 | #define I2S_IO_8CH_OUT_2CH_IN (0) | ||
242 | #define I2S_IO_6CH_OUT_4CH_IN (4) | ||
243 | #define I2S_IO_4CH_OUT_6CH_IN (6) | ||
244 | #define I2S_IO_2CH_OUT_8CH_IN (7) | ||
245 | |||
239 | #endif /* _ROCKCHIP_IIS_H */ | 246 | #endif /* _ROCKCHIP_IIS_H */ |