|
发表于 2016-3-24 09:47:38
只看该作者
来自 10#
本帖最后由 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);
|
|