說明:本文适用于 RK3288 kernel4.4 SDK 版本。
RK3288 的 HDMI 和 codec 共用一組 i2s 。如果需要 HDMI 和 Codec 同時輸出音頻,直接使用 SDK 自帶的 hdmi_analog_sound 節點配置。如果需要 HDMI 和 codec 可以單獨輸出,需要将 HDMI 單獨注冊成一個 PCM 裝置。
注:hdmi_analog_sound 和 simple-audio-card 這兩種注冊方式隻能二選一。
HDMI 和 Codec 同時輸出
方案一:直接使用 hdmi_analog_sound 預設節點配置( 以 RT5640 為例 )
//RK3288 kernel4.4
/ {
hdmi_analog_sound: hdmi-analog-sound {
status = "okay";
compatible = "rockchip,rk3288-hdmi-analog",
"rockchip,rk3368-hdmi-analog";
rockchip,model = "rockchip,rt5640-codec";
rockchip,cpu = <&i2s>;
rockchip,codec = <&rt5640>, <&hdmi>;
rockchip,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack";
rockchip,routing =
"MIC1", "Microphone Jack",
"MIC2", "Microphone Jack",
"Microphone Jack", "micbias1",
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
};
};
&i2s {
status = "okay";
};
&hdmi{
status = "okay";
};
&i2c2 {
status = "okay";
rt5640: rt5640@1c {
#sound-dai-cells = <0>;
compatible = "realtek,rt5640";
reg = <0x1c>;
clocks = <&cru SCLK_I2S0_OUT>;
clock-names = "mclk";
interrupt-parent = <&gpio6>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0_mclk>;
};
};
方案二:關閉上層 HDMI 裝置插入檢測,DTS 用 simple-audio-card 注冊 Codec 聲霸卡。
1、上層注釋掉 hdmi 裝置插入的檢測:
diff --git a/services/java/com/android/server/WiredAccessoryManager.java b/services/java/com/android/server/WiredAccessoryManager.java
index c8d3510..2fb231e 100644
--- a/services/java/com/android/server/WiredAccessoryManager.java
+++ b/services/java/com/android/server/WiredAccessoryManager.java
@@ -374,7 +374,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
//
// If the kernel does not have an "hdmi_audio" switch, just fall back on the older
// "hdmi" switch instead.
- uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
+/* uei = new UEventInfo(NAME_HDMI_AUDIO, BIT_HDMI_AUDIO, 0);
if (uei.checkSwitchExists()) {
retVal.add(uei);
} else {
@@ -385,7 +385,7 @@ final class WiredAccessoryManager implements WiredAccessoryCallbacks {
Slog.w(TAG, "This kernel does not have HDMI audio support");
}
}
-
+*/
return retVal;
}
2、simple-audio-card 注冊 Codec 聲霸卡
//RK3288 kernel4.4
/{
rt5640_codec: rt5640-codec{
status = "okay";
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "rockchip,rt5640-codec";
simple-audio-card,mclk-fs = <512>;
simple-audio-card,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"MIC1", "Microphone Jack",
"MIC2", "Microphone Jack",
"Microphone Jack", "micbias1",
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
simple-audio-card,dai-link@0 {
format = "i2s";
cpu {
sound-dai = <&i2s>;
};
codec {
sound-dai = <&rt5640>;
};
};
};
&i2s {
status = "okay";
};
&i2c2 {
status = "okay";
rt5640: rt5640@1c {
#sound-dai-cells = <0>;
compatible = "realtek,rt5640";
reg = <0x1c>;
clocks = <&cru SCLK_I2S0_OUT>;
clock-names = "mclk";
interrupt-parent = <&gpio6>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0_mclk>;
};
};
HDMI 和 codec 單獨輸出
實作 HDMI 和 codec 音頻單獨輸出需要将 hdmi 單獨注冊成一個 PCM 裝置,HDMI 裝置插入後上層會切換輸出裝置為 AUDIO_DEVICE_OUT_HDMI ,然後在 HAL 層打開對應的 PCM 裝置即可。
DTS配置如下:
//RK3288 kernel4.4
/{
rt5640_codec: rt5640-codec{
status = "okay";
compatible = "simple-audio-card";
simple-audio-card,format = "i2s";
simple-audio-card,name = "rockchip,rt5640-codec";
simple-audio-card,mclk-fs = <512>;
simple-audio-card,widgets =
"Microphone", "Microphone Jack",
"Headphone", "Headphone Jack";
simple-audio-card,routing =
"MIC1", "Microphone Jack",
"MIC2", "Microphone Jack",
"Microphone Jack", "micbias1",
"Headphone Jack", "HPOL",
"Headphone Jack", "HPOR";
simple-audio-card,dai-link@0 {
format = "i2s";
cpu {
sound-dai = <&i2s>;
};
codec {
sound-dai = <&rt5640>;
};
};
simple-audio-card,dai-link@1 {
format = "i2s";
cpu {
sound-dai = <&i2s>;
};
codec {
sound-dai = <&hdmi>;
};
};
};
};
&hdmi_analog_sound {
status = "disabled";
};
&i2s {
status = "okay";
};
&i2c2 {
status = "okay";
rt5640: rt5640@1c {
#sound-dai-cells = <0>;
compatible = "realtek,rt5640";
reg = <0x1c>;
clocks = <&cru SCLK_I2S0_OUT>;
clock-names = "mclk";
interrupt-parent = <&gpio6>;
interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
pinctrl-names = "default";
pinctrl-0 = <&i2s0_mclk>;
};
};
注冊成功後,可以通過 adb 檢視注冊上的 pcm裝置。
rk3228:/ # ls dev/snd
ls dev/snd
. .. controlC0 pcmC0D0c pcmC0D0p pcmC0D1p timer
其中 pcmC0D1p 對應的就是 HDMI pcm 裝置,然後在 hal 層調用 pcmC0D1p ,修改如下:
hardware/rockchip/audio/tinyalsa_hal$ git diff .
diff --git a/tinyalsa_hal/audio_hw.c b/tinyalsa_hal/audio_hw.c
index 13dd42e..fd7c664 100755
--- a/tinyalsa_hal/audio_hw.c
+++ b/tinyalsa_hal/audio_hw.c
@@ -615,7 +615,7 @@ static int start_output_stream(struct stream_out *out)
}
#endif
#endif
- out->pcm[PCM_CARD_HDMI] = pcm_open(PCM_CARD_HDMI, out->pcm_device,
+ out->pcm[PCM_CARD_HDMI] = pcm_open(0, 1,
PCM_OUT | PCM_MONOTONIC, &out->config);
if (out->pcm[PCM_CARD_HDMI] &&
!pcm_is_ready(out->pcm[PCM_CARD_HDMI])) {
注:具體 hdmi 對應的是哪個 pcm 裝置需要根據實際情況來定,如果不清楚怎麼确認,底層可以先通過 tinyalsa 來确定 hdmi 的 pcm 裝置,然後參照上述 hal 層的代碼修改成對應的 hdmi pcm 裝置 即可。