当前位置:   article > 正文

Rockchip RK3588 MIPI-DSI2 详解_rk3588 mipi dsi 详解

rk3588 mipi dsi 详解

Rockchip RK3588 MIPI-DSI2 详解

目录

Introduction

DSI-2 是 MIPI 联盟定义的一组通信协议的一部分, DWC-MIPI-DSI2 是一个实现 MIPI-DSI2 规范中定义的所有协议功能的数字核控制器,可以兼容 D-PHY 和 C-PHY 的物理接口,支持两路的 Display Stream Compression (DSC) 数据传输, RK3588 有两个 DSI-2 控制器和两个独立的物理的 D/C-PHY, 可以同时最多支持两路 MIPI 输出。
在这里插入图片描述

MIPI-DSI2 Features

  1. MIPI® Alliance Specification for Display Serial Interface 2 (DSI-2) Version 1.1
  2. MIPI® Alliance Specification for Display Command Set (DCS) Version 1.4
  3. MIPI® Alliance Specification for D-PHY v2.0
  4. MIPI® Alliance Specification for C-PHY v1.1
  5. Four data lanes on D-PHY and three data trios on C-PHY
  6. Bidirectional communication and escape mode through data lane 0
  7. Continuous and non-continuous clock modes on D-PHY and non-continuous clock mode on C-PHY
  8. End of Transmission packet (EoTp)
  9. Scrambling
  10. VESA DSC 1.1/1.2a
  11. Up to 4.5 Gbps per lane in D-PHY
  12. Up to 2.0 Gsps per trio in C-PHY

MIPI DSI-2 Host 与 MIPI DSI Host 的差别

MIPI DSI-2 除了可以兼容 MIPI DSI 的所有协议功能外, 还增加支持 MIPI C-PHY.
在这里插入图片描述

MIPI DPHY 差别

RK3588 平台 MIPI DPHY 不同以往平台 MIPI DPHY 版本, 其带宽最高可以到 4.5 Gbps.

在这里插入图片描述

应用领域

MIPI DSI基于差分信号传输,可以降低引脚数量和硬件设计复杂度,并保持良好的硬件兼容性。另外,基于MIPI DSI协议的IP还具备低功耗、低EMI的特性。

其应用领域如下图:

在这里插入图片描述

驱动代码说明:

uboot

驱动位置
drivers/video/drm/dw_mipi_dsi2.c
drivers/video/drm/samsung_mipi_dcphy.c
  • 1
  • 2
驱动配置
CONFIG_DRM_ROCKCHIP_DW_MIPI_DSI2=y
CONFIG_DRM_ROCKCHIP_SAMSUNG_MIPI_DCPHY=y
  • 1
  • 2

kernel

驱动位置
MIPI DSI-2 host controller:
drivers/gpu/drm/rockchip/dw-mipi-dsi2-rockchip.c

MIPI DCPHY:
drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
  • 1
  • 2
  • 3
  • 4
  • 5
驱动配置
cONFIG_ROCKCHIP_DW_MIPI_DSI=y
CONFIG_PHY_ROCKCHIP_SAMSUNG_DCPHY=y
  • 1
  • 2
参考设备树

DTS 路径:

arch/arm64/boot/dts/rockchip/rk3588-evb.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb1-lp4.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb2-lp4.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb3-lp5.dtsi
arch/arm64/boot/dts/rockchip/rk3588-evb4-lp4.dtsi
arch/arm64/boot/dts/rockchip/rk3588s-evb.dtsi
arch/arm64/boot/dts/rockchip/rk3588s-evb1-lp4x.dtsi
arch/arm64/boot/dts/rockchip/rk3588s-evb2-lp5.dtsi
arch/arm64/boot/dts/rockchip/rk3588s-evb4-lp4x.dtsi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

dts 配置用例场景说明:

rk3588-evb1: dsi0->dphy->1080p_panel && dsi1->dphy->1080p_panel;
rk3588-evb2: dsi1->dphy->1080p_panel;
rk3588-evb3: dsi0->dphy->1080p_panel && dsi1->cphy->cphy_panel;
rk3588-evb4: dsi0->dphy->1080p_panel;
rk3588s-evb1: dsi0->dphy->1080p_panel && dsi1->dphy->cmd_no_dsc_panel;
rk3588s-evb2: dsi0->cphy->cphy_panel & dsi1->dphy->1080p_panel;
rk3588s-evb4: dsi0->dphy->1080p_panel && dsi1->dphy->cmd_dsc_panel;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

屏端配置

DTS 配置

dsi0_panel: panel@0 {
	status = "okay";
	compatible = "simple-panel-dsi";
	reg = <0>;
	power-supply = <&vcc3v3_lcd_n>;
	backlight = <&backlight>;
	reset-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>;
	reset-delay-ms = <10>;
	enable-delay-ms = <10>;
	prepare-delay-ms = <10>;
	unprepare-delay-ms = <10>;
	disable-delay-ms = <60>;
	dsi,flags = <(MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |
		MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
	dsi,format = <MIPI_DSI_FMT_RGB888>;
	dsi,lanes  = <4>;
	//phy-c-option;
	//compressed-data;
	//slice-width = <720>;
	//slice-height = <65>;
	//version-major = <1>;
	//version-minor = <1>;

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

	panel-exit-sequence = [
		05 00 01 28
		05 00 01 10
	];

	disp_timings0: display-timings {
		native-mode = <&dsi0_timing0>;
		dsi0_timing0: timing0 {
			clock-frequency = <132000000>;
			hactive = <1080>;
			vactive = <1920>;
			hfront-porch = <15>;
			hsync-len = <4>;
			hback-porch = <30>;
			vfront-porch = <15>;
			vsync-len = <2>;
			vback-porch = <15>;
			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <0>;
			pixelclk-active = <0>;
		};
	};
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

配置说明

通用配置
PropertyDescriptionValue
compatiblecompatiblesimple-panel-dsi
power-supply屏端供电 [option]相关regulator引用
backlight背光背光引用
enable-gpios屏使能GPIO [option]GPIO引用描述
reset-gpios屏复位GPIOGPIO引用描述
reset-delay-mspanel sequence delay参考 panel spec
enable-delay-ms
prepare-delay-ms
unprepare-delay-ms
disable-delay-ms
dsi,flagsDSI2 工作模式cmd mode:
MIPI_DSI_MODE_LPM |
MIPI_DSI_MODE_EOT_PACKET
video mode:
MIPI_DSI_MODE_VIDEO |
MIPI_DSI_MODE_VIDEO_BURST |
MIPI_DSI_MODE_LPM |
MIPI_DSI_MODE_EOT_PACKET
dsi,format像素数据格式MIPI_DSI_FMT_RGB888
MIPI_DSI_FMT_RGB666
MIPI_DSI_FMT_RGB666_PACKED
MIPI_DSI_FMT_RGB565
dsi,lanesmipi data 通道数1/2/3 trios [cphy]
6 trios [cphy 双通道]
1/2/3/4 lanes [dphy]
8 lanes [dphy 双通道]
phy-c-optionC-PHY panel [option]布尔类型string
compressed-data带DSC panel [option]布尔类型string
slice-width定义dsc slice宽 [option]参照panel spec
slice-height定义dsc slice高 [option]
version-major定义dsc版本 [option]参照panel spec
version-minor
panel-init-sequence屏上电初始化序列[hex]
data_type delay_ms payload_lenth payload
panel-exit-sequence屏下电初始化序列
display-timingpanel timing参考panel spec
display Timing

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UOZ8oGbq-1657674965348)(Rockchip_RK3588_Developer_Guide_MIPI_DSI2/Display-Timing.png)]

dsi,flags
CLK Type

默认情况, MIPI DPHY 的时钟通道是连续模式,如下图:

在这里插入图片描述

当 MIPI_DSI_CLOCK_NON_CONTINUOUS 追加到 dsi,flags 时,MIPI DPHY 的时钟通道将会配置成非连续模式,如下图:

在这里插入图片描述

Eotp

Eotp 是一个短包用于指示数据链路上高速传输的结束。Eotp 主要作用是增强系统高速传输通信的稳健性,出于这个目的,DSI 不需要在 LP 模式发送 Eotp。

Eotp 不同于其他 DSI 包,它有固定的格式:

Data Type = DI [5:0] = 0b001000
Virtual Channel = DI [7:6] = 0b00
Payload Data [15:0] = 0x0F0F
ECC [7:0] = 0x01

将 MIPI_DSI_MODE_EOT_PACKET 追加到 dsi,flags 属性可以开关 Soc MIPI DSI TX 在高速模式发送 Eotp。
如下是在 HSDT 模式下捕获 Eotp 波形:

在这里插入图片描述

BLANK_HS_EN

在数据通道,一般存在一行会有两个 LP11 消隐, 如下图:

在这里插入图片描述

但往往有些显示模组或者外接 MIPI 转接芯片,不支持在 Hblank阶段有两个 LP-11, 可以将 BLK_HFP_HS_EN 或 BLK_HBP_HS_EN 追加到 dsi,flags 属性,使HFP 或 HBP 以高速的形式存在。

在这里插入图片描述

屏上电时序

在这里插入图片描述

屏下电时序

在这里插入图片描述

初始化序列常见数据类型
data typedescriptionpacket size
0x03Generic Short WRITE, no parametersshort
0x13Generic Short WRITE, 1 parametersshort
0x23Generic Short WRITE, 2 parametersshort
0x29Generic long WRITE,long
0x05DCS Short WRITE, no parametersshort
0x15DCS Short WRITE, 1 parametersshort
0x07DCS Short WRITE, 1 parameters, DSC ENshort
0x0aDCS long WRITE, PPS, 128 byteslong

Display Route

在这里插入图片描述

MIPI with DSC

在这里插入图片描述

MIPI with DSC Bypass

在这里插入图片描述

DTS 配置

如 DSI0 挂载在 VP3:

&dsi0_in_vp2 {
	status = "disabled";
};

&dsi0_in_vp3 {
	status = "okay";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

如 DSI1 挂载 VP2:

&dsi1_in_vp2 {
	status = "okay";
};

&dsi1_in_vp3 {
	status = "disabled";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

开机LOGO

route_dsi0

例如 vp3->dsi0 或 vp3->dsc0->dsi0:

&route_dsi0 {
	status = "okay";
	connect = <&vp3_out_dsi0>;
};
  • 1
  • 2
  • 3
  • 4

route_dsi1

例如 vp2->dsi1 或 vp2->dsc1->dsi1:

&route_dsi1 {
	status = "okay";
	connect = <&vp2_out_dsi1>;
};
  • 1
  • 2
  • 3
  • 4

route_dsi0 && route_dsi1

例如 (vp3->dsi0 或 vp3->dsc0->dsi0) && (vp2->dsi1 或 vp2->dsc1->dsi1):

&route_dsi0 {
	status = "okay";
	connect = <&vp3_out_dsi0>;
};

&route_dsi1 {
	status = "okay";
	connect = <&vp2_out_dsi1>;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

DSI HOST

ports
以下实例中 ports 是用来 Dispaly Interface 和 panel 之间进行关联。
详细配置说明参阅如下文档:

Documentation/devicetree/bindings/graph.txt
  • 1

单 DSI

在这里插入图片描述

DSI0
&dsi0 {
	status = "okay";
	//rockchip,lane-rate = <1000>;
	dsi0_panel: panel@0 {
		status = "okay";
		compatible = "simple-panel-dsi";
		...

		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>;
			};
		};
	};

};

&mipi_dcphy0 {
	status = "okay";
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
DSI1
&dsi1 {
	status = "okay";
	//rockchip,lane-rate = <1000>;
	dsi1_panel: panel@0 {
		status = "okay";
		compatible = "simple-panel-dsi";
		...

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

			port@0 {
				reg = <0>;
				panel_in_dsi1: endpoint {
					remote-endpoint = <&dsi1_out_panel>;
				};
			};
		};
	};

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

		port@1 {
			reg = <1>;
			dsi1_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi1>;
			};
		};
	};
};

&mipi_dcphy1 {
	status = "okay";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

双通道 DSI

MODE1:

在这里插入图片描述

MODE2:

在这里插入图片描述

双通道的配置注意如下标红属性:
rockchip,dual-channel = <&dsi1>
dsi,lanes = <8>;//DPHY 屏, CPHY 屏值改成 6

&dsi0 {
	status = "okay";
	rockchip,dual-channel = <&dsi1>;

	dsi0_panel {
		status = "okay";
		compatible = "simple-panel-dsi";
		dsi,lanes  = <8>;
		...

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

			timing0: timing0 {
				clock-frequency = <260000000>;
				hactive = <1440>;
				vactive = <2560>;
				hfront-porch = <150>;
				hsync-len = <30>;
				hback-porch = <60>;
				vfront-porch = <8>;
				vsync-len = <4>;
				vback-porch = <4>;
				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_dsi0: endpoint {
					remote-endpoint = <&dsi0_out_panel>;
				};
			};
		};
	};

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

		port@1 {
			reg = <1>;
			dsi0_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi0>;
			};
		};
	};
};

&dsi1 {
	status = "okay";
};

&mipi_dcphy0 {
	status = "okay";
};

&mipi_dcphy1 {
	status = "okay";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

Dual-link DSI

在这里插入图片描述

&dsi0 {
	status = "okay";
	//rockchip,lane-rate = <1000>;
	dsi0_panel: panel@0 {
		status = "okay";
		compatible = "simple-panel-dsi";
		...

		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>;
			};
		};
	};

};

&dsi1 { status = "okay";
	//rockchip,lane-rate = <1000>;
	dsi1_panel: panel@0 {
		status = "okay";
		compatible = "simple-panel-dsi";
		...

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

			port@0 {
				reg = <0>;
				panel_in_dsi1: endpoint {
					remote-endpoint = <&dsi1_out_panel>;
				};
			};
		};
	};

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

		port@1 {
			reg = <1>;
			dsi1_out_panel: endpoint {
				remote-endpoint = <&panel_in_dsi1>;
			};
		};
	};
};

&mipi_dcphy0 {
	status = "okay";
};

&mipi_dcphy1 {
	status = "okay";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75

DCPHY

实际应用配置中默认是配置成D-PHY,通过屏端配置介绍可知,通过下面可以配置成 C-PHY:

dsi0_panel: panel@0 {
	...
	phy-c-option;
	...
};
  • 1
  • 2
  • 3
  • 4
  • 5

D-PHY

在这里插入图片描述

1. Up to 4.5 Gbps per lane in D-PHY
2. 一个D-PHY port 最多4lanes,每个lane由两条差分线组成

C-PHY

在这里插入图片描述

1. Up to 2.0 Gsps per trio in C-PHY
2. 一个C-PHY port 最多3lanes,每个lane由 tree-wire-trios 组成

协议分析

DSI Layer Definitions

在这里插入图片描述

D Option

Lane states and line levels

在这里插入图片描述

下表罗列在 DPHY Lane 正常操作中可能出现的所有通道状态。

在这里插入图片描述

Global Operation Flow Diagram

在这里插入图片描述

DSI 数据通道可以驱动到如下三种模式:

  1. Escape Mode (只有 Dp0/Dn0 会操作在该模式);
  2. Bus Turnaround Request (只有 Dp0/Dn0 会操作在该模式);
  3. High-Speed Data Transmission。

这三种模式和它们进入对应模式的序列定义如下:

在这里插入图片描述

Escape Modes

当数据通道处于 LP 模式,数据通道0用于 Escape Mode, 数据通道应通过 LP-11->LP-10->LP-00->LP-01->LP-00 进入 Escape Mode,通过 LP-00->LP-10->LP-11 退出 Escape Mode.

在这里插入图片描述

Escape Commands

一旦数据通道进入 Escape 模式, 发送器应该发送 8-bit Escape Comands 指示请求行为,Escape Comands 如下:

在这里插入图片描述

LPDT

当数据通道进入 Escape 模式且向显示模块发送 Low-Power Data Transmission(LPDT) 序列,Soc 的 MIPI DSI TX 可以通过 LPDT 模式向显示模块发送数据, 一般就是通过这种方式向 MIPI 显示模块下载初始化序列。

在这里插入图片描述

通过示波器捕获 LPDT 波形如下:

在这里插入图片描述

ULPS

在这里插入图片描述

HSDT

当 DPHY 的时钟通道在高速时钟模式时,显示模块可以进入高速数据传输模式,所有的数据通道同时进入高速数据传输模式,但可以不同时退出高速模式。数据通道通过如下序列进入高速模式:
LP-11 -> LP-01 -> LP-00 -> HS-0 -> SoT(0001_1101).

1. Start: LP-11
2. HS-Request: LP-01
3. HS-Settle: LP-00 -> HS-0 (RX: Lane Termination Enable)
4. Rx Synchronization: SoT(0001_1101)
5. End: High-Speed Data Transmission (HSDT) - Ready to receive High-Speed Data Load
  • 1
  • 2
  • 3
  • 4
  • 5

数据通道退出高速数据传输模式流程:在最后一个有效负载数据之后立即切换差分状态位并保持该状态一段时间 Ths-trail。

在这里插入图片描述

通过示波器捕获 HSDT 波形如下:

在这里插入图片描述

BTA

当需要从显示模块获取信息时,Soc DPHY 的第一数据通道可以通过执行总线翻转步骤。操作步骤如下:

在这里插入图片描述

通过示波器在 HSDT 时向显示模块回读并捕获 BTA 波形如下:

在这里插入图片描述

Endian Policy

无论是在 LP 和 HS 数据传输模式,数据都是以长包和短包形式打包并传输给显示模块。

SPa

在这里插入图片描述

Example:

在这里插入图片描述

LPDT-SPa

通过示波器在 LPDT 时向显示模块发送如上 SPa 并捕获波形如下:

在这里插入图片描述

HSDT-SPa

通过示波器在 HSDT 时向显示模块发送如上 SPa 并捕获波形如下:

在这里插入图片描述

LPa

在这里插入图片描述

Example:
在这里插入图片描述

LPDT-LPa

通过示波器在 LPDT 时向显示模块发送如上 LPa 并捕获波形如下:

在这里插入图片描述

HSDT-LPa

通过示波器在 HSDT 时向显示模块发送如上 LPa 并捕获波形如下:

在这里插入图片描述

DI

如上 SPa 和 LPa 中都有一个 Data Identification (DI), 一个包是长短包就是由 DI 决定,DI 是包头的一部分,由两个部分组成:

在这里插入图片描述

MIPI 协议中目前定义的绝大部分数据类型如下:
在这里插入图片描述

Video Mode Interface Timing
Horizontal Display Timing (Video mode)

在这里插入图片描述

Non-Burst Mode with Sync Pulses

在这里插入图片描述

通过示波器捕获 Non Burst Sync Pulse 波形如下:

在这里插入图片描述

Burst Mode

在这里插入图片描述

通过示波器捕获 Video Burst 波形如下:

在这里插入图片描述

常见问题

查看VOP timing 和 Connector 信息

console:/ # cat /d/dri/0/summary
Video Port0: DISABLED
Video Port1: DISABLED
Video Port2: DISABLED
Video Port3: ACTIVE
    Connector: DSI-2
        bus_format[100a]: RGB888_1X24
        overlay_mode[0] output_mode[0] color_space[0]
    Display mode: 1080x1920p60
        clk[132000] real_clk[132000] type[48] flag[a]
        H: 1080 1095 1099 1129
        V: 1920 1935 1937 1952
    Cluster3-win0: ACTIVE
        win_id: 6
        format: AB24 little-endian (0x34324241) SDR[0] color_space[0] glb_alpha[0xff]
        rotate: xmirror: 0 ymirror: 0 rotate_90: 0 rotate_270: 0
        csc: y2r[0] r2y[0] csc mode[0]
        zpos: 0
        src: pos[0, 0] rect[1080 x 1920]
        dst: pos[0, 0] rect[1080 x 1920]
        buf[0]: addr: 0x000000000376e000 pitch: 4352 offset: 0
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

查看 DSI2 相关 clk tree

console:/ # cat /d/clk/clk_summary | grep vop
    clk_vop_pmu                       0        0        0    24000000          0     0  50000
          dclk_vop3                   1        2        0    33000000          0     0  50000
          dclk_vop1_src               0        1        0   594000000          0     0  50000
             dclk_vop1                0        1        0   594000000          0     0  50000
          dclk_vop0_src               0        1        0   594000000          0     0  50000
             dclk_vop0                0        1        0   594000000          0     0  50000
             aclk_vop_low_root        1        1        0   396000000          0     0  50000
             hclk_vop_root            2        4        0   198000000          0     0  50000
                hclk_vop              1        3        0   198000000          0     0  50000
          aclk_vop_root               1        1        0   500000000          0     0  50000
             aclk_vop_doby            0        0        0   500000000          0     0  50000
             aclk_vop_sub_src         1        1        0   500000000          0     0  50000
                aclk_vop              1        4        0   500000000          0     0  50000
             pclk_vop_root            3        5        0   100000000          0     0  50000
          dclk_vop2_src               1        1        0   148500000          0     0  50000
             dclk_vop2                1        2        0   148500000          0     0  50000
console:/ # cat /d/clk/clk_summary | grep dsi
                pclk_dsihost1         1        2        0   100000000          0     0  50000
                pclk_dsihost0         1        2        0   100000000          0     0  50000
    clk_dsihost1                      1        2        0   351000000          0     0  50000
    clk_dsihost0                      1        2        0   351000000          0     0  50000
console:/ # cat /d/clk/clk_summary | grep mipi
          mipi1_clk_src               0        0        0    33000000          0     0  50000
             mipi1_pixclk             0        0        0    33000000          0     0  50000
          mipi0_clk_src               0        0        0   148500000          0     0  50000
             mipi0_pixclk             0        0        0   148500000          0     0  50000
    clk_usbdpphy_mipidcpphy_ref       5        5        0    24000000          0     0  50000
    clk_mipi_camaraout_m4             0        0        0    24000000          0     0  50000
    clk_mipi_camaraout_m3             0        0        0    24000000          0     0  50000
    clk_mipi_camaraout_m2             0        0        0    24000000          0     0  50000
    clk_mipi_camaraout_m0             0        0        0    24000000          0     0  50000
          clk_mipi_camaraout_m1       0        0        0    37125000          0     0  50000
                pclk_mipi_dcphy1       1        1        0   100000000          0     0  50000
                pclk_mipi_dcphy0       1        1        0   100000000          0     0  50000
console:/ #
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

如何查看指定 DSI lane 速率

DSI lane 速率的指定有两种,一种是驱动自动计算:

dmesg | grep dsi

[   77.369812] dw-mipi-dsi2 fde20000.dsi: [drm:dw_mipi_dsi2_encoder_enable] final DSI-Link bandwidth: 879 x 4 Mbps
  • 1
  • 2
  • 3

一种是通过如下属性手动指定:

&dsi0 {
	...
	rockchip,lane-rate = <1000>;
	...
}
  • 1
  • 2
  • 3
  • 4
  • 5

MIPI DSI2 HOST 没有自己color bar 功能,通过如下命令可以让 VOP2 投显 color bar

根据显示路由选择对应的命令:

vp0:
io -4 0xfdd90c08 0x1 && io -4 0xfdd90000 0xffffffff

vp1:
io -4 0xfdd90d08 0x1 && io -4 0xfdd90000 0xffffffff

vp2:
io -4 0xfdd90e08 0x1 && io -4 0xfdd90000 0xffffffff

vp3:
io -4 0xfdd90f08 0x1 && io -4 0xfdd90000 0xffffffff
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如何判断显示异常的时候,MIPI DSI2 和 panel 是否通信正常

uboot:

--- a/drivers/video/drm/rockchip_panel.c
+++ b/drivers/video/drm/rockchip_panel.c
@@ -260,6 +260,7 @@ static void panel_simple_prepare(struct rockchip_panel *panel)
 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
 	struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev);
 	int ret;
+	u8 mode;

 	if (priv->prepared)
 		return;
@@ -285,6 +286,8 @@ static void panel_simple_prepare(struct rockchip_panel *panel)
 	if (plat->delay.init)
 		mdelay(plat->delay.init);

+	mipi_dsi_dcs_get_power_mode(dsi, &mode);
+	printf("===>mode: 0x%x\n", mode);
 	if (plat->on_cmds) {
 		if (priv->cmd_type == CMD_TYPE_SPI)
 			ret = rockchip_panel_send_spi_cmds(panel->state,
@@ -298,6 +301,8 @@ static void panel_simple_prepare(struct rockchip_panel *panel)
 			printf("failed to send on cmds: %d\n", ret);
 	}

+	mipi_dsi_dcs_get_power_mode(dsi, &mode);
+	printf("===>mode: 0x%x\n", mode);
 	priv->prepared = true;
 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

kernel

--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -506,6 +506,7 @@ static int panel_simple_prepare(struct drm_panel *panel)
 	unsigned int delay;
 	int err;
 	int hpd_asserted;
+	u8 mode;

 	if (p->prepared)
 		return 0;
@@ -554,6 +555,8 @@ static int panel_simple_prepare(struct drm_panel *panel)
 		}
 	}

+	mipi_dsi_dcs_get_power_mode(p->dsi, &mode);
+	printk("===>mode: 0x%x\n, mode");
 	if (p->desc->init_seq)
 		if (p->dsi)
 			panel_simple_xfer_dsi_cmd_seq(p, p->desc->init_seq);
@@ -561,6 +564,9 @@ static int panel_simple_prepare(struct drm_panel *panel)
 	if (p->desc->delay.init)
 		msleep(p->desc->delay.init);

+	mipi_dsi_dcs_get_power_mode(p->dsi, &mode);
+	printk("===>mode: 0x%x\n, mode");
+
 	p->prepared = true;

 	return 0;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

通信正常会有如下打印,否者排查屏端时序确保屏是否就绪:

===> mode: 0x8
===> mode: 0x9c
  • 1
  • 2

backlight驱动probe失败

console:/ # dmesg | grep backlight
[    3.164274] pwm-backlight: probe of backlight failed with error -16
  • 1
  • 2

Command Mode 显示模组如何配置 TE

为防止图像显示撕裂,显示控制器刷帧的频率应该和显示模组从GRAM中刷图的频率保持一致。RK3588只支持显示模组将TE信号外部反馈的方式。

&dsi0 {
	...
	/* 显示模组TE信号连接到MIPI_TE0 */
	pinctrl-names = "default";
	pinctrl-0 = <&mipi_te0>;
	...
};

&dsi1 {
	...
	/* 显示模组TE信号连接到MIPI_TE1 */
	pinctrl-names = "default";
	pinctrl-0 = <&mipi_te1>;
	...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

下图捕获MIPI DSI发送数据信号场频和显示模组TE信号频率一致波形:

在这里插入图片描述

双通道MIPI切换主从顺序

如果硬件设计将双通道的两个MIPI Ports接反了,可以通过如下配置进行软件纠正:

&dsi0 {
	...
	rockchip,data-swap;
	rockchip,dual-channel = <&dsi1>;
	...
};

&dsi1 {
	status = "okay";
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

调试节点

在MIPI DSI信号测试过程中需要对信号进行调整,如下是相关调试节点路径:

dcphy0:
cd /sys/devices/platform/feda0000.phy/
dcphy1:
cd /sys/devices/platform/fedb0000.phy/
  • 1
  • 2
  • 3
  • 4
Patch
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
index 1d5db69ee..c5d11f30c 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-dcphy.c
@@ -142,6 +142,25 @@
 #define T_TA_GET(x)		UPDATE(x, 7, 4)
 #define T_TA_GO(x)		UPDATE(x, 3, 0)

+
+#define REG_400M_MASK		GENMASK(6, 4)
+#define REG_400M(x)		UPDATE(x, 6, 4)
+#define BIAS_CON4		0x0010
+#define I_MUX_SEL_MASK		GENMASK(6, 5)
+#define I_MUX_SEL(x)		UPDATE(x, 6, 5)
+#define CAP_PEAKING_MASK	GENMASK(14, 12)
+#define CAP_PEAKING(x)		UPDATE(x, 14, 12)
+#define RES_UP_MASK		GENMASK(7, 4)
+#define RES_UP(x)		UPDATE(x, 7, 4)
+#define RES_DN_MASK		GENMASK(3, 0)
+#define RES_DN(x)		UPDATE(x, 3, 0)
+#define T_HS_ZERO_MASK		GENMASK(15, 8)
+#define T_HS_PREPARE_MASK	GENMASK(7, 0)
+#define T_HS_EXIT_MASK		GENMASK(15, 8)
+#define T_HS_TRAIL_MASK		GENMASK(7, 0)
+#define T_TA_GET_MASK		GENMASK(7, 4)
+#define T_TA_GO_MASK		GENMASK(3, 0)
+
 /* MIPI_CDPHY_GRF registers */
 #define MIPI_DCPHY_GRF_CON0	0x0000
 #define S_CPHY_MODE		HIWORD_UPDATE(1, 3, 3)
@@ -1194,6 +1213,421 @@ struct samsung_mipi_cphy_timing samsung_mipi_cphy_timing_table[] = {
 	{   80,  1, 50, 25,  2,  0, 2 },
 };

+static ssize_t
+reg_400m_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int level;
+
+	regmap_read(samsung->regmap, BIAS_CON2, &val);
+	level = (val & REG_400M_MASK) >> 4;
+
+	return sprintf(buf, "%d\n", level);
+
+}
+
+static ssize_t
+reg_400m_store(struct device *device, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+
+	if (val > 7)
+		val = 7;
+
+	regmap_update_bits(samsung->regmap, BIAS_CON2, REG_400M_MASK, REG_400M(val));
+
+	return count;
+}
+static DEVICE_ATTR_RW(reg_400m);
+
+static ssize_t
+cap_peaking_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int level;
+
+	regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);
+	level = (val & CAP_PEAKING_MASK) >> 12;
+
+	return sprintf(buf, "%d\n", level);
+
+}
+
+static ssize_t
+cap_peaking_store(struct device *device, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+
+	if (val > 7)
+		val = 7;
+
+	regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, CAP_PEAKING_MASK, CAP_PEAKING(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, CAP_PEAKING_MASK, CAP_PEAKING(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, CAP_PEAKING_MASK, CAP_PEAKING(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, CAP_PEAKING_MASK, CAP_PEAKING(val));
+	regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, CAP_PEAKING_MASK, CAP_PEAKING(val));
+
+	return count;
+}
+static DEVICE_ATTR_RW(cap_peaking);
+
+static ssize_t
+res_up_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int level;
+
+	regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);
+	level = (val & RES_UP_MASK) >> 4;
+
+	return sprintf(buf, "%d\n", level);
+
+}
+
+static ssize_t
+res_up_store(struct device *device, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+
+	if (val > 15)
+		val = 15;
+
+	regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, RES_UP_MASK, RES_UP(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, RES_UP_MASK, RES_UP(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, RES_UP_MASK, RES_UP(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, RES_UP_MASK, RES_UP(val));
+	regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, RES_UP_MASK, RES_UP(val));
+
+	return count;
+}
+static DEVICE_ATTR_RW(res_up);
+
+static ssize_t
+res_dn_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int level;
+
+	regmap_read(samsung->regmap, COMBO_MD0_ANA_CON0, &val);
+	level = (val & RES_DN_MASK);
+
+	return sprintf(buf, "%d\n", level);
+
+}
+
+static ssize_t
+res_dn_store(struct device *device, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+
+	if (val > 15)
+		val = 15;
+
+	regmap_update_bits(samsung->regmap, DPHY_MC_ANA_CON0, RES_DN_MASK, RES_DN(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD0_ANA_CON0, RES_DN_MASK, RES_DN(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD1_ANA_CON0, RES_DN_MASK, RES_DN(val));
+	regmap_update_bits(samsung->regmap, COMBO_MD2_ANA_CON0, RES_DN_MASK, RES_DN(val));
+	regmap_update_bits(samsung->regmap, DPHY_MD3_ANA_CON0, RES_DN_MASK, RES_DN(val));
+
+	return count;
+}
+static DEVICE_ATTR_RW(res_dn);
+
+static ssize_t
+output_voltage_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int level;
+
+	regmap_read(samsung->regmap, BIAS_CON4, &val);
+	level = (val & I_MUX_SEL_MASK) >> 5;
+
+	return sprintf(buf, "%d\n", level);
+
+}
+
+static ssize_t
+output_voltage_store(struct device *device, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+
+	if (val > 3)
+		val = 3;
+
+	regmap_update_bits(samsung->regmap, BIAS_CON4,
+			   I_MUX_SEL_MASK, I_MUX_SEL(val));
+
+	return count;
+}
+static DEVICE_ATTR_RW(output_voltage);
+
+static ssize_t
+hs_exit_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int hs_exit;
+
+	regmap_read(samsung->regmap, COMBO_MD0_TIME_CON2, &val);
+	hs_exit = (val & GENMASK(15, 8)) >> 8;
+
+	return sprintf(buf, "%d\n", hs_exit);
+
+}
+
+static ssize_t hs_exit_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+	unsigned long hs_exit;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	hs_exit = T_HS_EXIT(val);
+	regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON2, T_HS_EXIT_MASK, hs_exit);
+	regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON2, T_HS_EXIT_MASK, hs_exit);
+	regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON2, T_HS_EXIT_MASK, hs_exit);
+
+	if (!samsung->c_option) {
+		regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON2, T_HS_EXIT_MASK, hs_exit);
+		regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON2, T_HS_EXIT_MASK, hs_exit);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(hs_exit);
+
+static ssize_t
+hs_trail_or_post_3_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int hs_trail;
+
+	regmap_read(samsung->regmap, COMBO_MD0_TIME_CON2, &val);
+	hs_trail = val & GENMASK(7, 0);
+
+	return sprintf(buf, "%d\n", hs_trail);
+
+}
+
+static ssize_t hs_trail_or_post_3_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+	unsigned long hs_trail;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	hs_trail = T_HS_TRAIL(val);
+	regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON2, T_HS_TRAIL_MASK, hs_trail);
+	regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON2, T_HS_TRAIL_MASK, hs_trail);
+	regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON2, T_HS_TRAIL_MASK, hs_trail);
+
+	if (!samsung->c_option) {
+		regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON2, T_HS_TRAIL_MASK, hs_trail);
+		regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON2, T_HS_TRAIL_MASK, hs_trail);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(hs_trail_or_post_3);
+
+static ssize_t
+hs_zero_or_prebegin_3_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int hs_zero;
+
+	regmap_read(samsung->regmap, COMBO_MD0_TIME_CON1, &val);
+	hs_zero = (val & GENMASK(15, 8)) >> 8;
+
+	return sprintf(buf, "%d\n", hs_zero);
+
+}
+
+static ssize_t hs_zero_or_prebegin_3_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+	unsigned long hs_zero;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	hs_zero = T_HS_ZERO(val);
+	regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON1,
+			   T_HS_ZERO_MASK, hs_zero);
+	regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON1,
+			   T_HS_ZERO_MASK, hs_zero);
+	regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON1,
+			   T_HS_ZERO_MASK, hs_zero);
+
+	if (!samsung->c_option) {
+		regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON1,
+				   T_HS_ZERO_MASK, hs_zero);
+		regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON1,
+				   T_HS_ZERO_MASK, hs_zero);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(hs_zero_or_prebegin_3);
+
+static ssize_t
+hs_prepare_or_prepare_3_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int hs_prepare;
+
+	regmap_read(samsung->regmap, COMBO_MD0_TIME_CON1, &val);
+	hs_prepare = val & GENMASK(7, 0);
+
+	return sprintf(buf, "%d\n", hs_prepare);
+}
+
+static ssize_t hs_prepare_or_prepare_3_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+	unsigned long hs_prepare;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	hs_prepare = T_HS_PREPARE(val);
+	regmap_update_bits(samsung->regmap, COMBO_MD0_TIME_CON1,
+			   T_HS_PREPARE_MASK, hs_prepare);
+	regmap_update_bits(samsung->regmap, COMBO_MD1_TIME_CON1,
+			   T_HS_PREPARE_MASK, hs_prepare);
+	regmap_update_bits(samsung->regmap, COMBO_MD2_TIME_CON1,
+			   T_HS_PREPARE_MASK, hs_prepare);
+
+	if (!samsung->c_option) {
+		regmap_update_bits(samsung->regmap, DPHY_MC_TIME_CON1,
+				   T_HS_PREPARE_MASK, hs_prepare);
+		regmap_update_bits(samsung->regmap, DPHY_MD3_TIME_CON1,
+				   T_HS_PREPARE_MASK, hs_prepare);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(hs_prepare_or_prepare_3);
+
+static ssize_t
+lpx_show(struct device *device, struct device_attribute *attr, char *buf)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned int val;
+	unsigned int lpx;
+
+	regmap_read(samsung->regmap, COMBO_MD0_TIME_CON0, &val);
+	lpx = (val & GENMASK(11, 4)) >> 4;
+
+	return sprintf(buf, "%d\n", lpx);
+
+}
+
+static ssize_t lpx_store(struct device *device, struct device_attribute *attr,
+			 const char *buf, size_t count)
+{
+	struct samsung_mipi_dcphy *samsung = dev_get_drvdata(device);
+	unsigned long val;
+	unsigned long lpx = 0;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	lpx |= T_LPX(val);
+	/*  T_LP_EXIT_SKEW/T_LP_ENTRY_SKEW unconfig */
+	regmap_write(samsung->regmap, COMBO_MD0_TIME_CON0, lpx);
+	regmap_write(samsung->regmap, COMBO_MD1_TIME_CON0, lpx);
+	regmap_write(samsung->regmap, COMBO_MD2_TIME_CON0, lpx);
+
+	if (!samsung->c_option) {
+		regmap_write(samsung->regmap, DPHY_MC_TIME_CON0, lpx);
+		regmap_write(samsung->regmap, DPHY_MD3_TIME_CON0, lpx);
+	}
+
+	return count;
+}
+static DEVICE_ATTR_RW(lpx);
+
+static struct attribute *samsung_mipi_dcphy_cts_attrs[] = {
+	&dev_attr_lpx.attr,
+	&dev_attr_hs_prepare_or_prepare_3.attr,
+	&dev_attr_hs_zero_or_prebegin_3.attr,
+	&dev_attr_hs_trail_or_post_3.attr,
+	&dev_attr_hs_exit.attr,
+	&dev_attr_output_voltage.attr,
+	&dev_attr_res_up.attr,
+	&dev_attr_res_dn.attr,
+	&dev_attr_cap_peaking.attr,
+	&dev_attr_reg_400m.attr,
+	NULL
+};
+
+static const struct attribute_group samsung_mipi_dcphy_cts_attr_group = {
+	.attrs = samsung_mipi_dcphy_cts_attrs,
+};
+
+static int samsung_mipi_dcphy_cts_sysfs_add(struct samsung_mipi_dcphy *samsung)
+{
+	struct device *dev = samsung->dev;
+	int ret;
+
+	ret = sysfs_create_group(&dev->kobj, &samsung_mipi_dcphy_cts_attr_group);
+	if (ret) {
+		dev_err(dev, "failed to register sysfs. err: %d\n", ret);
+		return ret;
+	};
+
+	return 0;
+}
+
 static void samsung_mipi_dcphy_bias_block_enable(struct samsung_mipi_dcphy *samsung)
 {
 	regmap_write(samsung->regmap, BIAS_CON0, 0x0010);
@@ -1912,6 +2346,11 @@ static int samsung_mipi_dcphy_probe(struct platform_device *pdev)
 		return PTR_ERR(phy_provider);
 	}

+
+	ret = samsung_mipi_dcphy_cts_sysfs_add(samsung);
+	if (ret)
+		return ret;
+
 	pm_runtime_enable(dev);

 	return 0;

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
驱动强度
echo level > output_voltage
  • 1

驱动默认如下配置:

  1. D-PHY: 2’b00
  2. C-PHY: 2’b10

level 参考如下:

  1. 2b’00 : 400mV
  2. 2b’01 : 200mV
  3. 2b’10 : 530mV
  4. 2b’11 : 530mV
共模电压
echo level > reg_400m
  • 1

level 参考如下:

  1. 3’b000: 380mV / 230mV
  2. 3’b001: 390mV / 220mV
  3. 3’b010: 400mV / 210mV
  4. 3’b011: 410mV / 200mV
  5. 3’b100: 420mV / 190mV
  6. 3’b101: 430mV / 180mV
  7. 3’b110: 440mV / 170mV
  8. 3’b111: 450mV / 160mV
cap peaking
echo level > cap_peaking

level: 0~7
  • 1
  • 2
  • 3
信号timing

如下图中信号红色框中的信号参数都是可以调整的。

在这里插入图片描述

在这里插入图片描述

如下信号调整count值可以在回读基础上做调整修改,比如Tlpx:

cat lpx
  • 1
Tlpx
echo count > lpx
  • 1
Ths_prepare_or_prepare_3
echo count > hs_prepare_or_prepare_3
  • 1
Ths_zero_or_prebegin_3
echo count > hs_zero_or_prebegin_3
  • 1
Ths_trail_or_post_3
echo count > hs_trail_or_post_3
  • 1
Ths_exit
echo count > hs_exit
  • 1
High-Speed Driver Up Resistor Control
echo level > res_up
  • 1

level参考如下:

  1. 4’b0000: 43 ohm
  2. 4’b0001: 46 ohm
  3. 4’b0010: 49 ohm
  4. 4’b0011: 52 ohm
  5. 4’b0100: 56 ohm
  6. 4’b0101: 60 ohm
  7. 4’b0110: 66 ohm
  8. 4’b0111: 73 ohm
  9. 4’b1000: 30 ohm
  10. 4’b1001: 31.2 ohm
  11. 4’b1010: 32.5 ohm
  12. 4’b1011: 34 ohm
  13. 4’b1100: 35.5 ohm
  14. 4’b1101: 37 ohm
  15. 4’b1110: 39 ohm
  16. 4’b1111: 41 ohm
High-Speed Driver Down Resistor Control
echo level > res_dn
  • 1

level 参考如下:

  1. 4’b0000: 43 ohm
  2. 4’b0001: 46 ohm
  3. 4’b0010: 49 ohm
  4. 4’b0011: 52 ohm
  5. 4’b0100: 56 ohm
  6. 4’b0101: 60 ohm
  7. 4’b0110: 66 ohm
  8. 4’b0111: 73 ohm
  9. 4’b1000: 30 ohm
  10. 4’b1001: 31.2 ohm
  11. 4’b1010: 32.5 ohm
  12. 4’b1011: 34 ohm
  13. 4’b1100: 35.5 ohm
  14. 4’b1101: 37 ohm
  15. 4’b1110: 39 ohm
  16. 4’b1111: 41 ohm
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/330280
推荐阅读
相关标签
  

闽ICP备14008679号