RK3566 多Mipi屏的兼容

需求:项目需求需要同一个固件兼容两款不同IC的mipi屏。以便有一个IC停产之后使用不受影响。由于是同一个模组厂商,所以设计初就要求硬件接口一样或者兼容。
方法:一开始的想法很简单和网上以及同行提供的方法一样在uboot阶段去读屏的ID,然后再把对应屏ID放到cmdline里面去传到kernel.在kernel里面做判断屏ID,来使用不同的panel-init-sequence 和timing。这种方法也可行。把屏的ID放到cmdline的方法是我也没找到,有大佬解答一下吗?
然后询问RK,RK提供了另一种方案不依靠cmdline传参。dts中dsi节点下面添加不同的panel节点。开机uboot阶段,通过mipi dsi读取每个屏的id寄存器与dts中设置的目标寄存器值进行比较。如果不是完全一致,就会将对应的panel节点的status设置成“disabled”。
最后会留下来唯一一个是status是“okay”的panel。kernel在加载panel的时候找到这个status是okay的panel,其他的不会加载。okay我们按照这个做法来实现我们的需求。

首先对DTB做一个深入了解。要不然怎么理解在uboot阶段把dts里面的status掉呢。在系统启动过程中,由bootloader将dtb文件加载到内存,并告知linux内核dtb在内存中的首地址(中途可能会对某些节点进行创建或者修改)。内核在start_kernel中会对dtb文件进行解析,并形成对应的device_node和property结构体;至此,dtb文件便完成任务了大佬做的详细解答可点
dtb的组成

在这里插入图片描述
其中structure block区域描述了设备树本身的结构和内容,strings block包含了设备树中所有属性的名称。以上都是参照链接上知乎大佬arch的文章内容。那么我理解就是dtb本身就是一个二进制文件。里面包含了我们的dts的文件内容包括节点以及属性。既然都以二进制存在。而且dtb的起始地址已知。我们只要找到节点的偏移地址以及status属性就可以把okay -> disabled.欧克解决; 这个下面就开始分析代码。

首先我们要咨询屏的IC厂屏的ID在那个寄存器里面。然后编写dts。如下:

&dsi0 {
	status = "okay";
//天钰IC 8553
	panel@0 {
		status = "okay";
		compatible = "simple-panel-dsi";
		reg = <0>;
		backlight = <&backlight>;
		iovcc-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
		//avdd-gpios = <&gpio4 RK_PC7 GPIO_ACTIVE_HIGH>;
		avdd-gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>;
		init-delay-ms = <60>;
		reset-delay-ms = <60>;
		enable-delay-ms = <60>;
		prepare-delay-ms = <60>;
		unprepare-delay-ms = <60>;
		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>;
		num = <0>;												//panel的唯一标识,必须是大于等于0的整数
	  	id = [95]; 												//读取id寄存器的返回值数组,十六进制
		id-reg = <0x04>;										//id寄存器地址,1个字节,需要加“0x”表示十六进制,
		panel-read-id-sequence= [05 78 01 11
		-------------
		];

		panel-exit-sequence = [
			05 0A 01 28
			05 78 01 10
		];

		disp_timings0: display-timings {
			native-mode = <&dsi0_timing0>;
			dsi0_timing0: timing0 {
				clock-frequency = <160000000>;
				hactive = <1080>;
				vactive = <2340>;
				hfront-porch = <60>;
				hsync-len = <2>;
				hback-porch = <60>;
				vfront-porch = <20>;
				vsync-len = <2>;
				vback-porch = <8>;
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <0>;
				pixelclk-active = <1>;
			};
		};

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

			port@0 {
				reg = <0>;
				panel0_in_dsi0: endpoint {
					remote-endpoint = <&dsi0_out_panel0>;
				};
			};
		};
	};
//奇景 83112a	
	panel@1 {
		status = "okay";
		compatible = "simple-panel-dsi";
		reg = <0>;
		backlight = <&backlight>;
		iovcc-gpios = <&gpio0 RK_PC7 GPIO_ACTIVE_HIGH>;
		//avdd-gpios = <&gpio4 RK_PC7 GPIO_ACTIVE_HIGH>;
		avdd-gpios = <&gpio3 RK_PC3 GPIO_ACTIVE_HIGH>;
		reset-gpios = <&gpio3 RK_PC1 GPIO_ACTIVE_LOW>;
		init-delay-ms = <60>;
		reset-delay-ms = <60>;
		enable-delay-ms = <60>;
		prepare-delay-ms = <60>;
		unprepare-delay-ms = <60>;
		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>;
		num = <1>;												//panel的唯一标识,必须是大于等于0的整数
	  	id = [83];											//读取id寄存器的返回值数组,十六进制
		id-reg = <0xB9>;										//id寄存器地址,1个字节,需要加“0x”表示十六进制,
		panel-read-id-sequence= [05 78 01 11
								 05 32 01 29 ];		//如果屏读寄存器前需要发命令,添写在这个数组里面,否则就不要配置这个数组
		panel-init-sequence = [
			--------------
			15 78 02 11 00
			15 0A 02 29 00
		];

		panel-exit-sequence = [
			05 0A 01 28
			05 78 01 10
		];

		display-timings {
			native-mode = <&dsi0_timing1>;
			dsi0_timing1: timing1 {
				clock-frequency = <155000000>;//mast Keep FPS  53
				hactive = <1080>;
				vactive = <2340>;
				hfront-porch = <48>;
				hsync-len = <44>;
				hback-porch = <48>;
				vfront-porch = <42>;
				vsync-len = <5>;
				vback-porch = <7>;
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <0>;
				pixelclk-active = <1>;
			};
		};

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

			port@0 {
				reg = <0>;
				panel1_in_dsi0: endpoint {
					remote-endpoint = <&dsi0_out_panel1>;
				};
			};
		};
	};

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

		port@0 {
			reg = <0>;

			dsi0_out_panel0: endpoint {
				remote-endpoint = <&panel0_in_dsi0>;
			};
		};
		port@1 {
			reg = <1>;

			dsi0_out_panel1: endpoint {
				remote-endpoint = <&panel1_in_dsi0>;
			};
		};
	};
};

这里省略初始话代码。主要添加了:

		reg = <0>;//dsi的vic number,必须是0
		num = <0>;//panel的唯一标识,必须是大于等于0的整数
	  	id = [04 05]; //读取id寄存器的返回值数组,十六进制
		id-reg = <0x0a>;//id寄存器地址,1个字节,需要加“0x”表示十六进制,
		panel-read-id-sequence= [39 00 04 FF 98 81 01 ];//如果屏读寄存器前需要发命令,添写在这个数组里面,否则就不要配置这个数组。

然后我们在uboot里面获取id 和id_reg。然后是最主要的read屏的寄存器读出ID来和id比较。然后再看是okay改节点还是disabled掉改节点

1.从dts上找到panle节点。根据上面的dts我们有俩个panel节点分别是panel@0 和panel@1 并利用device_node *np记录节点

+++ b/video/drm/dw_mipi_dsi.c
static int dw_mipi_dsi_connector_fixup_dts(struct display_state *state, void *blob)
{
	struct connector_state *conn_state = &state->conn_state; 
	struct panel_state *panel_state = &state->panel_state;
   int num = panel_state->panel->num;	
	const struct device_node *np;
	const char *path;
	int panel_node,connector;
	
	np = ofnode_to_np(conn_state->node);
	path = np->full_name;
	connector = fdt_path_offset(blob, path);

	for (panel_node = fdt_subnode_offset(blob, connector, "panel");
	     panel_node >= 0;
	     panel_node = fdt_next_subnode(blob, panel_node)){
 
		 dbg("fixup panel(num=%d) target =%d\n",fdtdec_get_int(blob, panel_node, "num", 0),num);

	    if(fdtdec_get_int(blob, panel_node, "num", 0) != num){
	    
			fdt_status_disabled(blob, panel_node);
	    }else{
			fdt_status_okay(blob, panel_node);
		}
	 }
		
	return 0;
}

利用 fdt_subnode_offset 函数找到名称为panel的节点偏移。

2.找到节点中的id以及id_reg等属性的值并给到一个定义好的结构体内填充

static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
{
	struct rockchip_panel_plat *plat = dev_get_platdata(dev);
	const void *data;
	int len = 0;
	int ret;

	plat->power_invert = dev_read_bool(dev, "power-invert");

	plat->delay.prepare = dev_read_u32_default(dev, "prepare-delay-ms", 0);
	plat->delay.unprepare = dev_read_u32_default(dev, "unprepare-delay-ms", 0);
	plat->delay.enable = dev_read_u32_default(dev, "enable-delay-ms", 0);
	plat->delay.disable = dev_read_u32_default(dev, "disable-delay-ms", 0);
	plat->delay.init = dev_read_u32_default(dev, "init-delay-ms", 0);
	plat->delay.reset = dev_read_u32_default(dev, "reset-delay-ms", 0);

	plat->bus_format = dev_read_u32_default(dev, "bus-format",
						MEDIA_BUS_FMT_RBG888_1X24);
	plat->bpc = dev_read_u32_default(dev, "bpc", 8);
	plat->id_reg =  dev_read_u32_default(dev, "id-reg", 0);
	plat->num = dev_read_u32_default(dev, "num", 0);
	data = dev_read_prop(dev, "id", &len);

	dbg("wzf:-------%s------\n",__func__);
	if(data){
		plat->id = malloc(sizeof(*plat->id));
		if (!plat->id)
			return -ENOMEM;
		plat->id->buf = malloc(sizeof(char) * len); 	   
		memcpy(plat->id->buf, data, len);
		plat->id->len = len;
		dbg("wzf:----plat dtb reg = %x id = %s len = %d",plat->id_reg,plat->id->buf,len);
	}

	dbg("mingming-->dts id reg = 0x%x\n",plat->id_reg);
	for(len =0;len < plat->id->len;len++){
			dbg("dts id[%d] = %x\n", len, *(plat->id->buf + len) );
	}
	data = dev_read_prop(dev, "panel-init-sequence", &len);
	if (data) {
		plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
		if (!plat->on_cmds)
			return -ENOMEM;

		ret = rockchip_panel_parse_cmds(data, len, plat->on_cmds);
		if (ret) {
			dbg("failed to parse panel init sequence\n");
			goto free_on_cmds;
		}
	}
	data = dev_read_prop(dev, "panel-read-id-sequence", &len);
	if (data) {
		plat->read_id_cmds = calloc(1, sizeof(*plat->read_id_cmds));
		if (!plat->read_id_cmds)
			return -ENOMEM;

		ret = rockchip_panel_parse_cmds(data, len, plat->read_id_cmds);
		if (ret) {
			dbg("failed to parse panel read id sequence\n");
			goto free_read_id_cmds;
		}
	}else{
	    plat->read_id_cmds = NULL;
	}
	data = dev_read_prop(dev, "panel-exit-sequence", &len);
	if (data) {
		plat->off_cmds = calloc(1, sizeof(*plat->off_cmds));
		if (!plat->off_cmds) {
			ret = -ENOMEM;
			goto free_on_cmds;
		}

		ret = rockchip_panel_parse_cmds(data, len, plat->off_cmds);
		if (ret) {
			dbg("failed to parse panel exit sequence\n");
			goto free_cmds;
		}
	}

	return 0;

利用 dev_read_u32_default 函数获取dts中我们填充的对比的id给到buf以及我们读的寄存器地址,以及地址长度 plat->id_reg,plat->id->buf,len(这里原本俩块屏的id是 JD9525 以及 HI83211a但是 我们比较一个就可以比较出来我就只填了 95 83)
JD9525 : plat->id-> buf = 95 plat->id_reg = 0x04 len =1;
HI83211a: plat->id-> buf = 83 plat->id_reg = 0x89 len =1;

3.拿到DTS中要比对的数据那么我们就要从寄存器中读取数据

static int rockchip_dsi_panel_getId(struct rockchip_panel *panel)
{
	u8 *buf;
	int i,len,ret = -1;
	int count = 3;

	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
	struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev);
	dbg("%s(%d) start\n", __func__, __LINE__);
	
	len = plat->id->len;
	printf("mingming-->%s(%d) start len:%d\n", __func__, __LINE__, len);
	buf = malloc(sizeof(char) * len);
	
	if (priv->power_supply)
		regulator_set_enable(priv->power_supply, !plat->power_invert);
//这段要根据自己的上电时序修改
	if (dm_gpio_is_valid(&priv->enable_gpio))
		dm_gpio_set_value(&priv->enable_gpio, 1);

	if (plat->delay.prepare)
		mdelay(plat->delay.prepare);

	if (dm_gpio_is_valid(&priv->reset_gpio))
		dm_gpio_set_value(&priv->reset_gpio, 1);

	if (plat->delay.reset)
		mdelay(plat->delay.reset);

	if (dm_gpio_is_valid(&priv->reset_gpio))
		dm_gpio_set_value(&priv->reset_gpio, 0);

	if (plat->delay.init)
		mdelay(plat->delay.init);
	priv->prepared = true;

	
	if (plat->read_id_cmds) {
		printf("send read id cmds\n");
		rockchip_panel_send_dsi_cmds(dsi, plat->read_id_cmds);
	    free(plat->read_id_cmds);
		plat->read_id_cmds = NULL;
	}else{
		if (plat->on_cmds) {
		printf("send on cmds\n");
		ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds);
		if (ret)
			printf("failed to send on cmds: %d\n", ret);	   }     
	   
	}

  ret = -1;
	while((ret < 0) && count > 0){
		if(len > 1){
			ret = mipi_dsi_set_maximum_return_packet_size(dsi, len);  //设置要读取的值的长度由于我们dts上只有一个字节 len 为一所以他只				 会读一个字节出来
		}
		ret = mipi_dsi_dcs_read(dsi, plat->id_reg, buf,len);  //getId核心代码
		count --;
	}
		
	//  printf("panel_simple_prepare buf = %d \n",buf[0]);
	if(ret == len)
		for(i = 0; i < len; i++){
		printf("read buf id[%d] = %x,panel target id[%d] = %x\n", i, *(buf + i), i, *(plat->id->buf + i));
			if(*(buf + i) != *(plat->id->buf + i)){  //和第二步中的plat->id->buf比对
				plat->num = -1;
				return -1;
			}
		}
	else{
		    dbg("read panel(num = %d) timeout or no response\n",plat->num);
			plat->num = -1;
			return -1;
	}
	panel->num = plat->num;
	return 0;
}	

这个利用函数mipi_dsi_dcs_read(dsi, plat->id_reg, buf,len)plat->id_reg从寄存器中读取值给到buf。
那么只要buf拿到值就可以和第二步中的plat->id->buf比对if(*(buf + i) != *(plat->id->buf + i))由于我们只有一个字节 i = 0;如果多个字节i自增就可以对比多个字节。 如果匹配getId就会返回0 否则就返回-1

4getId通过判断dts的id和寄存器的ID匹对来判断屏的dts和屏是否匹配。然后就要okay 该panel节点 或者disabled该节点。

static int panel_matching(struct display_state *state)
{
	struct connector_state *conn_state = &state->conn_state;
	struct panel_state *panel_state = &state->panel_state;
	const struct rockchip_connector *conn = conn_state->connector;
	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
	ofnode panel_node;
	struct udevice *panel_dev;
	int ret;


       if (conn_funcs->init) {
           ret = conn_funcs->init(state);
	    if (ret){
			printf("failed to init connector\n");
	    		goto deinit;
	    }
        }
	
	if (conn_state->phy)
			rockchip_phy_init(conn_state->phy);
	
	ofnode_for_each_subnode(panel_node, conn_state->node) {

        if (ofnode_valid(panel_node) && ofnode_is_available(panel_node)) {
	        ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_node,
	        				  &panel_dev);
	        if (ret){
	        	 dbg("this sub node is not a panel node\n");
	        	 continue;
	        }
	        
        }
        struct rockchip_panel *panel = (struct rockchip_panel *)dev_get_driver_data(panel_dev);
       if (panel){

			panel->state = state;
		    panel_state->panel = panel;
        }
        if (!conn_funcs) {
	        printf("failed to find connector functions\n");
	        return -ENXIO;
        }
        
        if (panel_state->panel)
          rockchip_panel_init(panel_state->panel);
		
       	if (conn_funcs->prepare)
 		    conn_funcs->prepare(state);

       printf("%s(%d) getid\n", __func__, __LINE__);			   
	    if(rockchip_panel_getId(panel_state->panel) != -1){   //调用getId函数 如果)=-1 就是屏和dts匹配直接break;如果不等于执行下面的rockchip_panel_disable函数 把该节点disabled掉
	   	   dbg("dsi find panel id\n");
		   rockchip_panel_unprepare(panel_state->panel);
	   	   break;
	    }
	    rockchip_panel_unprepare(panel_state->panel);
 	    rockchip_panel_disable(panel_state->panel);
	}
	if (conn_funcs->disable)
	   conn_funcs->disable(state);
    
	if (conn_funcs->unprepare)
	   conn_funcs->unprepare(state);
	return 0;
	deinit:
	if (conn_funcs->deinit)
		conn_funcs->deinit(state);
	return ret;	    
}

通过 ofnode_for_each_subnode遍历dsi下所有子节点。然后调用getId函数 如 != - 1 就是屏和dts匹配直接break;如果不等于执行下面的rockchip_panel_disable函数 把该节点disabled掉。因此我们的所有panel节点都应设置为okay。然后等待disabeld掉不适用的节点。

补充说明:
把节点disabled掉的并不是rockchip_panel_disable函数。而是fdt_setprope等fdt函数。
在这里插入图片描述
然后我们把板子里面的dtb文件导出来查看是否正常被disabled掉status参考链接
在这里插入图片描述
把板子里面的/sys/firmware/fdt文件导出来。
再放到我们的编译服务器使用dtc命令 把fdt转化成dts文件
dtc -I dtb -O dts fdt

导出来的dts文件:
        dsi@fe060000 {
                compatible = "rockchip,rk3568-mipi-dsi";
                reg = <0x00 0xfe060000 0x00 0x10000>;
                interrupts = <0x00 0x44 0x04>;
                clocks = <0x1f 0xe8 0x1f 0xda 0x2e>;
                clock-names = "pclk\0hclk\0hs_clk";
                resets = <0x1f 0x110>;
                reset-names = "apb";
                phys = <0x2e>;
                phy-names = "mipi_dphy";
                power-domains = <0x21 0x09>;
                rockchip,grf = <0x32>;
                #address-cells = <0x01>;
                #size-cells = <0x00>;
                status = "okay";
                phandle = <0x190>;

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

                        port@0 {
                                reg = <0x00>;
                                #address-cells = <0x01>;
                                #size-cells = <0x00>;
                                phandle = <0x191>;

                                endpoint@0 {
                                        reg = <0x00>;
                                        remote-endpoint = <0x14>;
                                        status = "okay";
                                        phandle = <0x89>;
                                };

                                endpoint@1 {
                                        reg = <0x01>;
                                        remote-endpoint = <0x94>;
                                        status = "disabled";
                                        phandle = <0x8d>;
                                };

                                endpoint {
                                        remote-endpoint = <0x95>;
                                        phandle = <0x9a>;
                                };
                        };

                        port@1 {
                                reg = <0x01>;

                                endpoint {
                                        remote-endpoint = <0x96>;
                                        phandle = <0x9c>;
                                };
                        };
                };

                panel@0 {
                        status = "okay";
                        compatible = "simple-panel-dsi";
                        reg = <0x00>;
                        backlight = <0x97>;
                        iovcc-gpios = <0x36 0x17 0x00>;
                        avdd-gpios = <0x98 0x13 0x00>;
                        reset-gpios = <0x98 0x11 0x01>;
                        init-delay-ms = <0x3c>;
                        reset-delay-ms = <0x3c>;
                        enable-delay-ms = <0x3c>;
                        prepare-delay-ms = <0x3c>;
                        unprepare-delay-ms = <0x3c>;
                        disable-delay-ms = <0x3c>;
                        dsi,flags = <0xa03>;
                        dsi,format = <0x00>;
                        dsi,lanes = <0x04>;
                        num = <0x00>;
                        id = [95];
                        id-reg = <0x04>;
                        panel-read-id-sequence = <0x5780111 0x5320129>;
                        panel-init-sequence = [39 00 04 df 95 25 ba 15 00 02 de 00 39 00 04 b9 7c 43 85 39 00 08 bb 00 11 43 1f 1f 11 11 39 00 03 bd 00 22 39 00 04 bc 2e 30 73 39 00 05 bf 2c 2c 3f c3 39 00 06 c0 00 f7 01 f7 01 39 00 04 c1 04 11 40 39 01 41 c3 3b 01 06 05 03 03 03 01 01 01 01 01 01 01 01 01 06 2b 30 54 58 7d 01 80 ff ff 00 05 03 7f 00 04 00 04 00 04 02 13 ff ff 02 13 03 00 03 02 03 03 00 03 ff ff 00 07 ff ff 03 0d 03 0d 03 0d 03 0d 39 01 40 c4 01 06 05 03 03 03 01 01 01 01 01 01 01 01 01 06 2b 30 54 58 7d 01 80 03 0d 00 05 03 0d 00 04 00 04 00 04 02 13 02 13 02 13 03 03 03 03 03 03 00 03 ff ff 00 07 03 0d 03 0d 03 0d 03 0d 03 0d 39 01 18 c6 01 49 00 36 00 0a 05 82 01 00 00 01 00 01 00 00 00 00 00 35 00 00 01 15 00 02 c7 40 39 00 08 c8 45 92 87 00 00 00 00 39 00 17 cd 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 00 00 00 3f 3f 39 00 1d ce 00 00 00 00 00 00 00 00 00 00 00 0c 0c 0c 0c 0c 0c fc fc ff fc fc 0c 0c 0c 00 00 00 39 01 35 cf 00 00 00 00 00 00 00 00 00 33 00 3f 33 33 3f 3f 3f 33 33 33 33 33 33 33 33 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00 00 00 00 00 00 00 00 ff 00 00 00 00 39 01 20 d0 00 1f 1f 1f 1f 1f 1f 1f 1f 1e 1f df df df f6 f5 f4 c5 c7 d5 de de de df c1 ff ff ff f0 00 00 39 01 20 d1 00 1f 1f 1f 1f 1f 1f 1f 1f 1e 1f df df df f6 f5 f4 c4 c6 d5 de de de df c0 ff ff ff f0 00 00 39 01 1d d2 00 1f 1f 1f 1f 1f 1f 1f 1f 1e 1f 1f 1f 1f 36 35 34 c6 c4 d5 de de 1f 1e 00 00 00 00 39 01 1d d3 00 1f 1f 1f 1f 1f 1f 1f 1f 1e 1f 1f 1f 1f 36 35 34 c7 c5 d5 de de 1f 1e 01 00 00 00 39 01 3e d4 10 10 00 08 00 05 00 00 00 00 00 01 02 00 11 e0 01 00 04 01 01 11 e0 03 00 05 01 01 00 00 02 04 0a 09 38 00 0f 00 00 00 00 00 00 00 00 03 00 26 30 00 00 00 00 00 00 00 00 01 00 00 00 39 01 5d d5 01 10 01 00 00 00 00 00 00 00 00 e8 00 01 00 07 32 5a 10 40 05 00 01 00 30 30 00 01 14 00 71 00 04 10 04 06 00 00 00 00 00 09 00 00 00 1b 00 00 01 00 01 00 01 00 01 00 06 00 2b 00 30 00 54 00 59 00 7d 00 00 00 ff ff ff 3f 3f 00 00 1f ff 00 00 00 1f ff 00 ff ff ff ff ff ff 00 39 01 14 d7 00 02 84 00 00 00 00 00 00 00 00 00 00 02 84 00 00 00 00 15 00 02 de 01 15 00 02 b5 69 39 01 30 c2 00 00 00 01 55 55 6a aa ff f0 00 00 0e 21 33 42 52 5c 68 7d 91 a0 ac e1 05 22 3e 57 70 70 8e ab cd f6 25 65 91 ab cb dd f4 0e 28 49 78 bb f8 39 01 30 c1 00 00 00 01 55 55 6a aa ff f0 04 05 16 29 3b 4a 5a 64 70 85 99 a8 b4 e9 0d 2a 46 5f 78 78 96 b3 d5 fe 2d 6d 99 b3 d3 e5 fc 16 30 51 80 c3 ff 39 01 30 c3 00 00 00 01 55 55 6a aa ff f0 00 00 0e 21 33 42 52 5c 68 7d 91 a0 ac e1 05 22 3e 57 70 70 8e ab cd f6 25 65 91 ab cb dd f4 0e 28 49 78 bb f8 39 01 30 c4 00 00 00 01 55 55 6a aa ff f0 04 05 16 29 3b 4a 5a 64 70 85 99 a8 b4 e9 0d 2a 46 5f 78 78 96 b3 d5 fe 2d 6d 99 b3 d3 e5 fc 16 30 51 80 c3 ff 39 01 30 c6 00 00 00 01 55 55 6a aa ff f0 00 00 0e 21 33 42 52 5c 68 7d 91 a0 ac e1 05 22 3e 57 70 70 8e ab cd f6 25 65 91 ab cb dd f4 0e 28 49 78 bb f8 39 01 30 c5 00 00 00 01 55 55 6a aa ff f0 04 05 16 29 3b 4a 5a 64 70 85 99 a8 b4 e9 0d 2a 46 5f 78 78 96 b3 d5 fe 2d 6d 99 b3 d3 e5 fc 16 30 51 80 c3 ff 39 01 0c c7 15 14 07 07 09 07 87 63 62 63 04 15 00 02 de 02 15 00 02 bf 04 15 00 02 c1 20 39 00 0a c2 02 42 d0 02 00 c0 41 72 fb 15 00 02 c5 0e 39 00 08 c4 00 11 0f 80 1c 01 08 39 00 17 e5 10 da d8 02 2b c0 2b c0 09 04 40 40 00 20 00 00 00 00 28 00 00 00 39 00 05 ec 77 00 5f 02 15 00 02 de 03 39 00 03 d0 00 65 15 00 02 de 00 05 1e 01 35 05 78 01 11 05 32 01 29];
                        panel-exit-sequence = <0x50a0128 0x5780110>;

                        display-timings {
                                native-mode = <0x99>;
                                phandle = <0x192>;

                                timing0 {
                                        clock-frequency = <0x9896800>;
                                        hactive = <0x438>;
                                        vactive = <0x924>;
                                        hfront-porch = <0x3c>;
                                        hsync-len = <0x02>;
                                        hback-porch = <0x3c>;
                                        vfront-porch = <0x14>;
                                        vsync-len = <0x02>;
                                        vback-porch = <0x08>;
                                        hsync-active = <0x00>;
                                        vsync-active = <0x00>;
                                        de-active = <0x00>;
                                        pixelclk-active = <0x01>;
                                        phandle = <0x99>;
                                };
                        };

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

                                port@0 {
                                        reg = <0x00>;

                                        endpoint {
                                                remote-endpoint = <0x9a>;
                                                phandle = <0x95>;
                                        };
                                };
                        };
                };

                panel@1 {
                        status = "disabled";
                        compatible = "simple-panel-dsi";
                        reg = <0x00>;
                        backlight = <0x97>;
                        iovcc-gpios = <0x36 0x17 0x00>;
                        avdd-gpios = <0x98 0x13 0x00>;
                        reset-gpios = <0x98 0x11 0x01>;
                        init-delay-ms = <0x3c>;
                        reset-delay-ms = <0x3c>;
                        enable-delay-ms = <0x3c>;
                        prepare-delay-ms = <0x3c>;
                        unprepare-delay-ms = <0x3c>;
                        disable-delay-ms = <0x3c>;
                        dsi,flags = <0xa03>;
                        dsi,format = <0x00>;
                        dsi,lanes = <0x04>;
                        num = <0x01>;
                        id = [83];
                        id-reg = <0xb9>;
                        panel-read-id-sequence = <0x5780111 0x5320129>;
                        panel-init-sequence = [39 00 04 b9 83 11 2a 39 00 09 b1 08 25 25 80 80 4a 4f aa 39 00 0f b2 00 02 00 90 24 00 0a 28 ea 11 00 01 15 a0 39 00 03 d2 2b 2b 39 00 1c b4 02 ba 02 ba 02 ba 04 bc 00 00 04 bc 00 ff 00 ff 00 00 0c 12 00 2a 06 06 0f 00 86 39 00 04 b6 8c 8c e3 15 00 02 cc 08 39 05 30 d3 40 00 00 00 00 01 00 14 14 03 01 11 08 03 03 03 03 32 10 00 00 00 32 10 0a 00 0a 32 10 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ea 1c 39 05 31 d5 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 c0 c0 18 18 40 40 18 18 18 18 31 31 30 30 2f 2f 01 00 03 02 20 20 c0 c0 c0 c0 19 19 40 40 25 24 39 05 31 d6 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 18 40 40 18 18 40 40 18 18 18 18 31 31 30 30 2f 2f 00 01 02 03 20 20 40 40 40 40 40 40 19 19 24 25 39 00 0d d8 aa aa aa aa ff ea aa aa aa aa ff ea 15 00 02 bd 01 39 00 0d d8 aa aa af ff ff ff aa aa af ff ff ff 15 00 02 bd 02 39 00 0d d8 aa aa af ff ff ff aa aa af ff ff ff 15 00 02 bd 03 39 00 19 d8 aa aa ae bf ab ea aa aa ae bf ab ea aa aa af ff ff ff aa aa af ff ff ff 15 00 02 bd 00 15 00 02 c1 01 15 00 02 bd 01 39 00 3a c1 ff fa f6 f2 ee ea e6 dd d9 d5 d1 cd c8 c4 c0 bc b7 b3 ae a6 9d 95 8c 84 7c 74 6c 64 5c 55 4c 46 3f 37 2f 28 20 19 12 0a 07 05 03 01 00 28 03 e9 95 8c 8e f9 c8 18 e7 12 00 15 00 02 bd 02 39 00 3a c1 ff fa f6 f2 ee ea e6 dd d9 d5 d1 cd c8 c4 c0 bc b7 b3 ae a6 9d 95 8c 84 7c 74 6c 64 5c 55 4c 46 3f 37 2f 28 20 19 12 0a 07 05 03 01 00 28 03 e9 95 8c 8e f9 c8 18 e7 12 00 15 00 02 bd 03 39 00 3a c1 ff fa f6 f2 ee ea e6 dd d9 d5 d1 cd c8 c4 c0 bc b7 b3 ae a6 9d 95 8c 84 7c 74 6c 64 5c 55 4c 46 3f 37 2f 28 20 19 12 0a 07 05 03 01 00 28 03 e9 95 8c 8e f9 c8 18 e7 12 00 15 00 02 bd 00 39 00 1a e7 0f 0f 1e 68 1e 65 00 50 01 14 00 00 02 02 02 05 14 14 32 b9 23 b9 08 13 69 15 00 02 bd 01 39 00 09 e7 02 00 ba 01 a4 0e 20 0f 15 00 02 bd 02 39 00 1e e7 00 00 08 40 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 00 70 01 70 02 00 15 00 02 bd 00 39 00 03 c0 22 22 15 00 02 bd 02 39 00 0a b4 00 92 12 11 88 12 12 00 53 15 00 02 bd 01 39 00 04 b1 64 01 09 15 00 02 bd 00 39 00 07 c7 00 00 04 e0 33 00 15 00 02 e9 c3 39 00 05 cb 91 d2 00 02 15 00 02 e9 3f 15 78 02 11 00 15 0a 02 29 00];
                        panel-exit-sequence = <0x50a0128 0x5780110>;

                        display-timings {
                                native-mode = <0x9b>;

                                timing1 {
                                        clock-frequency = <0x93d1cc0>;
                                        hactive = <0x438>;
                                        vactive = <0x924>;
                                        hfront-porch = <0x30>;
                                        hsync-len = <0x2c>;
                                        hback-porch = <0x30>;
                                        vfront-porch = <0x2a>;
                                        vsync-len = <0x05>;
                                        vback-porch = <0x07>;
                                        hsync-active = <0x00>;
                                        vsync-active = <0x00>;
                                        de-active = <0x00>;
                                        pixelclk-active = <0x01>;
                                        phandle = <0x9b>;
                                };
                        };

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

                                port@0 {
                                        reg = <0x00>;

                                        endpoint {
                                                remote-endpoint = <0x9c>;
                                                phandle = <0x96>;
                                        };
                                };
                        };
                };
        };

可以看到panel@1已经被disabled掉了 。原本我们的dts都写的是okay。表示我们功能已经实现。

ok流程代码分析结束。我们再追一下源码看rockchip_panel_disable是怎么做的

static void panel_simple_enable(struct rockchip_panel *panel)
{
	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);

	if (priv->enabled)
		return;

	if (plat->delay.enable)
		mdelay(plat->delay.enable);

	if (priv->backlight)
		backlight_enable(priv->backlight);

	priv->enabled = true;
}

static void panel_simple_disable(struct rockchip_panel *panel)
{
	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);

	if (!priv->enabled)
		return;

	if (priv->backlight)
		backlight_disable(priv->backlight);

	if (plat->delay.disable)
		mdelay(plat->delay.disable);

	priv->enabled = false;
}

看不懂。好了我们在来看一下mipi_dsi的函数

ssize_t mipi_dsi_dcs_read(struct mipi_dsi_device *dsi, u8 cmd, void *data,
			  size_t len)
{
	struct mipi_dsi_msg msg = {
		.channel = dsi->channel,
		.type = MIPI_DSI_DCS_READ,
		.tx_buf = &cmd,
		.tx_len = 1,
		.rx_buf = data,
		.rx_len = len
	};

	return mipi_dsi_device_transfer(dsi, &msg);
}

好了它就是填充了一个消息结构体,然后跟i2c一样transfer。读到数据。具体mipi帧格式我也不知道。
uboot patch

diff --git a/video/drm/dw_mipi_dsi.c b/video/drm/dw_mipi_dsi.c
old mode 100644
new mode 100755
index bf43669..7cd2f29
--- a/video/drm/dw_mipi_dsi.c
+++ b/video/drm/dw_mipi_dsi.c
@@ -18,6 +18,7 @@
 #include <syscon.h>
 #include <asm/arch-rockchip/clock.h>
 #include <linux/iopoll.h>
+#include <fdt_support.h>
 
 #include "rockchip_display.h"
 #include "rockchip_crtc.h"
@@ -655,7 +656,7 @@ static int dw_mipi_dsi_read_from_fifo(struct dw_mipi_dsi *dsi,
 	int ret;
 
 	ret = readl_poll_timeout(dsi->base + DSI_CMD_PKT_STATUS,
-				 val, !(val & GEN_RD_CMD_BUSY), 5000);
+				 val, !(val & GEN_RD_CMD_BUSY), 50000);
 	if (ret) {
 		printf("entire response isn't stored in the FIFO\n");
 		return ret;
@@ -718,7 +719,6 @@ static ssize_t dw_mipi_dsi_transfer(struct dw_mipi_dsi *dsi,
 	struct mipi_dsi_packet packet;
 	int ret;
 	int val;
-
 	if (msg->flags & MIPI_DSI_MSG_USE_LPM) {
 		dsi_update_bits(dsi, DSI_VID_MODE_CFG, LP_CMD_EN, LP_CMD_EN);
 		dsi_update_bits(dsi, DSI_LPCLK_CTRL, PHY_TXREQUESTCLKHS, 0);
@@ -1237,6 +1237,7 @@ static int dw_mipi_dsi_connector_prepare(struct display_state *state)
 	}
 
 	lane_rate = dw_mipi_dsi_get_lane_rate(dsi);
+	if(lane_rate == 0) lane_rate = 1000000000UL;
 	if (dsi->dphy.phy)
 		dw_mipi_dsi_set_hs_clk(dsi, lane_rate);
 	else
@@ -1279,12 +1280,43 @@ static int dw_mipi_dsi_connector_disable(struct display_state *state)
 	return 0;
 }
 
+static int dw_mipi_dsi_connector_fixup_dts(struct display_state *state, void *blob)
+{
+	struct connector_state *conn_state = &state->conn_state; 
+	struct panel_state *panel_state = &state->panel_state;
+    int num = panel_state->panel->num;	
+	const struct device_node *np;
+	const char *path;
+	int panel_node,connector;
+	
+	np = ofnode_to_np(conn_state->node);
+	path = np->full_name;
+	connector = fdt_path_offset(blob, path);
+
+	for (panel_node = fdt_subnode_offset(blob, connector, "panel");
+	     panel_node >= 0;
+	     panel_node = fdt_next_subnode(blob, panel_node)){
+ 
+		 dbg("fixup panel(num=%d) target =%d\n",fdtdec_get_int(blob, panel_node, "num", 0),num);
+
+	    if(fdtdec_get_int(blob, panel_node, "num", 0) != num){
+	    
+			fdt_status_disabled(blob, panel_node);
+	    }else{
+			fdt_status_okay(blob, panel_node);
+		}
+	 }
+		
+	return 0;
+}
+
 static const struct rockchip_connector_funcs dw_mipi_dsi_connector_funcs = {
 	.init = dw_mipi_dsi_connector_init,
 	.prepare = dw_mipi_dsi_connector_prepare,
 	.unprepare = dw_mipi_dsi_connector_unprepare,
 	.enable = dw_mipi_dsi_connector_enable,
 	.disable = dw_mipi_dsi_connector_disable,
+	.fixup_dts = dw_mipi_dsi_connector_fixup_dts,
 };
 
 static int dw_mipi_dsi_probe(struct udevice *dev)
diff --git a/video/drm/rockchip_display.c b/video/drm/rockchip_display.c
old mode 100644
new mode 100755
index 139a338..2636fde
--- a/video/drm/rockchip_display.c
+++ b/video/drm/rockchip_display.c
@@ -236,6 +236,77 @@ static int connector_panel_init(struct display_state *state)
 	return 0;
 }
 
+static int panel_matching(struct display_state *state)
+{
+	struct connector_state *conn_state = &state->conn_state;
+	struct panel_state *panel_state = &state->panel_state;
+	const struct rockchip_connector *conn = conn_state->connector;
+	const struct rockchip_connector_funcs *conn_funcs = conn->funcs;
+	ofnode panel_node;
+	struct udevice *panel_dev;
+	int ret;
+
+
+        if (conn_funcs->init) {
+            ret = conn_funcs->init(state);
+	    if (ret){
+			printf("failed to init connector\n");
+	    		goto deinit;
+	    }
+        }
+	
+	if (conn_state->phy)
+			rockchip_phy_init(conn_state->phy);
+	
+	ofnode_for_each_subnode(panel_node, conn_state->node) {
+
+        if (ofnode_valid(panel_node) && ofnode_is_available(panel_node)) {
+	        ret = uclass_get_device_by_ofnode(UCLASS_PANEL, panel_node,
+	        				  &panel_dev);
+	        if (ret){
+	        	 dbg("this sub node is not a panel node\n");
+	        	 continue;
+	        }
+	        
+        }
+        struct rockchip_panel *panel = (struct rockchip_panel *)dev_get_driver_data(panel_dev);
+        if (panel){
+
+			panel->state = state;
+		    panel_state->panel = panel;
+        }
+        if (!conn_funcs) {
+	        printf("failed to find connector functions\n");
+	        return -ENXIO;
+        }
+        
+        if (panel_state->panel)
+          rockchip_panel_init(panel_state->panel);
+		
+       	if (conn_funcs->prepare)
+   		    conn_funcs->prepare(state);
+
+        printf("%s(%d) getid\n", __func__, __LINE__);			   
+	    if(rockchip_panel_getId(panel_state->panel) != -1){
+	   	   dbg("dsi find panel id\n");
+		   rockchip_panel_unprepare(panel_state->panel);
+	   	   break;
+	    }
+	    rockchip_panel_unprepare(panel_state->panel);
+ 	    rockchip_panel_disable(panel_state->panel);
+	}
+	if (conn_funcs->disable)
+	   conn_funcs->disable(state);
+    
+	if (conn_funcs->unprepare)
+	   conn_funcs->unprepare(state);
+	return 0;
+	deinit:
+	if (conn_funcs->deinit)
+		conn_funcs->deinit(state);
+	return ret;	    
+}
+
 int drm_mode_vrefresh(const struct drm_display_mode *mode)
 {
 	int refresh = 0;
@@ -544,6 +615,20 @@ static int display_init(struct display_state *state)
 		return -ENXIO;
 	}
 
+	 ofnode_for_each_subnode(node, state->conn_state.node) {
+			const	struct device_node *np;
+			const char *path;
+			np = ofnode_to_np(node);
+			path = np->full_name;
+			if(strstr(path,"panel"))
+		        i++;
+	 }
+
+		if (i > 1 && panel_matching(state)) {
+			printf("Warn: Failed to match panel drivers\n");
+		}
+
+
 	if (crtc_state->crtc->active &&
 	    memcmp(&crtc_state->crtc->active_mode, &conn_state->mode,
 		   sizeof(struct drm_display_mode))) {
diff --git a/video/drm/rockchip_display.h b/video/drm/rockchip_display.h
old mode 100644
new mode 100755
index 5e89157..3cd0075
--- a/video/drm/rockchip_display.h
+++ b/video/drm/rockchip_display.h
@@ -53,6 +53,12 @@ enum rockchip_mcu_cmd {
 /* for use special outface */
 #define ROCKCHIP_OUT_MODE_AAAA	15
 
+#if 1
+#define dbg(format, arg...) printf("DSI-READ: " format "\n", ## arg)
+#else
+#define dbg(format, arg...) do {} while(0)
+#endif 
+
 struct rockchip_mcu_timing {
 	int mcu_pix_total;
 	int mcu_cs_pst;
@@ -95,7 +101,7 @@ struct crtc_state {
 
 struct panel_state {
 	struct rockchip_panel *panel;
-
+	int num;
 	ofnode dsp_lut_node;
 };
 
diff --git a/video/drm/rockchip_panel.c b/video/drm/rockchip_panel.c
old mode 100644
new mode 100755
index 6e27364..c949139
--- a/video/drm/rockchip_panel.c
+++ b/video/drm/rockchip_panel.c
@@ -41,6 +41,11 @@ struct rockchip_panel_cmds {
 	int cmd_cnt;
 };
 
+struct dsi_panel_id {
+	u8 *buf;
+	int len;
+};
+
 struct rockchip_panel_plat {
 	bool power_invert;
 	u32 bus_format;
@@ -57,6 +62,10 @@ struct rockchip_panel_plat {
 
 	struct rockchip_panel_cmds *on_cmds;
 	struct rockchip_panel_cmds *off_cmds;
+	struct rockchip_panel_cmds *read_id_cmds;
+	unsigned int id_reg;
+	struct dsi_panel_id *id;
+	unsigned int num;
 };
 
 struct rockchip_panel_priv {
@@ -299,6 +308,7 @@ static void panel_simple_prepare(struct rockchip_panel *panel)
 	}
 
 	priv->prepared = true;
+
 }
 
 static void panel_simple_unprepare(struct rockchip_panel *panel)
@@ -361,6 +371,11 @@ static void panel_simple_disable(struct rockchip_panel *panel)
 	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
 	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
 
+	if (dm_gpio_is_valid(&priv->reset_gpio))
+		dm_gpio_free(panel->dev, &priv->reset_gpio);
+	if (dm_gpio_is_valid(&priv->enable_gpio))
+		dm_gpio_free(panel->dev, &priv->enable_gpio);
+
 	if (!priv->enabled)
 		return;
 
@@ -381,12 +396,93 @@ static void panel_simple_init(struct rockchip_panel *panel)
 	conn_state->bus_format = panel->bus_format;
 }
 
+static int rockchip_dsi_panel_getId(struct rockchip_panel *panel)
+{
+	u8 *buf;
+	int i,len,ret = -1;
+	int count = 3;
+
+	struct rockchip_panel_plat *plat = dev_get_platdata(panel->dev);
+	struct rockchip_panel_priv *priv = dev_get_priv(panel->dev);
+	struct mipi_dsi_device *dsi = dev_get_parent_platdata(panel->dev);
+	dbg("%s(%d) start\n", __func__, __LINE__);
+	
+	len = plat->id->len;
+	printf("mingming-->%s(%d) start len:%d\n", __func__, __LINE__, len);
+	buf = malloc(sizeof(char) * len);
+	
+	if (priv->power_supply)
+		regulator_set_enable(priv->power_supply, !plat->power_invert);
+
+	if (dm_gpio_is_valid(&priv->enable_gpio))
+		dm_gpio_set_value(&priv->enable_gpio, 1);
+
+	if (plat->delay.prepare)
+		mdelay(plat->delay.prepare);
+
+	if (dm_gpio_is_valid(&priv->reset_gpio))
+		dm_gpio_set_value(&priv->reset_gpio, 1);
+
+	if (plat->delay.reset)
+		mdelay(plat->delay.reset);
+
+	if (dm_gpio_is_valid(&priv->reset_gpio))
+		dm_gpio_set_value(&priv->reset_gpio, 0);
+
+	if (plat->delay.init)
+		mdelay(plat->delay.init);
+	priv->prepared = true;
+
+	
+	if (plat->read_id_cmds) {
+		printf("send read id cmds\n");
+		rockchip_panel_send_dsi_cmds(dsi, plat->read_id_cmds);
+	    free(plat->read_id_cmds);
+		plat->read_id_cmds = NULL;
+	}else{
+		if (plat->on_cmds) {
+		printf("send on cmds\n");
+		ret = rockchip_panel_send_dsi_cmds(dsi, plat->on_cmds);
+		if (ret)
+			printf("failed to send on cmds: %d\n", ret);
+	   }     
+	   
+	}
+
+  ret = -1;
+	while((ret < 0) && count > 0){
+		if(len > 1){
+			ret = mipi_dsi_set_maximum_return_packet_size(dsi, len);
+		}
+		ret = mipi_dsi_dcs_read(dsi, plat->id_reg, buf,len);
+		count --;
+	}
+		
+	//  printf("panel_simple_prepare buf = %d \n",buf[0]);
+	if(ret == len)
+		for(i = 0; i < len; i++){
+			printf("read buf id[%d] = %x,panel target id[%d] = %x\n", i, *(buf + i), i, *(plat->id->buf + i));
+			if(*(buf + i) != *(plat->id->buf + i)){
+				plat->num = -1;
+				return -1;
+			}
+		}
+	else{
+		    dbg("read panel(num = %d) timeout or no response\n",plat->num);
+			plat->num = -1;
+			return -1;
+	}
+	panel->num = plat->num;
+	return 0;
+}	
+
 static const struct rockchip_panel_funcs rockchip_panel_funcs = {
 	.init = panel_simple_init,
 	.prepare = panel_simple_prepare,
 	.unprepare = panel_simple_unprepare,
 	.enable = panel_simple_enable,
 	.disable = panel_simple_disable,
+	.getId = rockchip_dsi_panel_getId,
 };
 
 static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
@@ -408,7 +504,23 @@ static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
 	plat->bus_format = dev_read_u32_default(dev, "bus-format",
 						MEDIA_BUS_FMT_RBG888_1X24);
 	plat->bpc = dev_read_u32_default(dev, "bpc", 8);
+	plat->id_reg =  dev_read_u32_default(dev, "id-reg", 0);
+	plat->num = dev_read_u32_default(dev, "num", 0);
+	data = dev_read_prop(dev, "id", &len);
 
+	if(data){
+		plat->id = malloc(sizeof(*plat->id));
+		if (!plat->id)
+			return -ENOMEM;
+		plat->id->buf = malloc(sizeof(char) * len); 	   
+		memcpy(plat->id->buf, data, len);
+		plat->id->len = len;
+	}
+
+	dbg("mingming-->dts id reg = 0x%x\n",plat->id_reg);
+	for(len =0;len < plat->id->len;len++){
+		dbg("dts id[%d] = %x\n", len, *(plat->id->buf + len) );
+	}
 	data = dev_read_prop(dev, "panel-init-sequence", &len);
 	if (data) {
 		plat->on_cmds = calloc(1, sizeof(*plat->on_cmds));
@@ -421,7 +533,20 @@ static int rockchip_panel_ofdata_to_platdata(struct udevice *dev)
 			goto free_on_cmds;
 		}
 	}
+	data = dev_read_prop(dev, "panel-read-id-sequence", &len);
+	if (data) {
+		plat->read_id_cmds = calloc(1, sizeof(*plat->read_id_cmds));
+		if (!plat->read_id_cmds)
+			return -ENOMEM;
 
+		ret = rockchip_panel_parse_cmds(data, len, plat->read_id_cmds);
+		if (ret) {
+			printf("failed to parse panel read id sequence\n");
+			goto free_read_id_cmds;
+		}
+	}else{
+	    plat->read_id_cmds = NULL;
+	}
 	data = dev_read_prop(dev, "panel-exit-sequence", &len);
 	if (data) {
 		plat->off_cmds = calloc(1, sizeof(*plat->off_cmds));
@@ -443,6 +568,9 @@ free_cmds:
 	free(plat->off_cmds);
 free_on_cmds:
 	free(plat->on_cmds);
+free_read_id_cmds:
+	free(plat->read_id_cmds);
+
 	return ret;
 }
 
diff --git a/video/drm/rockchip_panel.h b/video/drm/rockchip_panel.h
old mode 100644
new mode 100755
index 3a7587f..8ab9764
--- a/video/drm/rockchip_panel.h
+++ b/video/drm/rockchip_panel.h
@@ -16,6 +16,7 @@ struct rockchip_panel_funcs {
 	void (*unprepare)(struct rockchip_panel *panel);
 	void (*enable)(struct rockchip_panel *panel);
 	void (*disable)(struct rockchip_panel *panel);
+	int (*getId)(struct rockchip_panel *panel);
 };
 
 struct rockchip_panel {
@@ -24,7 +25,7 @@ struct rockchip_panel {
 	unsigned int bpc;
 	const struct rockchip_panel_funcs *funcs;
 	const void *data;
-
+	int num;
 	struct display_state *state;
 };
 
@@ -37,6 +38,17 @@ static inline void rockchip_panel_init(struct rockchip_panel *panel)
 		panel->funcs->init(panel);
 }
 
+static inline int rockchip_panel_getId(struct rockchip_panel *panel)
+{
+	if (!panel)
+		return -1;
+
+	if (panel->funcs && panel->funcs->getId)
+	    return 	panel->funcs->getId(panel);
+
+	return -1;
+}
+
 static inline void rockchip_panel_prepare(struct rockchip_panel *panel)
 {
 	if (!panel)

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值