背景

  • Platform: RK3399
  • OS: Android7.1.2
  • Kernel: v4.4.103

项目经常会遇到屏供应商屏幕停产,驱动IC升级等问题,如果产品已经量产或出货,软件上就需要考虑新旧屏幕的兼容问题,避免维护多套软件代码。
这里我们遇到了MIPI屏升级驱动IC的情况。

分析

主要思路就是初始化屏幕之前,先读取驱动IC的ID,然后通过不同的ID去使用DTS里面的不同初始化参数,也可以通过读取不同的ID来加载不同的DTS。此方式主要适用于兼容的驱动IC之间,除了初始化参数不同之外,其他参数基本相同的情形。

RK3399的MIPI屏采用的是DRM,panel-simple驱动
需注意的是uboot和内核里面都需要同步修改。

解决

主要路径及文件:

  • kernel:
    路径:kernel/drivers/gpu/drm
    相关文件:panel-simple.c-->drm_mipi_dsi.c->dw-mipi-dsi.c

  • uboot:
    路径:u-boot/drivers/video
    相关文件:rockchip_dsi_panel.c -> rockchip_mipi_dsi.c->rockchip-dw-mipi-dsi

kernel部分修改

panel-simple.c文件修改:

  1. panel_simple_enable函数中添加
    读取ID操作及根据ID发送不同的初始化代码:
    +	/*---- modify start 2020.5.7----*/
    +	/// new/old MIPI LCD, read ID DCh
    +	//mipi_dsi_generic_read(dsi, );
    +	err = mipi_dsi_dcs_read(dsi, 0xDC, &mipi_id3, sizeof(mipi_id3));
    +	if (err <= 0) {	
    +		dev_err(&dsi->dev, "mipi_dsi_dcs_read ID ,error=%d!!\n", err);
    +		return err;
     	}
    +	DBG("mipi_dsi_dcs_read ID=%x\n", mipi_id3);
    +	
    +	if(mipi_id3 == 0x04) //new LCD
    +	{
    +		if (p->on_cmds_new) {
    +			err = panel_simple_dsi_send_cmds(p, p->on_cmds_new);
    +			if (err)
    +				dev_err(p->dev, "failed to send new on cmds\n");
    +		}	
    +	}
    +	else if(mipi_id3 == 0xff)
    +	{
    +		if (p->on_cmds) {
    +			err = panel_simple_dsi_send_cmds(p, p->on_cmds);
    +			if (err)
    +				dev_err(p->dev, "failed to send on cmds\n");
    +		}
    +	}
    +	/*---- modify end 2020.5.7----*/

需要注意读取ID的时机和位置
需要确认dw-mipi-dsi.c中是否支持DCS读操作(MIPI_DSI_DCS_READ),以前的老版本好像是不支持的,需要更新代码

  1. panel_simple_dsi_probe添加获取不同屏的初始化代码:
    +	data = of_get_property(dsi->dev.of_node, "panel-init-sequence-new", &len);
    +	if (data) {
    +		panel->on_cmds_new = devm_kzalloc(&dsi->dev,
    +					      sizeof(*panel->on_cmds_new),
    +					      GFP_KERNEL);
    +		if (!panel->on_cmds_new)
    +			return -ENOMEM;
    +		err = panel_simple_dsi_parse_dcs_cmds(&dsi->dev, data, len,
    +						      panel->on_cmds_new);
    +		if (err) {
    +			dev_err(&dsi->dev, "failed to parse panel init sequence new\n");
    +			return err;
    +		}
    +	}
    +	/*---- modify end 2020.5.13----*/
    +	data = of_get_property(dsi->dev.of_node, "panel-init-sequence-old", &len);

    uboot部分修改

    同kernel类似

扩展

  • MIPI Generic和DCS指令的区别:
    在读/写指令时,Generic指令 是不区分 Index 和 parameter 的,而 DCS 会默认把 data0 作为Index 然后计算 parameter 数目
    mipi_dsi_generic_read/mipi_dsi_generic_write
    mipi_dsi_dcs_read/mipi_dsi_dcs_write/mipi_dsi_dcs_write_buffer

  • DCS commands
    命令的前面三个字节分别表示命令类型、延时和命令净荷长度。从第四个字节开始表示命令的有效 payload

  • 模式
    video mode和command mode
    MIPI_DSI_MODE_LPM MIPI_DSI_MODE_EOT_PACKET
    MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_LPM

  • 硬件排查:

  1. 检查各种供电电压及电平
    VCCIO的电平与reset的电平
  2. 上电时序
    reset的时序,en和reset引脚的控制
  3. cmd发送是否成功,看打印,
  4. 信号完整性
    时钟数据是否有波形,降低时钟试试

参考

https://blog.csdn.net/kris_fei/article/details/79073705
https://blog.csdn.net/kris_fei/article/details/79003925
https://blog.csdn.net/kris_fei/article/details/79099111