11
11
*/
12
12
13
13
#include <linux/module.h>
14
+ #include <linux/mfd/syscon.h>
14
15
#include <linux/delay.h>
15
16
#include <linux/of_gpio.h>
17
+ #include <linux/of_device.h>
16
18
#include <linux/clk.h>
17
19
#include <linux/pm_runtime.h>
18
20
#include <linux/regmap.h>
23
25
24
26
#define DRV_NAME "rockchip-i2s"
25
27
28
+ struct rk_i2s_pins {
29
+ u32 reg_offset ;
30
+ u32 shift ;
31
+ };
32
+
26
33
struct rk_i2s_dev {
27
34
struct device * dev ;
28
35
@@ -33,6 +40,7 @@ struct rk_i2s_dev {
33
40
struct snd_dmaengine_dai_dma_data playback_dma_data ;
34
41
35
42
struct regmap * regmap ;
43
+ struct regmap * grf ;
36
44
37
45
/*
38
46
* Used to indicate the tx/rx status.
@@ -42,6 +50,7 @@ struct rk_i2s_dev {
42
50
bool tx_start ;
43
51
bool rx_start ;
44
52
bool is_master_mode ;
53
+ const struct rk_i2s_pins * pins ;
45
54
};
46
55
47
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
309
I2S_TXCR_VDW_MASK | I2S_TXCR_CSR_MASK ,
301
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
336
regmap_update_bits (i2s -> regmap , I2S_DMACR , I2S_DMACR_TDL_MASK ,
304
337
I2S_DMACR_TDL (16 ));
305
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
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
534
static int rockchip_i2s_probe (struct platform_device * pdev )
489
535
{
490
536
struct device_node * node = pdev -> dev .of_node ;
537
+ const struct of_device_id * of_id ;
491
538
struct rk_i2s_dev * i2s ;
492
539
struct snd_soc_dai_driver * soc_dai ;
493
540
struct resource * res ;
@@ -501,6 +548,17 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
501
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
562
/* try to prepare related clocks */
505
563
i2s -> hclk = devm_clk_get (& pdev -> dev , "i2s_hclk" );
506
564
if (IS_ERR (i2s -> hclk )) {
@@ -540,7 +598,6 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
540
598
i2s -> capture_dma_data .addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES ;
541
599
i2s -> capture_dma_data .maxburst = 4 ;
542
600
543
- i2s -> dev = & pdev -> dev ;
544
601
dev_set_drvdata (& pdev -> dev , i2s );
545
602
546
603
pm_runtime_enable (& pdev -> dev );
@@ -606,14 +663,6 @@ static int rockchip_i2s_remove(struct platform_device *pdev)
606
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
666
static const struct dev_pm_ops rockchip_i2s_pm_ops = {
618
667
SET_RUNTIME_PM_OPS (i2s_runtime_suspend , i2s_runtime_resume ,
619
668
NULL )
0 commit comments