基于 NXP i.MX8QM Bumblebee 智能座舱 HannStar HSD123KPW2 屏幕调试

一. 前言

WPI  i.MX8QM Bumblebee 智能座舱项目需要调试  HSD123KPW2 的屏幕 ,屏幕的接口为 LVDS ,分辨率为 1920 X 720 ,屏幕通过 Serdes 的方式与主板相连 ,主板串行器为 TI DS90UB947 ,屏幕解串器为 TI DS90UB948 ,主板把 LVDS 信号通过 TI DS90UB947 串行器发送给屏幕解串器 DS90UB948 , DS90UB948 输出双 LVDS 信号给屏幕进行显示



                                                                                                             图1 信号数据流程图
  

二. 屏幕调试环境


2.1.  软件环境 :

使用的是 imx-yocto_L4.14.98_0.0.0 


2.2.  硬件环境 :

Bumblebee-MB_V1.0(i.MX8QM 智能座舱)

HSD123KPW2  , 1920 X 720 , 12.3 寸的屏幕


                                 图2 Bumblebee-MB_V1.0



三. 实现 Serdes 数据通信

通过 i2cdetect 工具检查不到 TI947 和 TI948 这两个设备 ,通过电路图发现 :需要使能 LVDS0_VDD1V8 ,LVDS0_VDD_1V1 这两个电平


                                                                                                              图3 DS90UB947 原理图


LVDS0_VDD1V8  对应的  i.MX8QM 芯片引脚是 ESAI0_FST,LVDS0_VDD_1V1 对应的  i.MX8QM 芯片引脚是 ESAI0_FSR ,

                                                        图4 i.MX8QM 芯片引脚图

使能上面两个电压后通过 i2cdetect 工具还是检查不到 DS90UB947 和 DS90UB948 这两个设备 ,通过查看 DS90UB947-Q1 的规格书了解到 :

DS90UB947 有一个 I2CSEL 的引脚 ,I2C 选择为 1.8V ,这个脚需要上拉


                                                                                  图5 TI947 I2CSEL 使用方法


在进行了以上操作后 ,通过 i2cdetect 工具 可以识别到 DS90UB947 和 DS90UB94948 这两个设备

从下图可以知道 DS90UB947 的设备地址为 0X0C
 

                                                 图6 TI947 设备地址

通过读取 DS90UB947 0X06 的地址 ,知道 Des ID 7 位地址为 0X34


                                                                  图7  DS90UB947 0X06 寄存器


                                         图8 DS90UB948 设备地址


四.  驱动程序编写

4.1 DS90UB947 & DS90UB948 寄存器配置

在 kernel-source/drivers/gpu/drm/bridge 路径下添加驱动程序 ti947.c

4.1.1  DS90UB947 I2C WRITE 函数 

struct STi947_config {
    unsigned char ti947_reg;
    unsigned char ti947_data;
};

struct sTI947 {
   struct i2c_client *lvds_i2c;
   struct regmap *lvds_regmap;
   struct drm_bridge bridge;
   struct drm_connector connector;
   struct gpio_desc *reset_gpio;
   bool is_hdmi;
   bool split_mode;
};

static int ti947_write_reg(struct sTI947 *ti947, u8 reg, u8 val) 
{
  struct regmap *regmap = ti947->lvds_regmap;
  int ret;

  ret = regmap_write(regmap, reg, val);
  return ret;
}

4.1.2  DS90UB947 I2C READ 函数 

static int ti947_read_reg(struct sTI947 *ti947, u8 reg)
{
   struct regmap *regmap = ti947->lvds_regmap;
   int ret;
   unsigned int status;

   ret = regmap_read(regmap, reg, &status);
   reg = status;

   return ret;
}

4.1.3   使能 LVDS0_VDD1V8 和 LVDS0_VDD_1V1

#define IMX_GPIO_NR(bank, pin) (480 - (bank * 32) + (pin & 0x1f))
#define LSIO_GPIO2_IO27 IMX_GPIO_NR(2, 27)      /* GPIO2_27 LVDS1_1V1_EN */
#define LSIO_GPIO2_IO28 IMX_GPIO_NR(2, 28)      /* GPIO2_28 LVDS1_1V8_EN */

static void Ti947_StartUp(void)
{
   gpio_request(LSIO_GPIO2_IO27, "gpio2_io27_LVDS1_1V1_EN");
   gpio_direction_output(LSIO_GPIO2_IO27, 1);

   gpio_request(LSIO_GPIO2_IO28, "lsio_gpio2_io28_LVDS1_1V8_EN");
   gpio_direction_output(LSIO_GPIO2_IO28, 1);
}

4.1.4    DS90UB947 初始化函数

static int ti947_init(struct sTI947 *ti947)
{
   int i,num;

   num = ARRAYSIZE(ti947_para);

   for ( i = 0; i< num; i++)
   {
     u8 reg = ti947_para[i].ti947_reg;
     u8 val = ti947_para[i].ti947_data;

     if (ti947_write_reg(ti947,reg,val) < 0)
     {
        printk("ti947_write_reg fail : reg = 0x%02x.\n", reg);
     }
   }
}

4.1.5  注册 DS90UB947 & DS90UB948  I2C 设置

#define LVDS1_TI947_I2C_ADDR  0x0C
#define LVDS1_TI948_I2C_ADDR  0x34

static int ti947_probe(struct i2c_client *client,static int ti947_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    。。。。。。。。。。。。。。。。。。。。。。。。
     ti947->lvds_i2c = i2c_new_dummy(client->adapter , LVDS1_TI947_I2C_ADDR) ;
     
     ti948->lvds_i2c = i2c_new_dummy(client->adapter , LVDS1_TI948_I2C_ADDR);

     Ti947_StartUp();

      ti947_init(ti947); 
}

DS90UB948 I2C 设备初始化可以参考 DS90UB947 部分

4.1.6  DS90UB947 寄存器配置

struct STi947_config ti947_para[] = {
{0x03, 0x9a},
{0x05, 0x04},
{0x1e, 0x01},
{0x07, 0x32},
{0x08, 0x32},
{0x0d, 0x23},
{0x0e, 0x73},
{0x0f, 0x07},
{0x10, 0x33},
{0x11, 0x33},
{0x12, 0x00},
{0x14, 0x04},
{0x17, 0x1e},
{0x30, 0x00},
{0x4f, 0x8c},
{0x54, 0x00},
{0x56, 0x00},
{0x5b, 0x21},
{0x5c, 0x67},
{0x64, 0x70},
{0x65, 0x04},
{0x66, 0x03},
{0x67, 0x02},
{0x6e, 0x20},
{0x70, 0x30},
{0x77, 0x30},
{0x71, 0x94},
{0x78, 0x94},

{0x72, 0x96},
{0x79, 0x96},
{0x73, 0x90},
{0x7a, 0x90}
};

4.1.7  DS90UB948 寄存器配置

struct ti948_config ti948_para[] =
{
 {0x03, 0x78},
 {0x05, 0x1e},
 {0x34, 0x01},
 {0x1d, 0x19},
 {0x1e, 0x39},
 {0x1f, 0x03},
 {0x20, 0x59},
 {0x21, 0x55},
 {0x23, 0x30},
 {0x26, 0x15},
 {0x27, 0x15},
 {0x43, 0x03},
 {0x49, 0xe1},
 {0x64, 0x70},
 {0x65, 0x04},
 {0x66, 0x03},
 {0x67, 0x02}
};

4.2 HannStar HSD123KPW2  屏幕参数配置

我们首先了解一下这块屏的 Timing


                                                                     图9 HSD123KPW2 Timing

根据以上信息 ,我们在 drivers/gpu/drm/panel/panel-simple.c 添加 HSD123KPW2 屏幕参数部分

添加 hannstar_hsd100pxn1_timing :

@@ -977,6 +977,19 @@ static const struct display_timing hannstar_hsd100pxn1_timing = {
.flags = DISPLAY_FLAGS_DE_HIGH,
};

+static const struct display_timing hannstar_hsd123kp2_timing = {
+ .pixelclock = { 55000000, 65000000, 75000000 },
+ .hactive = { 1920, 1920, 1920 },
+ .hfront_porch = { 40, 40, 40 },
+ .hback_porch = { 220, 220, 220 },
+ .hsync_len = { 20, 60, 100 },
+ .vactive = { 720, 720, 720 },
+ .vfront_porch = { 7, 7, 7 },
+ .vback_porch = { 21, 21, 21 },
+ .vsync_len = { 10, 10, 10 },
+ .flags = DISPLAY_FLAGS_DE_HIGH,
+};
+


添加 panel_desc hannstar_hsd100pxn1 关于数据格式信息 :

@@ -988,6 +1001,17 @@ static const struct panel_desc hannstar_hsd100pxn1 = {
.bus_format = MEDIA_BUS_FMT_RGB666_1X7X3_SPWG,
};

+static const struct panel_desc hannstar_hsd123kpw2_timing= {
+ .timings = &hannstar_hsd123kp2_timing,
+ .num_timings = 1,
+ .bpc = 6,
+ .size = {
+ .width = 203,
+ .height = 152,
+ },
+ .bus_format = MEDIA_BUS_FMT_RGB888_1X7X4_SPWG,
+};
+


添加 platform_of_match :

@@ -2049,6 +2073,10 @@ static const struct of_device_id platform_of_match[] = {
.compatible = "hannstar,hsd100pxn1",
.data = &hannstar_hsd100pxn1,
}, {
+ .compatible = "hanstar,hsd123kpw2",
+ .data = &hannstar_hsd123kpw2_timing,
+ }, {
+ }, {
.compatible = "hit,tx23d38vm0caa",
.data = &hitachi_tx23d38vm0caa
}, {


4.3 i.MX8 LVDS 信号输出

修改 /arch/arm64/boot/dts/freescale/fsl-imx8qm-mek.dtsi

+&i2c1_lvds0 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lvds0_lpi2c1_M>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ lvds-to-Panel@4c {
+ compatible = "ti,ti947";
+ reg = <0x4c>;
+
+ port {
+ ti947_0_in: endpoint {
+ clock-lanes = <3>;
+ data-lanes = <0 1 2 4>;
+ remote-endpoint = <&lvds0_out>;
};
};
};
};


+&i2c1_lvds1 {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_lvds1_lpi2c1>;
+ clock-frequency = <100000>;
+ status = "okay";
+
+ lvds-to-hdmi-bridge@4c {
+ compatible = "ti,ti947";
+ reg = <0x4c>;
+
+ port {
+ ti947_1_in: endpoint {
+ clock-lanes = <3>;
+ data-lanes = <0 1 2 4>;
+ remote-endpoint = <&lvds1_out>;
+ };
+ };
+ };
+};
+


添加一个 fsl-imx8qm-mek-hanstar-hsd123kpw2-lvds-panel.dts 文件 :

+++ b/arch/arm64/boot/dts/freescale/fsl-imx8qm-mek-hanstar-hsd123kpw2-lvds-panel.dts
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2017-2018 NXP
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "fsl-imx8qm-mek.dts"
+
+/ {
+ lvds0_panel {
+ compatible = "hanstar,hsd123kpw2";
+ backlight = <&lvds_backlight1>;
+
+ port {
+ panel_lvds0_in: endpoint {
+ remote-endpoint = <&lvds0_out>;
+ };
+ };
+ };
+
+ lvds1_panel {
+ compatible = "hanstar,hsd123kpw2";
+ backlight = <&lvds_backlight1>;
+
+ port {
+ panel_lvds1_in: endpoint {
+ remote-endpoint = <&lvds1_out>;
+ };
+ };
+ };
+
+};
+
+
+&ldb1_phy {
+ status = "okay";
+};
+
+&ldb1 {
+ status = "okay";
+ fsl,dual-channel;
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+
+ port@1 {
+ reg = <1>;
+
+ lvds0_out: endpoint {
+ remote-endpoint = <&panel_lvds0_in>;
+ };
+ };
+ };
+};
+
+&ldb2_phy {
+ status = "disabled";
+};
+
+&ldb2 {
+ status = "disabled";
+ fsl,dual-channel;
+
+ lvds-channel@0 {
+ fsl,data-mapping = "spwg";
+ fsl,data-width = <24>;
+ status = "disabled";
+
+ port@1 {
+ reg = <1>;
+ lvds1_out: endpoint {
+ remote-endpoint = <&panel_lvds1_in>;
+ };
+ };
+ };
+};
+


五. 点亮屏幕

运行 root@imx8qmmek:/opt/viv_samples/vdk# ./tutorial1


                                        图10 三角形画面

运行 root@imx8qmmek:/opt/viv_samples/vdk# ./tutorial2


                                        图11 长方体画面

对 Bumblebee 智能座舱  HSD123KPW2 屏幕进行调试 , 首先是打通 DS90UB947 和 DS90UB948 之间的通信 ,需要使能 1.8V 和 1.1V ,然后是对 I2CSEL PIN 脚进行上拉 ,这样可以打通 DS90UB947 和 DS90UB948 之间的通信 ,接着是对  DS90UB947 和 DS90UB948 进行初始化 ,然后是设置屏的 Timing 和 LVDS 信号输出 ,通过以上内容相信大家已经了解怎样通过 Serdes 的方式调试 LVDS 信号输出的屏幕 


六 参考文档

【1】 DS90UB947-q1.pdf  SNLS454A –NOVEMBER 2014–REVISED MARCH 2019
【2】 DS90UB948-q1.pdf  ZHCSEN7A –OCTOBER 2014–REVISED JANUARY 2016
【3】 HSD123KPW2-A10 Formal Specification 2.0.pdf    DC140-002917    Revision : 2.0

相关视频

【视频博文】基于 NXP i.MX8QM Bumblebee 智能座舱 FPD-LINK 接口 1920x720 屏幕调试

WPI  i.MX8QM Bumblebee 智能座舱项目需要调试  HSD123KPW2 的屏幕 ,屏幕的接口为 LVDS ,分辨率为 1920 X 720 ,

屏幕通过 Serdes 的方式与主板相连 ,主板串行器为 TI DS90UB947 ,屏幕解串器为 TI DS90UB948 ,主板把 LVDS 信号通过 TI DS90UB947 串行器

发送给屏幕解串器 DS90UB948 , DS90UB948 输出双 LVDS 信号给屏幕进行显示

★博文内容均由个人提供,与平台无关,如有违法或侵权,请与网站管理员联系。

★文明上网,请理性发言。内容一周内被举报5次,发文人进小黑屋喔~

评论

enn

enn

2022年3月21日
我目前简单先用的948点亮屏幕,方式采用内部的pattern test,但是写入寄存器之后并没有图形显示
enn

enn

2022年3月21日
您好,想请教您一下关于948上传数据屏幕不会显示的原因可能有哪些?