aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSugar Zhang <sugar.zhang@rock-chips.com>2016-04-11 05:26:03 -0400
committerMark Brown <broonie@kernel.org>2016-05-30 11:19:41 -0400
commit170abcaae8bec0a53f2f7708a83119ec42fb09e2 (patch)
tree81e39509d076707f6ac8c433686088003b07d46c
parent1a695a905c18548062509178b98bc91e67510864 (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.txt5
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c67
-rw-r--r--sound/soc/rockchip/rockchip_i2s.h7
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
26Required properties for controller which support multi channels
27playback/capture:
28
29- rockchip,grf: the phandle of the syscon node for GRF register.
30
26Example for rk3288 I2S controller: 31Example for rk3288 I2S controller:
27 32
28i2s@ff890000 { 33i2s@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
28struct rk_i2s_pins {
29 u32 reg_offset;
30 u32 shift;
31};
32
26struct rk_i2s_dev { 33struct 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
47static int i2s_runtime_suspend(struct device *dev) 56static 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
521static const struct rk_i2s_pins rk3399_i2s_pins = {
522 .reg_offset = 0xe220,
523 .shift = 11,
524};
525
526static 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
488static int rockchip_i2s_probe(struct platform_device *pdev) 534static 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
609static 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
617static const struct dev_pm_ops rockchip_i2s_pm_ops = { 666static 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 */