rk3568通过ADC区分硬件多mipi屏兼容实现
本文摘要:针对多硬件型号适配不同MIPI LCD屏的需求,提出通过ADC检测硬件ID的方案。在uboot和kernel层分别实现ADC驱动调用,通过dts配置不同硬件对应的屏参和初始化序列。主要修改包括:在rk3568-evb.dtsi中新增ADC通道配置和两种屏参方案,在panel-simple.c中增加IIO接口支持。关键实现包括:1)uboot下ADC uclass驱动调用 2)dts多配置
·
需求:通过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)
更多推荐



所有评论(0)