RK3568平台 LT9211转接芯片调试笔记_rk3588 lt9211 mipi

下图为LT9211的典型应用图:

二.LT9211原理图

三.车载显示器和摄像头系统

四.调试LT9211输出 MIPI数据

(1)insmod加载ko文件后,ls /dev 查看是否生成新的video节点。

->如果没有生成video节点,查看ko是否加载失败,dts配置是否正确。

(2)查看设备是否成功挂载在IIC上

->i2cdetect -r -y 5 (lt9211在iic1上地址为ox2b)。

(3)查看LT9211_ChipID寄存器值


`void LT9211_ChipID(void)
{
 lt8918_write_reg(0xff,0x81);//register bank
 pr_info("\r\nLT9211 Chip ID:%x,",lt8918_read_reg(0x00));//18
 pr_info("%x, ",lt8918_read_reg(0x01));//1
 pr_info("%x, ",lt8918_read_reg(0x02));//e4
}`

(4)检查LT9211打印log

hfp,hbp,hsync,vfp,vbp,vysnc输出正确。

(5)测量mipi信号

MIPI data :1.8V的方波。

图像数据在soc mipi接收过程是需要检测到各个lane的LP11-LP10-LP00的一个状态切换后才会切换

到高速模式准备接收。

(6)确认mipi lane数与硬件连接的是否一致。

五.LT9211MCU程序

/******************************************************************************
  * @project: LT9211
  * @file: lt9211.c
  * @author: zll
  * @company: LONTIUM COPYRIGHT and CONFIDENTIAL
  * @date: 2019.04.10
/******************************************************************************/

#include	"include.h"

u16 hact, vact;
u16 hs, vs;
u16 hbp, vbp;
u16 htotal, vtotal;
u16 hfp, vfp;
u8 VideoFormat=0;
u32 lvds_clk_in = 0;

#define OFFSET 5

struct video_timing *pVideo_Format;

//hfp, hs, hbp, hact, htotal, vfp, vs, vbp, vact, vtotal, pixclk
struct video_timing video_640x480_60Hz     ={ 8, 96,  40, 640,   800, 33,  2,  10, 480,   525,  25000};
struct video_timing video_720x480_60Hz     ={16, 62,  60, 720,   858,  9,  6,  30, 480,   525,  27000};
struct video_timing video_1280x720_60Hz    ={110,40, 220,1280,  1650,  5,  5,  20, 720,   750,  74250};
struct video_timing video_1280x720_30Hz    ={110,40, 220,1280,  1650,  5,  5,  20, 720,   750,  74250};
struct video_timing video_1366x768_60Hz    ={26, 110,110,1366,  1592,  13, 6,  13, 768,   800,  81000};
struct video_timing video_1920x720_60Hz    ={148,44, 88, 1920,  2200, 28,  5,  12, 720,   765,  88000};
struct video_timing video_1920x1080_30Hz   ={88, 44, 148,1920,  2200,  4,  5,  36, 1080, 1125,  74250};
struct video_timing video_1920x1080_60Hz   ={88, 44, 148,1920,  2200,  4,  5,  36, 1080, 1125, 148500};
struct video_timing video_1920x1200_60Hz   ={48, 32,  80,1920,  2080,  3,  6,  26, 1200, 1235, 154000};
struct video_timing video_3840x2160_30Hz   ={176,88, 296,3840,  4400,  8,  10, 72, 2160, 2250, 297000};


void LT9211_ChipID(void)
{
    HDMI_WriteI2C_Byte(0xff,0x81);//register bank
    print("\r\nLT9211 Chip ID:%x,",HDMI_ReadI2C_Byte(0x00));
    print("%x,",HDMI_ReadI2C_Byte(0x01));
    print("%x",HDMI_ReadI2C_Byte(0x02));
}

/** video chk soft rst **/
void lt9211_vid_chk_rst(void)       
{
    HDMI_WriteI2C_Byte(0xff,0x81);	  
    HDMI_WriteI2C_Byte(0x10,0xbe); 
    Timer0_Delay1ms(10);
    HDMI_WriteI2C_Byte(0x10,0xfe); 
}

/** lvds rx logic rst **/
void lt9211_lvdsrx_logic_rst(void)       
{
    HDMI_WriteI2C_Byte(0xff,0x81);	   
    HDMI_WriteI2C_Byte(0x0c,0xeb);
    Timer0_Delay1ms(10);
    HDMI_WriteI2C_Byte(0x0c,0xfb);
}

void LT9211_SystemInt(void)
{
    /* system clock init */		   
    HDMI_WriteI2C_Byte(0xff,0x82);
    HDMI_WriteI2C_Byte(0x01,0x18);
    
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x06,0x61); 	
    HDMI_WriteI2C_Byte(0x07,0xa8); //fm for sys_clk
    
    HDMI_WriteI2C_Byte(0xff,0x87); //  ʼ   txpll  Ĵ    б Ĭ  ֵ      
    HDMI_WriteI2C_Byte(0x14,0x08); //default value
    HDMI_WriteI2C_Byte(0x15,0x00); //default value
    HDMI_WriteI2C_Byte(0x18,0x0f);
    HDMI_WriteI2C_Byte(0x22,0x08); //default value
    HDMI_WriteI2C_Byte(0x23,0x00); //default value
    HDMI_WriteI2C_Byte(0x26,0x0f); 
}

void LT9211_LvdsRxPhy(void)
{
    #ifdef INPUT_PORTA
    print("\r\nPort A PHY Config");
    HDMI_WriteI2C_Byte(0xff,0x82);
    HDMI_WriteI2C_Byte(0x02,0x8B);   //Port A LVDS mode enable
    HDMI_WriteI2C_Byte(0x05,0x21);   //port A CLK lane swap
    HDMI_WriteI2C_Byte(0x07,0x1f);   //port A clk enable
    HDMI_WriteI2C_Byte(0x04,0xa0);   //select port A clk as byteclk
    //HDMI_WriteI2C_Byte(0x09,0xFC); //port A P/N swap
        
    HDMI_WriteI2C_Byte(0xff,0x86);		
    HDMI_WriteI2C_Byte(0x33,0xe4);   //Port A Lane swap
    #endif
        
    #ifdef INPUT_PORTB
    print("\r\nPort B PHY Config");
    HDMI_WriteI2C_Byte(0xff,0x82);
    HDMI_WriteI2C_Byte(0x02,0x88);   //Port A/B LVDS mode enable
    HDMI_WriteI2C_Byte(0x05,0x21);   //port A CLK lane swap and rterm turn-off
    HDMI_WriteI2C_Byte(0x0d,0x21);   //port B CLK lane swap
    HDMI_WriteI2C_Byte(0x07,0x1f);   //port A clk enable  (ֻ  Portbʱ,porta  lane0 clkҪ  )
    HDMI_WriteI2C_Byte(0x0f,0x1f);   //port B clk enable
    //HDMI_WriteI2C_Byte(0x10,0x00);   //select port B clk as byteclk
    HDMI_WriteI2C_Byte(0x04,0xa1);   //reserve
    //HDMI_WriteI2C_Byte(0x11,0x01);   //port B P/N swap
    HDMI_WriteI2C_Byte(0x10,0xfc);
    
    HDMI_WriteI2C_Byte(0xff,0x86);		
    HDMI_WriteI2C_Byte(0x34,0xe4);   //Port B Lane swap
    
    HDMI_WriteI2C_Byte(0xff,0xd8);		
    HDMI_WriteI2C_Byte(0x16,0x80);
    #endif
    
    HDMI_WriteI2C_Byte(0xff,0x81);
    HDMI_WriteI2C_Byte(0x20,0x7f); 	
    HDMI_WriteI2C_Byte(0x20,0xff);  //mlrx calib reset
}

void LT9211_LvdsRxDigital(void)
{	  
    HDMI_WriteI2C_Byte(0xff,0x85);
    HDMI_WriteI2C_Byte(0x88,0x10);      //LVDS input, MIPI output
    
    HDMI_WriteI2C_Byte(0xff,0xd8);

    if(INPUT_PORT_NUM == 1)             //1Port LVDS Input
    {
        HDMI_WriteI2C_Byte(0x10,0x80);
        print("\r\nLVDS Port Num: 1");
    }
    else if(INPUT_PORT_NUM == 2)        //2Port LVDS Input
    {
        HDMI_WriteI2C_Byte(0x10,0x00);
        print("\r\nLVDS Port Num: 2");
    }
    else
    {
        print("\r\nPort Num Set Error");
    } 	

    lt9211_vid_chk_rst();              //video chk soft rst
    lt9211_lvdsrx_logic_rst();         //lvds rx logic rst		
	
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x30,0x45);     //port AB input port sel	 
	
    if(LVDS_FORMAT == JEDIA_FORMAT)
    {
        HDMI_WriteI2C_Byte(0xff,0x85);
        HDMI_WriteI2C_Byte(0x59,0xd0); 	
        HDMI_WriteI2C_Byte(0xff,0xd8);
        HDMI_WriteI2C_Byte(0x11,0x40);
    }
}

int lt9211_lvds_clkstb_check(void)
{
    u8 porta_clk_state = 0;
    u8 portb_clk_state = 0;
    
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x00,0x01);
    Timer0_Delay1ms(300);
    porta_clk_state = (HDMI_ReadI2C_Byte(0x08) & (0x20));
    
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x00,0x02);
    Timer0_Delay1ms(300);
    portb_clk_state = (HDMI_ReadI2C_Byte(0x08) & (0x20));
    
    if(INPUT_PORT_NUM == 1)
    {
        #ifdef INPUT_PORTA
        if( porta_clk_state )
        {
            return 1;
        }
        else
        {
            return 0;
        }
        #endif
        #ifdef INPUT_PORTB
        if( portb_clk_state )
        {
            return 1;
        }
        else
        {
            return 0;
        }
        #endif
    }
    else if(INPUT_PORT_NUM == 2)
    {
        if(porta_clk_state && portb_clk_state)
        {
            return 1;
        }
        else
        {
            return 0;
        }
    }
}

void LT9211_ClockCheckDebug(void)
{
#ifdef _uart_debug_
    u32 fm_value;

    lvds_clk_in = 0;
    #ifdef INPUT_PORTA
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x00,0x01);
    Timer0_Delay1ms(50);
    fm_value = 0;
    fm_value = (HDMI_ReadI2C_Byte(0x08) &(0x0f));
    fm_value = (fm_value<<8) ;
    fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
    fm_value = (fm_value<<8) ;
    fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
    print("\r\nPort A lvds clock: ");
    printdec_u32(fm_value);
    lvds_clk_in = fm_value;
    #endif
	
    #ifdef INPUT_PORTB
    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x00,0x02);
    Timer0_Delay1ms(50);
    fm_value = 0;
    fm_value = (HDMI_ReadI2C_Byte(0x08) &(0x0f));
    fm_value = (fm_value<<8) ;
    fm_value = fm_value + HDMI_ReadI2C_Byte(0x09);
    fm_value = (fm_value<<8) ;
    fm_value = fm_value + HDMI_ReadI2C_Byte(0x0a);
    print("\r\nPort B lvds clock: ");
    printdec_u32(fm_value);
    lvds_clk_in = fm_value;
    #endif

#endif
}

void LT9211_LvdsRxPll(void)
{
    u8 loopx = 0;
    
    HDMI_WriteI2C_Byte(0xff,0x82);
    HDMI_WriteI2C_Byte(0x25,0x05);
    HDMI_WriteI2C_Byte(0x27,0x02);	
	
    if(INPUT_PORT_NUM == 1)             //1Port LVDS Input
    {
        HDMI_WriteI2C_Byte(0x24,0x24); //RXPLL_LVDSCLK_MUXSEL,PIXCLK_MUXSEL	0x2c.
        HDMI_WriteI2C_Byte(0x28,0x44); //0x64
    }
    else if(INPUT_PORT_NUM == 2)        //2Port LVDS Input
    {
        HDMI_WriteI2C_Byte(0x24,0x2c); //RXPLL_LVDSCLK_MUXSEL,PIXCLK_MUXSEL	0x2c.
        HDMI_WriteI2C_Byte(0x28,0x64); //0x64
    }
    else
    {
        print("\r\n LvdsRxPll: lvds port count error");
    }
    Timer0_Delay1ms(10);
    HDMI_WriteI2C_Byte(0xff,0x87);
    HDMI_WriteI2C_Byte(0x05,0x00);
    HDMI_WriteI2C_Byte(0x05,0x80);
    Timer0_Delay1ms(100);
    for(loopx = 0; loopx < 10; loopx++) //Check Rx PLL cal
    {
        HDMI_WriteI2C_Byte(0xff,0x87);			
        if(HDMI_ReadI2C_Byte(0x12)& 0x80)
        {
            if(HDMI_ReadI2C_Byte(0x11)& 0x80)
            {
                print("\r\nLT9211 rx cal done");
            }
            else
            {
                print("\r\nLT9211 rx cal undone!!");
            }					
            print("\r\nLT9211 rx pll lock");
            break;
        }
        else
        {
            print("\r\nLT9211 rx pll unlocked");
        }
    }
}

void LT9211_VideoCheck(void)
{
    u8 sync_polarity;

    HDMI_WriteI2C_Byte(0xff,0x86);
    HDMI_WriteI2C_Byte(0x20,0x00);
	
    sync_polarity = HDMI_ReadI2C_Byte(0x70);
    vs = HDMI_ReadI2C_Byte(0x71);

    hs = HDMI_ReadI2C_Byte(0x72);
    hs = (hs<<8) + HDMI_ReadI2C_Byte(0x73);
	
    vbp = HDMI_ReadI2C_Byte(0x74);
    vfp = HDMI_ReadI2C_Byte(0x75);

    hbp = HDMI_ReadI2C_Byte(0x76);
    hbp = (hbp<<8) + HDMI_ReadI2C_Byte(0x77);

    hfp = HDMI_ReadI2C_Byte(0x78);
    hfp = (hfp<<8) + HDMI_ReadI2C_Byte(0x79);

    vtotal = HDMI_ReadI2C_Byte(0x7A);
    vtotal = (vtotal<<8) + HDMI_ReadI2C_Byte(0x7B);

    htotal = HDMI_ReadI2C_Byte(0x7C);
    htotal = (htotal<<8) + HDMI_ReadI2C_Byte(0x7D);

    vact = HDMI_ReadI2C_Byte(0x7E);
    vact = (vact<<8)+ HDMI_ReadI2C_Byte(0x7F);

    hact = HDMI_ReadI2C_Byte(0x80);
    hact = (hact<<8) + HDMI_ReadI2C_Byte(0x81);

    print("\r\nsync_polarity = %x", sync_polarity);
	if(!(sync_polarity & 0x01)) //hsync
	{
        HDMI_WriteI2C_Byte(0xff,0xd8);
        HDMI_WriteI2C_Byte(0x10, (HDMI_ReadI2C_Byte(0x10)| 0x10));
	}
	if(!(sync_polarity & 0x02)) //vsync
	{
        HDMI_WriteI2C_Byte(0xff,0xd8);
**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数嵌入式工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/ee850bb817598d2da16b147515683d43.png)

![img](https://img-blog.csdnimg.cn/img_convert/1a6d3c675fdad801df8535902e9ed0df.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/7bd11ef398363bde453852397eca4208.png)

 **既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

![img](https://img-blog.csdnimg.cn/img_convert/584c92b56596c0ca4f099a1114173e35.png)

![img](https://img-blog.csdnimg.cn/img_convert/08e219a55a9104122bd24ff3fbefe547.png)

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[外链图片转存中...(img-BPwgFZgV-1712306365975)]

[外链图片转存中...(img-6QM1jbnB-1712306365976)]

 

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**

**如果你觉得这些内容对你有帮助,可以+V:Vip1104z获取!!! (备注:嵌入式)**

<img src="https://img-community.csdnimg.cn/images/73bb5de17851459088c6af944156ee24.jpg" alt="img" style="zoom: 67%;" />



# 最后

**资料整理不易,觉得有帮助的朋友可以帮忙点赞分享支持一下小编~**

**你的支持,我的动力;祝各位前程似锦,offer不断,步步高升!!!**

**[更多资料点击此处获qu!!](https://bbs.csdn.net/topics/618376385)**
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值