linuxOS_D21X/source/linux-5.10/drivers/video/lt8911exb/lt8911.c

1028 lines
29 KiB
C
Raw Normal View History

2026-04-02 11:13:49 +00:00
#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<EFBFBD><EFBFBD>37<EFBFBD><EFBFBD>38<EFBFBD><EFBFBD> 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<EFBFBD><EFBFBD>40<EFBFBD><EFBFBD>41<EFBFBD><EFBFBD> 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<EFBFBD><EFBFBD>44<EFBFBD><EFBFBD>45<EFBFBD><EFBFBD> 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<EFBFBD><EFBFBD>47<EFBFBD><EFBFBD>48<EFBFBD><EFBFBD> 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)
{
/***************************
ע<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD>ģʽ
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 )
{
/***************************
ע<EFBFBD><EFBFBD><EFBFBD>С<EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!
<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ĭ<EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><EFBFBD>ģʽ
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;
// }
//}