天天看點

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

目錄

    1. 平台環境及驗證工具

      1.1 軟體環境

      1.2 硬體環境

    1. libdrm 移植
    1. DRM 元件探測
    1. HDMI圖像顯示調試流程

      4.1 故障定位過程

      4.1.1 modetest 比對 connector 分辨率失敗

      4.1.2 DRM connector HDMI 注冊失敗

      4.1.3 HDMI 驅動初始化錯誤

      4.1.4 擷取 HDMI EDID 失敗

      4.1.5 Invalid crtc for plane錯誤

      4.1.6 atomic driver check failed錯誤

    1. 圖像輸出結果
    1. 熱插拔結果
    1. 故障彙總及解決流程
    1. HDMI 調試方法
    1. 總結
  • 附錄

    i2c-tools移植

    下載下傳位址

    說明文檔

    交叉編譯

1. 平台環境及驗證工具

1.1 軟體環境

U-Boot 版本
U-Boot 2017.11 (Jun 16 2020 - 18:06:57 +0800) for itop-4412
           
kernel 版本
[[email protected]]# uname -r
4.14.2
[[email protected]]#
           

驗證工具

libdrm

1.2 硬體環境

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄
kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

2. libdrm 移植

libdrm 版本

1 #! /bin/sh
    2 # Guess values for system-dependent variables and create Makefiles.
    3 # Generated by GNU Autoconf 2.69 for libdrm 2.4.100.
    4 #
    5 # Report bugs to <https://bugs.freedesktop.org/enter_bug.cgi?product=DRI>.
           

編譯

通過直接配置 Makefile 來規定交叉編譯方式

./configure CC=/usr/local/arm/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro-toolchain/bin/arm-none-linux-gnueabi-gcc --enable-static --host=arm --prefix=$HOME

make

make install
           

将./test/modetest/modetest 拷貝到根檔案系統的/usr/bin,重新燒錄檔案系統,再次啟動加載核心,執行 modetest,結果如下,說明移植成功。

[[email protected]]# modetest -help
usage: modetest [-acDdefMPpsCvw]

 Query options:

        -c      list connectors
        -e      list encoders
        -f      list framebuffers
        -p      list CRTCs and planes (pipes)

 Test options:

        -P <plane_id>@<crtc_id>:<w>x<h>[+<x>+<y>][*<scale>][@<format>]  set a plane
        -s <connector_id>[,<connector_id>][@<crtc_id>]:<mode>[-<vrefresh>][@<format>]   set a mode
        -C      test hw cursor
        -v      test vsynced page flipping
        -w <obj_id>:<prop_name>:<value> set property
        -a      use atomic API
        -F pattern1,pattern2    specify fill patterns

 Generic options:

        -d      drop master after mode set
        -M module       use the given driver
        -D device       use the given device

        Default is to dump all info.
[[email protected]]#
           

3. DRM 元件探測

執行 modetest,預設打開 exynos DRM 裝置,各 DRM 元件均探測到,說明 DRM 系統已完成加載。

結果如下:

[[email protected]]# modetest
...
trying to open device 'exynos'...done
Encoders:
id      crtc    type    possible crtcs  possible clones
43      42      TMDS    0x00000001      0x00000000

Connectors:
id      encoder status          name            size (mm)       modes   encoders
44      43      connected       VGA-1           0x0             1       43
...

CRTCs:
id      fb      pos     size
42      47      (0,0)   (480x272)
...

Planes:
id      crtc    fb      CRTC x,y        x,y     gamma size      possible crtcs
27      42      47      0,0             0,0     0               0x00000001
...

Frame buffers:
id      size    pitch
[[email protected]]#
           

4. HDMI 圖像顯示調試流程

檢視探測出的各 DRM 元件 ID,使用 modetest 驗證 HDMI

modetest -M exynos -D 0 -a -s [email protected]:1024x600  -P [email protected]:1024x600 -Ftiles
           

結果:

螢幕沒有點亮,modetest 列印輸出如下:

[[email protected]]# modetest -M exynos -D 0 -a -s [email protected]:1024x600  -P [email protected]:1024x60
0 -Ftiles
failed to find mode "1024x600" for connector 44
Enter modetest.c main 2103
Enter modetest.c atomic_set_planes 1331 primary_fill val 0
failed to set gamma: Function not implemented
Enter modetest.c atomic_set_plane 1144
testing [email protected] on plane 27, crtc 42
Enter modetest.c atomic_set_plane 1170
Enter buffers.c bo_create 137 pattern 0
buffers.c bo_create bo_map addr 0xb6b42000
Enter pattern.c util_fill_pattern 1265 pattern 0
format val 0x34325258
Enter pattern.c fill_tiles_rgb32 966
Enter width: 1024 height: 600 stride: 4096
pattern.c fill_tiles_rgb32 968 mem_s_addr:0xb6b42000
           

4.1 故障定位過程

4.1.1 modetest 比對 connector 分辨率失敗

在 modetest 大列印資訊中,存在下面的内容,提示 connector 的分辨率不支援 1024x600。

電路闆加載 3.0 核心時可以點亮螢幕,是以,基本排除硬體原因。

檢視到上面的 failed 資訊,來自于 modetest.c 中的 pipe_find_crtc_and_mode(),由于未正确擷取到 connector mode 導緻。

static int pipe_find_crtc_and_mode(struct device *dev, struct pipe_arg *pipe)
{
		drmModeModeInfo *mode = NULL;
		int i;

		pipe->mode = NULL;

		for (i = 0; i < (int)pipe->num_cons; i++) {
			mode = connector_find_mode(dev, pipe->con_ids[i],
						   pipe->mode_str, pipe->vrefresh);
			if (mode == NULL) {
				fprintf(stderr,
					  "failed to find mode \"%s\" for connector %s\n",
					  pipe->mode_str, pipe->cons[i]);
				return -EINVAL;
			}
		}

		...
}
           

connector_find_mode()主要是圍繞 connector 的 name 來進行 mode 查詢的。

下面是位于 modetest.c 中的 connector_find_mode()代碼

```cpp
static drmModeModeInfo *
connector_find_mode(struct device *dev, uint32_t con_id, const char *mode_str,
        const unsigned int vrefresh)
{
 ...

	connector = get_connector_by_id(dev, con_id);
	if (!connector || !connector->count_modes)
		return NULL;

	for (i = 0; i < connector->count_modes; i++) {
		mode = &connector->modes[i];
		if (!strcmp(mode->name, mode_str)) {
    ...
			if (vrefresh == 0)
				return mode;
			else if (mode->vrefresh == vrefresh)
				return mode;
		}
	}

	return NULL;
}
           

回過頭再看 connector 的 name,顯示的是 VGA-1,而我們連接配接的是 HDMI 螢幕,顯然不正确。

Connectors:
id      encoder status          name            size (mm)       modes   encoders
44      43      connected       VGA-1           0x0             1       43
           

connector 的 name 是 DRM connector 初始化時指定的。

int drm_connector_init(struct drm_device *dev,
		       struct drm_connector *connector,
		       const struct drm_connector_funcs *funcs,
		       int connector_type)
{
 ...
	connector->name =
		kasprintf(GFP_KERNEL, "%s-%d",
			  drm_connector_enum_list[connector_type].name,
			  connector->connector_type_id);
	if (!connector->name) {
		ret = -ENOMEM;
		goto out_put_type_id;
	}
 ...
}
           

drm_connector_enum_list 是系統支援的 connector 裝置類型

static struct drm_conn_prop_enum_list drm_connector_enum_list[] = {
	{ DRM_MODE_CONNECTOR_Unknown, "Unknown" },
	{ DRM_MODE_CONNECTOR_VGA, "VGA" },
	{ DRM_MODE_CONNECTOR_DVII, "DVI-I" },
	{ DRM_MODE_CONNECTOR_DVID, "DVI-D" },
	{ DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
	{ DRM_MODE_CONNECTOR_Composite, "Composite" },
	{ DRM_MODE_CONNECTOR_SVIDEO, "SVIDEO" },
	{ DRM_MODE_CONNECTOR_LVDS, "LVDS" },
	{ DRM_MODE_CONNECTOR_Component, "Component" },
	{ DRM_MODE_CONNECTOR_9PinDIN, "DIN" },
	{ DRM_MODE_CONNECTOR_DisplayPort, "DP" },
	{ DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
	{ DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
	{ DRM_MODE_CONNECTOR_TV, "TV" },
	{ DRM_MODE_CONNECTOR_eDP, "eDP" },
	{ DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
	{ DRM_MODE_CONNECTOR_DSI, "DSI" },
	{ DRM_MODE_CONNECTOR_DPI, "DPI" },
};
           

在 connector 裝置初始化時指定類型名字,itop 裝置樹使能了 fimd,connector 預設為 VGA

static int exynos_dpi_create_connector(struct drm_encoder *encoder)
{
 ...
	ret = drm_connector_init(encoder->dev, connector,
				 &exynos_dpi_connector_funcs,
				 DRM_MODE_CONNECTOR_VGA);
	if (ret) {
		DRM_ERROR("failed to initialize connector with drm\n");
		return ret;
	}
 ...
}
           

檢視 DRM 系統注冊出的 connector,發現隻有 VGA-A,沒有 HDMI。

[[email protected]]# ls /sys/devices/platform/exynos-drm/drm/card0/
card0-VGA-1  dev          device       power        subsystem    uevent
           
是以,modetest 比對 connector 分辨率失敗的原因是未注冊 DRM connector HDMI,進而無法找到待比對的分辨率模式表導緻。

4.1.2 DRM connector HDMI 注冊失敗

首先檢視 HDMI 裝置樹結點,結點狀态為 disabled,顯然不正确。

[[email protected]]# cat /sys/firmware/devicetree/base/[email protected]/status
disabled[[email protected]]#

[[email protected]]# cat /sys/devices/platform/12d00000.hdmi/of_node/status
disabled[[email protected]]#
[[email protected]]#
           

exynos4.dtsi 中定義了 HDMI 裝置樹結點,但裝置樹結點狀态為 disabled。

hdmi: [email protected] {
	compatible = "samsung,exynos4210-hdmi";
 ...
	status = "disabled";
};
           

是以,在 exynos4412-itop-elite.dts"增加 hdmi 附加結點,将結點狀态設定為 okay。

&hdmi {
        status = "okay";
};
           

系統重新加載裝置樹之後,HDMI 結點狀态已為 okay,但使用 modetest 檢視 connector 時,依然沒有注冊出 HDMI。

裝置樹結點狀态正确,回頭 dmesg 檢視 HDMI 的初始化過程,發現初始化過程錯誤退出,而這個錯誤退出位于 component_add()之前,是以也就無法完成 DRM connector 的注冊。

[    1.856555] [drm:hdmi_probe] *ERROR* cannot get hpd gpio property
[    1.861171] [drm:hdmi_probe] *ERROR* hdmi_resources_init failed
[    1.867268] exynos-hdmi: probe of 12d00000.hdmi failed with error -2
           
connector HDMI 未注冊的原因是驅動初始化錯誤導緻

4.1.3 HDMI 驅動初始化錯誤

HDMI 初始化過程中,提示無法找到用于 HDMI 熱插拔功能的 hpd。

擷取 hpd 的代碼如下,從代碼中可以看出是從裝置樹中解析出用于熱插拔的 GPIO

static int hdmi_resources_init(struct hdmi_context *hdata)
{
 ...
	hdata->hpd_gpio = devm_gpiod_get(dev, "hpd", GPIOD_IN);
	if (IS_ERR(hdata->hpd_gpio)) {
		DRM_ERROR("cannot get hpd gpio property\n");
		return PTR_ERR(hdata->hpd_gpio);
	}
 ...
}
           

在 exynos4.dtsi 的 HDMI 裝置樹結點中沒有定義 hpd,是以,結合原理圖,在裝置樹檔案 exynos4412-itop-elite.dts 中增加 hpd 屬性

&hdmi {
        hpd-gpios = <&gpx3 7 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&hdmi_hpd>;
        vdd-supply = <&ldo8_reg>;
        vdd_osc-supply = <&ldo10_reg>;
        vdd_pll-supply = <&ldo8_reg>;
        status = "okay";
};
           

系統重新開機加載新裝置樹之後,已經可以解析 hpd。

但是依然報錯,錯誤如下:

[    1.863752] [drm] Failed to get ddc i2c adapter by node
           

錯誤資訊中提示未找到 i2c,檢視 exynos4412 資料手冊發現 HDMI 内部沒有 DDC 通道,使用 CPU 的 i2c 作為 DDC 來進行外部通訊。

檢視 iTOP 原理圖發現 HDMI 使用了 i2c_0,而裝置樹中 i2c_0 結點狀态為 disabled。

在 exynos4412-itop-elite.dts 将 i2c_0 狀态修改為 okay。

&i2c_0 {
	status = "okay";
};
           

i2c_0 使能之後,已經正确識别 i2c adapter

但是依然報錯,錯誤如下:

[    1.874641] [drm] Failed to get hdmi phy i2c client
           

錯誤的列印資訊來自于 hdmi_get_phy_io(),代碼如下,

static int hdmi_get_phy_io(struct hdmi_context *hdata)
{
 ...

	if (hdata->drv_data->is_apb_phy) {
		...
	} else {
		hdata->hdmiphy_port = of_find_i2c_device_by_node(np);
		if (!hdata->hdmiphy_port) {
			DRM_INFO("Failed to get hdmi phy i2c client\n");
			ret = -EPROBE_DEFER;
			goto out;
		}
	}
 ...
}
           

exynos4412 的 HDMI 内部內建 PHY,通過 i2c_8 來配置 PHY 的寄存器配置,檢視 exynos4.dtsi 裝置樹的 i2c_8 結點狀态為 disabled。

在 exynos4412-itop-elite.dts 将 i2c_8 狀态修改為 okay。

&i2c_8 {
         status = "okay";
};
           

i2c_8 使能之後,HDMI 初始化通過,再次執行 modetest,可以看到已注冊 connector HDMI-A-1

[[email protected]]# modetest
...
trying to open device 'exynos'...done
...
Connectors:
id      encoder status          name            size (mm)       modes   encoders
44      43      connected       VGA-1           0x0             1       43
...
56      0       connected       HDMI-A-1        0x0             0       55
...
           
connector HDMI 未注冊的原因是驅動初始化過程中與裝置樹相關的錯誤導緻
    1. 未在 pinctrl 中指定 HDMI 用于熱插拔的 GPIO
    1. 未使能 HDMI 用于外部通訊的 I2C0
    1. 未使能 HDMI 用于配置 PHY 的 I2C8

但是,modetest 比對 connector 分辨率依然失敗。

重新檢視 modetest 探測的 DRM 資訊,發現未擷取到 HDMI EDID 資訊。

[[email protected]]# modetest
...
56      0       connected       HDMI-A-1        0x0             0       55
...
props:
        1 EDID:
                flags: immutable blob
                blobs:

                value:
           

4.1.4 擷取 HDMI EDID 失敗

檢視核心列印資訊,發現下面的 log 資訊,提示不存在 i2c adapter。

[  133.348462] [drm:drm_helper_probe_single_connector_modes] [CONNECTOR:38:HDMI-A-1]
[  133.348642] [drm:drm_do_probe_ddc_edid] drm: skipping non-existent adapter s3c2410-i2c
           

函數 drm_do_probe_ddc_edid()的函數定義在 drivers/gpu/drm/drm_edid.c 中,通過調用 i2c 驅動代碼來讀出 128Bytes 的 EDID 資訊。

static int
drm_do_probe_ddc_edid(void *data, u8 *buf, unsigned int block, size_t len)
{
			struct i2c_adapter *adapter = data;
			unsigned char start = block * EDID_LENGTH;
			unsigned char segment = block >> 1;
			unsigned char xfers = segment ? 3 : 2;
			int ret, retries = 5;

			do {
				struct i2c_msg msgs[] = {
					{
						.addr	= DDC_SEGMENT_ADDR,
						.flags	= 0,
						.len	= 1,
						.buf	= &segment,
					}, {
						.addr	= DDC_ADDR,
						.flags	= 0,
						.len	= 1,
						.buf	= &start,
					}, {
						.addr	= DDC_ADDR,
						.flags	= I2C_M_RD,
						.len	= len,
						.buf	= buf,
					}
				};

				ret = i2c_transfer(adapter, &msgs[3 - xfers], xfers);

				if (ret == -ENXIO) {
					DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",
							adapter->name);
					break;
				}
			} while (ret != xfers && --retries);

			return ret == xfers ? 0 : -1;
}
           

由于 exynos4412 的 HDMI DDC 通道是通過 CPU 的 i2c_0 來實作的。是以,在 HDMI 驅動中不需要單獨注冊 i2c adapter 的功能函數。僅需要查找到 HDMI 所對應的 i2c adapter 即可。

通過 hdmi_get_ddc_adapter()來擷取 i2c adapter。

static int hdmi_get_ddc_adapter(struct hdmi_context *hdata)
{
	const char *compatible_str = "samsung,exynos4210-hdmiddc";
	struct device_node *np;
	struct i2c_adapter *adpt;

	np = of_find_compatible_node(NULL, NULL, compatible_str);
	if (np)
		np = of_get_next_parent(np);
	else
		np = of_parse_phandle(hdata->dev->of_node, "ddc", 0);

	if (!np) {
		DRM_ERROR("Failed to find ddc node in device tree\n");
		return -ENODEV;
	}

	adpt = of_find_i2c_adapter_by_node(np);
	of_node_put(np);

	if (!adpt) {
		DRM_INFO("Failed to get ddc i2c adapter by node\n");
		return -EPROBE_DEFER;
	}

	hdata->ddc_adpt = adpt;

	return 0;
}
           

驅動在執行上面函數時并未報錯,驅動代碼層面基本沒有什麼問題。

使用 i2c-tools 單獨驗證 i2c0 資料通路是否正常,由于加載的檔案系統中并沒有 i2c-tools 這個工具,是以需要移植一個。

i2c-tools 移植見附錄

使用 i2cdetect -l 檢視注冊出來的 i2c 總線包括了 i2c0。

[[email protected]]# i2cdetect -l
i2c-0   i2c             s3c2410-i2c                             I2C adapter
i2c-1   i2c             s3c2410-i2c                             I2C adapter
i2c-3   i2c             s3c2410-i2c                             I2C adapter
i2c-4   i2c             s3c2410-i2c                             I2C adapter
i2c-7   i2c             s3c2410-i2c                             I2C adapter
           

檢視 i2c0 下未挂載任何裝置。

[[email protected]]# i2cdetect -r -y 7
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
           

而 HDMI 規範中描述在 i2c slave addr 0x50 處應為顯示裝置。i2c_0 裝置樹結點也定義了 slave addr。

&i2c_0 {
        status = "okay";

        samsung,i2c-sda-delay = <100>;
        samsung,i2c-max-bus-freq = <66000>;
        samsung,i2c-slave-addr = <0x50>;
};
           

使用示波器測量電平轉換晶片前端的 i2c_scl\sda,有信号,電平轉換晶片後端 i2c 沒信号

![](https://img-blog.csdnimg.cn/img_convert/6bfd94e71800bb8783fd1c539a70d021.png

測量上圖中 HDMI_IIC_EN 信号為低。檢視電平轉換晶片資料手冊,該信号不應該為低。

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

HDMI_IIC_EN 在核心闆原理圖中對應 GPL0_6

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

GPL0_6 應該通過 pinctrl 子系統來控制,配置其電平狀态為高。添加 gpl0_6 的 pinctrl 相關的裝置樹代碼,如下:

hdmi_iic_en: hdmi-iic-en {
        samsung,pins = "gpl0-6";
        samsung,pin-function = <EXYNOS_PIN_FUNC_OUTPUT>;
        samsung,pin-pud = <EXYNOS_PIN_PULL_UP>;
        samsung,pin-val = <1>;
};
           

重新啟動系統加載新裝置樹,再次使用 i2cdetect 檢視 i2c0 的 0x50 處已經有裝置了。

[ro[email protected]]# i2cdetect -y -r 0
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:                         -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- 37 -- -- 3a -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- 4a 4b -- -- -- --
50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
           

再次使用 modetest 探測 DRM connector HDMI 的 EDID,成功擷取到 EDID 資訊,如下:

Connectors:
id      encoder status          name            size (mm)       modes   encoders
38      37      connected       HDMI-A-1        470x260         15      37
  modes:
        name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot)
  1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver
  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 74250 flags: phsync, pvsync, interlace; type: driver
  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 74176 flags: phsync, pvsync, interlace; type: driver
  1920x1080 50 1920 2448 2492 2640 1080 1084 1089 1125 148500 flags: phsync, pvsync; type: driver
  1920x1080i 50 1920 2448 2492 2640 1080 1084 1094 1125 74250 flags: phsync, pvsync, interlace; type: driver
  1280x720 60 1280 1390 1430 1650 720 725 730 750 74250 flags: phsync, pvsync; type: driver
  1280x720 60 1280 1390 1430 1650 720 725 730 750 74176 flags: phsync, pvsync; type: driver
  1280x720 50 1280 1720 1760 1980 720 725 730 750 74250 flags: phsync, pvsync; type: driver
  1024x768 60 1024 1048 1184 1344 768 771 777 806 65000 flags: nhsync, nvsync; type: driver
  800x600 60 800 840 968 1056 600 601 605 628 40000 flags: phsync, pvsync; type: driver
  800x600 56 800 824 896 1024 600 601 603 625 36000 flags: phsync, pvsync; type: driver
  720x576 50 720 732 796 864 576 581 586 625 27000 flags: nhsync, nvsync; type: driver
  720x480 60 720 736 798 858 480 489 495 525 27027 flags: nhsync, nvsync; type: driver
  720x480 60 720 736 798 858 480 489 495 525 27000 flags: nhsync, nvsync; type: driver
  640x480 60 640 656 752 800 480 490 492 525 25200 flags: nhsync, nvsync; type: driver
  props:
        1 EDID:
                flags: immutable blob
                blobs:

                value:
                        00ffffffffffff0012e50021502d3101
                        1c130103812f1a782e3585a656489a24
                        125054afef0001010101010101010101
                        010101010101a1130040415819202c58
                        3600dc0c1100001a000000ff00300a0a
                        0a0a0a0a0a0a0a0a0a0a000000fd0038
                        4b1e5315000a202020202020000000fc
                        0048444d490a0a0a0a0a0a0a0a0a01f9
                        020321714e0607020315961112130414
                        051f90230907078301000065030c0010
                        008c0ad090204031200c405500b98821
                        000018011d8018711c1620582c2500b9
                        882100009e011d80d0721c1620102c25
                        80b9882100009e011d00bc52d01e20b8
                        285540b9882100001e023a80d072382d
                        40102c4580b9882100001e00000000d0
           

擷取 HDMI EDID 失敗的原因是 I2C 不通導緻

iTOP 的 HDMI 使用外部的 i2c 總線作為 DDC 通道,是以需要經過電平轉換晶片。該晶片通過 CPU GPIO 來控制使能狀态,但 kernel 代碼中并沒有這一部分 pinctrl 裝置樹代碼,是以電平轉換晶片未工作導緻 i2c 不通,進而無法擷取到 EDID。

擷取到 EDID 後,利用 modetest 來驗證 HDMI 圖像輸出,螢幕依然無法點亮。

modetest 提示的錯誤資訊是"Atomic Commit failed"。

dmesg 提示的錯誤資訊是"Invalid crtc for plane"

[  585.393299] [drm:drm_atomic_check_only] checking ef1bdc80
[  585.393306] [drm:drm_atomic_check_only] Invalid crtc for plane
[  585.393314] [drm:drm_atomic_check_only] [PLANE:27:plane-0] atomic core check failed
           

4.1.5 Invalid crtc for plane 錯誤

檢視 modetest 探測出來的 DRM connector 元件,發現有兩個,一個是 HDMI 另外一個是 VGA-1,而 VGA-1 通過檢視代碼是 fimd 注冊出來的。

懷疑是 fimd 與 vop 同時存在有沖突,嘗試關掉 fimd。修改裝置樹檔案 exynos4412-itop-elite.dts,将 fimd 的 status 設定為 disabled。

&fimd {
        pinctrl-0 = <&lcd_clk &lcd_data24>;
        pinctrl-names = "default";
        status = "disabled";
        samsung,invert-vclk;
        ...
};
           

fimd 和 HDMI 所在的 mixer 屬兩個圖形圖像處理單元

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄
kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

重新啟動系統加載新裝置樹,再次執行 modetest 發現"Invalid crtc for plane"已經被消掉。

"Invalid crtc for plane"的原因是 fimd 和 mixer 不應該同時存在導緻

但螢幕沒有被點亮。

檢視 dmesg 資訊,提示"atomic driver check failed"

[   56.351044] [drm:exynos_plane_atomic_check] plane : offset_x/y(0,0), width/height(800,600)
[   56.351056] [drm:mixer_atomic_check] xres=800, yres=600, refresh=60, intl=0
[   56.351064] [drm:drm_atomic_helper_check_planes] [CRTC:36:crtc-0] atomic driver check failed
           

4.1.6 atomic driver check failed 錯誤

這個錯誤的列印資訊來自于 drm_atomic_helper_check_planes(),但實際是 mixer_atomic_check()異常退出引起。在 mixer_atomic_check()函數中有分辨率的限制。而 modetest 給定的分辨率參數不符合要求。

modetest -M exynos -D 0 -a -s [email protected]:800x600  -P [email protected]:800x600 -Ftiles
           
static int mixer_atomic_check(struct exynos_drm_crtc *crtc,
		       struct drm_crtc_state *state)
{
	struct drm_display_mode *mode = &state->adjusted_mode;
	u32 w, h;

	w = mode->hdisplay;
	h = mode->vdisplay;

	DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n",
		mode->hdisplay, mode->vdisplay, mode->vrefresh,
		(mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0);

	if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) ||
		(w >= 1024 && w <= 1280 && h >= 576 && h <= 720) ||
		(w >= 1664 && w <= 1920 && h >= 936 && h <= 1080))
		return 0;

	return -EINVAL;
}
           
"atomic driver check failed"的原因是 modetest 給的的分辨率參數不符合 mixer 要求

按照 mixer 要求,modetest 參數改成下面這樣,驗證通過。

modetest -M exynos -D 0 -a -s [email protected]:1280x720  -P [email protected]:1280x720 -Ftiles
           

5. 圖像輸出結果

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

6. 熱插拔結果

以下兩種驗證方式,螢幕可以恢複圖像顯示

  • 拔插 HDMI 連接配接線
  • 螢幕上下電

7. 故障彙總及解決流程

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

8. HDMI 調試方法

HDMI 調試方法

中斷
/proc/irq/119/hdmi

裝置樹of_node
/sys/devices/platform/12d00000.hdmi
/sys/devices/platform/13870000.i2c/i2c-1/1-0066/s5m8767-pmic/regulator/regulator.5/12d00000.hdmi-vdd_osc
/sys/devices/platform/13870000.i2c/i2c-1/1-0066/s5m8767-pmic/regulator/regulator.3/12d00000.hdmi-vdd_pll
/sys/devices/platform/13870000.i2c/i2c-1/1-0066/s5m8767-pmic/regulator/regulator.3/12d00000.hdmi-vdd

裝置樹EDT
/sys/firmware/devicetree/base/[email protected]
/sys/firmware/devicetree/base/[email protected]/[email protected]
/sys/firmware/devicetree/base/[email protected]/hdmi-phandle
/sys/firmware/devicetree/base/[email protected]/hdmi-cec
/sys/firmware/devicetree/base/[email protected]/hdmi-hpd

驅動
/sys/bus/platform/devices/12d00000.hdmi
/sys/bus/platform/drivers/exynos-hdmi
/sys/bus/platform/drivers/exynos-hdmi/12d00000.hdmi

DDC相關
/proc/irq/53/13860000.i2c
/sys/devices/platform/13860000.i2c
/sys/bus/platform/devices/13860000.i2c
/sys/bus/platform/drivers/s3c-i2c/13860000.i2c
           

DRM 有關的調試方法

echo 0xf > /sys/module/drm/parameters/debug
modetest
dmesg
           

9. 總結

exynos4412的HDMI遵循1.4協定,支援i2s和spdif兩種音頻接口。通過mixer将視訊資料發送給HDMI控制器。内部內建的PHY子產品使用CPU I2C總線來配置。

HDMI内部組成如下:

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

HDMI子系統組成如下:

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

基于上面的框圖,需要的驅動包括:

    1. mixer驅動
    1. HDMI驅動
    1. I2C驅動
    1. pinctrl驅動

附錄

i2c-tools 移植

下載下傳位址

https://mirrors.edge.kernel.org/pub/software/utils/i2c-tools/
           

說明文檔

交叉編譯

修改 Makefile

27 COMPILE_PREFIX := /usr/local/arm/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/fsl-linaro-toolchain/bin/arm-none-linux-gnueabi-
 28 CC      := $(COMPILE_PREFIX)gcc
 29 AR      := $(COMPILE_PREFIX)ar
 30 STRIP   := $(COMPILE_PREFIX)strip
           

執行 make USE_STATIC_LIB=1,進行靜态編譯

在 tools 下生成了 i2cdetect、i2cdump、i2cget、i2cset、i2ctransfer

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

拷貝到檔案系統即可

kernel下HDMI調試記錄1. 平台環境及驗證工具2. libdrm 移植3. DRM 元件探測4. HDMI 圖像顯示調試流程5. 圖像輸出結果6. 熱插拔結果7. 故障彙總及解決流程8. HDMI 調試方法9. 總結附錄

繼續閱讀