Firefly开源社区

标题: [求救] 新手上路 i2s [已解決] [打印本页]

作者: woody.lee    时间: 2016-2-2 11:35
标题: [求救] 新手上路 i2s [已解決]
本帖最后由 woody.lee 于 2016-3-30 16:35 编辑

手邊的案子 rk3128 需要透過 i2s 後接 兩顆 ssm2603
網路上相關範例很少, 請教大神, 給予指點, 提供方向. 或是各相關文檔.
銘謝大德
=============================================
目前進度, 接 外部 i2c0 接腳
root@firefly:/media/firefly/LIVE# i2cdetect -y -r 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- 1a 1b UU -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- UU -- -- -- -- -- -- -- -- -- UU -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
root@firefly:/media/firefly/LIVE# lsmod
Module                  Size  Used by
mali                  172826  0
snd_soc_ssm2602        12044  0
rk30xxnand_ko         123132  2
==============================================
不知道還缺哪些動作需要補上


作者: leung先森    时间: 2016-3-1 09:42
rk3128外接codec用的是i2s-2channel
首先要确认好需要配置的i2s信号,看是否存在复用之类的
第二,要开启I2S_MCLK,clk_i2s_2ch_out
对应:
  1. + i2s->clk_i2s_2ch_out = clk_get(&pdev->dev, "clk_i2s_2ch_out");
  2. + if (IS_ERR(i2s->clk_i2s_2ch_out)) {
  3. + dev_err(&pdev->dev, "Can't retrieve clk_i2s_2ch_out\n");
  4. + ret = PTR_ERR(i2s->clk_i2s_2ch_out);
  5. + goto err;
  6. +}
  7. + clk_prepare_enable(i2s->clk_i2s_2ch_out);
复制代码


后面再确认clk输出

作者: woody.lee    时间: 2016-3-1 11:39
leung先森 发表于 2016-3-1 09:42
rk3128外接codec用的是i2s-2channel
首先要确认好需要配置的i2s信号,看是否存在复用之类的
第二,要开启 ...

Hi leung,

    首先, 十分百分千分萬分萬萬分, 感謝您的回應.

    為避免 pin腳共用的問題, 於 dts檔中將大多數的status 設定為 disabled, 或用 /* ... */ 註解

    根據您提供的範例程式碼, 從 sound/soc/rockchip/rk30_i2s.c 中, struct rk30_i2s_info 結構中沒有 member, struct clk *clk_i2s_2ch_out, 所以需要在此處另加上去嗎??

    另外, 從網路上搜尋, 發現有以下兩種key value pair
        clocks = <&clk_i2s_2ch>, <&clk_i2s_2ch_out>, <&clk_gates7 2>;
        clock-names = "i2s_clk", "i2s_mclk", "i2s_hclk";
  直覺是用來辨識與對應 clock, 如果是這樣的話, 是否只需要加入描述於dts檔, 即無須額外的源碼修改

感恩 大德,
作者: leung先森    时间: 2016-3-1 16:41
woody.lee 发表于 2016-3-1 11:39
Hi leung,

    首先, 十分百分千分萬分萬萬分, 感謝您的回應.
  1. diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi
  2. index fb0a437..2f62fc9 100755
  3. --- a/arch/arm/boot/dts/rk312x.dtsi
  4. +++ b/arch/arm/boot/dts/rk312x.dtsi
  5. dmas = <&pdma 0>, <&pdma 1>;
  6. //#dma-cells = <2>;
  7. dma-names = "tx", "rx";
  8. - //pinctrl-names = "default", "sleep";
  9. + pinctrl-names = "default", "sleep";
  10. //pinctrl-0 = <&i2s0_mclk &i2s0_sclk &i2s0_lrckrx &i2s0_lrcktx &i2s0_sdi
  11. &i2s0_sdo>;
  12. //pinctrl-1 = <&i2s0_gpio>;
  13. - status = "disabled";
  14. + pinctrl-0 = <&i2s0_mclk_mux0 &i2s0_sclk_mux0 &i2s0_lrckrx_mux0
  15. &i2s0_lrcktx_mux0 &i2s0_sdi_mux0 &i2s0_sdo_mux0>;
  16. + pinctrl-1 = <&i2s0_gpio_mux0>;
  17. + status = "okay";
  18. };
  19. i2s1: i2s@10200000 {
  20. @@ -496,6 +498,7 @@
  21. dmas = <&pdma 14>, <&pdma 15>;
  22. //#dma-cells = <2>;
  23. dma-names = "tx", "rx";
  24. + status = "disabled";
  25. };
  26. spdif: spdif@10204000 {
  27. diff --git a/sound/soc/rockchip/rk30_i2s.c b/sound/soc/rockchip/rk30_i2s.c
  28. old mode 100644
  29. new mode 100755
  30. index df121bb..d6d39c4
  31. --- a/sound/soc/rockchip/rk30_i2s.c
  32. +++ b/sound/soc/rockchip/rk30_i2s.c
  33. @@ -60,6 +60,7 @@ struct rk30_i2s_info {
  34. struct clk *i2s_clk;// i2s clk ,is bclk lrck
  35. struct clk *i2s_mclk;//i2s mclk,rk32xx can different i2s clk.
  36. struct clk *i2s_hclk;
  37. +struct clk *clk_i2s_2ch_out;
  38. struct snd_dmaengine_dai_dma_data capture_dma_data;
  39. struct snd_dmaengine_dai_dma_data playback_dma_data;
  40. @ -582,6 +583,13 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
  41. #endif
  42. clk_prepare_enable(i2s->i2s_mclk);
  43. }
  44. +
  45. +
  46. +i2s->clk_i2s_2ch_out = clk_get(&pdev->dev, "clk_i2s_2ch_out");
  47. +if (IS_ERR(i2s->clk_i2s_2ch_out)) {
  48. + dev_err(&pdev->dev, "Can't retrieve clk_i2s_2ch_out\n");
  49. + ret = PTR_ERR(i2s->clk_i2s_2ch_out);
  50. + goto err;
  51. +}
  52. +clk_prepare_enable(i2s->clk_i2s_2ch_out);
  53. mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  54. if (!mem) {
  55. diff --git a/sound/soc/rockchip/rk30_i2s.c b/sound/soc/rockchip/rk30_i2s.c
  56. index 3c8b5d2..6bed949 100755
  57. --- a/sound/soc/rockchip/rk30_i2s.c
  58. +++ b/sound/soc/rockchip/rk30_i2s.c
  59. @ -563,6 +563,10 @ static int rockchip_i2s_probe(struct platform_device *pdev)
  60. }
  61. }
  62. + /*GRF_SOC_CON1 sdi select GPIO0B6*/
  63. + val = readl_relaxed(RK_GRF_VIRT + 0x0144);
  64. + val = val | 0x00200020;
  65. + writel_relaxed(val, RK_GRF_VIRT + 0x0144);
  66. if(pdev->id >= MAX_I2S) {
  67. dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
  68. ret = -ENOMEM;
复制代码


稍微参考一下,排版不是很好
作者: woody.lee    时间: 2016-3-2 09:27
Hi leung,

感恩, 看到 clock 的波形了:)

root@firefly:/home/firefly# find / -name "*i2s*"
/proc/i2s_reg
/sys/bus/platform/devices/10220000.i2s0
/sys/bus/platform/drivers/rockchip-i2s
/sys/bus/platform/drivers/rockchip-i2s/10220000.i2s0
/sys/devices/10220000.i2s0
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_gpll_div2/aclk_peri/hclk_peri_pre/g_hclk_i2s_2ch
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_gpll_div2/aclk_peri/hclk_peri_pre/g_hclk_i2s_8ch
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_2ch_pll
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_2ch_pll/i2s_2ch_frac
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_2ch_pll/i2s_2ch_frac/clk_i2s_2ch
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_2ch_pll/i2s_2ch_frac/clk_i2s_2ch/i2s_clkout
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_2ch_pll/i2s_2ch_frac/clk_i2s_2ch/i2s_clkout/clk_i2s_2ch_out
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_8ch_pll
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_8ch_pll/i2s_8ch_frac
/sys/kernel/debug/clk/xin24m/clk_gpll/clk_i2s_8ch_pll/clk_i2s_8ch
/sys/kernel/debug/clk/i2s_clkin

我根據 rk_rk312x.c 去新增 rk_ssm2603.c
[    1.380374] ssm2602.c: {ssm2602_modinit}{821}
[    1.380402] ssm2602.c: spi_register_driver {ssm2602_modinit}{825}
[    1.380470] ssm2602.c: i2c_add_driver {ssm2602_modinit}{832}
[    1.380570] ssm2602.c: {ssm2602_i2c_probe}{765}
[    1.380790] ssm2602.c: {ssm2602_i2c_probe}{765}
[    1.381017] ssm2602.c: return 0 {ssm2602_modinit}{841}
[    1.382761] rk_ssm2603.c: {rockchip_ssm2603_audio_probe}{443}
[    1.382795] rk_ssm2603.c: found of_id {rockchip_ssm2603_audio_probe}{450}
[    1.382818] rk_ssm2603.c: {rockchip_ssm2603_audio_probe}{472}
[    1.382949] rk_ssm2603.c: {rockchip_ssm2603_audio_probe}{480}
[    1.383028] rk_ssm2603.c: {rockchip_ssm2603_audio_probe}{508}
[    1.383129] audio-ssm2603 audio-ssm2603.15: ASoC: CODEC DAI ssm2603-hifi not registered
[    1.383202] rk_ssm2603.c: {rockchip_ssm2603_audio_probe}{511}
[    1.383226] rk_ssm2603.c rk_ssm2603rockchip_ssm2603_audio_probe() register card failed:-517
[    1.383272] platform audio-ssm2603.15: Driver audio-ssm2603 requests probe deferral
但還是沒註冊上去(|||)
估計應該是內容有誤, dts 也沒寫正確
+    audio-ssm2603 {
+        status = "okay";
+        compatible = "audio-ssm2603";
+        dais {
+            dai0 {
+                i2s-controller = <&i2s0>;
+                audio-codec = <&ssm2603a>;
+                format = "i2s";
+                continuous-clock;
+                //bitclock-inversion;
+                //frame-inversion;
+                //bitclock-master;
+                //frame-master;
+            };
+            dai1 {
+                i2s-controller = <&i2s0>;
+                audio-codec = <&ssm2603b>;
+                format = "i2s";
+                continuous-clock;
+                //bitclock-inversion;
+                //frame-inversion;
+                bitclock-master;
+                //frame-master;
+            };
+        };
+    };
+&i2s0 {
+        status = "okay";
+        codec = <&ssm2603a>, <&ssm2603b>;
};
&i2c0 {
         status = "okay";
+        ssm2603a: ssm2603@1a {
+        status = "okay";
+          compatible = "adi,ssm2603";
+          reg = <0x1a>;
+          //gpios = <&gpio0 GPIO_A0 GPIO_ACTIVE_HIGH>, <&gpio0 GPIO_A1 GPIO_ACTIVE_HIGH>;
+          //ctrl-pin = <&gpio0 GPIO_A0 GPIO_ACTIVE_HIGH>;
+          //data-pin = <&gpio0 GPIO_A1 GPIO_ACTIVE_HIGH>;
+          //clocks = <&clk_i2s_2ch>, <&clk_i2s_2ch_out>, <&clk_gates7 2>;
+          //clock-names = "i2s_clk", "i2s_mclk", "i2s_hclk";
+        };

不停嘗試錯誤, 也到了 #359了
root@firefly:/home/firefly# uname -a
Linux firefly 3.10.0 #359 SMP PREEMPT Wed Mar 2 09:15:18 CST 2016 armv7l armv7l armv7l GNU/Linux

再次感謝, 銘謝大德.
作者: leung先森    时间: 2016-3-2 11:17
woody.lee 发表于 2016-3-2 09:27
Hi leung,

感恩, 看到 clock 的波形了

[    1.383129] audio-ssm2603 audio-ssm2603.15: ASoC: CODEC DAI ssm2603-hifi not registered
-----------------------------------
从这个地方开始排查,首先要确认好machine driver和codec driver那些card info是否对应一致,
大小写是否一致。还是不行,就要一个个环节去排查

作者: woody.lee    时间: 2016-3-2 16:58
leung先森 发表于 2016-3-2 11:17
[    1.383129] audio-ssm2603 audio-ssm2603.15: ASoC: CODEC DAI ssm2603-hifi not registered
------ ...

Hi leung,

  謝謝您, 目前看起來有一些新東西,
root@firefly:/media/firefly/sda# arecord -l ; aplay -l
**** List of CAPTURE Hardware Devices ****
card 0: RKSSM2603 [RK_SSM2603], device 0: Playback ssm2602-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
**** List of PLAYBACK Hardware Devices ****
card 0: RKSSM2603 [RK_SSM2603], device 0: Playback ssm2602-hifi-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0

aplay 有播放的動作 (但是沒有聲音)
root@firefly:/media/firefly/sda# aplay -D plughw:0,0 lightning.wav -v
Playing WAVE 'lightning.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0
    1 <- 0
Its setup is:
  stream       : PLAYBACK
  access       : RW_INTERLEAVED
  format       : U8
  subformat    : STD
  channels     : 1
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 8
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 4000
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 2097152000
Slave: Hardware PCM card 0 'RK_SSM2603' device 0 subdevice 0
Its setup is:
  stream       : PLAYBACK
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 16
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 4000
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 2097152000
  appl_ptr     : 0
  hw_ptr       : 0

arecord 有錄音的動作 (在電腦上撥放的聲音 == 冷氣的最高品質...)
root@firefly:/media/firefly/sda# arecord -D plughw:0,0 ssm2603r.wav -v
Recording WAVE 'ssm2603r.wav' : Unsigned 8 bit, Rate 8000 Hz, Mono
Plug PCM: Route conversion PCM (sformat=S16_LE)
  Transformation table:
    0 <- 0*0.5 + 1*0.5
Its setup is:
  stream       : CAPTURE
  access       : RW_INTERLEAVED
  format       : U8
  subformat    : STD
  channels     : 1
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 8
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 2097152000
Slave: Hardware PCM card 0 'RK_SSM2603' device 0 subdevice 0
Its setup is:
  stream       : CAPTURE
  access       : MMAP_INTERLEAVED
  format       : S16_LE
  subformat    : STD
  channels     : 2
  rate         : 8000
  exact rate   : 8000 (8000/1)
  msbits       : 16
  buffer_size  : 4000
  period_size  : 1000
  period_time  : 125000
  tstamp_mode  : NONE
  period_step  : 1
  avail_min    : 1000
  period_event : 0
  start_threshold  : 1
  stop_threshold   : 4000
  silence_threshold: 0
  silence_size : 0
  boundary     : 2097152000
  appl_ptr     : 0
  hw_ptr       : 0

[    1.381524] ssm2602.c: {ssm2602_modinit}{829}
[    1.381554] ssm2602.c: spi_register_driver {ssm2602_modinit}{833}
[    1.381621] ssm2602.c: i2c_add_driver {ssm2602_modinit}{840}
[    1.381718] ssm2602.c: {ssm2602_i2c_probe}{773}
[    1.381934] ssm2602.c: {ssm2602_i2c_probe}{773}
[    1.382166] ssm2602.c: return 0 {ssm2602_modinit}{849}
[    1.384061] HERE WOODY: {sound/soc/soc-core.c}{soc_bind_dai_link}{867}
[    1.384094] codec_dai->name: {rockchip-spdif} dai_link->codec_dai_name: {ssm2602-hifi}
[    1.384119] HERE WOODY: {sound/soc/soc-core.c}{soc_bind_dai_link}{867}
[    1.384140] codec_dai->name: {rockchip-i2s.0} dai_link->codec_dai_name: {ssm2602-hifi}
[    1.384163] HERE WOODY: {sound/soc/soc-core.c}{soc_bind_dai_link}{867}
[    1.384184] codec_dai->name: {ssm2602-hifi} dai_link->codec_dai_name: {ssm2602-hifi}
[    1.384207] HERE WOODY: {sound/soc/soc-core.c}{soc_bind_dai_link}{867}
[    1.384228] codec_dai->name: {ssm2602-hifi} dai_link->codec_dai_name: {ssm2602-hifi}
[    1.384251] HERE WOODY: {sound/soc/soc-core.c}{soc_bind_dai_link}{867}
[    1.384272] codec_dai->name: {snd-soc-dummy-dai} dai_link->codec_dai_name: {ssm2602-hifi}
[    1.384440] ssm2602.c: {ssm260x_probe} {641}
[    1.386028] ssm2602.c: {ssm2602_probe} {597}
[    1.386794] ssm2602.c: {ssm2602_probe} {607}
[    1.386821] soc-core.c control->name: {Master Playback Volume} {snd_soc_add_controls} {2308}
[    1.386859] soc-core.c control->name: {Master Playback ZC Switch} {snd_soc_add_controls} {2308}
[    1.386890] soc-core.c control->name: {Sidetone Playback Volume} {snd_soc_add_controls} {2308}
[    1.386918] soc-core.c control->name: {Mic Boost (+20dB)} {snd_soc_add_controls} {2308}
[    1.386947] soc-core.c control->name: {Mic Boost2 (+20dB)} {snd_soc_add_controls} {2308}
[    1.386986] soc-core.c control->name: {Mic Switch} {snd_soc_add_controls} {2308}
[    1.387014] ssm2602.c: {ssm2602_probe} {611} ret: {0}
[    1.387471] soc-core.c control->name: {Capture Volume} {snd_soc_add_controls} {2308}
[    1.387508] soc-core.c control->name: {Capture Switch} {snd_soc_add_controls} {2308}
[    1.387537] soc-core.c control->name: {ADC High Pass Filter Switch} {snd_soc_add_controls} {2308}
[    1.387567] soc-core.c control->name: {Store DC Offset Switch} {snd_soc_add_controls} {2308}
[    1.387595] soc-core.c control->name: {Playback De-emphasis} {snd_soc_add_controls} {2308}
[    1.388160] rk_ssm2603.c rk_ssm2603Enter::rk30_ssm2603_init----192
[    1.389525] rockchip-ssm2603 audio-ssm2603.15:  ssm2602-hifi <-> rockchip-i2s.0 mapping ok
...
[   46.899871] ssm2602.c: {ssm2602_set_dai_fmt} {446}

感恩, 持續錯誤嘗試中, 謝謝.
作者: leung先森    时间: 2016-3-2 17:25
woody.lee 发表于 2016-3-2 16:58
Hi leung,

  謝謝您, 目前看起來有一些新東西,

芯片datasheet,查一下playback和capture寄存器是否有配置正确。
如果还是不行,那么我也没办法了。
Good Luck !
作者: woody.lee    时间: 2016-3-2 17:34
Hi leung,

謝謝您喔,
[  113.836599] ssm2602.c: {ssm2602_set_dai_fmt} {446}
[  226.052741] rockchip_snd_rxctrl: i2s clr reg warning =3
[  234.007977] ssm2602.c: {ssm2602_set_dai_fmt} {446}
[  234.121490] rockchip_snd_txctrl: i2s clr reg warning =3
[  235.889611] ssm2602.c: {ssm2602_set_dai_fmt} {446}
[  236.001438] rockchip_snd_txctrl: i2s clr reg warning =3
[  239.681329] ssm2602.c: {ssm2602_set_dai_fmt} {446}
[  239.793146] rockchip_snd_txctrl: i2s clr reg warning =3

Linux firefly 3.10.0 #394 SMP PREEMPT Wed Mar 2 17:22:20 CST 2016 armv7l armv7l armv7l GNU/Linux
持續錯誤嘗試 @@a
作者: woody.lee    时间: 2016-3-24 09:47
本帖最后由 woody.lee 于 2016-3-24 15:31 编辑

總結一下, 遇到的問題有:
  1. dts 修改後未更新 resource.img (dtb包在resource.img)
  2. toolchain 請務必使用 arm-eabi-4.6, 驗證過使用 4.8, 遇到有編譯上與編譯完成後進不了系統的問題
  3. 文件有部分的 typo: chapter-05-general-register-file(grf).pdf
     GRF_SOC_CON1[5] 基本上0,1值的描述與GRF_SOC_CON1[6]是一樣的
         但是文件 chapter-28-i2s-2-channel.pdf 在 28.5 Interface description 中的描述
         I2S has 2 IOMUX, which controlled by GRF_SOC_CON1[5].
         假設 chapter-28-i2s-2-channel.pdf 為真, 兩組外部接腳只能選用一組音效輸出
     目前個人的實做上, 兩組接腳只有成功 GRF_GPIO0B_IOMUX 一組
         在嘗試 GRF_GPIO1A_IOMUX 一組, 驗證是不成功的, 失敗原因: 不明
         就目前工作需求, 現階段已滿足後續測試需求, 如果其他先進驗證成功的也請回文告知, 感恩
  4. 有想嘗試編成模組(.ko), 但是功力不到位, 載入後系統提示:
     rockchip-ssm2603 audio-ssm2603a.21: ASoC: CODEC (null) not registered
         估計是因為在載入時, 源碼沒有去 dtb 撈出 iic addr. 的資訊, 所以驅動沒掛上,
     如果其他先進知道如何處理, 也請回文告知, 感恩
# 4. 後來嘗試成功了, 想了下 codec 的code 應該可以先 built-in, 所以 make menuconfig
<M>   SoC I2S Audio support for rockchip - SSM2602/SSM2603/SSM2604
...
<*>   Build all ASoC CODEC drivers
...

編譯失敗:
sound/built-in.o: In function `rk610_codec_probe':
last.c:(.text+0x8c274): undefined reference to `rk610_control_init_codec'
sound/built-in.o: In function `rk616_set_dai_sysclk':
last.c:(.text+0x8d034): undefined reference to `rk616_mclk_set_rate'
make: *** [vmlinux] Error 1

直接去掉編譯失敗的 codec
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index b7ef0b9..f520f3d 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -117,8 +117,8 @@ config SND_SOC_ALL_CODECS
        select SND_SOC_RT5639 if I2C
        select SND_SOC_RT5616 if I2C
        select SND_SOC_RT5512 if I2C
-       select SND_SOC_RK610 if I2C
-       select SND_SOC_RK616 if I2C
+#      select SND_SOC_RK610 if I2C
+#      select SND_SOC_RK616 if I2C
        select SND_SOC_WM8903 if I2C && GENERIC_HARDIRQS
        select SND_SOC_WM8904 if I2C
        select SND_SOC_WM8940 if I2C


========================================================================================================
新增與更動檔案如下:
        new file:   sound/soc/rockchip/rk_ssm2602.c
        modified:   arch/arm/boot/dts/rk3128-fireprime.dts
        modified:   arch/arm/boot/dts/rk312x.dtsi
        modified:   arch/arm/configs/fireprime-linux_defconfig
        modified:   sound/soc/codecs/ssm2602.c
        modified:   sound/soc/codecs/ssm2602.h
        modified:   sound/soc/rockchip/Kconfig
        modified:   sound/soc/rockchip/Makefile
        modified:   sound/soc/rockchip/rk30_i2s.c

========================================================================================================
以下有省略一些 printk(...) 的輸出, 所以行號對不上, 但是看前後內容也可以知道關鍵點在哪
rk_ssm2602.c 基本上是拷貝 sound/soc/rockchip/rk_rk312x.c 做修改, 這裡就不浪費各位先進的眼力了
diff --git a/arch/arm/configs/fireprime-linux_defconfig b/arch/arm/configs/fireprime-linux_defconfig
index ab3a97f..8281284 100644
--- a/arch/arm/configs/fireprime-linux_defconfig
+++ b/arch/arm/configs/fireprime-linux_defconfig
@@ -405,6 +405,7 @@ CONFIG_MALI_PLATFORM_THIRDPARTY_NAME="rk"
CONFIG_MALI400=m
# CONFIG_MALI400_PROFILING is not set
CONFIG_MALI_SHARED_INTERRUPTS=y
+CONFIG_MALI_DT=y
CONFIG_FB=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
# CONFIG_LCD_CLASS_DEVICE is not set
@@ -444,6 +445,7 @@ CONFIG_SND_RK_SOC_RT5631=y
CONFIG_SND_RK_SOC_RT3224=y
CONFIG_SND_RK_SOC_RK3036=y
CONFIG_SND_RK_SOC_RK312X=y
+CONFIG_SND_RK_SOC_SSM2602=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_HID_A4TECH=y

--------------------------------------------------------------------------------------------------------
diff --git a/arch/arm/boot/dts/rk3128-fireprime.dts b/arch/arm/boot/dts/rk3128-fireprime.dts
index 303fe58..c362e9a 100755
--- a/arch/arm/boot/dts/rk3128-fireprime.dts
+++ b/arch/arm/boot/dts/rk3128-fireprime.dts
@@ -122,6 +122,21 @@
test-power {
         status = "okay";
};
+    audio-ssm2603a
+    {
+        status = "okay";
+        compatible = "rockchip-ssm2603a";
+        dais {
+            dai0 {
+                audio-controller = <&i2s0>;
+                audio-codec = <&ssm2603a>;
+                format = "i2s";
+                //continuous-clock;
+                clocks = <&clk_i2s_2ch>, <&clk_i2s_2ch_out>, <&clk_gates7 2>;
+                clock-names = "i2s_clk", "i2s_mclk", "i2s_hclk";
+            };
+        };
+    };
};

&i2c0 {
@@ -138,7 +153,16 @@ test-power {
                        //reset-gpio = <&gpio8 GPIO_A6 GPIO_ACTIVE_LOW>;
                        max-x = <1280>;
                        max-y = <800>;
-               };
+               };
+        ssm2603a: ssm2603@1a {
+            compatible = "adi,ssm2603";
+            reg = <0x1a>;
+        };
+        ssm2603b: ssm2603@1b {
+            compatible = "adi,ssm2603";
+            reg = <0x1b>;
+        };
+
};

--------------------------------------------------------------------------------------------------------
diff --git a/sound/soc/rockchip/rk30_i2s.c b/sound/soc/rockchip/rk30_i2s.c
index 3c8b5d2..4796e8a 100755
--- a/sound/soc/rockchip/rk30_i2s.c
+++ b/sound/soc/rockchip/rk30_i2s.c
@@ -63,6 +63,7 @@ struct rk30_i2s_info {
        struct clk *i2s_clk;// i2s clk ,is bclk lrck
        struct clk *i2s_mclk;//i2s mclk,rk32xx can different i2s clk.
        struct clk *i2s_hclk;
+       struct clk *clk_i2s_2ch_out;
        struct snd_dmaengine_dai_dma_data capture_dma_data;
        struct snd_dmaengine_dai_dma_data playback_dma_data;

@@ -447,7 +489,7 @@ static struct snd_soc_dai_ops rockchip_i2s_dai_ops = {

#define ROCKCHIP_I2S_STEREO_RATES SNDRV_PCM_RATE_8000_96000
#define ROCKCHIP_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
-                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8)
+                       SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE )

struct snd_soc_dai_driver rockchip_i2s_dai[] = {
        {
+#define   CLKFREQ    12000000 /* 24576000 */
+
#ifdef CLK_SET_lATER
static void set_clk_later_work(struct work_struct *work)
{
        struct rk30_i2s_info *i2s = rk30_i2s;
-       clk_set_rate(i2s->i2s_clk, 11289600);
+       clk_set_rate(i2s->i2s_clk, CLKFREQ);
        if(!IS_ERR(i2s->i2s_mclk) )
-               clk_set_rate(i2s->i2s_mclk, 11289600);
+               clk_set_rate(i2s->i2s_mclk, CLKFREQ);
}
#endif

@@ -563,6 +607,46 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
                }
        }

+    if ( pdev->id == 0 )
+    {
+        int val;
+
+        /*GRF_SOC_CON1 sdi select GPIO0B6() or GPIO1A5(default)*/
+        val = 0;
+        val = readl_relaxed(RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
+        if (1) /* 1: GPIO0B6; 0(default): GPIO1A5 */
+        { // test OK
+            val = ( val | 0x00200020 );
+            writel_relaxed(val, RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
+            printk("rk30_i2s.c: {%s} {%d} GPIO0B6 {0x%08x} val: {0x%08x}\r\n", __func__, __LINE__, RK312X_GRF_SOC_CON1, val);
+            // GPIO0B ( SSM2603 reg: 0x1a )
+            val = 0;
+            val = readl_relaxed(RK_GRF_VIRT + RK312X_GRF_GPIO0B_IOMUX);
+            val = val | 0x3DCD1545;
+            writel_relaxed(val, RK_GRF_VIRT + RK312X_GRF_GPIO0B_IOMUX);
+        }
+        else
+        { // test FAIL
+#if 0 // if document errata
+            if ( ( val & 0x00000020) == 1 )
+            {
+                val = ( val | 0x00200000 ) & 0xFFFFFFDF;
+                writel_relaxed(val, RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
+            }
+#else
+            val = ( val | 0x00200020 );
+            writel_relaxed(val, RK_GRF_VIRT + RK312X_GRF_SOC_CON1);
+            printk("rk30_i2s.c: {%s} {%d} GPIO0B6 {0x%08x} val: {0x%08x}\r\n", __func__, __LINE__, RK312X_GRF_SOC_CON1, val);
+#endif
+            printk("rk30_i2s.c: {%s} {%d} GPIO1A5 {0x%08x} val: {0x%08x}\r\n", __func__, __LINE__, RK312X_GRF_SOC_CON1, val);
+            // GPIO1A ( SSM2603 reg: 0x1b )
+            val = 0;
+            val = readl_relaxed(RK_GRF_VIRT + RK312X_GRF_GPIO1A_IOMUX);
+            val = val | 0x0f7f0555;
+            writel_relaxed(val, RK_GRF_VIRT + RK312X_GRF_GPIO1A_IOMUX);
+        }
+    }
+
        if(pdev->id >= MAX_I2S) {
                dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
                ret = -ENOMEM;
@@ -595,22 +679,31 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
        INIT_DELAYED_WORK(&i2s->clk_delayed_work, set_clk_later_work);
        schedule_delayed_work(&i2s->clk_delayed_work, msecs_to_jiffies(10));
#else
-       clk_set_rate(i2s->iis_clk, 11289600);
+       clk_set_rate(i2s->iis_clk, CLKFREQ);
#endif
        clk_prepare_enable(i2s->i2s_clk);

        i2s->i2s_mclk= clk_get(&pdev->dev, "i2s_mclk");
        if(IS_ERR(i2s->i2s_mclk) ) {
-               printk("This platfrom have not i2s_mclk,no need to set i2s_mclk.\n");
+               printk("This platfrom i2s-id: {%d} have not i2s_mclk,no need to set i2s_mclk.\n", pdev->id);
        }else{
        #ifdef CLK_SET_lATER

        #else
-               clk_set_rate(i2s->i2s_mclk, 11289600);
+               clk_set_rate(i2s->i2s_mclk, CLKFREQ);
        #endif
                clk_prepare_enable(i2s->i2s_mclk);
        }

+    i2s->clk_i2s_2ch_out = clk_get(&pdev->dev, "clk_i2s_2ch_out");
+    if (IS_ERR(i2s->clk_i2s_2ch_out)) {
+      dev_err(&pdev->dev, "Can't retrieve clk_i2s_2ch_out\n");
+      ret = PTR_ERR(i2s->clk_i2s_2ch_out);
+      goto err;
+    }
+    clk_prepare_enable(i2s->clk_i2s_2ch_out);
+
+
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "No memory resource\n");

--------------------------------------------------------------------------------------------------------
diff --git a/arch/arm/boot/dts/rk312x.dtsi b/arch/arm/boot/dts/rk312x.dtsi
index 8e85546..49ab362 100755
--- a/arch/arm/boot/dts/rk312x.dtsi
+++ b/arch/arm/boot/dts/rk312x.dtsi
@@ -480,10 +480,10 @@
                dmas = <&pdma 0>, <&pdma 1>;
                //#dma-cells = <2>;
                dma-names = "tx", "rx";
-               //pinctrl-names = "default", "sleep";
-               //pinctrl-0 = <&i2s0_mclk &i2s0_sclk &i2s0_lrckrx &i2s0_lrcktx &i2s0_sdi &i2s0_sdo>;
-               //pinctrl-1 = <&i2s0_gpio>;
-               status = "disabled";
+        pinctrl-names = "default", "sleep";
+        pinctrl-0 = <&i2s0_mclk_mux0 &i2s0_sclk_mux0 &i2s0_lrckrx_mux0 &i2s0_lrcktx_mux0 &i2s0_sdi_mux0 &i2s0_sdo_mux0>;
+        pinctrl-1 = <&i2s0_gpio_mux0>;
+        status = "okay";
        };

        i2s1: i2s1@10200000 {
@@ -496,6 +496,7 @@
                dmas = <&pdma 14>, <&pdma 15>;
                //#dma-cells = <2>;
                dma-names = "tx", "rx";
+        //status = "disabled";
        };

        spdif: spdif@10204000 {

--------------------------------------------------------------------------------------------------------
diff --git a/sound/soc/rockchip/Makefile b/sound/soc/rockchip/Makefile
index de59180..953ef9f 100755
--- a/sound/soc/rockchip/Makefile
+++ b/sound/soc/rockchip/Makefile
@@ -42,6 +42,7 @@ snd-soc-hdmi-i2s-objs := rk_hdmi_i2s.o
snd-soc-hdmi-spdif-objs := rk_hdmi_spdif.o
snd-soc-rt5512-objs := rk_rt5512.o
snd-soc-cx2070x-objs := rk_cx2070x.o
+snd-soc-ssm2602-objs := rk_ssm2602.o

obj-$(CONFIG_SND_RK_SOC_WM8994) += snd-soc-wm8994.o
obj-$(CONFIG_SND_RK_SOC_WM8988) += snd-soc-wm8988.o
@@ -71,5 +72,6 @@ obj-$(CONFIG_SND_RK_SOC_RK3026) += snd-soc-rk3026.o
obj-$(CONFIG_SND_RK_SOC_RK3190) += snd-soc-rk3190.o
obj-$(CONFIG_SND_RK_SOC_RT5512) += snd-soc-rt5512.o
obj-$(CONFIG_SND_RK_SOC_CX2070X) += snd-soc-cx2070x.o
+obj-$(CONFIG_SND_RK_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_RK_SOC_HDMI_I2S) += snd-soc-hdmi-i2s.o
obj-$(CONFIG_SND_RK_SOC_HDMI_SPDIF) += snd-soc-hdmi-spdif.o

--------------------------------------------------------------------------------------------------------
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index f8d30e5..e213d6d
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -773,16 +1151,25 @@ static const struct i2c_device_id ssm2602_i2c_id[] = {
};
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);

+static const struct of_device_id ssm2602_of_match[] = {
+    { .compatible = "adi,ssm2602" },
+    { .compatible = "adi,ssm2603" },
+    { .compatible = "adi,ssm2604" },
+    { /* Sentinel */ }
+};
+
/* corgi i2c codec control layer */
static struct i2c_driver ssm2602_i2c_driver = {
        .driver = {
                .name = "ssm2602",
                .owner = THIS_MODULE,
+               .of_match_table = of_match_ptr(ssm2602_of_match),
        },
        .probe = ssm2602_i2c_probe,
        .remove = ssm2602_i2c_remove,
        .id_table = ssm2602_i2c_id,
};
+
#endif


@@ -798,13 +1185,16 @@ static int __init ssm2602_modinit(void)

#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
        ret = i2c_add_driver(&ssm2602_i2c_driver);
-       if (ret)
+       if (ret != 0)
+    {
+        printk("ssm2602.c: fail to register i2c_add_driver %d {%s}{%d}\r\n", ret, __FUNCTION__, __LINE__);
                return ret;
+    }
#endif

+    printk("ssm2602.c: return 0 {%s}{%d}\r\n", __FUNCTION__, __LINE__);
        return ret;
}
-module_init(ssm2602_modinit);

static void __exit ssm2602_exit(void)
{
@@ -816,6 +1206,8 @@ static void __exit ssm2602_exit(void)
        i2c_del_driver(&ssm2602_i2c_driver);
#endif
}
+MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
+module_init(ssm2602_modinit);
module_exit(ssm2602_exit);

作者: etomeok    时间: 2016-4-11 13:05
本帖最后由 etomeok 于 2016-4-11 13:14 编辑

楼主,请问问题解决了吗,两路I2S外接的两颗codec能同时工作吗?
作者: woody.lee    时间: 2016-4-11 13:11
etomeok 发表于 2016-4-11 13:05
楼主,请问问题解决了吗,两路I2S外接的codec能同时工作吗?

我有總結下實作過程與結果, 可能寫得不明確, 我這邊實作下只有一路會動, 另外一路沒試成功{:2_28:}
作者: dong_yoyo    时间: 2017-4-25 17:00
rockchip-ssm2603 audio-ssm2603a.21: ASoC: CODEC (null) not registered
请问这个是怎么解决的,我添加音频驱动也碰到了这个错误
作者: dianziit    时间: 2017-4-25 21:28
woody
作者: woody.lee    时间: 2017-4-27 15:54
dong_yoyo 发表于 2017-4-25 17:00
rockchip-ssm2603 audio-ssm2603a.21: ASoC: CODEC (null) not registered
请问这个是怎么解决的,我添加 ...

請參考 十樓(#10), 謝謝.
作者: woody.lee    时间: 2017-4-27 15:54
dianziit 发表于 2017-4-25 21:28
woody

作啥啊? 這不是聊天室 @@a
作者: icfancy    时间: 2019-6-10 08:46
好东西,感谢




欢迎光临 Firefly开源社区 (https://dev.t-firefly.com/) Powered by Discuz! X3.1