《Sil-PR-1060-C》手冊,28頁起安全
圖中說明 sil9136 支持 S/PDIF, I2S or DSD模式,主機能夠經過配置TPI選擇不一樣的模式app
這個寄存器表比較重要,說明了sil9136的寄存器配置函數
0x26 寄存器this
0x27 寄存器編碼
注意:圖中說明的 0x24 和 0x25 寄存器只有在 S/PDIF 模式下有效,便是 0x26[7:6]=01 時。3d
直接跳到配置 I2S 流程,實現配置邏輯rest
SetAudioMute(AUDIO_MUTE_MUTED);
WriteByteTPI(TPI_I2S_IN_CFG, (0x80x10));
do{ WriteByteTPI(TPI_I2S_EN, 0x80); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0x80); do{ WriteByteTPI(TPI_I2S_EN, 0x91); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0x91); do{ WriteByteTPI(TPI_I2S_EN, 0xA2); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0xA2); do{ WriteByteTPI(TPI_I2S_EN, 0xB3); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0xB3);
ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, 0x38, 0x18);
WriteByteTPI(TPI_I2S_CHST_0, 0x00); WriteByteTPI(TPI_I2S_CHST_1, 0x00); WriteByteTPI(TPI_I2S_CHST_2, 0x00); WriteByteTPI(TPI_I2S_CHST_3, 0x02); WriteByteTPI(TPI_I2S_CHST_4, 0x0B);
這步驟先給出最終代碼再分析:SetAudioInfoFrames(TWO_CHANNELS, 0x00, 0x00, 0x18, 0x00);
code
說明了配置 audio infoframe 的必要性和須要參考的文件 HDMI Specification,根據本文件說明,瞭解到sil9136 支持 HDMI1.4 協議,因此準備好文件《HDMI_1.4》,並找到關於 audio infoframe 的說明。orm
圖A視頻
圖B
圖C
圖Cc1,《CEA-861-D安全》
圖Cc2,《CEA-861-D安全》
圖D
結合例程源碼 bool SetAudioInfoFrames
函數,得出只須要了解幾個參數配置便可。
Fs
就是採樣頻率 SF0...SF2B_Data[6] = (Fs >> 1) | (SS >> 6);
B_Data[8] = SpeakerConfig;
得出 SpeakerConfig 爲 圖C中的PB4////////////////////////////////////////////////////////////////////////////// // // FUNCTION : SetAudioInfoFrames() // // PURPOSE : Load Audio InfoFrame data into registers and send to sink // // INPUT PARAMS : (1) Channel count (2) speaker configuration per CEA-861D // Tables 19, 20 (3) Coding type: 0x09 for DSD Audio. 0 (refer // to stream header) for all the rest (4) Sample Frequency. Non // zero for HBR only (5) Audio Sample Length. Non zero for HBR // only. // // OUTPUT PARAMS : None // // GLOBALS USED : None // // RETURNS : TRUE // ////////////////////////////////////////////////////////////////////////////// bool SetAudioInfoFrames(byte ChannelCount, byte CodingType, byte SS, byte Fs, byte SpeakerConfig) { byte B_Data[SIZE_AUDIO_INFOFRAME]; // 14 byte i; TPI_TRACE_PRINT((">>SetAudioInfoFrames()\n")); for (i = 0; i < SIZE_AUDIO_INFOFRAME +1; i++) B_Data[i] = 0; B_Data[0] = EN_AUDIO_INFOFRAMES; // 0xC2 B_Data[1] = TYPE_AUDIO_INFOFRAMES; // 0x84 B_Data[2] = AUDIO_INFOFRAMES_VERSION; // 0x01 B_Data[3] = AUDIO_INFOFRAMES_LENGTH; // 0x0A B_Data[5] = ChannelCount; // 0 for "Refer to Stream Header" or for 2 Channels. 0x07 for 8 Channels B_Data[5] |= (CodingType << 4); // 0xC7[7:4] == 0b1001 for DSD Audio B_Data[4] = 0x84 + 0x01 + 0x0A; // Calculate checksum // B_Data[6] = (Fs << 2) | SS; B_Data[6] = (Fs >> 1) | (SS >> 6); //write Fs to 0x27[5:3] and SS to 0x27[7:6] to update the IForm with the current value. // ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, BITS_7_6 | BITS_5_4_3, (B_Data[6] & BITS_1_0) << 6 | (B_Data[6] & 0x1C) << 1); B_Data[8] = SpeakerConfig; for (i = 5; i < SIZE_AUDIO_INFOFRAME; i++) B_Data[4] += B_Data[i]; B_Data[4] = 0x100 - B_Data[4]; g_audio_Checksum = B_Data[4]; // Audio checksum for global use WriteBlockTPI(TPI_AUDIO_BYTE_0, SIZE_AUDIO_INFOFRAME, B_Data); #ifdef DEV_EMBEDDED EnableEmbeddedSync(); #endif return TRUE; }
WriteByteTPI(TPI_AUDIO_INTERFACE_REG, AUD_IF_I2S | TWO_CHANNEL_LAYOUT | 0x01);
/** * @brief setPrivateAudio(void) * @param * @retval * @author lzm */ void setPrivateAudio(void) { byte Tmp = 0; /* Select I2S input mode using TPI 0x26[7:6], with Mute enabled (bit [4] = 1). */ SetAudioMute(AUDIO_MUTE_MUTED); /* Write register TPI 0x20 to select the general incoming SD format. */ WriteByteTPI(TPI_I2S_IN_CFG, (SCK_SAMPLE_EDGE | 0x10)); /* Write register TPI 0x1F up to four times, to program each of the SD inputs. */ do{ WriteByteTPI(TPI_I2S_EN, 0x80); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0x80); do{ WriteByteTPI(TPI_I2S_EN, 0x91); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0x91); do{ WriteByteTPI(TPI_I2S_EN, 0xA2); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0xA2); do{ WriteByteTPI(TPI_I2S_EN, 0xB3); Tmp = ReadByteTPI(TPI_I2S_EN); }while(Tmp != 0xB3); // /* Program register TPI 0x27 with the correct audio about. */ // WriteByteTPI(TPI_AUDIO_SAMPLE_CTRL, AUDIO_SAMPLE_SIZE_24BIT | AUDIO_SAMPLE_FREQ_48KHZ | AUDIO_SAMPLE_HBR_DISABLE); /* Program register TPI 0x27[5:3] with the correct audio rate */ ReadModifyWriteTPI(TPI_AUDIO_SAMPLE_CTRL, 0x38, AUDIO_SAMPLE_FREQ_48KHZ); /* Program registers TPI 0x21-x25 with the correct header information for the stream that will be sent over HDMI. */ WriteByteTPI(TPI_I2S_CHST_0, 0x00); WriteByteTPI(TPI_I2S_CHST_1, 0x00); WriteByteTPI(TPI_I2S_CHST_2, 0x00); WriteByteTPI(TPI_I2S_CHST_3, 0x02); WriteByteTPI(TPI_I2S_CHST_4, 0x0B); /* Write registers TPI 0xBF-xCD with the appropriate Audio InfoFrame information. */ SetAudioInfoFrames(TWO_CHANNELS, 0x00, 0x00, 0x18, 0x00); /* Set the audio packet header layout indicator to 2-channel or multi-channel mode as needed using the sequence described below. Note that Audio InfoFrame byte 1 must also have this same setting. */ /* Again write register TPI 0x26 with I2S selected, this time with Mute disabled (bit [4] = 0). */ WriteByteTPI(TPI_AUDIO_INTERFACE_REG, AUD_IF_I2S | TWO_CHANNEL_LAYOUT | 0x01); SetAudioMute(AUDIO_MUTE_NORMAL); }