16
16
#include <linux/init.h>
17
17
#include <linux/io.h>
18
18
#include <linux/interrupt.h>
19
+ #include <linux/mfd/syscon.h>
19
20
#include <linux/module.h>
20
21
#include <linux/reset.h>
21
22
#include <linux/slab.h>
@@ -198,7 +199,8 @@ static void i2s_start(struct dw_i2s_dev *dev,
198
199
else
199
200
i2s_write_reg (dev -> i2s_base , IRER , 1 );
200
201
201
- if (dev -> use_pio )
202
+ /* I2S needs to enable IRQ to make a handshake with DMAC on the JH7110 SoC */
203
+ if (dev -> use_pio || dev -> is_jh7110 )
202
204
i2s_enable_irqs (dev , substream -> stream , config -> chan_nr );
203
205
else
204
206
i2s_enable_dma (dev , substream -> stream );
@@ -216,7 +218,7 @@ static void i2s_stop(struct dw_i2s_dev *dev,
216
218
else
217
219
i2s_write_reg (dev -> i2s_base , IRER , 0 );
218
220
219
- if (dev -> use_pio )
221
+ if (dev -> use_pio || dev -> is_jh7110 )
220
222
i2s_disable_irqs (dev , substream -> stream , 8 );
221
223
else
222
224
i2s_disable_dma (dev , substream -> stream );
@@ -227,6 +229,21 @@ static void i2s_stop(struct dw_i2s_dev *dev,
227
229
}
228
230
}
229
231
232
+ static int dw_i2s_startup (struct snd_pcm_substream * substream ,
233
+ struct snd_soc_dai * cpu_dai )
234
+ {
235
+ struct dw_i2s_dev * dev = snd_soc_dai_get_drvdata (cpu_dai );
236
+
237
+ if (dev -> is_jh7110 ) {
238
+ struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd (substream );
239
+ struct snd_soc_dai_link * dai_link = rtd -> dai_link ;
240
+
241
+ dai_link -> trigger_stop = SND_SOC_TRIGGER_ORDER_LDC ;
242
+ }
243
+
244
+ return 0 ;
245
+ }
246
+
230
247
static void dw_i2s_config (struct dw_i2s_dev * dev , int stream )
231
248
{
232
249
u32 ch_reg ;
@@ -453,6 +470,7 @@ static int dw_i2s_dai_probe(struct snd_soc_dai *dai)
453
470
454
471
static const struct snd_soc_dai_ops dw_i2s_dai_ops = {
455
472
.probe = dw_i2s_dai_probe ,
473
+ .startup = dw_i2s_startup ,
456
474
.hw_params = dw_i2s_hw_params ,
457
475
.prepare = dw_i2s_prepare ,
458
476
.trigger = dw_i2s_trigger ,
@@ -637,17 +655,39 @@ static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
637
655
638
656
if (dev -> quirks & DW_I2S_QUIRK_16BIT_IDX_OVERRIDE )
639
657
idx = 1 ;
640
- /* Set DMA slaves info */
641
- dev -> play_dma_data .pd .data = pdata -> play_dma_data ;
642
- dev -> capture_dma_data .pd .data = pdata -> capture_dma_data ;
643
- dev -> play_dma_data .pd .addr = res -> start + I2S_TXDMA ;
644
- dev -> capture_dma_data .pd .addr = res -> start + I2S_RXDMA ;
645
- dev -> play_dma_data .pd .max_burst = 16 ;
646
- dev -> capture_dma_data .pd .max_burst = 16 ;
647
- dev -> play_dma_data .pd .addr_width = bus_widths [idx ];
648
- dev -> capture_dma_data .pd .addr_width = bus_widths [idx ];
649
- dev -> play_dma_data .pd .filter = pdata -> filter ;
650
- dev -> capture_dma_data .pd .filter = pdata -> filter ;
658
+
659
+ if (dev -> is_jh7110 ) {
660
+ /* Use platform data and snd_dmaengine_dai_dma_data struct at the same time */
661
+ u32 comp2 = i2s_read_reg (dev -> i2s_base , I2S_COMP_PARAM_2 );
662
+ u32 idx2 ;
663
+
664
+ if (COMP1_TX_ENABLED (comp1 )) {
665
+ idx2 = COMP1_TX_WORDSIZE_0 (comp1 );
666
+ dev -> play_dma_data .dt .addr = res -> start + I2S_TXDMA ;
667
+ dev -> play_dma_data .dt .fifo_size = dev -> fifo_th * 2 *
668
+ (fifo_width [idx2 ]) >> 8 ;
669
+ dev -> play_dma_data .dt .maxburst = 16 ;
670
+ }
671
+ if (COMP1_RX_ENABLED (comp1 )) {
672
+ idx2 = COMP2_RX_WORDSIZE_0 (comp2 );
673
+ dev -> capture_dma_data .dt .addr = res -> start + I2S_RXDMA ;
674
+ dev -> capture_dma_data .dt .fifo_size = dev -> fifo_th * 2 *
675
+ (fifo_width [idx2 ] >> 8 );
676
+ dev -> capture_dma_data .dt .maxburst = 16 ;
677
+ }
678
+ } else {
679
+ /* Set DMA slaves info */
680
+ dev -> play_dma_data .pd .data = pdata -> play_dma_data ;
681
+ dev -> capture_dma_data .pd .data = pdata -> capture_dma_data ;
682
+ dev -> play_dma_data .pd .addr = res -> start + I2S_TXDMA ;
683
+ dev -> capture_dma_data .pd .addr = res -> start + I2S_RXDMA ;
684
+ dev -> play_dma_data .pd .max_burst = 16 ;
685
+ dev -> capture_dma_data .pd .max_burst = 16 ;
686
+ dev -> play_dma_data .pd .addr_width = bus_widths [idx ];
687
+ dev -> capture_dma_data .pd .addr_width = bus_widths [idx ];
688
+ dev -> play_dma_data .pd .filter = pdata -> filter ;
689
+ dev -> capture_dma_data .pd .filter = pdata -> filter ;
690
+ }
651
691
652
692
return 0 ;
653
693
}
@@ -689,6 +729,190 @@ static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
689
729
690
730
}
691
731
732
+ /* clocks initialization with master mode on JH7110 SoC */
733
+ static int jh7110_i2s_crg_master_init (struct dw_i2s_dev * dev )
734
+ {
735
+ static struct clk_bulk_data clks [] = {
736
+ { .id = "mclk" },
737
+ { .id = "mclk_ext" },
738
+ { .id = "mclk_inner" },
739
+ { .id = "apb" },
740
+ { .id = "i2sclk" },
741
+ };
742
+ struct reset_control * resets = devm_reset_control_array_get_exclusive (dev -> dev );
743
+ int ret ;
744
+ struct clk * pclk ;
745
+ struct clk * bclk_mst ;
746
+ struct clk * mclk ;
747
+ struct clk * mclk_ext ;
748
+ struct clk * mclk_inner ;
749
+
750
+ if (IS_ERR (resets ))
751
+ return dev_err_probe (dev -> dev , PTR_ERR (resets ), "failed to get i2s resets\n" );
752
+
753
+ ret = clk_bulk_get (dev -> dev , ARRAY_SIZE (clks ), clks );
754
+ if (ret )
755
+ return dev_err_probe (dev -> dev , ret , "failed to get i2s clocks\n" );
756
+
757
+ mclk = clks [0 ].clk ;
758
+ mclk_ext = clks [1 ].clk ;
759
+ mclk_inner = clks [2 ].clk ;
760
+ pclk = clks [3 ].clk ;
761
+ bclk_mst = clks [4 ].clk ;
762
+
763
+ ret = clk_prepare_enable (pclk );
764
+ if (ret )
765
+ goto exit ;
766
+
767
+ /* Use inner mclk first and avoid uninitialized gpio for external mclk */
768
+ ret = clk_set_parent (mclk , mclk_inner );
769
+ if (ret )
770
+ goto err_dis_pclk ;
771
+
772
+ ret = clk_prepare_enable (bclk_mst );
773
+ if (ret )
774
+ goto err_dis_pclk ;
775
+
776
+ /* deassert resets before set clock parent */
777
+ ret = reset_control_deassert (resets );
778
+ if (ret )
779
+ goto err_dis_all ;
780
+
781
+ /* external clock (12.288MHz) for Audio */
782
+ ret = clk_set_parent (mclk , mclk_ext );
783
+ if (ret )
784
+ goto err_dis_all ;
785
+
786
+ /* i2sclk will be got and enabled repeatedly later and should be disabled now. */
787
+ clk_disable_unprepare (bclk_mst );
788
+ clk_bulk_put (ARRAY_SIZE (clks ), clks );
789
+ dev -> is_jh7110 = true;
790
+
791
+ return 0 ;
792
+
793
+ err_dis_all :
794
+ clk_disable_unprepare (bclk_mst );
795
+ err_dis_pclk :
796
+ clk_disable_unprepare (pclk );
797
+ exit :
798
+ clk_bulk_put (ARRAY_SIZE (clks ), clks );
799
+ return ret ;
800
+ }
801
+
802
+ /* clocks initialization with slave mode on JH7110 SoC */
803
+ static int jh7110_i2s_crg_slave_init (struct dw_i2s_dev * dev )
804
+ {
805
+ static struct clk_bulk_data clks [] = {
806
+ { .id = "mclk" },
807
+ { .id = "mclk_ext" },
808
+ { .id = "apb" },
809
+ { .id = "bclk_ext" },
810
+ { .id = "lrck_ext" },
811
+ { .id = "bclk" },
812
+ { .id = "lrck" },
813
+ { .id = "mclk_inner" },
814
+ { .id = "i2sclk" },
815
+ };
816
+ struct reset_control * resets = devm_reset_control_array_get_exclusive (dev -> dev );
817
+ int ret ;
818
+ struct clk * pclk ;
819
+ struct clk * bclk_mst ;
820
+ struct clk * bclk_ext ;
821
+ struct clk * lrck_ext ;
822
+ struct clk * bclk ;
823
+ struct clk * lrck ;
824
+ struct clk * mclk ;
825
+ struct clk * mclk_ext ;
826
+ struct clk * mclk_inner ;
827
+
828
+ if (IS_ERR (resets ))
829
+ return dev_err_probe (dev -> dev , PTR_ERR (resets ), "failed to get i2s resets\n" );
830
+
831
+ ret = clk_bulk_get (dev -> dev , ARRAY_SIZE (clks ), clks );
832
+ if (ret )
833
+ return dev_err_probe (dev -> dev , ret , "failed to get i2s clocks\n" );
834
+
835
+ mclk = clks [0 ].clk ;
836
+ mclk_ext = clks [1 ].clk ;
837
+ pclk = clks [2 ].clk ;
838
+ bclk_ext = clks [3 ].clk ;
839
+ lrck_ext = clks [4 ].clk ;
840
+ bclk = clks [5 ].clk ;
841
+ lrck = clks [6 ].clk ;
842
+ mclk_inner = clks [7 ].clk ;
843
+ bclk_mst = clks [8 ].clk ;
844
+
845
+ ret = clk_prepare_enable (pclk );
846
+ if (ret )
847
+ goto exit ;
848
+
849
+ ret = clk_set_parent (mclk , mclk_inner );
850
+ if (ret )
851
+ goto err_dis_pclk ;
852
+
853
+ ret = clk_prepare_enable (bclk_mst );
854
+ if (ret )
855
+ goto err_dis_pclk ;
856
+
857
+ ret = reset_control_deassert (resets );
858
+ if (ret )
859
+ goto err_dis_all ;
860
+
861
+ /* The sources of BCLK and LRCK are the external codec. */
862
+ ret = clk_set_parent (bclk , bclk_ext );
863
+ if (ret )
864
+ goto err_dis_all ;
865
+
866
+ ret = clk_set_parent (lrck , lrck_ext );
867
+ if (ret )
868
+ goto err_dis_all ;
869
+
870
+ ret = clk_set_parent (mclk , mclk_ext );
871
+ if (ret )
872
+ goto err_dis_all ;
873
+
874
+ /* The i2sclk will be got and enabled repeatedly later and should be disabled now. */
875
+ clk_disable_unprepare (bclk_mst );
876
+ clk_bulk_put (ARRAY_SIZE (clks ), clks );
877
+ dev -> is_jh7110 = true;
878
+
879
+ return 0 ;
880
+
881
+ err_dis_all :
882
+ clk_disable_unprepare (bclk_mst );
883
+ err_dis_pclk :
884
+ clk_disable_unprepare (pclk );
885
+ exit :
886
+ clk_bulk_put (ARRAY_SIZE (clks ), clks );
887
+ return ret ;
888
+ }
889
+
890
+ /* Special syscon initialization about RX channel with slave mode on JH7110 SoC */
891
+ static int jh7110_i2srx_crg_init (struct dw_i2s_dev * dev )
892
+ {
893
+ struct regmap * regmap ;
894
+ unsigned int args [2 ];
895
+
896
+ regmap = syscon_regmap_lookup_by_phandle_args (dev -> dev -> of_node ,
897
+ "starfive,syscon" ,
898
+ 2 , args );
899
+ if (IS_ERR (regmap ))
900
+ return dev_err_probe (dev -> dev , PTR_ERR (regmap ), "getting the regmap failed\n" );
901
+
902
+ /* Enable I2Srx with syscon register, args[0]: offset, args[1]: mask */
903
+ regmap_update_bits (regmap , args [0 ], args [1 ], args [1 ]);
904
+
905
+ return jh7110_i2s_crg_slave_init (dev );
906
+ }
907
+
908
+ static int jh7110_i2stx0_clk_cfg (struct i2s_clk_config_data * config )
909
+ {
910
+ struct dw_i2s_dev * dev = container_of (config , struct dw_i2s_dev , config );
911
+ u32 bclk_rate = config -> sample_rate * 64 ;
912
+
913
+ return clk_set_rate (dev -> clk , bclk_rate );
914
+ }
915
+
692
916
static int dw_i2s_probe (struct platform_device * pdev )
693
917
{
694
918
const struct i2s_platform_data * pdata = of_device_get_match_data (& pdev -> dev );
@@ -712,15 +936,25 @@ static int dw_i2s_probe(struct platform_device *pdev)
712
936
if (IS_ERR (dev -> i2s_base ))
713
937
return PTR_ERR (dev -> i2s_base );
714
938
715
- dev -> reset = devm_reset_control_array_get_optional_shared (& pdev -> dev );
716
- if (IS_ERR (dev -> reset ))
717
- return PTR_ERR (dev -> reset );
939
+ dev -> dev = & pdev -> dev ;
940
+ dev -> is_jh7110 = false;
941
+ if (pdata ) {
942
+ if (pdata -> i2s_pd_init ) {
943
+ ret = pdata -> i2s_pd_init (dev );
944
+ if (ret )
945
+ return ret ;
946
+ }
947
+ }
718
948
719
- ret = reset_control_deassert (dev -> reset );
720
- if (ret )
721
- return ret ;
949
+ if (!dev -> is_jh7110 ) {
950
+ dev -> reset = devm_reset_control_array_get_optional_shared (& pdev -> dev );
951
+ if (IS_ERR (dev -> reset ))
952
+ return PTR_ERR (dev -> reset );
722
953
723
- dev -> dev = & pdev -> dev ;
954
+ ret = reset_control_deassert (dev -> reset );
955
+ if (ret )
956
+ return ret ;
957
+ }
724
958
725
959
irq = platform_get_irq_optional (pdev , 0 );
726
960
if (irq >= 0 ) {
@@ -779,7 +1013,7 @@ static int dw_i2s_probe(struct platform_device *pdev)
779
1013
goto err_clk_disable ;
780
1014
}
781
1015
782
- if (!pdata ) {
1016
+ if (!pdata || dev -> is_jh7110 ) {
783
1017
if (irq >= 0 ) {
784
1018
ret = dw_pcm_register (pdev );
785
1019
dev -> use_pio = true;
@@ -821,8 +1055,36 @@ static void dw_i2s_remove(struct platform_device *pdev)
821
1055
}
822
1056
823
1057
#ifdef CONFIG_OF
1058
+ static const struct i2s_platform_data jh7110_i2stx0_data = {
1059
+ .cap = DWC_I2S_PLAY | DW_I2S_MASTER ,
1060
+ .channel = TWO_CHANNEL_SUPPORT ,
1061
+ .snd_fmts = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE ,
1062
+ .snd_rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 ,
1063
+ .i2s_clk_cfg = jh7110_i2stx0_clk_cfg ,
1064
+ .i2s_pd_init = jh7110_i2s_crg_master_init ,
1065
+ };
1066
+
1067
+ static const struct i2s_platform_data jh7110_i2stx1_data = {
1068
+ .cap = DWC_I2S_PLAY | DW_I2S_SLAVE ,
1069
+ .channel = TWO_CHANNEL_SUPPORT ,
1070
+ .snd_fmts = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE ,
1071
+ .snd_rates = SNDRV_PCM_RATE_8000_192000 ,
1072
+ .i2s_pd_init = jh7110_i2s_crg_slave_init ,
1073
+ };
1074
+
1075
+ static const struct i2s_platform_data jh7110_i2srx_data = {
1076
+ .cap = DWC_I2S_RECORD | DW_I2S_SLAVE ,
1077
+ .channel = TWO_CHANNEL_SUPPORT ,
1078
+ .snd_fmts = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE ,
1079
+ .snd_rates = SNDRV_PCM_RATE_8000_192000 ,
1080
+ .i2s_pd_init = jh7110_i2srx_crg_init ,
1081
+ };
1082
+
824
1083
static const struct of_device_id dw_i2s_of_match [] = {
825
1084
{ .compatible = "snps,designware-i2s" , },
1085
+ { .compatible = "starfive,jh7110-i2stx0" , .data = & jh7110_i2stx0_data , },
1086
+ { .compatible = "starfive,jh7110-i2stx1" , .data = & jh7110_i2stx1_data ,},
1087
+ { .compatible = "starfive,jh7110-i2srx" , .data = & jh7110_i2srx_data ,},
826
1088
{},
827
1089
};
828
1090
0 commit comments