diff --git a/layers/meta-unisoc/recipes-kernel/linux/linux-unisoc-5.4/uis7885/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi b/layers/meta-unisoc/recipes-kernel/linux/linux-unisoc-5.4/uis7885/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi --- a/layers/meta-unisoc/recipes-kernel/linux/linux-unisoc-5.4/uis7885/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi +++ b/layers/meta-unisoc/recipes-kernel/linux/linux-unisoc-5.4/uis7885/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi @@ -42,9 +42,9 @@ hfront-porch = <88>; hsync-len = <44>; hback-porch = <148>; - vfront-porch = <56>; - vsync-len = <6>; - vback-porch = <60>; + vfront-porch = <4>; + vsync-len = <5>; + vback-porch = <36>; }; }; }; diff --git a/source/kernel/kernel5.4/arch/arm64/boot/dts/sprd/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi b/source/kernel/kernel5.4/arch/arm64/boot/dts/sprd/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi --- a/source/kernel/kernel5.4/arch/arm64/boot/dts/sprd/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi +++ b/source/kernel/kernel5.4/arch/arm64/boot/dts/sprd/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi @@ -42,9 +42,9 @@ hfront-porch = <88>; hsync-len = <44>; hback-porch = <148>; - vfront-porch = <56>; - vsync-len = <6>; - vback-porch = <60>; + vfront-porch = <4>; + vsync-len = <5>; + vback-porch = <36>; }; }; }; diff --git a/source/bsp/u-boot22/arch/arm/dts/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi b/source/bsp/u-boot22/arch/arm/dts/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi --- a/source/bsp/u-boot22/arch/arm/dts/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi +++ b/source/bsp/u-boot22/arch/arm/dts/lcd/lcd_lt8912b_mipi_hdmi_1080p.dtsi @@ -47,9 +47,9 @@ hfront-porch = <88>; hsync-len = <44>; hback-porch = <148>; - vfront-porch = <56>; + vfront-porch = <38>; vsync-len = <6>; - vback-porch = <60>; + vback-porch = <40>; }; }; }; diff --git a/source/kernel/kernel5.4/drivers/video/LT8912B/src/LT8912B.c b/source/kernel/kernel5.4/drivers/video/LT8912B/src/LT8912B.c --- a/source/kernel/kernel5.4/drivers/video/LT8912B/src/LT8912B.c +++ b/source/kernel/kernel5.4/drivers/video/LT8912B/src/LT8912B.c @@ -9,6 +9,7 @@ u8 Hsync_L, Hsync_H, Vsync_L, Vsync_H; u8 mipi_det_fail_count = 0; u8 mipi_relock_count = 0; +bool mipi_video_ready = 0; bool suspend_on = 0; @@ -24,11 +25,13 @@ struct video_timing video_1280x720_60Hz = {110, 40, 220, 1280, 1650, 5, 5, 20, 720, 750, 1,1, 4, AR_16_9, 74250}; struct video_timing video_1280x800_60Hz = {28, 32, 100, 1280, 1440, 2, 6, 15, 800, 823, 0,0, 0, AR_16_9, 71000}; //struct video_timing video_1920x1080_60Hz = {88, 44, 148, 1920, 2200, 4, 5, 36, 1080, 1125, 1,1,16, AR_16_9, 148500}; -struct video_timing video_1920x1080_60Hz = {88, 44, 148, 1920, 2200, 56, 6, 60, 1080, 1202, 1,1, 0, AR_16_9, 153600}; +struct video_timing video_1920x1080_60Hz = {88, 44, 148, 1920, 2200, 4, 5, 36, 1080, 1125, 1,1,16, AR_16_9, 153600}; struct video_timing *video; -void DDSConfig(void); +void DDSConfig(struct video_timing *video_format); +void HdmiOutput(bool on); +u8 LT8912_Get_HPD(void); void DigitalClockEn(void) { @@ -72,25 +75,66 @@ { u8 VIC = video_format->vic; u8 AR = video_format->aspact_ratio; - u8 pb0,pb2,pb4,Sync_Polarity; + u8 pb0,pb1,pb2,pb4,Sync_Polarity; + u8 pb6, pb7, pb8, pb9, pb10, pb11, pb12, pb13; + u8 checksum; I2CADR = 0x94; HDMI_WriteI2C_Byte(0x3c,0x41); //enable null package Sync_Polarity = (video_format->h_polarity*0x02) + (video_format->v_polarity*0x01); - pb2 = (AR<<4) + 0x08; - pb4 = VIC; - pb0 = (((pb2 + pb4) <= 0x5f)?(0x5f - pb2 - pb4):(0x15f - pb2 - pb4)); + if (video_format->hact == 1920 && video_format->vact == 1080) { + Sync_Polarity = 0x03; + pb1 = 0x1c; + pb2 = 0xa8; + pb4 = 0x10; + pb6 = 0x29; + pb7 = 0x00; + pb8 = 0x61; + pb9 = 0x04; + pb10 = 0xc0; + pb11 = 0x00; + pb12 = 0x40; + pb13 = 0x08; + } else { + pb1 = 0x10; + pb2 = (AR<<4) + 0x08; + pb4 = VIC; + pb6 = 0x00; + pb7 = 0x00; + pb8 = 0x00; + pb9 = 0x00; + pb10 = 0x00; + pb11 = 0x00; + pb12 = 0x00; + pb13 = 0x00; + } + + checksum = 0x82 + 0x02 + 0x0d + pb1 + pb2 + pb4; + checksum += pb6 + pb7 + pb8 + pb9; + checksum += pb10 + pb11 + pb12 + pb13; + pb0 = 0x100 - checksum; I2CADR = 0x90; HDMI_WriteI2C_Byte(0xab,Sync_Polarity); //sync polarity I2CADR = 0x94; HDMI_WriteI2C_Byte(0x43,pb0); //PB0:check sum - HDMI_WriteI2C_Byte(0x44,0x10); //PB1:RGB888 + HDMI_WriteI2C_Byte(0x44,pb1); //PB1 HDMI_WriteI2C_Byte(0x45,pb2); //PB2 HDMI_WriteI2C_Byte(0x46,0x00); //PB3 HDMI_WriteI2C_Byte(0x47,pb4); //PB4:vic + HDMI_WriteI2C_Byte(0x49,pb6); + HDMI_WriteI2C_Byte(0x4a,pb7); + HDMI_WriteI2C_Byte(0x4b,pb8); + HDMI_WriteI2C_Byte(0x4c,pb9); + HDMI_WriteI2C_Byte(0x4d,pb10); + HDMI_WriteI2C_Byte(0x4e,pb11); + HDMI_WriteI2C_Byte(0x4f,pb12); + HDMI_WriteI2C_Byte(0x50,pb13); + printk("%s AviInfoframe %ux%u pb0=0x%02x pb1=0x%02x pb2=0x%02x vic=%u sync=0x%02x\n", + LOG_FLAG, video_format->hact, video_format->vact, + pb0, pb1, pb2, pb4, Sync_Polarity); } void MipiAnalog(void) @@ -128,7 +172,13 @@ void MIPI_Video_Setup(struct video_timing *video_format) { + u8 settle = 0x10; + + if (video_format->vact == 1080) + settle = 0x0a; + I2CADR = 0x92; + HDMI_WriteI2C_Byte(0x11, settle); // settle HDMI_WriteI2C_Byte(0x18,(u8)(video_format->hs%256)); // hwidth HDMI_WriteI2C_Byte(0x19,(u8)(video_format->vs%256)); // vwidth HDMI_WriteI2C_Byte(0x1c,(u8)(video_format->hact%256)); // H_active[7:0] @@ -146,6 +196,10 @@ HDMI_WriteI2C_Byte(0x3d,(u8)(video_format->hbp/256)); // HBP[15:8] HDMI_WriteI2C_Byte(0x3e,(u8)(video_format->hfp%256)); // HFP[7:0] HDMI_WriteI2C_Byte(0x3f,(u8)(video_format->hfp/256)); // HFP[15:8] + printk("%s MIPI_Video_Setup %ux%u total=%ux%u pclk=%u settle=0x%02x vic=%u\n", + LOG_FLAG, video_format->hact, video_format->vact, + video_format->htotal, video_format->vtotal, + video_format->pclk_khz, settle, video_format->vic); video = video_format; } @@ -168,19 +222,26 @@ MipiAnalog(); MipiBasicSet(); - DDSConfig(); + DDSConfig(&video_1920x1080_60Hz); MIPI_Video_Setup(&video_1920x1080_60Hz); AviInfoframe(&video_1920x1080_60Hz); MIPIRxLogicRes(); } -void DDSConfig(void) +void DDSConfig(struct video_timing *video_format) { + u32 dds_word; + + dds_word = (video_format->pclk_khz / 1000) * 0x16C16; + dds_word += ((video_format->pclk_khz % 1000) * 0x16C16 + 500) / 1000; + I2CADR = 0x92; - HDMI_WriteI2C_Byte(0x4e,0x93);//strm_sw_freq_word[ 7: 0] - HDMI_WriteI2C_Byte(0x4f,0x3E);//strm_sw_freq_word[15: 8] - HDMI_WriteI2C_Byte(0x50,0x29);//strm_sw_freq_word[23:16] + HDMI_WriteI2C_Byte(0x4e,(u8)(dds_word & 0xff));//strm_sw_freq_word[ 7: 0] + HDMI_WriteI2C_Byte(0x4f,(u8)((dds_word >> 8) & 0xff));//strm_sw_freq_word[15: 8] + HDMI_WriteI2C_Byte(0x50,(u8)((dds_word >> 16) & 0xff));//strm_sw_freq_word[23:16] HDMI_WriteI2C_Byte(0x51,0x80);//[0]=strm_sw_freq_word[24] + printk("%s DDSConfig pclk=%u kHz word=0x%06x\n", + LOG_FLAG, video_format->pclk_khz, dds_word); HDMI_WriteI2C_Byte(0x1e,0x4f); HDMI_WriteI2C_Byte(0x1f,0x5e);//full_value 464 HDMI_WriteI2C_Byte(0x20,0x01); @@ -231,8 +292,15 @@ I2CADR = 0x94; HDMI_WriteI2C_Byte(0x06,0x08); HDMI_WriteI2C_Byte(0x07,0xF0); - HDMI_WriteI2C_Byte(0x34,0xD2);//0xE2:32FS; 0xD2:64FS + HDMI_WriteI2C_Byte(0x09,0x00); + HDMI_WriteI2C_Byte(0x34,0xE2);//0xE2:32FS; 0xD2:64FS + HDMI_WriteI2C_Byte(0x35,0x00);//N = 6144(0x1800) + HDMI_WriteI2C_Byte(0x36,0x18); + HDMI_WriteI2C_Byte(0x37,0x00); + HDMI_WriteI2C_Byte(0x3c,0x41); + HDMI_WriteI2C_Byte(0x3e,0x0a); HDMI_WriteI2C_Byte(0x0F,0x2B); + printk("%s HDMI audio packet setup: 48k N=0x1800\n", LOG_FLAG); } void AudioSpdifEn(void) @@ -500,11 +568,8 @@ if (mipi_det_fail_count < 0xff) mipi_det_fail_count++; - if (mipi_det_fail_count >= 10 && mipi_relock_count < 5) { - mipi_relock_count++; - mipi_det_fail_count = 0; - LT8912B_MIPI_Relock(); - } + if (mipi_det_fail_count == 10) + printk("%s MIPI input invalid, skip auto relock\n", LOG_FLAG); } else { mipi_det_fail_count = 0; } @@ -525,7 +590,7 @@ video_valid = true; printk("%s videoformat = VESA_1280x800_60\n",LOG_FLAG); } - else if(Vsync_H == 0x04 && Vsync_L <= 0xb6&&Vsync_L >= 0x63)//0x4b2 + else if(Vsync_H == 0x04 && Vsync_L <= 0x67&&Vsync_L >= 0x63)//0x465 { video = &video_1920x1080_60Hz; video_valid = true; @@ -544,9 +609,21 @@ if (video_valid) { mipi_det_fail_count = 0; mipi_relock_count = 0; + mipi_video_ready = 1; + DDSConfig(video); MIPI_Video_Setup(video); AviInfoframe(video); MIPIRxLogicRes(); + + #ifdef _hdmi_output + if (LT8912_Get_HPD() && !Tx_HPD) { + msleep(50); + HdmiOutput(1); + Tx_HPD = 1; + printk("%s HDMI output enabled after valid MIPI video\n", + LOG_FLAG); + } + #endif } } @@ -716,7 +793,7 @@ HDMIPllAnalog(); MipiAnalog(); MipiBasicSet(); - DDSConfig(); + DDSConfig(&video_1920x1080_60Hz); MIPI_Video_Setup(&video_1920x1080_60Hz); MIPI_Input_det(); AudioIIsEn(); @@ -726,7 +803,7 @@ lt8912_check_dds(); // can be removed when debug stage. #endif - #ifdef _lvds_bypass + #ifdef _lvds_output lvds_output_cfg(); LvdsOutput(1); #endif @@ -737,7 +814,7 @@ ///////////////////////////////////////////////////////////// #ifdef _hdmi_output - if(LT8912_Get_HPD()) + if(LT8912_Get_HPD() && mipi_video_ready) { if(!Tx_HPD) { @@ -769,7 +846,7 @@ #ifdef _hdmi_output if(LT8912_Get_HPD()) { - if(!Tx_HPD) + if(mipi_video_ready && !Tx_HPD) { LT8912B_Suspend(0); HdmiOutput(1);