需求:通过ADC来判断当前的硬件型号,选择不同的MIPI LCD屏参.

任务分解:
1)  uboot调用ADC,获取硬件型号ID
2)  uboot下MIPI屏参以及初始化序列DTS配置的解析位置
根据不通ID赋值不同的屏参及初始化序列
3)  kernel调用ADC值,获取硬件型号ID
4)  kernel下MIPI屏参以及初始化序列DTS配置的解析位置
5)  验证,回归,归档code


涉及技术点
1) : uboot下ADC uclass驱动框架
2) : dts解析
3) : kernel下ADC IIO驱动框架 
4) : source 关键字获取源码参考实现

修改点:
svn status . | grep M > 1.diff
sed -i '/\.a/d' 1.diff
uboot:
M       drivers/video/drm/rockchip_panel.c
M       drivers/video/drm/rockchip_display.c
kernel
M       arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
M       drivers/gpu/drm/panel/panel-simple.c
M       drivers/video/of_display_timing.c

参考资料:
https://blog.csdn.net/jamecer/article/details/140007947
https://blog.csdn.net/longruic/article/details/141471108
https://blog.csdn.net/wzf_Cql/article/details/128958339?spm=1001.2014.3001.5502
uboot/drivers/input/key-uclass.c
kernel/drivers/input/keyboard/adc-keys.c
ROCKCHIP_SARADC_DOC参考使用文档


附上code!
Index: arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi
===================================================================
--- arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi	(revision 3480)
+++ arch/arm64/boot/dts/rockchip/rk3568-evb.dtsi	(working copy)
@@ -306,6 +306,8 @@
 	dsi0_panel: panel@0 {
 		status = "okay";
 		compatible = "simple-panel-dsi";
+		io-channels = <&saradc 1>;
+		io-channel-names = "hwid";
 		reg = <0>;
 		power-supply = <&vcc3v3_lcd0_n>;
   		backlight = <&backlight>;
@@ -324,7 +326,7 @@
 			MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET)>;
 		dsi,format = <MIPI_DSI_FMT_RGB888>;
 		dsi,lanes  = <4>;
-		panel-init-sequence = [
+		panel-init-sequence-A = [
 15 00 02 B0 5A
 15 00 02 B1 00
 15 00 02 89 01
@@ -586,6 +588,108 @@
 05 78 01 11
 05 1E 01 29
 		];
+		panel-init-sequence-B = [
+15 00 02 B0 00
+15 00 02 B6 03
+15 00 02 BA 8F
+15 00 02 BD 3b
+15 00 02 C2 0F
+15 00 02 C3 03
+15 00 02 C4 0F
+15 00 02 C5 03
+
+15 00 02 B0 06
+15 00 02 C0 A5
+15 00 02 D5 54
+15 00 02 C0 00 
+
+15 00 02 B0 01
+15 00 02 D3 01
+15 00 02 E7 02
+15 00 02 D2 05
+15 00 02 E6 06
+15 00 02 D1 07
+15 00 02 E5 08
+15 00 02 D0 09
+15 00 02 E4 0A
+15 00 02 CF 0B
+15 00 02 E3 0C
+15 00 02 CE 1B
+15 00 02 E2 1C
+15 00 02 CD 1D
+15 00 02 E1 1E
+15 00 02 CA 11
+15 00 02 C9 12
+15 00 02 DE 11
+15 00 02 DD 12
+15 00 02 C8 0D
+15 00 02 DC 0E
+15 00 02 C3 0F
+15 00 02 D7 10
+15 00 02 C6 00
+15 00 02 C7 00
+15 00 02 C4 00
+15 00 02 C5 00
+15 00 02 D8 00
+15 00 02 D9 00
+15 00 02 DA 00
+15 00 02 DB 00
+
+15 00 02 B0 02
+15 00 02 C0 00
+15 00 02 C1 0A
+15 00 02 C2 14
+15 00 02 C3 24
+15 00 02 C4 30
+15 00 02 C5 32
+15 00 02 C6 32
+15 00 02 C7 32
+15 00 02 C8 32
+15 00 02 C9 32
+15 00 02 CA 32
+15 00 02 CB 32
+15 00 02 CC 32
+15 00 02 CD 2A
+15 00 02 CE 2A
+15 00 02 CF 2A
+15 00 02 D0 07
+15 00 02 D2 00
+15 00 02 D3 0A
+15 00 02 D4 14
+15 00 02 D5 24
+15 00 02 D6 30
+15 00 02 D7 32
+15 00 02 D8 32
+15 00 02 D9 32
+15 00 02 DA 32
+15 00 02 DB 32
+15 00 02 DC 32
+15 00 02 DD 32
+15 00 02 DE 32
+15 00 02 DF 2A
+15 00 02 E0 2A
+15 00 02 E1 2A
+15 00 02 E2 07
+
+15 00 02 B0 03
+15 00 02 BE 03
+15 00 02 CC 44
+15 00 02 C8 07
+15 00 02 C9 05
+15 00 02 CA 42
+15 00 02 E4 F0
+15 00 02 E5 0A
+15 00 02 DB 01
+15 00 02 D9 01
+15 00 02 D4 01
+15 00 02 D5 00
+15 00 02 D6 03
+15 00 02 D7 04
+15 00 02 D2 04
+15 00 02 D3 04
+15 00 02 CF 60
+15 00 02 CD 3E
+		];	
 
 		panel-exit-sequence = [
 		];
@@ -593,19 +697,32 @@
 		disp_timings0: display-timings {
 			native-mode = <&dsi0_timing0>;
 			dsi0_timing0: timing0 {
-				clock-frequency = <48000000>;
-				hactive = <600>;
-				vactive = <1024>;
-				hfront-porch = <80>;
-				hsync-len = <1>;
-				hback-porch = <60>;
-				vfront-porch = <25>;
-				vsync-len = <1>;
-				vback-porch = <35>;
-				hsync-active = <0>;
-				vsync-active = <0>;
-				de-active = <0>;
-				pixelclk-active = <1>;
+				clock-frequency-A = <48000000>;
+				hactive-A = <600>;
+				vactive-A = <1024>;
+				hfront-porch-A = <80>;
+				hsync-len-A = <1>;
+				hback-porch-A = <60>;
+				vfront-porch-A = <25>;
+				vsync-len-A = <1>;
+				vback-porch-A = <35>;
+				hsync-active-A = <0>;
+				vsync-active-A = <0>;
+				de-active-A = <0>;
+				pixelclk-active-A = <1>;
+				clock-frequency-B = <45000000>;
+				hactive-B = <600>;
+				vactive-B = <1024>;
+				hfront-porch-B = <50>;
+				hsync-len-B = <10>;
+				hback-porch-B = <50>;
+				vfront-porch-B = <20>;
+				vsync-len-B = <6>;
+				vback-porch-B = <20>;
+				hsync-active-B = <0>;
+				vsync-active-B = <0>;
+				de-active-B = <0>;
+				pixelclk-active-B = <1>;
 			};
 		};
 
Index: drivers/gpu/drm/panel/panel-simple.c
===================================================================
--- drivers/gpu/drm/panel/panel-simple.c	(revision 3480)
+++ drivers/gpu/drm/panel/panel-simple.c	(working copy)
@@ -27,6 +27,8 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/types.h>
 
 #include <drm/drmP.h>
 #include <drm/drm_crtc.h>
@@ -41,6 +43,7 @@
 
 #include "../rockchip/rockchip_drm_drv.h"
 
+static int hw_version=0;
 struct panel_cmd_header {
 	u8 data_type;
 	u8 delay;
@@ -146,6 +149,8 @@
 	SPI_3LINE_9BIT_MODE_DATA,
 	SPI_4LINE_8BIT_MODE,
 };
+int   get_hw_verion(void);
+void  set_hw_version(int);
 
 static inline int get_panel_cmd_type(const char *s)
 {
@@ -164,6 +169,20 @@
 {
 	return container_of(panel, struct panel_simple, base);
 }
+int get_hw_verion()
+{
+	printk("get hw_version=%d\n",hw_version);
+	return hw_version;
+}
+EXPORT_SYMBOL_GPL(get_hw_verion);
+void  set_hw_version(int value)
+{
+	if(value < 500)
+		hw_version=1;
+	else
+		hw_version=0;
+	printk("set hw_version=%d\n",hw_version);
+}	
 
 static int panel_simple_parse_cmd_seq(struct device *dev,
 				      const u8 *data, int length,
@@ -2925,6 +2944,7 @@
 	const void *data;
 	int len;
 	int err;
+	int hwid=0;
 
 	mode = devm_kzalloc(dev, sizeof(*mode), GFP_KERNEL);
 	if (!mode)
@@ -2949,7 +2969,11 @@
 	of_property_read_u32(np, "reset-delay-ms", &desc->delay.reset);
 	of_property_read_u32(np, "init-delay-ms", &desc->delay.init);
 
-	data = of_get_property(np, "panel-init-sequence", &len);
+	hwid = get_hw_verion();
+	if(hwid == 0)
+		data = of_get_property(np, "panel-init-sequence-A", &len);
+	else
+		data = of_get_property(np, "panel-init-sequence-B", &len);
 	if (data) {
 		desc->init_seq = devm_kzalloc(dev, sizeof(*desc->init_seq),
 					      GFP_KERNEL);
@@ -3238,6 +3262,26 @@
 	struct panel_desc_dsi *d;
 	const struct of_device_id *id;
 	int err;
+	struct iio_channel *channel;
+	int ret, value;
+	
+
+	channel = devm_iio_channel_get(dev, "hwid");
+	if (IS_ERR(channel)) {
+		printk("%s devm_iio_channel hw version id failed\n", __func__);
+		return PTR_ERR(channel);
+	}
+	if (!channel->indio_dev) {
+		printk("%s !channel adc error\n", __func__);
+		return -ENXIO;
+	}
+	ret = iio_read_channel_processed(channel, &value);
+	if (ret < 0) {
+		printk("%s read iio channel data failed\n", __func__);
+	} else {
+		printk("%s channel value = %d \n", __func__, value);
+	}
+	set_hw_version(value);
 
 	id = of_match_node(dsi_of_match, dsi->dev.of_node);
 	if (!id)
Index: drivers/video/of_display_timing.c
===================================================================
--- drivers/video/of_display_timing.c	(revision 3480)
+++ drivers/video/of_display_timing.c	(working copy)
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <video/display_timing.h>
 #include <video/of_display_timing.h>
+extern int get_hw_verion(void);
 
 /**
  * parse_timing_property - parse timing_entry from device_node
@@ -59,33 +60,63 @@
 {
 	u32 val = 0;
 	int ret = 0;
+	int hwid = 0;
 
 	memset(dt, 0, sizeof(*dt));
+	hwid = get_hw_verion();
 
-	ret |= parse_timing_property(np, "hback-porch", &dt->hback_porch);
-	ret |= parse_timing_property(np, "hfront-porch", &dt->hfront_porch);
-	ret |= parse_timing_property(np, "hactive", &dt->hactive);
-	ret |= parse_timing_property(np, "hsync-len", &dt->hsync_len);
-	ret |= parse_timing_property(np, "vback-porch", &dt->vback_porch);
-	ret |= parse_timing_property(np, "vfront-porch", &dt->vfront_porch);
-	ret |= parse_timing_property(np, "vactive", &dt->vactive);
-	ret |= parse_timing_property(np, "vsync-len", &dt->vsync_len);
-	ret |= parse_timing_property(np, "clock-frequency", &dt->pixelclock);
-
-	dt->flags = 0;
-	if (!of_property_read_u32(np, "vsync-active", &val))
-		dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
-				DISPLAY_FLAGS_VSYNC_LOW;
-	if (!of_property_read_u32(np, "hsync-active", &val))
-		dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
-				DISPLAY_FLAGS_HSYNC_LOW;
-	if (!of_property_read_u32(np, "de-active", &val))
-		dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
-				DISPLAY_FLAGS_DE_LOW;
-	if (!of_property_read_u32(np, "pixelclk-active", &val))
-		dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
-				DISPLAY_FLAGS_PIXDATA_NEGEDGE;
-
+	if(hwid == 0)
+	{	
+		ret |= parse_timing_property(np, "hback-porch-A", &dt->hback_porch);
+		ret |= parse_timing_property(np, "hfront-porch-A", &dt->hfront_porch);
+		ret |= parse_timing_property(np, "hactive-A", &dt->hactive);
+		ret |= parse_timing_property(np, "hsync-len-A", &dt->hsync_len);
+		ret |= parse_timing_property(np, "vback-porch-A", &dt->vback_porch);
+		ret |= parse_timing_property(np, "vfront-porch-A", &dt->vfront_porch);
+		ret |= parse_timing_property(np, "vactive-A", &dt->vactive);
+		ret |= parse_timing_property(np, "vsync-len-A", &dt->vsync_len);
+		ret |= parse_timing_property(np, "clock-frequency-A", &dt->pixelclock);
+
+		dt->flags = 0;
+		if (!of_property_read_u32(np, "vsync-active-A", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+					DISPLAY_FLAGS_VSYNC_LOW;
+		if (!of_property_read_u32(np, "hsync-active-A", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+					DISPLAY_FLAGS_HSYNC_LOW;
+		if (!of_property_read_u32(np, "de-active-A", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+					DISPLAY_FLAGS_DE_LOW;
+		if (!of_property_read_u32(np, "pixelclk-active-A", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+					DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+	}
+	else
+	{
+		ret |= parse_timing_property(np, "hback-porch-B", &dt->hback_porch);
+		ret |= parse_timing_property(np, "hfront-porch-B", &dt->hfront_porch);
+		ret |= parse_timing_property(np, "hactive-B", &dt->hactive);
+		ret |= parse_timing_property(np, "hsync-len-B", &dt->hsync_len);
+		ret |= parse_timing_property(np, "vback-porch-B", &dt->vback_porch);
+		ret |= parse_timing_property(np, "vfront-porch-B", &dt->vfront_porch);
+		ret |= parse_timing_property(np, "vactive-B", &dt->vactive);
+		ret |= parse_timing_property(np, "vsync-len-B", &dt->vsync_len);
+		ret |= parse_timing_property(np, "clock-frequency-B", &dt->pixelclock);
+
+		dt->flags = 0;
+		if (!of_property_read_u32(np, "vsync-active-B", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
+					DISPLAY_FLAGS_VSYNC_LOW;
+		if (!of_property_read_u32(np, "hsync-active-B", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
+					DISPLAY_FLAGS_HSYNC_LOW;
+		if (!of_property_read_u32(np, "de-active-B", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
+					DISPLAY_FLAGS_DE_LOW;
+		if (!of_property_read_u32(np, "pixelclk-active-B", &val))
+			dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
+					DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+	}	
 	if (!of_property_read_u32(np, "syncclk-active", &val))
 		dt->flags |= val ? DISPLAY_FLAGS_SYNC_POSEDGE :
 				DISPLAY_FLAGS_SYNC_NEGEDGE;
 				
Index: drivers/video/drm/rockchip_display.c
===================================================================
--- drivers/video/drm/rockchip_display.c	(revision 2162)
+++ drivers/video/drm/rockchip_display.c	(working copy)
@@ -76,6 +76,7 @@
 	bool phy_init;
 };
 
+extern int get_hw_verion(void);
 void rockchip_display_make_crc32_table(void)
 {
 	uint32_t c;
@@ -372,6 +373,7 @@
 	int hfront_porch, hback_porch, hsync_len;
 	int vfront_porch, vback_porch, vsync_len;
 	int val, flags = 0;
+	int hwid;
 
 #define FDT_GET_INT(val, name) \
 	val = ofnode_read_s32_default(node, name, -1); \
@@ -382,22 +384,46 @@
 
 #define FDT_GET_INT_DEFAULT(val, name, default) \
 	val = ofnode_read_s32_default(node, name, default);
+	
+	hwid = get_hw_verion();
 
-	FDT_GET_INT(hactive, "hactive");
-	FDT_GET_INT(vactive, "vactive");
-	FDT_GET_INT(pixelclock, "clock-frequency");
-	FDT_GET_INT(hsync_len, "hsync-len");
-	FDT_GET_INT(hfront_porch, "hfront-porch");
-	FDT_GET_INT(hback_porch, "hback-porch");
-	FDT_GET_INT(vsync_len, "vsync-len");
-	FDT_GET_INT(vfront_porch, "vfront-porch");
-	FDT_GET_INT(vback_porch, "vback-porch");
-	FDT_GET_INT(val, "hsync-active");
-	flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
-	FDT_GET_INT(val, "vsync-active");
-	flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
-	FDT_GET_INT(val, "pixelclk-active");
-	flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;
+	if(hwid == 0)
+	{	
+		FDT_GET_INT(hactive, "hactive-A");
+		FDT_GET_INT(vactive, "vactive-A");
+		FDT_GET_INT(pixelclock, "clock-frequency-A");
+		FDT_GET_INT(hsync_len, "hsync-len-A");
+		FDT_GET_INT(hfront_porch, "hfront-porch-A");
+		FDT_GET_INT(hback_porch, "hback-porch-A");
+		FDT_GET_INT(vsync_len, "vsync-len-A");
+		FDT_GET_INT(vfront_porch, "vfront-porch-A");
+		FDT_GET_INT(vback_porch, "vback-porch-A");
+		FDT_GET_INT(val, "hsync-active-A");
+		flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+		FDT_GET_INT(val, "vsync-active-A");
+		flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+		FDT_GET_INT(val, "pixelclk-active-A");
+		flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;
+	}
+	else
+	{
+		FDT_GET_INT(hactive, "hactive-B");
+		FDT_GET_INT(vactive, "vactive-B");
+		FDT_GET_INT(pixelclock, "clock-frequency-B");
+		FDT_GET_INT(hsync_len, "hsync-len-B");
+		FDT_GET_INT(hfront_porch, "hfront-porch-B");
+		FDT_GET_INT(hback_porch, "hback-porch-B");
+		FDT_GET_INT(vsync_len, "vsync-len-B");
+		FDT_GET_INT(vfront_porch, "vfront-porch-B");
+		FDT_GET_INT(vback_porch, "vback-porch-B");
+		FDT_GET_INT(val, "hsync-active-B");
+		flags |= val ? DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC;
+		FDT_GET_INT(val, "vsync-active-B");
+		flags |= val ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
+		FDT_GET_INT(val, "pixelclk-active-B");
+		flags |= val ? DRM_MODE_FLAG_PPIXDATA : 0;
+
+	}	
 
 	FDT_GET_INT_DEFAULT(val, "screen-rotate", 0);
 	if (val == DRM_MODE_FLAG_XMIRROR) {
Index: drivers/video/drm/rockchip_panel.c
===================================================================
--- drivers/video/drm/rockchip_panel.c	(revision 2162)
+++ drivers/video/drm/rockchip_panel.c	(working copy)
@@ -19,6 +19,7 @@
 #include <dm/uclass-id.h>
 #include <linux/media-bus-format.h>
 #include <power/regulator.h>
+#include <adc.h>
 
 #include "rockchip_display.h"
 #include "rockchip_crtc.h"
@@ -72,6 +73,31 @@
 	struct gpio_desc spi_scl_gpio;
 	struct gpio_desc spi_cs_gpio;
 };
+static int hw_version=0;
+
+#define   HW_ID    1
+int   get_hw_verion(void);
+int   set_hw_version(void);
+
+int get_hw_verion(void)
+{
+	printk("get hw_version=%d\n",hw_version);
+	return hw_version;
+}
+int  set_hw_version(void)
+{
+	int ret=0;
+	unsigned int adcval;
+	ret = adc_channel_single_shot("saradc",HW_ID, &adcval);
+	printf("initcode  adc ret=%d~~~~~~adcval=%d\n", ret,adcval)	;
+	
+	if(adcval < 500)
+		hw_version=1;
+	else
+		hw_version=0;
+	printk("set hw_version=%d\n",hw_version);
+	return hw_version;
+}	
 
 static inline int get_panel_cmd_type(const char *s)
 {
@@ -398,6 +424,9 @@
 	const void *data;
 	int len = 0;
 	int ret;
+	int hwid;
+	
+	set_hw_version();
 
 	plat->power_invert = dev_read_bool(dev, "power-invert");
 
@@ -412,7 +441,12 @@
 						MEDIA_BUS_FMT_RBG888_1X24);
 	plat->bpc = dev_read_u32_default(dev, "bpc", 8);
 
-	data = dev_read_prop(dev, "panel-init-sequence", &len);
+	hwid = get_hw_verion();
+	if(hwid == 0)
+		data = dev_read_prop(dev, "panel-init-sequence-A", &len);
+	else
+		data = dev_read_prop(dev, "panel-init-sequence-B", &len);
+
 	if (data) {
 		plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
 		if (!plat->on_cmds)
 				

 
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐