linuxOS_D21X/source/linux-5.10/drivers/video/lt8911exb/lt8911.c
2026-04-02 19:23:55 +08:00

1028 lines
29 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "include/include.h"
#ifdef _1080P_eDP_Panel_
#define LANE_CNT 2
#define PCR_PLL_PREDIV 0x40
#define PCR_M 0x17 //148.5M //hfp, hs, hbp,hact,htotal,vfp, vs, vbp, vact,vtotal,
struct video_timing video ={88, 44, 148,1920, 2200, 4, 5, 36, 1080, 1125, 148500};
//const struct video_timing video ={40, 40, 80,1920, 2200, 3, 5, 23, 1080, 1111, 148500};
#endif
#ifdef _1366x768_eDP_Panel_
#define LANE_CNT 1
#define PCR_PLL_PREDIV 0x40
#define PCR_M 0x17 //74M
//hfp, hs, hbp,hact,htotal,vfp, vs, vbp, vact,vtotal,
struct video_timing video = {100, 26,100,1366, 1592, 10, 10, 10, 768, 798, 76225};
#endif
u8 EDID_DATA[128] = {0};
static bool edp_idle_flag = 1;
#define MSA_SW_MODE 0x80 //MSA from register
#define MSA_HW_MODE 0x00 //MSA from video check
#define EDP_IDLE_PTN_ON 0x04
#define EDP_IDLE_PTN_OFF 0x00
//=======================================//
#define _MIPI_Lane_ 4 // 3 /2 / 1
#define _MIPI_data_PN_Swap_En 0xF0
#define _MIPI_data_PN_Swap_Dis 0x00
#define _MIPI_data_PN_ _MIPI_data_PN_Swap_Dis
//------------------------------------------//
#define _No_swap_ 0x00 // 3210 default
#define _MIPI_data_3210_ 0 // default
#define _MIPI_data_0123_ 21
#define _MIPI_data_2103_ 20
#define _MIPI_data_sequence_ _No_swap_
/*
LT8911EXB pin MIPI RX
D3<44><33>37<33><37>38<33><38> D3 2 3 2 1 1 3 2 3 2 0 0 3 0 3 0 1 1 2 0 2 0 1 1
D2<44><32>40<34><30>41<34><31> D2 3 1 1 2 3 2 3 0 0 2 3 0 3 1 1 0 3 0 2 1 1 0 2
D1<44><31>44<34><34>45<34><35> D1 1 2 3 3 2 0 1 2 3 3 2 1 1 0 3 3 0 1 1 0 2 2 0
D0<44><30>47<34><37>48<34><38> D0 0 0 0 0 0 1 0 1 1 1 1 2 2 2 2 2 2 3 3 3 3 3 3
0xD003 Reg value 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
//*/
//===========================================//
#define _eDP_data_PN_Swap_En 0xF0 // Please refer to the notes below
#define _eDP_data_PN_Swap_Dis 0x00
#define _eDP_data_PN_ _eDP_data_PN_Swap_Dis // defailt ; disable
/* eDP data P/N polarity swap
bit7 RGD_MLCTRL_LANE3_RVSD_EN
1 = data of lane3 polarity swap;
0 = normal.
bit6 RGD_MLCTRL_LANE2_RVSD_EN
1 = data of lane2 polarity swap;
0 = normal.
bit5 RGD_MLCTRL_LANE1_RVSD_EN
1 = data of lane1 polarity swap;
0 = normal.
bit4 RGD_MLCTRL_LANE0_RVSD_EN
1 = data of lane0 polarity swap;
0 = normal.
//*/
//------------------------------------------//
#define _Lane0_data_ 0
#define _Lane1_data_ 1
#define _Lane2_data_ 2
#define _Lane3_data_ 3
#define _eDP_data3_select_ (_Lane3_data_ << 6) // default; _Lane3_data_select_ is lane3
#define _eDP_data2_select_ (_Lane2_data_ << 4) // default; _Lane2_data_select_ is lane2
#define _eDP_data1_select_ (_Lane1_data_ << 2) // default; _Lane1_data_select_ is lane1
#define _eDP_data0_select_ (_Lane0_data_ << 0) // default; _Lane0_data_select_ is lane0
// example:lane1 and lane0 swap
//#define _eDP_data1_select_ (_Lane0_data_ << 2) // default _Lane1_data_select_ is lane0
//#define _eDP_data0_select_ (_Lane1_data_ << 0) // default _Lane0_data_select_ is lane1
#define _eDP_data_No_swap_ 0xe4 // default
#define _eDP_data_sequence_ _eDP_data_No_swap_ // default, no swap
// #define _eDP_data_sequence_ (_eDP_data3_select_ + _eDP_data2_select_ + _eDP_data1_select_ + _eDP_data0_select_)
//===========================================//
//init power gpio level and reset chip
void LT8911_Reset(void)
{
gpiod_set_value(lt8911exb->power_gpio,1);
msleep(5);
printk("set power High level ");
//complete chip reset logic
gpiod_set_value(lt8911exb->reset_gpio,1);
msleep(5);
gpiod_set_value(lt8911exb->reset_gpio,0);
msleep(5);
gpiod_set_value(lt8911exb->reset_gpio,1);
msleep(5);
printk("reset chip");
}
void LT8911_ChipID(void)
{
HDMI_WriteI2C_Byte(0xff,0x81);//register bank
HDMI_WriteI2C_Byte(0x08,0x7f);
printk("\r\nLT8911EX chip ID:%x,",HDMI_ReadI2C_Byte(0x00));
printk("%x, ",HDMI_ReadI2C_Byte(0x01));
printk("%x, ",HDMI_ReadI2C_Byte(0x02));
}
void LT8911_SetVideoTiming(struct video_timing *video_format)
{
// u32 pclk_khz;
// u8 dessc_m;
//edp msa
HDMI_WriteI2C_Byte(0xff,0xa8);
HDMI_WriteI2C_Byte(0x2d,0x88); //bit[7]<5D><>o1 = register msa, 0 = hardware msa
#ifdef _Msa_Active_Only_
HDMI_WriteI2C_Byte(0x05,0x00);
HDMI_WriteI2C_Byte(0x06,0x00);//htotal
HDMI_WriteI2C_Byte(0x07,0x00);
HDMI_WriteI2C_Byte(0x08,0x00);//h_start
HDMI_WriteI2C_Byte(0x09,0x00);
HDMI_WriteI2C_Byte(0x0a,0x00); //hsa
HDMI_WriteI2C_Byte(0x0b,(u8)(video_format->hact/256));
HDMI_WriteI2C_Byte(0x0c,(u8)(video_format->hact%256)); //hactive
HDMI_WriteI2C_Byte(0x0d,0x00);
HDMI_WriteI2C_Byte(0x0e,0x00);//vtotal
HDMI_WriteI2C_Byte(0x11,0x00);
HDMI_WriteI2C_Byte(0x12,0x00);
HDMI_WriteI2C_Byte(0x14,0x00);
HDMI_WriteI2C_Byte(0x15,(u8)(video_format->vact/256));
HDMI_WriteI2C_Byte(0x16,(u8)(video_format->vact%256)); //vactive
#else
HDMI_WriteI2C_Byte(0x05,(u8)(video_format->htotal/256));
HDMI_WriteI2C_Byte(0x06,(u8)(video_format->htotal%256));//htotal
HDMI_WriteI2C_Byte(0x07,(u8)((video_format->hs+video_format->hbp)/256));
HDMI_WriteI2C_Byte(0x08,(u8)((video_format->hs+video_format->hbp)%256));//h_start
HDMI_WriteI2C_Byte(0x09,(u8)(video_format->hs/256));
HDMI_WriteI2C_Byte(0x0a,(u8)(video_format->hs%256)); //hsa
HDMI_WriteI2C_Byte(0x0b,(u8)(video_format->hact/256));
HDMI_WriteI2C_Byte(0x0c,(u8)(video_format->hact%256)); //hactive
HDMI_WriteI2C_Byte(0x0d,(u8)(video_format->vtotal/256));
HDMI_WriteI2C_Byte(0x0e,(u8)(video_format->vtotal%256));//vtotal
HDMI_WriteI2C_Byte(0x11,(u8)((video_format->vs+video_format->vbp)/256));
HDMI_WriteI2C_Byte(0x12,(u8)((video_format->vs+video_format->vbp)%256));//v_start
HDMI_WriteI2C_Byte(0x14,(u8)(video_format->vs%256)); //vsa
HDMI_WriteI2C_Byte(0x15,(u8)(video_format->vact/256));
HDMI_WriteI2C_Byte(0x16,(u8)(video_format->vact%256)); //vactive
#endif
}
void LT8911_MIPI_Video_Timing(struct video_timing *video_format)
{
HDMI_WriteI2C_Byte(0xff,0xd0);
HDMI_WriteI2C_Byte(0x0d,(u8)(video_format->vtotal/256));
HDMI_WriteI2C_Byte(0x0e,(u8)(video_format->vtotal%256));//vtotal
HDMI_WriteI2C_Byte(0x0f,(u8)(video_format->vact/256));
HDMI_WriteI2C_Byte(0x10,(u8)(video_format->vact%256)); //vactive
HDMI_WriteI2C_Byte(0x11,(u8)(video_format->htotal/256));
HDMI_WriteI2C_Byte(0x12,(u8)(video_format->htotal%256));//htotal
HDMI_WriteI2C_Byte(0x13,(u8)(video_format->hact/256));
HDMI_WriteI2C_Byte(0x14,(u8)(video_format->hact%256)); //hactive
HDMI_WriteI2C_Byte(0x15,(u8)(video_format->vs%256)); //vsa
HDMI_WriteI2C_Byte(0x16,(u8)(video_format->hs%256)); //hsa
HDMI_WriteI2C_Byte(0x17,(u8)(video_format->vfp/256));
HDMI_WriteI2C_Byte(0x18,(u8)(video_format->vfp%256)); //vfp
HDMI_WriteI2C_Byte(0x19,(u8)(video_format->hfp/256));
HDMI_WriteI2C_Byte(0x1a,(u8)(video_format->hfp%256)); //hfp
}
void LT8911_Init(struct video_timing *video_format)
{
u8 i;
u8 pcr_m;
u32 pclk;
u8 pcr_pll_postdiv;
/* init */
HDMI_WriteI2C_Byte(0xff,0x81);
HDMI_WriteI2C_Byte(0x08,0x7f); //i2c over aux issue
HDMI_WriteI2C_Byte(0x49,0xff); //enable 0x87xx
HDMI_WriteI2C_Byte(0xff,0x82); //GPIO test output
HDMI_WriteI2C_Byte(0x5a,0x0e);
//for power consumption//
HDMI_WriteI2C_Byte(0xff,0x81);
HDMI_WriteI2C_Byte(0x05,0x06);
HDMI_WriteI2C_Byte(0x43,0x00);
HDMI_WriteI2C_Byte(0x44,0x1f);
#if(LANE_CNT == 4)
HDMI_WriteI2C_Byte(0x45,0xff);
HDMI_WriteI2C_Byte(0x46,0xfe);
#else
HDMI_WriteI2C_Byte(0x45,0xf7);
HDMI_WriteI2C_Byte(0x46,0xf6);
#endif
HDMI_WriteI2C_Byte(0x49,0x7f);
HDMI_WriteI2C_Byte(0xff,0x82);
#if(LANE_CNT == 4)
HDMI_WriteI2C_Byte(0x12,0xff);
#elif (LANE_CNT == 2)
HDMI_WriteI2C_Byte(0x12,0x33);
#else // 1 lane eDP
HDMI_WriteI2C_Byte(0x12,0x11);
#endif
/* mipi Rx analog */
HDMI_WriteI2C_Byte(0xff,0x82);
HDMI_WriteI2C_Byte(0x32,0x51);
HDMI_WriteI2C_Byte(0x35,0x22); //EQ current 0x42
HDMI_WriteI2C_Byte(0x3a,0x77); //0x77:EQ 12.5db ,0x33:EQ 6.5db
HDMI_WriteI2C_Byte(0x3b,0x77); //0x77:EQ 12.5db ,0x33:EQ 6.5db
HDMI_WriteI2C_Byte(0x4c,0x0c);
HDMI_WriteI2C_Byte(0x4d,0x00);
/* dessc_pcr pll analog */
HDMI_WriteI2C_Byte(0xff,0x82);
HDMI_WriteI2C_Byte(0x6a,0x40); //final setting: 0x40
HDMI_WriteI2C_Byte(0x6b,PCR_PLL_PREDIV); //0x44:pre-div = 2
//HDMI_WriteI2C_Byte(0x6b,0x44);
pclk = video_format->pclk_khz;
if(pclk< 88000)
{
HDMI_WriteI2C_Byte(0x6e,0x82);
pcr_pll_postdiv = 0x08;
}
else
if(pclk < 176000)
{
HDMI_WriteI2C_Byte(0x6e,0x81);
pcr_pll_postdiv = 0x04;
}
else
{
HDMI_WriteI2C_Byte(0x6e,0x80);
pcr_pll_postdiv = 0x02;
}
/* dessc pll digital */
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0xa9,0x31);
HDMI_WriteI2C_Byte(0xaa,0x17);
HDMI_WriteI2C_Byte(0xab,0xba);
HDMI_WriteI2C_Byte(0xac,0xe1);
HDMI_WriteI2C_Byte(0xad,0x47);
HDMI_WriteI2C_Byte(0xae,0x01);
HDMI_WriteI2C_Byte(0xae,0x11);
/* Digital Top */
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0xc0,0x01); //select mipi Rx
#ifdef _6bit_
HDMI_WriteI2C_Byte(0xb0,0xd0); //enable dither
#else // 8 bit
HDMI_WriteI2C_Byte(0xb0,0x00); //disable dither
#endif
/* mipi Rx Digital */
HDMI_WriteI2C_Byte(0xff, 0xd0);
HDMI_WriteI2C_Byte( 0x00, _MIPI_data_PN_ + _MIPI_Lane_ % 4 ); // 0: 4 Lane / 1: 1 Lane / 2 : 2 Lane / 3: 3 Lane
//HDMI_WriteI2C_Byte(0x00, 0x00); //0x03: 3lanes, 0x00: 4lanes
HDMI_WriteI2C_Byte(0x02, 0x08); //settle
HDMI_WriteI2C_Byte( 0x03, _MIPI_data_sequence_ ); // default is 0x00
HDMI_WriteI2C_Byte(0x08, 0x00);
HDMI_WriteI2C_Byte(0x0c, 0x80); //fifo position
HDMI_WriteI2C_Byte(0x1c, 0x80); //fifo position
HDMI_WriteI2C_Byte(0x24, 0x70); //pcr mode( de hs vs)
//HDMI_WriteI2C_Byte(0x2d, 0x1f); //M up limit
HDMI_WriteI2C_Byte(0x31, 0x0a); //M down limit
/*stage1 hs mode*/
HDMI_WriteI2C_Byte(0x25, 0x90); //line limit
HDMI_WriteI2C_Byte(0x2a, 0x3a); //step in limit
HDMI_WriteI2C_Byte(0x21, 0x4f); //hs_step
HDMI_WriteI2C_Byte(0x22, 0xff);
/*stage2 de mode*/
HDMI_WriteI2C_Byte(0x0a, 0x02); //de adjust pre line
HDMI_WriteI2C_Byte(0x38, 0x02); //de_threshold 1
HDMI_WriteI2C_Byte(0x39, 0x04); //de_threshold 2
HDMI_WriteI2C_Byte(0x3a, 0x08); //de_threshold 3
HDMI_WriteI2C_Byte(0x3b, 0x10); //de_threshold 4
HDMI_WriteI2C_Byte(0x3f, 0x02); //de_step 1
HDMI_WriteI2C_Byte(0x40, 0x04); //de_step 2
HDMI_WriteI2C_Byte(0x41, 0x08); //de_step 3
HDMI_WriteI2C_Byte(0x42, 0x10); //de_step 4
/*stage2 hs mode*/
HDMI_WriteI2C_Byte(0x1e, 0x01); // hs threshold
HDMI_WriteI2C_Byte(0x23, 0xf0); // hs step
HDMI_WriteI2C_Byte(0x2b, 0x80); //stable out // V1.8 20200417
pcr_m = (u8)( pclk * pcr_pll_postdiv / 25 / 1000 );
#ifdef _EDP_Pattern_
HDMI_WriteI2C_Byte(0x26,(pcr_m|0x80));
#else
HDMI_WriteI2C_Byte(0x26,pcr_m);
#endif
// #ifndef _1080P_eDP_Panel_
// LT8911_MIPI_Video_Timing(&video); //defualt setting is 1080P
// #endif
LT8911_MIPI_Video_Timing(&video); //defualt setting is 1080P
HDMI_WriteI2C_Byte(0xff,0x81); //PCR reset
HDMI_WriteI2C_Byte(0x03,0x7b);
HDMI_WriteI2C_Byte(0x03,0xff);
/* Txpll 2.7G*/
#ifdef _eDP_2G7_
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x19, 0x31 );
// HDMI_WriteI2C_Byte( 0x1a, 0x36 ); // sync m
HDMI_WriteI2C_Byte( 0x1a, 0x1b );
HDMI_WriteI2C_Byte( 0x1b, 0x00 ); // sync_k [7:0]
HDMI_WriteI2C_Byte( 0x1c, 0x00 ); // sync_k [13:8]
// txpll Analog
HDMI_WriteI2C_Byte( 0xff, 0x82 );
HDMI_WriteI2C_Byte( 0x09, 0x00 ); // div hardware mode, for ssc.
// HDMI_WriteI2C_Byte( 0x01, 0x18 );// default : 0x18
HDMI_WriteI2C_Byte( 0x02, 0x42 );
HDMI_WriteI2C_Byte( 0x03, 0x00 ); // txpll en = 0
HDMI_WriteI2C_Byte( 0x03, 0x01 ); // txpll en = 1
// HDMI_WriteI2C_Byte( 0x04, 0x3a );// default : 0x3A
HDMI_WriteI2C_Byte(0x0a,0x1b);
HDMI_WriteI2C_Byte(0x04,0x2a);
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x0c, 0x10 ); // cal en = 0
HDMI_WriteI2C_Byte( 0xff, 0x81 );
HDMI_WriteI2C_Byte( 0x09, 0xfc );
HDMI_WriteI2C_Byte( 0x09, 0xfd );
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x0c, 0x11 ); // cal en = 1
// ssc
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x13, 0x83 );
HDMI_WriteI2C_Byte( 0x14, 0x41 );
HDMI_WriteI2C_Byte( 0x16, 0x0a );
HDMI_WriteI2C_Byte( 0x18, 0x0a );
HDMI_WriteI2C_Byte( 0x19, 0x33 );
#endif
#ifdef _eDP_1G62_
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x19, 0x31 );
HDMI_WriteI2C_Byte( 0x1a, 0x20 ); // sync m
HDMI_WriteI2C_Byte( 0x1b, 0x19 ); // sync_k [7:0]
HDMI_WriteI2C_Byte( 0x1c, 0x99 ); // sync_k [13:8]
// txpll Analog
HDMI_WriteI2C_Byte( 0xff, 0x82 );
HDMI_WriteI2C_Byte( 0x09, 0x00 ); // div hardware mode, for ssc.
// HDMI_WriteI2C_Byte( 0x01, 0x18 );// default : 0x18
HDMI_WriteI2C_Byte( 0x02, 0x42 );
HDMI_WriteI2C_Byte( 0x03, 0x00 ); // txpll en = 0
HDMI_WriteI2C_Byte( 0x03, 0x01 ); // txpll en = 1
// HDMI_WriteI2C_Byte( 0x04, 0x3a );// default : 0x3A
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x0c, 0x10 ); // cal en = 0
HDMI_WriteI2C_Byte( 0xff, 0x81 );
HDMI_WriteI2C_Byte( 0x09, 0xfc );
HDMI_WriteI2C_Byte( 0x09, 0xfd );
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x0c, 0x11 ); // cal en = 1
//ssc
HDMI_WriteI2C_Byte( 0xff, 0x87 );
HDMI_WriteI2C_Byte( 0x13, 0x83 );
HDMI_WriteI2C_Byte( 0x14, 0x41 );
HDMI_WriteI2C_Byte( 0x16, 0x0a );
HDMI_WriteI2C_Byte( 0x18, 0x0a );
HDMI_WriteI2C_Byte( 0x19, 0x33 );
#endif
HDMI_WriteI2C_Byte( 0xff, 0x87 );
for(i=0;i<5;i++) //Check Tx PLL
{
msleep(5);
if (HDMI_ReadI2C_Byte(0x37)&0x02)
{
printk("\r\nLT8911 tx pll locked");
HDMI_WriteI2C_Byte(0xff,0x87);
HDMI_WriteI2C_Byte(0x1a,0x36);
HDMI_WriteI2C_Byte(0xff,0x82);
HDMI_WriteI2C_Byte(0x0a,0x36);
HDMI_WriteI2C_Byte(0x04,0x3a);
break;
}
else
{
printk("\r\nLT8911 tx pll unlocked");
HDMI_WriteI2C_Byte(0xff,0x81);
HDMI_WriteI2C_Byte(0x09,0xfc);
HDMI_WriteI2C_Byte(0x09,0xfd);
HDMI_WriteI2C_Byte(0xff,0x87);
HDMI_WriteI2C_Byte(0x0c,0x10);
HDMI_WriteI2C_Byte(0x0c,0x11);
}
}
HDMI_WriteI2C_Byte( 0xff, 0xac ); // Change Reg bank
HDMI_WriteI2C_Byte( 0x15, _eDP_data_sequence_ ); // eDP data swap
HDMI_WriteI2C_Byte( 0x16, _eDP_data_PN_); // eDP P / N swap
// AUX reset
HDMI_WriteI2C_Byte( 0xff, 0x81 ); // Change Reg bank
HDMI_WriteI2C_Byte( 0x07, 0xfe );
HDMI_WriteI2C_Byte( 0x07, 0xff );
HDMI_WriteI2C_Byte( 0x0a, 0xfc );
HDMI_WriteI2C_Byte( 0x0a, 0xfe );
/* tx phy */
HDMI_WriteI2C_Byte(0xff,0x82);
HDMI_WriteI2C_Byte(0x11,0x00);
HDMI_WriteI2C_Byte(0x13,0x10);
HDMI_WriteI2C_Byte(0x14,0x0c);
HDMI_WriteI2C_Byte(0x14,0x08);
HDMI_WriteI2C_Byte(0x13,0x20);
HDMI_WriteI2C_Byte(0xff,0x82);
HDMI_WriteI2C_Byte(0x0e,0x25);
//HDMI_WriteI2C_Byte(0x12,0xff);
HDMI_WriteI2C_Byte(0xff,0x80);
HDMI_WriteI2C_Byte(0x40,0x22);
/*eDP Tx Digital */
HDMI_WriteI2C_Byte(0xff,0xa8);
#ifdef _EDP_Pattern_
HDMI_WriteI2C_Byte( 0x24, 0x50 ); // bit2 ~ bit 0 : test panttern image mode
HDMI_WriteI2C_Byte( 0x25, 0x70 ); // bit6 ~ bit 4 : test Pattern color
HDMI_WriteI2C_Byte( 0x27, 0x50 ); //0x50:Pattern; 0x10:mipi video
// HDMI_WriteI2C_Byte( 0x2d, 0x00 ); // pure color setting
// HDMI_WriteI2C_Byte( 0x2d, 0x84 ); // black color
HDMI_WriteI2C_Byte( 0x2d, 0x88 ); // block
#else
HDMI_WriteI2C_Byte(0x27,0x10); //0x50:Pattern; 0x10:mipi video
//HDMI_WriteI2C_Byte(0x27,0x50); //0x50:Pattern; 0x10:mipi video
#endif
#ifdef _6bit_
HDMI_WriteI2C_Byte(0x17,0x00);
HDMI_WriteI2C_Byte(0x18,0x00);
#else
// _8bit_
HDMI_WriteI2C_Byte( 0x17, 0x10 );
HDMI_WriteI2C_Byte( 0x18, 0x20 );
#endif
// #ifndef _1080P_eDP_Panel_
// LT8911_eDP_Video_Timing(&video);
// #endif
HDMI_WriteI2C_Byte(0xff,0xa0); //nvid = 0x080000;
HDMI_WriteI2C_Byte(0x00,0x00);
HDMI_WriteI2C_Byte(0x01,0x80);
}
void LT8911_InterruptEnable(void)
{
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0x08,0x3f); //fm clr
HDMI_WriteI2C_Byte(0x65,0x7f); //vid chk hact clr
HDMI_WriteI2C_Byte(0x07,0x7f); //vid chk clr
}
u8 DpcdRead(u32 Address)
{
/***************************
ע<><D7A2><EFBFBD>С<EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>!
<20><><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>Ǵ<EFBFBD><C7B4>ģʽ
Pay attention to the Big-Endian and Little-Endian!
The default mode is Big-Endian here.
****************************/
u8 DpcdValue = 0x00;
u8 AddressH = 0x0f & (Address>>16);
u8 AddressM = 0xff & (Address>>8);
u8 AddressL = 0xff & Address ;
u8 reg;
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x00); //Soft Link train
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2a,0x01);
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2b,(0x90|AddressH)); //CMD
HDMI_WriteI2C_Byte(0x2b,AddressM); //addr[15:8]
HDMI_WriteI2C_Byte(0x2b,AddressL); //addr[7:0]
HDMI_WriteI2C_Byte(0x2b,0x00); //data lenth
HDMI_WriteI2C_Byte(0x2c,0x00); //start Aux read edid
msleep(10); //more than 10ms
reg = HDMI_ReadI2C_Byte(0x25);
if((reg&0x0f)== 0x0c)
{
if(HDMI_ReadI2C_Byte(0x39) == 0x22)
{
HDMI_ReadI2C_Byte(0x2b);
DpcdValue = HDMI_ReadI2C_Byte(0x2b);
}
else
goto no_reply;
}
else if((reg&0x0f)== 0x0a)
goto reply_nack;
else if((reg&0x0f)== 0x09)
goto reply_defer;
else
goto no_reply;
printk("\r\nDpcdRead: 0x%x%x%x= 0x%x ",AddressH,AddressM,AddressL,DpcdValue);
return DpcdValue;
/*error handle*/
no_reply:
printk("\r\nDpcdRead error: no_reply ");
return 0;
reply_nack:
printk("\r\nDpcdRead error: reply_nack ");
return 0;
reply_defer:
printk("\r\nDpcdRead error: reply_nack ");
return 0;
}
bool DpcdWrite(u32 Address,u8 value )
{
/***************************
ע<><D7A2><EFBFBD>С<EFBFBD>˵<EFBFBD><CBB5><EFBFBD><EFBFBD><EFBFBD>!
<20><><EFBFBD><EFBFBD>Ĭ<EFBFBD><C4AC><EFBFBD>Ǵ<EFBFBD><C7B4>ģʽ
Pay attention to the Big-Endian and Little-Endian!
The default mode is Big-Endian here.
****************************/
u8 AddressH = 0x0f & (Address>>16);
u8 AddressM = 0xff & (Address>>8);
u8 AddressL = 0xff & Address ;
u8 reg;
printk("\r\nDpcdWrite: 0x%x,0x%x,0x%x= 0x%x ",AddressH,AddressM,AddressL,value);
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x00); //Soft Link train
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2a,0x01);
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2b,(0x80|AddressH)); //CMD
HDMI_WriteI2C_Byte(0x2b,AddressM); //addr[15:8]
HDMI_WriteI2C_Byte(0x2b,AddressL); //addr[7:0]
HDMI_WriteI2C_Byte(0x2b,0x00); //data lenth
HDMI_WriteI2C_Byte(0x2b,value); //data lenth
HDMI_WriteI2C_Byte(0x2c,0x00); //start Aux read edid
msleep(10); //more than 10ms
reg = HDMI_ReadI2C_Byte(0x25);
if((reg&0x0f)== 0x0c)
{
return 0;
}
else if((reg&0x0f)== 0x0a)
goto reply_nack;
else if((reg&0x0f)== 0x09)
goto reply_defer;
else
goto no_reply;
/*error handle*/
no_reply:
printk("\r\nDpcdRead error: no_reply ");
return 1;
reply_nack:
printk("\r\nDpcdRead error: reply_nack ");
return 1;
reply_defer:
printk("\r\nDpcdRead error: reply_nack ");
return 1;
}
/*
void LT8911_LinkTrain(void)
{
printk("\r\nlink train start");
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x60); //Soft Link train
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2a,0x00);
HDMI_WriteI2C_Byte(0xff,0x81);
HDMI_WriteI2C_Byte(0x07,0xfe);
HDMI_WriteI2C_Byte(0x07,0xff);
HDMI_WriteI2C_Byte(0x0a,0xfc);
HDMI_WriteI2C_Byte(0x0a,0xfe);
HDMI_WriteI2C_Byte(0xff,0xa8);
HDMI_WriteI2C_Byte(0x2d,0x80); //edp output video ;
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0x1a,LANE_CNT);
//HDMI_WriteI2C_Byte(0x13,0xd1);
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x64);
HDMI_WriteI2C_Byte(0x01,0x0a);
HDMI_WriteI2C_Byte(0x0c,0x85);
HDMI_WriteI2C_Byte(0x0c,0xc5);
msleep(500);
edp_idle_flag = 0;
}
*/
void LT8911_LinkTrain(void)
{
HDMI_WriteI2C_Byte( 0xff, 0x81 );
HDMI_WriteI2C_Byte( 0x06, 0xdf ); // rset VID TX
HDMI_WriteI2C_Byte( 0x06, 0xff );
if(SCRAMBLE_MODE == 0x80)
{
/* Aux operater init */
HDMI_WriteI2C_Byte( 0xff, 0xac );
HDMI_WriteI2C_Byte( 0x00, 0x20 ); //Soft Link train
HDMI_WriteI2C_Byte( 0xff, 0xa6 );
HDMI_WriteI2C_Byte( 0x2a, 0x01 );
DpcdWrite(0x10a,0x01);
}
/* Aux setup */
HDMI_WriteI2C_Byte( 0xff, 0xac );
HDMI_WriteI2C_Byte( 0x00, 0x60 ); //Soft Link train
HDMI_WriteI2C_Byte(0xff,0xa6);
HDMI_WriteI2C_Byte(0x2a,0x00);
HDMI_WriteI2C_Byte(0xff,0x81);
HDMI_WriteI2C_Byte(0x07,0xfe);
HDMI_WriteI2C_Byte(0x07,0xff);
HDMI_WriteI2C_Byte(0x0a,0xfc);
HDMI_WriteI2C_Byte(0x0a,0xfe);
/* link train */
HDMI_WriteI2C_Byte(0xff,0xa8);
HDMI_WriteI2C_Byte(0x2d,MSA_SW_MODE|EDP_IDLE_PTN_OFF); //edp output video ;
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0x17,0xc0);
HDMI_WriteI2C_Byte(0x1a,LANE_CNT);
HDMI_WriteI2C_Byte(0xa1,(SCRAMBLE_MODE|0x02)); //scramble mode
//HDMI_WriteI2C_Byte(0x13,0xd1);
#ifdef _link_train_enable_
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x60);
HDMI_WriteI2C_Byte(0x01,0x0a);
HDMI_WriteI2C_Byte(0x0c,0x05);
HDMI_WriteI2C_Byte(0x0c,0x45);
//printk("\r\n\33[35mLT8911 link trian: hardware linktrain start...\033[37m");
printk("LT8911 link trian: hardware linktrain start...\r\n");
// msleep(500);
#else // NO_AUX_HANDSHAKE_LINK_TRAINING,<2C>fFast training
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x00);
HDMI_WriteI2C_Byte(0x01,0x0a);
HDMI_WriteI2C_Byte(0x14,0x80);
HDMI_WriteI2C_Byte(0x14,0x81);
msleep(50);
HDMI_WriteI2C_Byte(0x14,0x84);
msleep(50);
HDMI_WriteI2C_Byte(0x14,0xc0);
printk("\r\n\33[35mLT8911 link trian: no handshake linktrain\033[37m");
#endif
edp_idle_flag = 0;
}
void LT8911_LinkTrainResultCheck(void)
{
#ifdef _link_train_enable_
u8 i;
u8 val;
//int ret;
HDMI_WriteI2C_Byte(0xff,0xac);
for(i = 0; i< 10; i++)
{
val = HDMI_ReadI2C_Byte(0x82);
if(val & 0x20)
{
if((val & 0x1f)==0x1e){
printk("\r\nLT8911_LinkTrainResultCheck: edp link train successed: 0x%x", val);
}
else{
printk("\r\nLT8911_LinkTrainResultCheck: edp link train failed: 0x%x", val);
//while(1);
HDMI_WriteI2C_Byte(0xff,0xac);
HDMI_WriteI2C_Byte(0x00,0x00);
HDMI_WriteI2C_Byte(0x01,0x0a);
HDMI_WriteI2C_Byte(0x14,0x80);
HDMI_WriteI2C_Byte(0x14,0x81);
msleep(50);
HDMI_WriteI2C_Byte(0x14,0x84);
msleep(50);
HDMI_WriteI2C_Byte(0x14,0xc0);
printk("\r\nLT8911_LinkTrainResultCheck: Enable eDP video output while linktrian fail");
//while(1);
}
val = HDMI_ReadI2C_Byte(0x83);
printk("\r\nLT8911_LinkTrainResultCheck: panel link rate: 0x%x",val);
val = HDMI_ReadI2C_Byte(0x84);
printk("\r\nLT8911_LinkTrainResultCheck: panel link count: 0x%x",val);
return;
}
else
printk("\r\nLT8911_LinkTrainResultCheck: link trian on going...");
msleep(100);
}
#endif
}
/* mipi should be ready before configuring below video check setting*/
void LT8911_video_check(void)
{
//u8 temp;
u32 reg=0x00;
printk("\r\n----------------------------------------------------------------------");
/* mipi byte clk check*/
HDMI_WriteI2C_Byte(0xff,0x85);
HDMI_WriteI2C_Byte(0x1d,0x00); //FM select byte clk
HDMI_WriteI2C_Byte(0x40,0xf7);
HDMI_WriteI2C_Byte(0x41,0x30);
HDMI_WriteI2C_Byte(0xa1,(SCRAMBLE_MODE|0x02)); //video chech from mipi
HDMI_WriteI2C_Byte(0xff,0x81); //video check rst
HDMI_WriteI2C_Byte(0x09,0x7d);
HDMI_WriteI2C_Byte(0x09,0xfd);
HDMI_WriteI2C_Byte(0xff,0x85);
msleep(30);
if(HDMI_ReadI2C_Byte(0x50)== 0x03)
{
reg = HDMI_ReadI2C_Byte(0x4d);
reg = reg*256 + HDMI_ReadI2C_Byte(0x4e);
reg = reg*256 + HDMI_ReadI2C_Byte(0x4f);
printk("\r\nvideo check: mipi byteclk = %d",reg);
}
else
printk("\r\nvideo check: mipi clk unstable");
/* mipi vtotal check*/
reg = HDMI_ReadI2C_Byte(0x76);
reg = reg*256 + HDMI_ReadI2C_Byte(0x77);
printk("\r\nvideo check: Vtotal = %d",reg);
/* mipi word count check*/
HDMI_WriteI2C_Byte(0xff,0xd0);
reg = HDMI_ReadI2C_Byte(0x82);
reg = reg*256 + HDMI_ReadI2C_Byte(0x83);
reg = reg/3;
printk("\r\nvideo check: Hact(word counter) = %d",reg);
//printk(reg);
/* mipi Vact check*/
reg = HDMI_ReadI2C_Byte(0x85);
reg = reg*256 + HDMI_ReadI2C_Byte(0x86);
printk("\r\nvideo check: Vact = %d",reg);
//printk(reg);
printk("\r\nlane0 settle: 0x%x ",HDMI_ReadI2C_Byte(0x88));
printk("\r\nlane1 settle: 0x%x ",HDMI_ReadI2C_Byte(0x8a));
printk("\r\nlane2 settle: 0x%x ",HDMI_ReadI2C_Byte(0x8c));
printk("\r\nlane3 settle: 0x%x ",HDMI_ReadI2C_Byte(0x8e));
printk("\r\nlane0 sot: 0x%x ",HDMI_ReadI2C_Byte(0x89));
printk("\r\nlane1 sot: 0x%x ",HDMI_ReadI2C_Byte(0x8b));
printk("\r\nlane2 sot: 0x%x ",HDMI_ReadI2C_Byte(0x8d));
printk("\r\nlane3 sot: 0x%x ",HDMI_ReadI2C_Byte(0x8f));
printk("\r\n----------------------------------------------------------------------");
}
void LT8911_MainLoop(struct video_timing *video_format)
{
u16 reg;
u16 vtotal;
static int flag_mipi_on = 1;
vtotal = video_format->vtotal;
HDMI_WriteI2C_Byte(0xff,0x85);
//HDMI_WriteI2C_Byte(0x1d,0x00); //FM select byte clk
//HDMI_WriteI2C_Byte(0x40,0xf7);
//HDMI_WriteI2C_Byte(0x41,0x30);
HDMI_WriteI2C_Byte(0xa1,(SCRAMBLE_MODE|0x02)); //video chech from mipi
HDMI_WriteI2C_Byte(0xff,0x81); //video check rst
HDMI_WriteI2C_Byte(0x09,0x7d);
HDMI_WriteI2C_Byte(0x09,0xfd);
msleep(50);
HDMI_WriteI2C_Byte(0xff,0x85);
reg = HDMI_ReadI2C_Byte(0x76);
reg = reg*256 + HDMI_ReadI2C_Byte(0x77);
//printk("\r\nPCR reset: %d",reg);
//printk("\r\nvtotal: %d",vtotal);
if((reg <= (vtotal + 3))&&(reg >= (vtotal - 3)))
{
if(!flag_mipi_on)
{
msleep(1000);
HDMI_WriteI2C_Byte(0xff,0x81); //PCR reset
HDMI_WriteI2C_Byte(0x03,0x7b);
HDMI_WriteI2C_Byte(0x03,0xff);
msleep(100);
HDMI_WriteI2C_Byte(0xff,0xa8);
HDMI_WriteI2C_Byte(0x2d,0x88); //edp disable idle pattern;
flag_mipi_on = 1;
printk("\r\nPCR reset0");
}
HDMI_WriteI2C_Byte(0xff,0xd0);
if((HDMI_ReadI2C_Byte(0x84)&0x40) == 0x00)
{
HDMI_WriteI2C_Byte(0xff,0x81); //PCR reset
HDMI_WriteI2C_Byte(0x03,0x7b);
HDMI_WriteI2C_Byte(0x03,0xff);
msleep(500);
printk("\r\nPCR reset1");
}
else
{
// printk("\r\npcr stable:%x, mk: %x, %x, %x, %x",
// HDMI_ReadI2C_Byte(0x84),
// HDMI_ReadI2C_Byte(0x94),
// HDMI_ReadI2C_Byte(0x95),
// HDMI_ReadI2C_Byte(0x96),
// HDMI_ReadI2C_Byte(0x97));
// if((HDMI_ReadI2C_Byte(0x94)==0x17)&&((HDMI_ReadI2C_Byte(0x95)==0x53)||(HDMI_ReadI2C_Byte(0x95)==0x47)))
// {
// return;
// }
// else
// {
// HDMI_WriteI2C_Byte(0xff,0x81); //PCR reset
// HDMI_WriteI2C_Byte(0x03,0x7b);
// HDMI_WriteI2C_Byte(0x03,0xff);
// msleep(500);
// printk("\r\nPCR reset2");
// }
}
}
else
{
HDMI_WriteI2C_Byte(0xff,0xa8);
HDMI_WriteI2C_Byte(0x2d,0x8c); //edp enable idle pattern;
flag_mipi_on = 0;
}
}
void LT8911_pcr_mk_printk(void)
{
#ifdef _pcr_mk_printk_
u8 loopx = 0;
for(loopx = 0; loopx < 30; loopx++)
{
HDMI_WriteI2C_Byte(0xff,0xd0);
//printk("\r\npcr stable bit[4]:%x, mk: %x, %x, %x, %x",
HDMI_ReadI2C_Byte(0x84),
HDMI_ReadI2C_Byte(0x94),
HDMI_ReadI2C_Byte(0x95),
HDMI_ReadI2C_Byte(0x96),
HDMI_ReadI2C_Byte(0x97);
msleep(500);
}
#endif
}
void LT8911_htotal_stable_printk(void)
{
#ifdef _htotal_stable_check_
u8 loopx = 0;
u32 val;
for(loopx = 0; loopx < 30; loopx++)
{
HDMI_WriteI2C_Byte(0xff,0x85);
val = HDMI_ReadI2C_Byte(0x90);
val = val*256 + HDMI_ReadI2C_Byte(0x91);
//printk("\r\nmipi htotal: %d ",val);
msleep(10);
}
#endif
}
void LT8911_LinkTrainRresultDebug(void)
{
u8 i;
u8 val;
HDMI_WriteI2C_Byte(0xff,0xac);
for(i = 0; i< 10; i++)
{
val = HDMI_ReadI2C_Byte(0x82);
if(val & 0x20)
{
if((val & 0x1f)==0x1e)
{
//val = HDMI_ReadI2C_Byte(0x82);
printk("\r\nedp link train successed: %x", val);
}
else{
//val = HDMI_ReadI2C_Byte(0x82);
printk("\r\nedp link train failed: %x", val);
}
val = HDMI_ReadI2C_Byte(0x83);
printk("\r\npanel link rate: %x",val);
val = HDMI_ReadI2C_Byte(0x84);
printk("\r\npanel link count: %x",val);
return;
}
else
printk("\r\nlink trian on going...");
msleep(100);
}
}
//void IntbInterruptFun(void) interrupt 7
//{
// g_irq_flag = 1;
//}
//
//void InterruptTaskHandle(void)
//{
// if(g_irq_flag) // interrupt event happened
// {
// printk("\r\nirq task happened...");
//
// HDMI_WriteI2C_Byte(0xff,0xa8);
// HDMI_WriteI2C_Byte(0x2d,0x84); //edp output idle pattern;
//
// msleep(1500);
// HDMI_WriteI2C_Byte(0xff,0x85); //clr LT
// HDMI_WriteI2C_Byte(0x08,0xc0);
// HDMI_WriteI2C_Byte(0x08,0x00);
//
//
// HDMI_WriteI2C_Byte(0x65,0xff); //vid chk hact clr
// HDMI_WriteI2C_Byte(0x65,0x7f); //vid chk hact clr
//
// HDMI_WriteI2C_Byte(0x07,0xff); //vid chk clr
// HDMI_WriteI2C_Byte(0x07,0x7f); //vid chk clr
//
// edp_idle_flag = 1;
// if(PIF == 0x08) //clear MCU interrupt flag to handle next interrupt request.
// {
// PIF = 0x00;
// clr_IE0;
// }
// g_irq_flag = 0;
// }
//}