rv1126/1109平台下的lt8912显示驱动的调试

rv1126/1109平台下的lt8912显示驱动的调试 Eeko 2024-01-09 18:27:38 1219

lt8912显示驱动调试的注意事项

前言

使用的瑞芯微的rv1109的平台,显示接口为MIPI,需要外接LVDS的显示屏,同时外接HDMI显示屏显示。

硬件调试

硬件调试注意事项如下:

  • 检查原理图,确保原理图正确。
  • 检查接口的电平匹配问题,LT8912 io最大支持1.8V,注意电平转换问题(IIC,REST脚)。
  • 检查晶振是否振。
  • IIC不要强上拉,否则会导致IIC通信异常,我在调试时就遇到这个问题。
  • 实际调试中发现接了lt8912的芯片rest脚后,rv1109 对应的gpio 输出低电平时,从波形上看无法到0v的位置,波形比较奇特。但只要符合手册的要求,不显示实际功能。判断rest是否生效,看IIC通信是否正常。
  • 注意这是高速信号,PCB布版时有严格的要求(mipi信号的调试不能飞线进行调试),板的信号问题会影响后续的调试。

强烈建议使用4层板设计,并且注意差分对的阻抗匹配100Ω±10%,差分对间,差分对组间需要做等长。

软件调试

LT8912的配置
首先确认硬件电平是否正确, 查看REST脚是否按时序要求进行操作,手册上要求是拉低10ms再拉高,实际调试中,就用上电复位也是可以工作的。

  • 参考官方代码进行配置,配置很多,就不贴出来了,后面会讲注意事项和如何调试。

  • 代码写好后,在确保IIC通信正常的情况下,先把hdmi的 test pattern 模式设置了,如果能显示如下图,则说明lt8912芯片与硬件焊接基本没问题。

    // Test pattern 1080P 60Hz,其它分辨率的Timing设置请参考Sheet4 
    //I2CADR = 0x92;
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x72, 0x12 );
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x73, 0xc0 );   //RGD_PTN_DE_DLY[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x74, 0x00 );   //RGD_PTN_DE_DLY[11:8]  192
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x75, 0x29 );   //RGD_PTN_DE_TOP[6:0]  41
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x76, 0x80 );   //RGD_PTN_DE_CNT[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x77, 0x38 );   //RGD_PTN_DE_LIN[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x78, 0x47 );   //RGD_PTN_DE_LIN[10:8],RGD_PTN_DE_CNT[11:8]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x79, 0x98 );   //RGD_PTN_H_TOTAL[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x7a, 0x65 );   //RGD_PTN_V_TOTAL[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x7b, 0x48 );   //RGD_PTN_V_TOTAL[10:8],RGD_PTN_H_TOTAL[11:8]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x7c, 0x2c );   //RGD_PTN_HWIDTH[7:0]
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x7d, 0x05 );   //RGD_PTN_HWIDTH[9:8],RGD_PTN_VWIDTH[5:0]

    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x70, 0x80 );
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x71, 0x76 );

    // DDS,148.5M CLK,见Sheet4
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x4e, 0x33 );
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x4f, 0x33 );
    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x50, 0xd3 );

    lt8912b_write_byte(lt8912b_I2C_S_ADDR, 0x51, 0x80 );

这里请注意使用的屏是否支持HDMI。显示效果如下图所示

lt8912参数可能需要修改的地方
因为电路和屏的参数不一样,有些参数按照官方的配置并不能正确工作,需要做一些调整

  • 检查点1,MIPI 信号的PN看是否需要反接
#define _PN_Swap_En        0x20
#define _PN_Swap_Dis    0x00
u8 MIPI_Lane_PN_Swap = _PN_Swap_Dis;
lt8912b_write_byte( lt8912b_I2C_F_ADDR,0x3e, 0x96 + MIPI_Lane_PN_Swap );   // bit5=1: P/N swap ; 0 : Normal
  • 检查点2,设置lane的数量,rv1109 MIPI_Lane 为4
lt8912b_write_byte( lt8912b_I2C_S_ADDR,0x13, MIPI_Lane % 4 );      // 4 lane  // 01 lane // 02 2 lane //03 3lane
  • 检查点3,mipi 的数据通道是否反接,一般硬件不会 所接
lt8912b_write_byte( lt8912b_I2C_S_ADDR,0x15, MIPI_Lane_CH_Swap );  // 00: 0123 normal ; a8 : 3210 swap
  • 检查点4,检查一下屏的多少位的
#define _6_Bit_Color_    0x17
#define _8_Bit_Color_    0x13
lt8912b_write_byte( lt8912b_I2C_F_ADDR,0xa8, LVDS_Map + LVDS_mode + Color_Depth );

关于我使用的屏手册描述Color_Depth 供大家参考

16.2M 是6 bit color ,如果是16.7 M 则是8 bit_color . 关于位数问题,后面有补充。

  • 检查点5 ,查看lt8912的屏的时序配置
const u16    MIPI_Timing[6][8] =
{
    //H_act V_act    H_total V_total H_BP    H_sync    V_sync    V_BP
    { 720,    480,  858,    525,  60,  62,    6, 30 },    // 480P Vesa Timing
    { 1024, 768,  1344, 806,  160, 136, 6, 29 },    // 1024x768
    { 1280, 720,  1650, 750,  220, 40,    5, 20 },    // 720P Vesa Timing
    { 1280, 800,  1440, 823,  80,  32,    6, 14 },    // 1280x800 timing

    { 1024, 600,  1344, 635,  140, 20,    3, 20 },    // 1024x600
//    { 1024, 600,  1274, 645,  80,  10, 10, 23 },    // 1024x600
    { 1920, 1080, 2200, 1125, 148, 44,    5, 36 },    // 1080P  Vesa Timing
//    { 1920, 1200, 2080, 1235, 80,  32, 6,  26 },    // 1920x1200 154MHz Vesa Timing
//    { 1280, 480,  1460, 530,  80,  20, 10, 20 },    // 1280x480
};

信号源MIPI的设置

  • 接下来设置mipi信号 ,test pattern 模式能正常显示并不能说明mipi信号是正确的,因为测试模式没有使用mipi信号做为输入源。
    rv1109 的mipi驱动不用做修改,仅调整一下设备树就可以了,设备树的改法如下所示
&dsi {
    status = "okay";

    // rockchip,lane-rate = <480>;//900
    panel@0 {
        compatible ="simple-panel-dsi";
        reg = <0>;
        backlight = <&backlight>;
        /delete-property/ power-supply;
        prepare-delay-ms = <100>;
        reset-delay-ms = <10>;
        init-delay-ms = <100>;
        disable-delay-ms = <50>;
        unprepare-delay-ms = <20>;

        width-mm = <68>;
        height-mm = <121>;

        pinctrl-names = "default";
        pinctrl-0 = <&vdd_5v_3v3_h>;

        enable-gpios = <&gpio2 RK_PD1 GPIO_ACTIVE_HIGH>;
        reset-gpios  = <&gpio3 RK_PA4 GPIO_ACTIVE_LOW>;

        dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
              MIPI_DSI_MODE_VIDEO_HBP | MIPI_DSI_MODE_LPM |
              MIPI_DSI_MODE_EOT_PACKET)>;

        dsi,format = <MIPI_DSI_FMT_RGB888>;
        dsi,lanes = <4>;

        panel-init-sequence = [
            05 78 01 29
            05 78 01 11
        ];

        display-timings {
            native-mode = <&timing0>;

            timing0: timing0 {
                clock-frequency = <71000000>;
                hactive = <1280>;
                vactive = <800>;
                hback-porch = <80>;
                hfront-porch = <48>;
                vback-porch = <14>;
                vfront-porch = <3>;
                hsync-len = <32>;
                vsync-len = <6>;
                hsync-active = <0>;
                vsync-active = <0>;
                de-active = <0>;
                pixelclk-active = <0>;
            };
        };

        ports {
            #address-cells = <1>;
            #size-cells = <0>;

            port@0 {
                reg = <0>;
                panel_in_dsi: endpoint {
                    remote-endpoint = <&dsi_out_panel>;
                };
            };
        };
    };

    ports {
        #address-cells = <1>;
        #size-cells = <0>;

        port@1 {
            reg = <1>;
            dsi_out_panel: endpoint {
                remote-endpoint = <&panel_in_dsi>;
            };
        };
    };
};

这里要注意的地方:

驱动就使用方自带的驱动,“simple-panel-dsi”
rockchip,lane-rate 如果不知道设置多少,可以把这一行屏蔽,因为驱动中会自动计算速率,代码在dw-mipi-dsi.c中
像我这里设置为480(mipi clk 为240MHZ)就可以了,设置高了如900,mipi的clk为450Mhz,则图像会左右晃动。低了不能工作。
dsi,flags 中的 MIPI_DSI_MODE_VIDEO_HBP 这个设置一定要加上,否则不能显示,后面会说原因。
dsi,flags 中的 MIPI_DSI_MODE_EOT_PACKET 也要加,后面会有波形说明。

static unsigned long dw_mipi_dsi_get_lane_rate(struct dw_mipi_dsi *dsi)
{
    struct device *dev = dsi->dev;
    const struct drm_display_mode *mode = &dsi->mode;
    unsigned long max_lane_rate = dsi->pdata->max_bit_rate_per_lane;
    unsigned long lane_rate;
    unsigned int value;
    int bpp, lanes;
    u64 tmp;

    /* optional override of the desired bandwidth */
    if (!of_property_read_u32(dev->of_node, "rockchip,lane-rate", &value))
        return value * USEC_PER_SEC;

    bpp = mipi_dsi_pixel_format_to_bpp(dsi->format);
    if (bpp < 0)
        bpp = 24;

    lanes = dsi->slave ? dsi->lanes * 2 : dsi->lanes;
    tmp = (u64)mode->clock * 1000 * bpp;
    do_div(tmp, lanes);

    /* take 1 / 0.9, since mbps must big than bandwidth of RGB */
    tmp *= 10;
    do_div(tmp, 9);

    if (tmp > max_lane_rate)
        lane_rate = max_lane_rate;
    else
        lane_rate = tmp;

    return lane_rate;
}

屏的参数如下所示,对应timing0

时序波形分析

  • mipi 的clk信号幅度问题

这个幅值是正确的,注意,因为mipi是差分信号,还要看p,n信号的幅值差,要符合mipi标准。

  • 红色方框波形个数
    从下图中可以看出共23个波形 ,23 是等于 vback-porch + vfront-porch + vsync-len = 14+3+6 =23
            timing0: timing0 {
                clock-frequency = <71000000>;
                hactive = <1280>;
                vactive = <800>;
                hback-porch = <80>;
                hfront-porch = <48>;
                vback-porch = <14>;
                vfront-porch = <3>;
                hsync-len = <32>;
                vsync-len = <6>;
                hsync-active = <0>;
                vsync-active = <0>;
                de-active = <0>;
                pixelclk-active = <0>;
            };
        };

遇到的问题

  • 读lt8912寄存器 0x9c ~ 0x9f 读到的值都是ff ff 00 00

确保MIPI信号已经给到LT8912B之后,再读video check的寄存器。
连续多次读video check寄存器,正常情况下,每次读到的值都是相同的,如果MIPI信号接收不稳定,则读到的值会变化。

  • 读lt8912寄存器 0x0c ~ 0x0f

读(IIC addr:0x92) 0x0c ~ 0x0f 4个寄存器(0x0f寄存器是最高位,一般都是0x00),如果MIPI源发生的信号的pixel clk是148.5M,那么理论上读到的值应该是0x32/0x33/0xD3,允许低位跳动,既是0x0c寄存器值跳动,其它三个寄存器保持稳定,那么就说明成功恢复了pixel clk。
如果pixel clk的值一直不稳定,
1、请确认MIPI源的屏参 和 LT8912B的MIPI timing配置完全相同。
2、关闭MIPI CLK的展频,关闭EOTP。

  • EOTP 的关闭
dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
              MIPI_DSI_MODE_VIDEO_HBP | MIPI_DSI_MODE_LPM |
              MIPI_DSI_MODE_EOT_PACKET)>;

加上MIPI_DSI_MODE_EOT_PACKET 就是关闭EOT
查看EOT是否配置生效,可以使用如下命令
io -4 0xffb3002c
0xffb3002c 寄存器的值为 0x1c

说明已经关闭了。
eopt的信号见下图

这里会出现交互变化的过程,如果一直是高,或者一直是低,则表示eopt 没有关闭,注意高低变化不是按顺序出现,可能相邻的都是高,后面才变低。

  • 每个采样周期里面不能出现2个LP

上图这种波形是错误的,需要修改dsi,flags 的配置
2023-3-30 补充 关于6 bit 与 8bit 解释

那16.2M表示屏是6bit还是8bit,
抖动的实现原理是,如果要显示的颜色,不在真实能显示的颜色中,就用最近的两个颜色,用散点进行混合
用灰度来举例,有0,1,2,,,255一共256级灰度,8bit面板对每种灰度都可以完整表现。而6bit只能显示0,4,8,12,,,,252。这64级,如果要显示比如灰度为2的色块,就只能用0灰度和4灰度各50%的颜色点来混合形成。
于是,大块的色块就都一样,但是小的色块6bit就不行。
6Bit 则是253的3次方=16194277
8Bit 则是256的3次方=16777216
用6Bit 显示256灰阶,会造成色彩空间 3.5%的loss。

后面在处理屏亮度问题时

&backlight {
    compatible = "pwm-backlight";
    pwms = <&pwm0 0 5000000 0>;
    ......
    }

把屏的背光pwm调到屏规格推荐的200HZ, 占空比调到最大,屏的亮度还是不够(单纯调试pwm无效)。
后面检查屏的驱动发现 关于6bit 与8bit的配置有问题,要改成8bit

见 6+2bit color depth 这一行信息,修改后屏的显示亮度变亮。

声明:本文内容由易百纳平台入驻作者撰写,文章观点仅代表作者本人,不代表易百纳立场。如有内容侵权或者其他问题,请联系本站进行删除。
Eeko
红包 1 1 评论 打赏
评论
0个
内容存在敏感词
手气红包
    易百纳技术社区暂无数据
相关专栏
置顶时间设置
结束时间
删除原因
  • 广告/SPAM
  • 恶意灌水
  • 违规内容
  • 文不对题
  • 重复发帖
打赏作者
易百纳技术社区
Eeko
您的支持将鼓励我继续创作!
打赏金额:
¥1易百纳技术社区
¥5易百纳技术社区
¥10易百纳技术社区
¥50易百纳技术社区
¥100易百纳技术社区
支付方式:
微信支付
支付宝支付
易百纳技术社区微信支付
易百纳技术社区
打赏成功!

感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~

举报反馈

举报类型

  • 内容涉黄/赌/毒
  • 内容侵权/抄袭
  • 政治相关
  • 涉嫌广告
  • 侮辱谩骂
  • 其他

详细说明

审核成功

发布时间设置
发布时间:
是否关联周任务-专栏模块

审核失败

失败原因
备注
拼手气红包 红包规则
祝福语
恭喜发财,大吉大利!
红包金额
红包最小金额不能低于5元
红包数量
红包数量范围10~50个
余额支付
当前余额:
可前往问答、专栏板块获取收益 去获取
取 消 确 定

小包子的红包

恭喜发财,大吉大利

已领取20/40,共1.6元 红包规则

    易百纳技术社区