前言:
在nxp-imx8mm相关项目中用,使用龙讯的桥接芯片lt9611。在调试过程中,发现,audio挑显示器,在一些显示器上没有声音,主控的i2s clk,data信号都是输出到lt9611上的。于是在排查了一些必要条件后,把audio部分的问题归结到了lt9611 mcu的i2s接口上,即、lt9611 i2s 相关寄存器上。
1.原理图:
i2s:mclk,sclk,ws , data用示波器量都是有信号的。
2.官方提供的单片机mcu参考代码
audio部分:可以看到整个代码中,只有在函数入口初始化了lt9611的i2s相关寄存器。由于lt9611的datasheet没有找到,不知具体的寄存器代表什么意思,有点可惜,但是很确定的是,对i2s寄存器配置,打开了i2s通道。所以重点就是下面的i2s寄存器配置。
void LT9611_Audio_Init(void) //sujin
{
#if 1
if(lt9611.audio_out==audio_i2s)
{
printf("\r\nAudio inut = I2S 2ch");
HDMI_WriteI2C_Byte(0xff,0x84);
HDMI_WriteI2C_Byte(0x06,0x08);
HDMI_WriteI2C_Byte(0x07,0x10);
//48K sampling frequency
HDMI_WriteI2C_Byte(0x0f,0x2b); //0x2b: 48K, 0xab:96K
HDMI_WriteI2C_Byte(0x34,0xd4); //CTS_N 20180823 0xd5: sclk = 32fs, 0xd4: sclk = 64fs
HDMI_WriteI2C_Byte(0x35,0x00); // N value = 6144
HDMI_WriteI2C_Byte(0x36,0x18);
HDMI_WriteI2C_Byte(0x37,0x00);
//96K sampling frequency
//HDMI_WriteI2C_Byte(0x0f,0xab); //0x2b: 48K, 0xab:96K
//HDMI_WriteI2C_Byte(0x34,0xd4); //CTS_N 20180823 0xd5: sclk = 32fs, 0xd4: sclk = 64fs
//HDMI_WriteI2C_Byte(0x35,0x00); // N value = 12288
//HDMI_WriteI2C_Byte(0x36,0x30);
//HDMI_WriteI2C_Byte(0x37,0x00);
//44.1K sampling frequency
/*
HDMI_WriteI2C_Byte(0x0f,0x0b); //0x2b: 48K, 0xab:96K
HDMI_WriteI2C_Byte(0x34,0xd4); //CTS_N 20180823 0xd5: sclk = 32fs, 0xd4: sclk = 64fs
HDMI_WriteI2C_Byte(0x35,0x00); // N value = 6272
HDMI_WriteI2C_Byte(0x36,0x18);
HDMI_WriteI2C_Byte(0x37,0x80);
*/
}
if(lt9611.audio_out==audio_spdif)
{
printf("\r\nAudio inut = SPDIF");
HDMI_WriteI2C_Byte(0xff,0x84);
HDMI_WriteI2C_Byte(0x06,0x0c);
HDMI_WriteI2C_Byte(0x07,0x10);
HDMI_WriteI2C_Byte(0x34,0xd4); //CTS_N
}
#endif
}
void LT9611_Init(void)
{
u32 cnt = 0;
//RESET_LT9611();
LT9611_Chip_ID();
LT9611_System_Init();
//LT9611_RST_PD_Init();
LT9611_MIPI_Input_Analog();
LT9611_MIPI_Input_Digtal();
Timer0_Delay1ms(1000);
LT9611_Video_Check();
LT9611_PLL(video);
LT9611_MIPI_Pcr(video); //pcr setup
LT9611_Audio_Init();
LT9611_CSC();
LT9611_HDCP_Init();
LT9611_HDMI_TX_Digital(video);
LT9611_HDMI_TX_Phy();
LT9611_IRQ_Init();;
//LT9611_Read_EDID();
// LT9611_HDMI_CEC_ON(1);
// lt9611_cec_msg_set_logical_address();
lt9611_cec_msg_init(<9611_cec_msg);
LT9611_Enable_Interrupts(HPD_INTERRUPT_ENABLE, 1);
LT9611_Enable_Interrupts(VID_CHG_INTERRUPT_ENABLE, 0);
LT9611_Enable_Interrupts(CEC_INTERRUPT_ENABLE, 1);
LT9611_Frequency_Meter_Byte_Clk();
LT9611_Dphy_debug();
LT9611_Htotal_Sysclk();
LT9611_Pcr_MK_Print();
printf("\r\n==========================LT9611 Initial End===============================");
Timer0_Delay1ms(200); //HPD have debounce, wait HPD irq.
//while(1);
LT9611_HDP_Interrupt_Handle();
//lt9611_cec_msg_write_demo();
while(1)
{
if(irq_task_flag)
{
//print("\r\nirq task...");
LT9611_IRQ_Task();
irq_task_flag = 0;
set_EPI;
}
// lt9611_cec_msg_mainloop(<9611_cec_msg);
}
}
3.linux lt9611 驱动代码
驱动在probe后,上层调用的时候,先init部分寄存器,在hw有设置了相关的寄存器,并且对比官方参考代码,audio部分设置的寄存器还是有很大差别的。
static int rk_lt9611_audio_init(struct lt9611 *lt)
{
int ret = 0;
printk(KERN_ERR"\r\nAudio input = I2S 2ch");
ret = lt9611_write_byte(lt, BANK_SELECT_ADDR, SYSTEM_CTRL0_BLOCK);
if (ret) {
DRM_ERROR("Failed to select SYSTEM_CTRL0_BLOCK, ret=%d\n", ret);
return ret;
}
// HDMI_WriteI2C_Byte(0xff,0x82);
ret = lt9611_write_byte(lt, RGO_HDMITX_CTRL0_OFFSET, 0x8e); //0x8e: HDMI, 0x0e:DVI
if (ret) {
DRM_ERROR("Failed to set RGO_HDMITX_CTRL0_OFFSET, ret=%d\n", ret);
return ret;
}
// HDMI_WriteI2C_Byte(0xd6,0x8c);
ret = lt9611_write_byte(lt, RGO_HDMITX_CTRL1_OFFSET, 0x04);
if (ret) {
DRM_ERROR("Failed to set RGO_HDMITX_CTRL1_OFFSET, ret=%d\n", ret);
return ret;
}
// HDMI_WriteI2C_Byte(0xd7,0x04); //sync polarity
ret = lt9611_write_byte(lt,</