基于九鼎核心板的rk3288 双屏开发

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lb5761311/article/details/90024470

OS:Android 5.1
platform: rk3288
rk3288支持双屏异显,一般使用的是mipi、lvds 和HDMI进行异显示,我们这边使用的是mipi和lvds。mipi 是主屏10寸的竖屏。lvds副屏7.85寸竖屏。
双屏显示要注意以下问题

1、双屏异显时,一个显示接口当主屏,另一个当副屏;主副屏由板级dts文件确定,启动后无法动态更改;
2、 当两路显示接口显示不同分辨率时,rk3288只能为一路显示接口提供精确时钟,另一路显示接口时钟会有微小频偏;

首先要修改kernel 相关dts的配置,
1、添加7.85寸 400X1280屏幕的配置文件

--- /dev/null
+++ b/arch/arm/boot/dts/lcd-TG078UW025A0-LVDS400x1280.dtsi
@@ -0,0 +1,35 @@
+/*
+ * RockChip. LCD_LVDS400x1280
+ *
+ */
+
+ //{
+
+		display-timings {
+              	native-mode = <&tg078uw>;
+                    tg078uw: timing0 {
+				screen-type = <SCREEN_LVDS>;
+				lvds-format = <LVDS_8BIT_1>;
+				out-face    = <OUT_P888>;
+				/* Min   Typ   Max Unit
+				 * Clock Frequency fclk  44.9  51.2  63 MHz
+				 */
+				clock-frequency = <58000000>;
+				hactive = <400>;			  /* Horizontal display area thd 1024       DCLK 			*/
+				vactive = <1280>;			  /* Vertical display area tvd   600 		H 				*/
+				hback-porch = <160>;		  	  /* HS Width +Back Porch   160  160   160  DCLK (Thw+ thbp)*/
+				hfront-porch = <160>;		  /* HS front porch thfp    16   160   216  DCLK 		 	*/
+				vback-porch = <10>;			  /* VS front porch tvfp 	1 	 12    127  H  			 	*/
+				vfront-porch = <12>;		  /* VS Width+Back Porch    23   23    23   H (Tvw+ tvbp)	*/
+				hsync-len = <24>;			  /* HS Pulse Width thw 	1 	  -    140  DCLK 		 	*/
+				vsync-len = <2>;			  /* VS Pulse Width tvw 	1 	  - 	20  H	 		 	*/
+				hsync-active = <0>;
+				vsync-active = <0>;
+				de-active = <0>;
+				pixelclk-active = <0>;
+				swap-rb = <0>;
+				swap-rg = <0>;
+				swap-gb = <0>;
+                     	};
+               };
+//};

2、添加10寸 mipi屏幕800x1280屏幕的配置文件

diff --git a/arch/arm/boot/dts/lcd_TG101WX_800x1280_mipi.dtsi b/arch/arm/boot/dts/lcd_TG101WX_800x1280_mipi.dtsi
new file mode 100755
index 0000000..efa186f
--- /dev/null
+++ b/arch/arm/boot/dts/lcd_TG101WX_800x1280_mipi.dtsi
@@ -0,0 +1,2086 @@
+/*
+ * Copyright (C) 2014 Firefly, Inc.
+ * arch/arm/boot/dts/lcd_TG101WX-mipi.dtsi
+ * create date: 2014-04-15
+ * lcd model:
+ * resolution: 800x1280
+ * mipi channel: signal
+ */
+
+// {	
+		/* about mipi */
+//		disp_mipi_init: mipi_dsi_init{
+						mipi_dsi_init{
+				
+							compatible = "rockchip,mipi_dsi_init";
+					rockchip,screen_init	= <1>;
+					rockchip,dsi_lane		= <4>;
+					rockchip,dsi_hs_clk		= <900>;
+					rockchip,mipi_dsi_num	= <1>;
+		};
+
+//		disp_mipi_power_ctr: mipi_power_ctr {
+							 mipi_power_ctr {
+					compatible = "rockchip,mipi_power_ctr";					
+					mipi_lcd_rst:mipi_lcd_rst{						
+					compatible = "rockchip,lcd_rst";
+							rockchip,gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+							rockchip,delay = <10>;
.............

disp_mode为DUAL_LCD模式,主要用于支持双LCD显示的产品配置

1、fb节点中属性rockchip,disp-mode设置为DUAL_LCD

2、设置fb节点中rockchip,uboot-logo-on=<0>;



 &fb {
-	rockchip,disp-mode = <DUAL>;
-	rockchip,uboot-logo-on = <1>;
+	rockchip,disp-mode = <DUAL_LCD>;
+	rockchip,uboot-logo-on = <0>;
+	rockchip,disp-policy = <DISPLAY_POLICY_SDK>;
 };

添加相关lcd驱动的头文件

diff --git a/arch/arm/boot/dts/x3288_ricoh620.dts b/arch/arm/boot/dts/x3288_ricoh620.dts
index e95ad5b..eccbd13 100755
--- a/arch/arm/boot/dts/x3288_ricoh620.dts
+++ b/arch/arm/boot/dts/x3288_ricoh620.dts
#include "rk3288.dtsi"
 #include <dt-bindings/input/input.h>
-#include "lcd_1024x600_mipi.dti"
+//#include "lcd_1024x600_mipi.dti"
 //#include "x3288_lcd070hdr.dtsi"
 //#include "x3288_cpt070hdm.dtsi"
 //#include "x3288_lcd070hdm.dtsi"
 //#include "x3288_ej080hdl.dtsi"
 //#include "x3288_lcd101hdl.dtsi"
+//#include "lcd_TG101WX_800x1280_mipi.dtsi"
+//#include "lcd-TG078UW025A0-LVDS400x1280.dtsi"

3、rk_screen节点打开两个screen节点配置,分别设置 sceen_prop属性为PRMRY和EXTEND并include对应屏的时序配置文件

&rk_screen {
-	 display-timings = <&disp_timings>;
+//	 display-timings = <&disp_timings>;
+	status = "okay";
+	screen0 {
+		screen_prop = <PRMRY>;
+		native-mode = <DEFAULT_MODE>;
+		#include "lcd_TG101WX_800x1280_mipi.dtsi"
+	};
+	screen1 {
+		screen_prop = <EXTEND>;
+		native-mode = <DEFAULT_MODE>;
+		power_ctr {
+		rockchip,debug = <1>;
+			lcd_en {
+				rockchip,power_type = <GPIO>;
+				gpios = <&gpio5 GPIO_C0 GPIO_ACTIVE_HIGH>;
+				rockchip,delay = <2>;
+			};
+			
+			lcd_rst {
+				rockchip,power_type = <GPIO>;
+				gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+				rockchip,delay = <2>;
+			};
+
+			lcd_stby {
+				rockchip,power_type = <GPIO>;
+				gpios = <&gpio7 GPIO_A2 GPIO_ACTIVE_HIGH>;
+				rockchip,delay = <5>;
+			};
+		};
+		#include "lcd-TG078UW025A0-LVDS400x1280.dtsi"
+	};
 };
 

3、LCDC0和LCDC1节点同时打开

 /*lcdc0 as PRMRY(LCD),lcdc1 as EXTEND(HDMI)*/
 &lcdc0 {
 	status = "okay";
 	rockchip,mirror = <NO_MIRROR>;
-	rockchip,cabc_mode = <0>;
+//	rockchip,cabc_mode = <0>;
+
+};
+
+&lcdc1 {
+	status = "okay";
+	rockchip,mirror = <NO_MIRROR>;
+/*
 	power_ctr: power_ctr {
 		rockchip,debug = <0>;
 		lcd_en:lcd_en {
 			rockchip,power_type = <GPIO>;
-			gpios = <&gpio7 GPIO_A3 GPIO_ACTIVE_HIGH>;
-			rockchip,delay = <100>;
+			gpios = <&gpio5 GPIO_C0 GPIO_ACTIVE_HIGH>;
+			rockchip,delay = <10>;
+		};
+		
+		lcd_rst:lcd_rst {
+			rockchip,power_type = <GPIO>;
+			gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+			rockchip,delay = <10>;
 		};
 	};
+*/
 };

打开EDP、MIPI、LVDS中需要使用的两个节点,关闭不需要的其他设备节点,如HDMI和MIPI

+&hdmi {
+	status = "disabled";
+	rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
 };
 
-&hdmi {
+&lvds {
 	status = "okay";
-	rockchip,hdmi_video_source = <DISPLAY_SOURCE_LCDC1>;
+	prop = <EXTEND>;
 };
 
+&dsihost0 {
+	status = "okay";
+	prop = <PRMRY>;
+ };
+

如果主屏和副屏共用一个rst 管脚,如果出现唤醒 主屏或者副屏唤醒概率性问题

index d69fa23..03afa3c 100755
--- a/arch/arm/boot/dts/x3288_ricoh620.dts
+++ b/arch/arm/boot/dts/x3288_ricoh620.dts
@@ -557,6 +557,14 @@
        screen0 {
                screen_prop = <PRMRY>;
                native-mode = <DEFAULT_MODE>;
+               power_ctr {
+                       rockchip,debug = <1>;
+                       lcd_rst {
+                               rockchip,power_type = <GPIO>;
+                               gpios = <&gpio7 GPIO_A4 GPIO_ACTIVE_HIGH>;
+                               rockchip,delay = <2>;
+                       };
+               };
                #include "lcd_TG101WX_800x1280_mipi.dtsi"
        };

kernel相关的修改

diff --git a/arch/arm/configs/x3288_defconfig b/arch/arm/configs/x3288_defconfig
index 1b60f86..bcb971e 100755
--- a/arch/arm/configs/x3288_defconfig
+++ b/arch/arm/configs/x3288_defconfig
@@ -2453,10 +2453,10 @@ CONFIG_BACKLIGHT_PWM=y
 # CONFIG_BACKLIGHT_LP855X is not set
 # CONFIG_ADF is not set
 CONFIG_FB_ROCKCHIP=y
-# CONFIG_FB_MIRRORING is not set
-# CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL is not set
+ CONFIG_FB_MIRRORING=y
+CONFIG_DUAL_LCDC_DUAL_DISP_IN_KERNEL=y
 # CONFIG_ONE_LCDC_DUAL_OUTPUT_INF is not set
-CONFIG_NO_DUAL_DISP=y
+#CONFIG_NO_DUAL_DISP=y
 # CONFIG_FB_ROTATE is not set
 CONFIG_THREE_FB_BUFFER=y
 CONFIG_LCDC_RK3188=y
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index f9d0e98..a2c672f 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -134,9 +134,11 @@ static const struct backlight_ops pwm_backlight_ops = {
 	.check_fb	= pwm_backlight_check_fb,
 };
 
+struct device_node *storenode;
+
 #ifdef CONFIG_OF
 static int pwm_backlight_parse_dt(struct device *dev,
-				  struct platform_pwm_backlight_data *data)
+				  struct platform_pwm_backlight_data *data, int pwmnum)
 {
 	struct device_node *node = dev->of_node;
 	enum of_gpio_flags flags;
@@ -147,7 +149,10 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
 	if (!node)
 		return -ENODEV;
-
+	
+	if(pwmnum) 
+		node = storenode; 
+	
 	memset(data, 0, sizeof(*data));
 
 	/* determine the number of brightness levels */
@@ -180,7 +185,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 		data->max_brightness--;
 	}
 
-	data->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0,
+	data->enable_gpio = of_get_named_gpio_flags(dev->of_node, "enable-gpios", 0,
 						    &flags);
 	if (data->enable_gpio == -EPROBE_DEFER)
 		return -EPROBE_DEFER;
@@ -193,6 +198,7 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
 static struct of_device_id pwm_backlight_of_match[] = {
 	{ .compatible = "pwm-backlight" },
+	{ .compatible = "pwm2-backlight" },
 	{ }
 };
 
@@ -213,17 +219,22 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	struct backlight_device *bl;
 	struct pwm_bl_data *pb;
 	int ret;
-
+	int pwmnum;
+ 
+	ret = of_property_read_u32(pdev->dev.of_node, "pwmnumber",&pwmnum);
+	if(!pwmnum) 
+		storenode = pdev->dev.of_node; 
+//	printk("----pwmnum==%d-----\n",pwmnum);
 	if (!data) {
-		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata);
+		ret = pwm_backlight_parse_dt(&pdev->dev, &defdata, pwmnum);
 		if (ret < 0) {
 			dev_err(&pdev->dev, "failed to find platform data\n");
 			return ret;
 		}
 
 		data = &defdata;
-	}
-
+	} 
+	
 	if (data->init) {
 		ret = data->init(&pdev->dev);
 		if (ret < 0)
@@ -302,7 +313,10 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	props.type = BACKLIGHT_RAW;
 	props.max_brightness = data->max_brightness;
 #ifdef CONFIG_ARCH_ROCKCHIP
-	dev_set_name(&pdev->dev, "rk28_bl");
+	if(!pwmnum)
+		dev_set_name(&pdev->dev, "rk28_bl");
+	else
+		dev_set_name(&pdev->dev, "rk28_bl2");
 #endif
 	bl = backlight_device_register(dev_name(&pdev->dev), &pdev->dev, pb,
 				       &pwm_backlight_ops, &props);
@@ -320,7 +334,8 @@ static int pwm_backlight_probe(struct platform_device *pdev)
 	}
 
 	bl->props.brightness = data->dft_brightness;
-	backlight_update_status(bl);
+	if(!pwmnum)
+		backlight_update_status(bl);		
 
 	platform_set_drvdata(pdev, bl);
 	return 0;
diff --git a/drivers/video/rockchip/rk_fb.c b/drivers/video/rockchip/rk_fb.c
index 11984b8..4702367 100755
--- a/drivers/video/rockchip/rk_fb.c
+++ b/drivers/video/rockchip/rk_fb.c
@@ -72,9 +72,11 @@ EXPORT_SYMBOL(video_data_to_mirroring);
 extern phys_addr_t uboot_logo_base;
 extern phys_addr_t uboot_logo_size;
 extern phys_addr_t uboot_logo_offset;
-static struct rk_fb_trsm_ops *trsm_lvds_ops;
-static struct rk_fb_trsm_ops *trsm_edp_ops;
-static struct rk_fb_trsm_ops *trsm_mipi_ops;
+//static struct rk_fb_trsm_ops *trsm_lvds_ops;
+//static struct rk_fb_trsm_ops *trsm_edp_ops;
+//static struct rk_fb_trsm_ops *trsm_mipi_ops;
+static struct rk_fb_trsm_ops *trsm_prmry_ops;
+static struct rk_fb_trsm_ops *trsm_extend_ops;
 static int uboot_logo_on;
 
 static int rk_fb_debug_lvl;
@@ -108,6 +110,7 @@ int rk_fb_get_display_policy(void)
 
 int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
 {
+/*
 	switch (type) {
 	case SCREEN_RGB:
 	case SCREEN_LVDS:
@@ -128,12 +131,20 @@ int rk_fb_trsm_ops_register(struct rk_fb_trsm_ops *ops, int type)
 		       __func__, type);
 		break;
 	}
+*/
+	if (type == PRMRY)
+		trsm_prmry_ops = ops;
+	else if (type == EXTEND)
+		trsm_extend_ops = ops;
+	else
+		printk("%s, type:%d\n", __func__, type);
 	return 0;
 }
 
 struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
 {
 	struct rk_fb_trsm_ops *ops;
+/*
 	switch (type) {
 	case SCREEN_RGB:
 	case SCREEN_LVDS:
@@ -155,6 +166,13 @@ struct rk_fb_trsm_ops *rk_fb_trsm_ops_get(int type)
 		       __func__, type);
 		break;
 	}
+*/
+	if (type == PRMRY)
+		ops = trsm_prmry_ops;
+	else if (type == EXTEND)
+		ops = trsm_extend_ops;
+	else
+		printk("%s, type:%d\n", __func__, type);
 	return ops;
 }
 
@@ -278,10 +296,13 @@ static int rk_fb_data_fmt(int data_format, int bits_per_pixel)
 /*
  * rk display power control parse from dts
  */
-int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
+//int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
+int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
+			     struct rk_screen *rk_screen)
 {
-	struct device_node *root = of_get_child_by_name(dev_drv->dev->of_node,
-							"power_ctr");
+//	struct device_node *root = of_get_child_by_name(dev_drv->dev->of_node,
+//							"power_ctr");
+	struct device_node *root = of_get_child_by_name(np, "power_ctr");
 	struct device_node *child;
 	struct rk_disp_pwr_ctr_list *pwr_ctr;
 	struct list_head *pos;
@@ -290,10 +311,13 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
 	u32 debug = 0;
 	int ret;
 
-	INIT_LIST_HEAD(&dev_drv->pwrlist_head);
+//	INIT_LIST_HEAD(&dev_drv->pwrlist_head);
+	INIT_LIST_HEAD(rk_screen->pwrlist_head);
 	if (!root) {
-		dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",
-			dev_drv->id);
+//		dev_err(dev_drv->dev, "can't find power_ctr node for lcdc%d\n",
+//			dev_drv->id);
+		dev_err(rk_screen->dev, "can't find power_ctr node for lcdc%d\n",
+			rk_screen->lcdc_id);
 		return -ENODEV;
 	}
 
@@ -306,7 +330,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
 				pwr_ctr->pwr_ctr.type = GPIO;
 				pwr_ctr->pwr_ctr.gpio = of_get_gpio_flags(child, 0, &flags);
 				if (!gpio_is_valid(pwr_ctr->pwr_ctr.gpio)) {
-					dev_err(dev_drv->dev, "%s ivalid gpio\n",
+					dev_err(rk_screen->dev, "%s ivalid gpio\n",
 						child->name);
 					return -EINVAL;
 				}
@@ -314,7 +338,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
 				ret = gpio_request(pwr_ctr->pwr_ctr.gpio,
 						   child->name);
 				if (ret) {
-					dev_err(dev_drv->dev,
+					dev_err(rk_screen->dev,
 						"request %s gpio fail:%d\n",
 						child->name, ret);
 				}
@@ -325,7 +349,7 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
 				ret = of_property_read_string(child, "rockchip,regulator_name",
 							     &(pwr_ctr->pwr_ctr.rgl_name));
 				if (ret || IS_ERR_OR_NULL(pwr_ctr->pwr_ctr.rgl_name))
-					dev_err(dev_drv->dev, "get regulator name failed!\n");
+					dev_err(rk_screen->dev, "get regulator name failed!\n");
 				if (!of_property_read_u32(child, "rockchip,regulator_voltage", &val))
 					pwr_ctr->pwr_ctr.volt = val;
 				else
@@ -337,13 +361,13 @@ int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv)
 			pwr_ctr->pwr_ctr.delay = val;
 		else
 			pwr_ctr->pwr_ctr.delay = 0;
-		list_add_tail(&pwr_ctr->list, &dev_drv->pwrlist_head);
+		list_add_tail(&pwr_ctr->list, rk_screen->pwrlist_head);
 	}
 
 	of_property_read_u32(root, "rockchip,debug", &debug);
 
 	if (debug) {
-		list_for_each(pos, &dev_drv->pwrlist_head) {
+		list_for_each(pos, rk_screen->pwrlist_head) {
 			pwr_ctr = list_entry(pos, struct rk_disp_pwr_ctr_list,
 					     list);
 			printk(KERN_INFO "pwr_ctr_name:%s\n"
@@ -371,9 +395,16 @@ int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv)
 	struct regulator *regulator_lcd = NULL;
 	int count = 10;
 
-	if (list_empty(&dev_drv->pwrlist_head))
+//	if (list_empty(&dev_drv->pwrlist_head))
+	if (!dev_drv->cur_screen->pwrlist_head) {
+		pr_info("error:  %s, lcdc%d screen pwrlist null\n",
+			__func__, dev_drv->id);
 		return 0;
-	list_for_each(pos, &dev_drv->pwrlist_head) {
+//	list_for_each(pos, &dev_drv->pwrlist_head) {
+	}
+	if (list_empty(dev_drv->cur_screen->pwrlist_head))
+		return 0;
+	list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
 		pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
 					  list);
 		pwr_ctr = &pwr_ctr_list->pwr_ctr;
@@ -415,9 +446,16 @@ int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv)
 	struct regulator *regulator_lcd = NULL;
 	int count = 10;
 
-	if (list_empty(&dev_drv->pwrlist_head))
+//	if (list_empty(&dev_drv->pwrlist_head))
+	if (!dev_drv->cur_screen->pwrlist_head) {
+		pr_info("error:  %s, lcdc%d screen pwrlist null\n",
+			__func__, dev_drv->id);
+		return 0;
+//	list_for_each(pos, &dev_drv->pwrlist_head) {
+	}
+	if (list_empty(dev_drv->cur_screen->pwrlist_head))
 		return 0;
-	list_for_each(pos, &dev_drv->pwrlist_head) {
+	list_for_each(pos, dev_drv->cur_screen->pwrlist_head) {
 		pwr_ctr_list = list_entry(pos, struct rk_disp_pwr_ctr_list,
 					  list);
 		pwr_ctr = &pwr_ctr_list->pwr_ctr;
@@ -497,7 +535,8 @@ int rk_fb_prase_timing_dt(struct device_node *np, struct rk_screen *screen)
 		pr_err("parse display timing err\n");
 		return -EINVAL;
 	}
-	dt = display_timings_get(disp_timing, disp_timing->native_mode);
+//	dt = display_timings_get(disp_timing, disp_timing->native_mode);
+	dt = display_timings_get(disp_timing, screen->native_mode);
 	rk_fb_video_mode_from_timing(dt, screen);
 	return 0;
 
@@ -1583,6 +1622,7 @@ static void rk_fb_update_win(struct rk_lcdc_driver *dev_drv,
 				win->area[i].smem_start =
 					reg_win_data->reg_area_data[i].smem_start;
                                 if (inf->disp_mode == DUAL ||
+									inf->disp_mode == DUAL_LCD ||
                                     inf->disp_mode == NO_DUAL) {
 				        win->area[i].xpos =
 				                reg_win_data->reg_area_data[i].xpos;
@@ -3769,7 +3809,9 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi)
 		win = dev_drv->win[win_id];
 
 	if (!strcmp(fbi->fix.id, "fb0")) {
-		fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+//		fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+		fb_mem_size = get_fb_size(dev_drv->reserved_fb,
+					  dev_drv->cur_screen);
 #if defined(CONFIG_ION_ROCKCHIP)
 		if (rk_fb_alloc_buffer_by_ion(fbi, win, fb_mem_size) < 0)
 			return -ENOMEM;
@@ -3790,7 +3832,9 @@ static int rk_fb_alloc_buffer(struct fb_info *fbi)
 		if (dev_drv->prop == EXTEND && dev_drv->iommu_enabled) {
 			struct rk_lcdc_driver *dev_drv_prmry;
 			int win_id_prmry;
-			fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+//			fb_mem_size = get_fb_size(dev_drv->reserved_fb);
+			fb_mem_size = get_fb_size(dev_drv->reserved_fb,
+						  dev_drv->cur_screen);
 #if defined(CONFIG_ION_ROCKCHIP)
 			dev_drv_prmry = rk_get_prmry_lcdc_drv();
 			if (dev_drv_prmry == NULL)
@@ -3953,14 +3997,17 @@ static int init_lcdc_device_driver(struct rk_fb *rk_fb,
 		dev_drv->area_support[i] = 1;
 	if (dev_drv->ops->area_support_num)
 		dev_drv->ops->area_support_num(dev_drv, dev_drv->area_support);
-	rk_disp_pwr_ctr_parse_dt(dev_drv);
-	if (dev_drv->prop == PRMRY) {
-		rk_fb_set_prmry_screen(screen);
-		rk_fb_get_prmry_screen(screen);
-	}
-	dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
-	if (dev_drv->prop != PRMRY)
-		rk_fb_get_extern_screen(screen);
+//	rk_disp_pwr_ctr_parse_dt(dev_drv);
+//	if (dev_drv->prop == PRMRY) {
+//		rk_fb_set_prmry_screen(screen);
+//		rk_fb_get_prmry_screen(screen);
+//	}
+//	dev_drv->trsm_ops = rk_fb_trsm_ops_get(screen->type);
+//	if (dev_drv->prop != PRMRY)
+//		rk_fb_get_extern_screen(screen);
+	rk_fb_set_screen(screen, dev_drv->prop);
+	rk_fb_get_screen(screen, dev_drv->prop);
+	dev_drv->trsm_ops = rk_fb_trsm_ops_get(dev_drv->prop);
 	dev_drv->output_color = screen->color_mode;
 
 	return 0;
@@ -4280,15 +4327,24 @@ int rk_fb_register(struct rk_lcdc_driver *dev_drv,
 	} else {
                 struct fb_info *extend_fbi = rk_fb->fb[rk_fb->num_fb >> 1];
                 extend_fbi->var.pixclock = rk_fb->fb[0]->var.pixclock;
+				extend_fbi->var.xres_virtual = rk_fb->fb[0]->var.xres_virtual;
+				extend_fbi->var.yres_virtual = rk_fb->fb[0]->var.yres_virtual;
 		extend_fbi->fbops->fb_open(extend_fbi, 1);
 #if defined(CONFIG_ROCKCHIP_IOMMU)
 		if (dev_drv->iommu_enabled) {
 			if (dev_drv->mmu_dev)
 				rockchip_iovmm_set_fault_handler(dev_drv->dev,
 								 rk_fb_sysmmu_fault_handler);
+				if (dev_drv->ops->mmu_en)
+					dev_drv->ops->mmu_en(dev_drv);
 		}
 #endif
 		rk_fb_alloc_buffer(extend_fbi);
+		if (rk_fb->disp_mode == DUAL_LCD) {
+			extend_fbi->fbops->fb_set_par(extend_fbi);
+			extend_fbi->fbops->fb_pan_display(&extend_fbi->var,
+							  extend_fbi);
+		}
 	}
 #endif
 	return 0;
diff --git a/drivers/video/rockchip/screen/rk_screen.c b/drivers/video/rockchip/screen/rk_screen.c
index d5e3b15..fad07bf 100755
--- a/drivers/video/rockchip/screen/rk_screen.c
+++ b/drivers/video/rockchip/screen/rk_screen.c
@@ -4,14 +4,26 @@
 #include "lcd.h"
 #include "../hdmi/rockchip-hdmi.h"
 
-static struct rk_screen *rk_screen;
+//static struct rk_screen *rk_screen;
+static struct rk_screen *prmry_screen;
+static struct rk_screen *extend_screen;
+
+static void rk_screen_info_error(struct rk_screen *screen, int prop)
+{
+	pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
+	pr_err(">>please init %s screen info in dtsi file<<\n",
+	       (prop == PRMRY) ? "prmry" : "extend");
+	pr_err(">>>>>>>>>>>>>>>>>>>>error<<<<<<<<<<<<<<<<<<<<\n");
+}
 
 int rk_fb_get_extern_screen(struct rk_screen *screen)
 {
-	if (unlikely(!rk_screen) || unlikely(!screen))
+//	if (unlikely(!rk_screen) || unlikely(!screen))
+	if (unlikely(!extend_screen) || unlikely(!screen))
 		return -1;
 
-	memcpy(screen, rk_screen, sizeof(struct rk_screen));
+//	memcpy(screen, rk_screen, sizeof(struct rk_screen));
+	memcpy(screen, extend_screen, sizeof(struct rk_screen));
 	screen->dsp_lut = NULL;
 	screen->cabc_lut = NULL;
 	screen->type = SCREEN_NULL;
@@ -21,18 +33,39 @@ int rk_fb_get_extern_screen(struct rk_screen *screen)
 
 int  rk_fb_get_prmry_screen(struct rk_screen *screen)
 {
-	if (unlikely(!rk_screen) || unlikely(!screen))
+//	if (unlikely(!rk_screen) || unlikely(!screen))
+	if (unlikely(!prmry_screen) || unlikely(!screen))
 		return -1;
 
-	memcpy(screen, rk_screen, sizeof(struct rk_screen));
+//	memcpy(screen, rk_screen, sizeof(struct rk_screen));
+	memcpy(screen, prmry_screen, sizeof(struct rk_screen));
 	return 0;
 }
 
-int rk_fb_set_prmry_screen(struct rk_screen *screen)
+//int rk_fb_set_prmry_screen(struct rk_screen *screen)
+int  rk_fb_get_screen(struct rk_screen *screen, int prop)
 {
-	if (unlikely(!rk_screen) || unlikely(!screen))
+//	if (unlikely(!rk_screen) || unlikely(!screen))
+	struct rk_screen *cur_screen = NULL;
+
+	if (unlikely(!screen))
 		return -1;
+	if (prop == PRMRY) {
+		if (unlikely(!prmry_screen)) {
+			rk_screen_info_error(screen, prop);
+			return -1;
+		}
+		cur_screen = prmry_screen;
+	} else {
+		if (unlikely(!extend_screen)) {
+			rk_screen_info_error(screen, prop);
+			return -1;
+		}
+		cur_screen = extend_screen;
+	}
 
+	memcpy(screen, cur_screen, sizeof(struct rk_screen));
+/*
 	rk_screen->lcdc_id = screen->lcdc_id;
 	rk_screen->screen_id = screen->screen_id;
 	rk_screen->x_mirror = screen->x_mirror;
@@ -41,20 +74,57 @@ int rk_fb_set_prmry_screen(struct rk_screen *screen)
 	rk_screen->overscan.top = screen->overscan.left;
 	rk_screen->overscan.right = screen->overscan.left;
 	rk_screen->overscan.bottom = screen->overscan.left;
+*/
 	return 0;
 }
 
-size_t get_fb_size(u8 reserved_fb)
+//size_t get_fb_size(u8 reserved_fb)
+int rk_fb_set_screen(struct rk_screen *screen, int prop)
+{
+	struct rk_screen *cur_screen = NULL;
+
+	if (unlikely(!screen))
+		return -1;
+	if (prop == PRMRY) {
+		if (unlikely(!prmry_screen)) {
+			rk_screen_info_error(screen, prop);
+			return -1;
+		}
+		cur_screen = prmry_screen;
+	} else {
+		if (unlikely(!extend_screen)) {
+			rk_screen_info_error(screen, prop);
+			return -1;
+		}
+		cur_screen = extend_screen;
+	}
+
+	cur_screen->lcdc_id = screen->lcdc_id;
+	cur_screen->screen_id = screen->screen_id;
+	cur_screen->x_mirror = screen->x_mirror;
+	cur_screen->y_mirror = screen->y_mirror;
+	cur_screen->overscan.left = screen->overscan.left;
+	cur_screen->overscan.top = screen->overscan.left;
+	cur_screen->overscan.right = screen->overscan.left;
+	cur_screen->overscan.bottom = screen->overscan.left;
+
+	return 0;
+}
+
+size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen)
 {
 	size_t size = 0;
 	u32 xres = 0;
 	u32 yres = 0;
 
-	if (unlikely(!rk_screen))
+//	if (unlikely(!rk_screen))
+	if (unlikely(!screen))
 		return 0;
 
-	xres = rk_screen->mode.xres;
-	yres = rk_screen->mode.yres;
+//	xres = rk_screen->mode.xres;
+//	yres = rk_screen->mode.yres;
+	xres = screen->mode.xres;
+	yres = screen->mode.yres;
 
 	/* align as 64 bytes(16*4) in an odd number of times */
 	xres = ALIGN_64BYTE_ODD_TIMES(xres, ALIGN_PIXEL_64BYTE_RGB8888);
@@ -73,22 +143,61 @@ size_t get_fb_size(u8 reserved_fb)
 static int rk_screen_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-	int ret;
+//	int ret;
+	struct device_node *screen_np;
+	struct rk_screen *rk_screen;
+	int ret, screen_prop;
 
 	if (!np) {
 		dev_err(&pdev->dev, "Missing device tree node.\n");
 		return -EINVAL;
 	}
-	rk_screen = devm_kzalloc(&pdev->dev,
+/*	rk_screen = devm_kzalloc(&pdev->dev,
 			sizeof(struct rk_screen), GFP_KERNEL);
 	if (!rk_screen) {
 		dev_err(&pdev->dev, "kmalloc for rk screen fail!");
 		return  -ENOMEM;
+*/
+
+	for_each_child_of_node(np, screen_np) {
+		rk_screen = devm_kzalloc(&pdev->dev,
+					 sizeof(struct rk_screen), GFP_KERNEL);
+		if (!rk_screen) {
+			dev_err(&pdev->dev, "kmalloc for rk screen fail!");
+			return  -ENOMEM;
+		}
+		rk_screen->pwrlist_head = devm_kzalloc(&pdev->dev,
+				sizeof(struct list_head), GFP_KERNEL);
+		if (!rk_screen->pwrlist_head) {
+			dev_err(&pdev->dev, "kmalloc for rk_screen pwrlist_head fail!");
+			return  -ENOMEM;
+		}
+		of_property_read_u32(screen_np, "screen_prop", &screen_prop);
+		if (screen_prop == PRMRY)
+			prmry_screen = rk_screen;
+		else if (screen_prop == EXTEND)
+			extend_screen = rk_screen;
+		else
+			dev_err(&pdev->dev, "unknow screen prop: %d\n",
+				screen_prop);
+		rk_screen->prop = screen_prop;
+		of_property_read_u32(screen_np, "native-mode", &rk_screen->native_mode);
+		rk_screen->dev = &pdev->dev;
+		ret = rk_fb_prase_timing_dt(screen_np, rk_screen);
+		pr_info("%s screen timing parse %s\n",
+			(screen_prop == PRMRY) ? "prmry" : "extend",
+			ret ? "failed" : "success");
+		ret = rk_disp_pwr_ctr_parse_dt(screen_np, rk_screen);
+		pr_info("%s screen power ctrl parse %s\n",
+			(screen_prop == PRMRY) ? "prmry" : "extend",
+			ret ? "failed" : "success");
 	}
-	ret = rk_fb_prase_timing_dt(np, rk_screen);
-	dev_info(&pdev->dev, "rockchip screen probe %s\n",
-				ret ? "failed" : "success");
-	return ret;
+//	ret = rk_fb_prase_timing_dt(np, rk_screen);
+//	dev_info(&pdev->dev, "rockchip screen probe %s\n",
+//				ret ? "failed" : "success");
+//	return ret;
+	dev_info(&pdev->dev, "rockchip screen probe success\n");
+	return 0;
 }
 
 static const struct of_device_id rk_screen_dt_ids[] = {
diff --git a/drivers/video/rockchip/transmitter/rk32_dp.c b/drivers/video/rockchip/transmitter/rk32_dp.c
index 2b3457c..a1dbf5b 100755
--- a/drivers/video/rockchip/transmitter/rk32_dp.c
+++ b/drivers/video/rockchip/transmitter/rk32_dp.c
@@ -119,7 +119,8 @@ static int rk32_edp_init_edp(struct rk32_edp *edp)
 	struct rk_screen *screen = &edp->screen;
 	u32 val = 0;
 
-	rk_fb_get_prmry_screen(screen);
+//	rk_fb_get_prmry_screen(screen);
+	rk_fb_get_screen(screen, edp->prop);
 
 	if (cpu_is_rk3288()) {
 		if (screen->lcdc_id == 1)  /*select lcdc*/
@@ -1712,17 +1713,22 @@ static int rk32_edp_probe(struct platform_device *pdev)
 	struct resource *res;
 	struct device_node *np = pdev->dev.of_node;
 	int ret;
+	int prop;
 
 	if (!np) {
 		dev_err(&pdev->dev, "Missing device tree node.\n");
 		return -EINVAL;
 	}
 
+	of_property_read_u32(np, "prop", &prop);
+	pr_info("Use EDP as %s screen\n", (prop == PRMRY) ? "prmry" : "extend");
+	
 	edp = devm_kzalloc(&pdev->dev, sizeof(struct rk32_edp), GFP_KERNEL);
 	if (!edp) {
 		dev_err(&pdev->dev, "no memory for state\n");
 		return -ENOMEM;
 	}
+	edp->prop = prop;
 	edp->dev = &pdev->dev;
 	edp->video_info.h_sync_polarity	= 0;
 	edp->video_info.v_sync_polarity	= 0;
@@ -1734,7 +1740,8 @@ static int rk32_edp_probe(struct platform_device *pdev)
 
 	edp->video_info.link_rate	= LINK_RATE_1_62GBPS;
 	edp->video_info.lane_count	= LANE_CNT4;
-	rk_fb_get_prmry_screen(&edp->screen);
+//	rk_fb_get_prmry_screen(&edp->screen);
+	rk_fb_get_screen(&edp->screen, prop);
 	if (edp->screen.type != SCREEN_EDP) {
 		dev_err(&pdev->dev, "screen is not edp!\n");
 		return -EINVAL;
@@ -1809,7 +1816,8 @@ static int rk32_edp_probe(struct platform_device *pdev)
 	if (!support_uboot_display())
 		rk32_edp_clk_disable(edp);
 	rk32_edp = edp;
-	rk_fb_trsm_ops_register(&trsm_edp_ops, SCREEN_EDP);
+//	rk_fb_trsm_ops_register(&trsm_edp_ops, SCREEN_EDP);
+	rk_fb_trsm_ops_register(&trsm_edp_ops, prop);
 #if defined(CONFIG_DEBUG_FS)
 	edp->debugfs_dir = debugfs_create_dir("edp", NULL);
 	if (IS_ERR(edp->debugfs_dir)) {
diff --git a/drivers/video/rockchip/transmitter/rk32_dp.h b/drivers/video/rockchip/transmitter/rk32_dp.h
index 08347b5..8ec3e26 100755
--- a/drivers/video/rockchip/transmitter/rk32_dp.h
+++ b/drivers/video/rockchip/transmitter/rk32_dp.h
@@ -566,6 +566,7 @@ struct rk32_edp {
 	bool clk_on;
 	bool edp_en;
 	struct dentry *debugfs_dir;
+	int prop;
 };
 
 
diff --git a/drivers/video/rockchip/transmitter/rk32_lvds.c b/drivers/video/rockchip/transmitter/rk32_lvds.c
index d0a8b7a..793fafd 100755
--- a/drivers/video/rockchip/transmitter/rk32_lvds.c
+++ b/drivers/video/rockchip/transmitter/rk32_lvds.c
@@ -59,7 +59,8 @@ static int rk32_lvds_en(void)
 	u32 h_bp = 0;
 	u32 val = 0;
 
-	rk_fb_get_prmry_screen(screen);
+//	rk_fb_get_prmry_screen(screen);
+	rk_fb_get_screen(screen, lvds->prop);
 
 	/* enable clk */
 	rk32_lvds_clk_enable(lvds);
@@ -140,19 +141,23 @@ static int rk32_lvds_probe(struct platform_device *pdev)
 	struct rk32_lvds *lvds;
 	struct resource *res;
 	struct device_node *np = pdev->dev.of_node;
+	int prop;
 
 	if (!np) {
 		dev_err(&pdev->dev, "Missing device tree node.\n");
 		return -EINVAL;
 	}
 
+	of_property_read_u32(np, "prop", &prop);
+	pr_info("Use LVDS as %s screen\n", (prop == PRMRY) ? "prmry":"extend");
 	lvds = devm_kzalloc(&pdev->dev, sizeof(struct rk32_lvds), GFP_KERNEL);
 	if (!lvds) {
 		dev_err(&pdev->dev, "no memory for state\n");
 		return -ENOMEM;
 	}
 	lvds->dev = &pdev->dev;
-	rk_fb_get_prmry_screen(&lvds->screen);
+//	rk_fb_get_prmry_screen(&lvds->screen);
+	rk_fb_get_screen(&lvds->screen, prop);
 	if ((lvds->screen.type != SCREEN_RGB) && 
 		(lvds->screen.type != SCREEN_LVDS) &&
 		(lvds->screen.type != SCREEN_DUAL_LVDS) &&
@@ -185,7 +190,9 @@ static int rk32_lvds_probe(struct platform_device *pdev)
 	}
 
 	rk32_lvds = lvds;
-	rk_fb_trsm_ops_register(&trsm_lvds_ops,SCREEN_LVDS);
+//	rk_fb_trsm_ops_register(&trsm_lvds_ops,SCREEN_LVDS);
+	lvds->prop = prop;
+	rk_fb_trsm_ops_register(&trsm_lvds_ops, prop);
 	dev_info(&pdev->dev, "rk32 lvds driver probe success\n");
 
 	return 0;
diff --git a/drivers/video/rockchip/transmitter/rk32_lvds.h b/drivers/video/rockchip/transmitter/rk32_lvds.h
index ca424a7..833c80d 100755
--- a/drivers/video/rockchip/transmitter/rk32_lvds.h
+++ b/drivers/video/rockchip/transmitter/rk32_lvds.h
@@ -34,6 +34,7 @@ struct rk32_lvds {
 	struct clk              *pd;
 	struct rk_screen	screen;
 	bool			clk_on;
+	int prop;
 };
 
 static int inline lvds_writel(struct rk32_lvds *lvds, u32 offset, u32 val)
diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
index 1b82380..2d99bbb 100755
--- a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
+++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.c
@@ -1579,7 +1579,8 @@ static int rk32_dsi_enable(void)
 	MIPI_DBG("rk32_dsi_enable-------\n");
 	if (!dsi0->clk_on) {
 		dsi0->clk_on = 1;
-		rk_fb_get_prmry_screen(dsi0->screen.screen);
+//		rk_fb_get_prmry_screen(dsi0->screen.screen);
+		rk_fb_get_screen(dsi0->screen.screen, dsi0->screen.screen->prop);
 		dsi0->screen.lcdc_id = dsi0->screen.screen->lcdc_id;
 		rk32_init_phy_mode(dsi0->screen.lcdc_id);
 
@@ -1712,6 +1713,7 @@ static const struct of_device_id of_rk_mipi_dsi_match[] = {
 static int rk32_mipi_dsi_probe(struct platform_device *pdev)
 {
 	int ret = 0;
+	int prop;
 	static int id;
 	struct dsi *dsi;
 	struct mipi_dsi_ops *ops;
@@ -1719,6 +1721,7 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
 	struct mipi_dsi_screen *dsi_screen;
 	struct resource *res_host, *res_phy;
 	const struct dsi_type *data;
+	struct device_node *np = pdev->dev.of_node;
 	const struct of_device_id *of_id =
 			of_match_device(of_rk_mipi_dsi_match, &pdev->dev);
 	if (!of_id) {
@@ -1726,12 +1729,18 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 	data = of_id->data;
-
+	
+	of_property_read_u32(np, "prop", &prop);
+	pr_info("Use mipi_lcd as %s screen\n", (prop == PRMRY) ? "prmry" : "extend");
+	
 	dsi = devm_kzalloc(&pdev->dev, sizeof(struct dsi), GFP_KERNEL);
 	if (!dsi) {
 		dev_err(&pdev->dev, "request struct dsi fail!\n");
 		return -ENOMEM;
 	}
+	
+	dsi->prop = prop;
+	
 	dsi->ops.id = data->dsi_id;
 	printk(KERN_INFO "%s\n", data->label);
 	if (dsi->ops.id == DWC_DSI_VERSION) {
@@ -1834,7 +1843,8 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
 		dev_err(&pdev->dev, "request struct rk_screen fail!\n");
 		return -1;
 	}
-	rk_fb_get_prmry_screen(screen);
+//	rk_fb_get_prmry_screen(screen);
+	rk_fb_get_screen(screen, prop);
 
 	dsi->pdev = pdev;
 	ops = &dsi->ops;
@@ -1894,7 +1904,8 @@ static int rk32_mipi_dsi_probe(struct platform_device *pdev)
 		if(!support_uboot_display())
 			rk32_init_phy_mode(dsi_screen->lcdc_id);
 		*/
-		rk_fb_trsm_ops_register(&trsm_dsi_ops, SCREEN_MIPI);
+//		rk_fb_trsm_ops_register(&trsm_dsi_ops, SCREEN_MIPI);
+		rk_fb_trsm_ops_register(&trsm_dsi_ops, prop);
 #ifdef MIPI_DSI_REGISTER_IO
 		debugfs_create_file("mipidsi0", S_IFREG | S_IRUGO, dsi->debugfs_dir, dsi,
 							&reg_proc_fops);
diff --git a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
index de4b172..d48e381 100755
--- a/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
+++ b/drivers/video/rockchip/transmitter/rk32_mipi_dsi.h
@@ -311,6 +311,7 @@ struct dsi {
 #endif
 	struct dentry *debugfs_dir;
 	struct platform_device *pdev;
+	int prop;
 };
 
 int rk_mipi_get_dsi_clk(void);
diff --git a/include/dt-bindings/rkfb/rk_fb.h b/include/dt-bindings/rkfb/rk_fb.h
index b903f92..e999466 100755
--- a/include/dt-bindings/rkfb/rk_fb.h
+++ b/include/dt-bindings/rkfb/rk_fb.h
@@ -12,6 +12,7 @@
 #define NO_DUAL		0
 #define ONE_DUAL	1
 #define DUAL		2
+#define DUAL_LCD	3
 
 #define OUT_P888            0	//24bit screen,connect to lcdc D0~D23
 #define OUT_P666            1	//18bit screen,connect to lcdc D0~D17
@@ -73,6 +74,12 @@
 #define DISPLAY_POLICY_SDK	0
 #define DISPLAY_POLICY_BOX	1
 #define DISPLAY_POLICY_BOX_TEMP	2
+#define	DEFAULT_MODE		0
+#define	HDMI_720P		0
+#define HDMI_1080P		1
+#define	HDMI_2160P		2
+#define NTSC_CVBS		3
+#define PAL_CVBS		4
 
 /*      	lvds connect config       
  *                                        
diff --git a/include/linux/rk_fb.h b/include/linux/rk_fb.h
index e17c49c..5dc4bdb 100755
--- a/include/linux/rk_fb.h
+++ b/include/linux/rk_fb.h
@@ -713,11 +713,15 @@ extern int rk_fb_register(struct rk_lcdc_driver *dev_drv,
 				struct rk_lcdc_win *win, int id);
 extern int rk_fb_unregister(struct rk_lcdc_driver *dev_drv);
 extern struct rk_lcdc_driver *rk_get_lcdc_drv(char *name);
-extern int rk_fb_get_extern_screen(struct rk_screen *screen);
+//extern int rk_fb_get_extern_screen(struct rk_screen *screen);
 extern int rk_fb_get_prmry_screen( struct rk_screen *screen);
-extern int rk_fb_set_prmry_screen(struct rk_screen *screen);
+//extern int rk_fb_set_prmry_screen(struct rk_screen *screen);
+extern int rk_fb_get_screen(struct rk_screen *screen, int prop);
+extern int rk_fb_set_screen(struct rk_screen *screen, int prop);
 extern u32 rk_fb_get_prmry_screen_pixclock(void);
-extern int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv);
+//extern int rk_disp_pwr_ctr_parse_dt(struct rk_lcdc_driver *dev_drv);
+extern int rk_disp_pwr_ctr_parse_dt(struct device_node *np,
+				    struct rk_screen *rk_screen);
 extern int rk_disp_pwr_enable(struct rk_lcdc_driver *dev_drv);
 extern int rk_disp_pwr_disable(struct rk_lcdc_driver *dev_drv);
 extern bool is_prmry_rk_lcdc_registered(void);
diff --git a/include/linux/rk_screen.h b/include/linux/rk_screen.h
index af0ffe7..1b591e6 100644
--- a/include/linux/rk_screen.h
+++ b/include/linux/rk_screen.h
@@ -61,12 +61,16 @@ struct overscan {
 *ft: the time need to display one frame time
 */
 struct rk_screen {
+	struct device	*dev;
+	int prop;
+	struct list_head *pwrlist_head;
 	u16 type;
 	u16 lvds_format; 
 	u16 face;
 	u16 color_mode;
 	u8 lcdc_id;   
 	u8 screen_id; 
+	int native_mode;
 	struct fb_videomode mode;
 	u32 post_dsp_stx;
 	u32 post_dsp_sty;
@@ -144,7 +148,8 @@ struct rk29fb_info {
 };
 
 extern void set_lcd_info(struct rk_screen *screen, struct rk29lcd_info *lcd_info);
-extern size_t get_fb_size(u8 reserved_fb);
+//extern size_t get_fb_size(u8 reserved_fb);
+extern size_t get_fb_size(u8 reserved_fb, struct rk_screen *screen);
 
 extern void set_tv_info(struct rk_screen *screen);
 extern void set_hdmi_info(struct rk_screen *screen);

hardware 相关双屏的修改

diff --git a/rk_hwcomposer.cpp b/rk_hwcomposer.cpp
index a82b601..9888add 100755
--- a/rk_hwcomposer.cpp
+++ b/rk_hwcomposer.cpp
@@ -62,6 +62,7 @@ static int  hwc_device_close(struct hw_device_t * dev);
 
 int         hwc_sprite_replace(hwcContext * Context, hwc_display_contents_1_t * list);
 void*       hwc_control_3dmode_thread(void *arg);
+int         hwc_parse_screen_info(int *outX, int *outY);
 
 void*   hotplug_try_register(void *arg);
 void    hotplug_get_resolution(int* w,int* h);
@@ -9532,7 +9533,10 @@ int hotplug_get_config(int flag){
 	struct fb_var_screeninfo info = _contextAnchor->info;
 	int outX = 0;
 	int outY = 0;
-	hotplug_parse_mode(&outX, &outY);
+	if (hwc_get_int_property("ro.htg.force", "0"))
+	    hwc_parse_screen_info(&outX, &outY);
+	else
+	    hotplug_parse_mode(&outX, &outY);
 	info.xres = outX;
 	info.yres = outY;
 	info.yres_virtual = info.yres * 3;
@@ -9828,6 +9832,29 @@ OnError:
 
 }
 
+int hwc_parse_screen_info(int *outX, int *outY)
+{
+    char buf[100];
+    int width = 0;
+    int height = 0;
+    int fdExternal = -1;
+	fdExternal = open("/sys/class/graphics/fb4/screen_info", O_RDONLY);
+    if(fdExternal < 0){
+        ALOGE("hotplug_get_config:open fb screen_info error,cvbsfd=%d",fdExternal);
+        return -errno;
+	}
+    if(read(fdExternal,buf,sizeof(buf)) < 0){
+        ALOGE("error reading fb screen_info: %s", strerror(errno));
+        return -1;
+    }
+    close(fdExternal);
+	sscanf(buf,"xres:%d yres:%d",&width,&height);
+    ALOGD("hotplug_get_config:width=%d,height=%d",width,height);
+	*outX = width;
+	*outY = height;
+	return 0;
+}
+
 int hotplug_parse_mode(int *outX, int *outY)
 {
    int fd = open("/sys/class/display/HDMI/mode", O_RDONLY);
@@ -9996,10 +10023,15 @@ void *hotplug_try_register(void *arg)
             break;
         }
     }
-    if(getHdmiMode() == 1){
+    if (getHdmiMode() == 1) {
         handle_hotplug_event(1, 6);
 		ALOGI("hotplug_try_register at line = %d",__LINE__);
-    }else{
+    } else if (hwc_get_int_property("ro.htg.force", "0")) {
+        hotplug_free_dimbuffer();
+        hotplug_get_config(0);
+        handle_hotplug_event(1, 6);
+		ALOGI("hotplug_try_register at line = %d",__LINE__);
+    } else {
 #if (defined(RK3368_BOX) || defined(RK3288_BOX))
 #if RK3288_BOX
         if(context->mLcdcNum == 1){

framework 的修改。并修改为横屏显示

commit 1eec3be5d9404b1093911561d407291e791322d0
Author: xia <[email protected]>
Date:   Sun Mar 17 12:30:06 2019 +0800

    change 90 rotation for lvds screen

diff --git a/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 5ebe64d..db06390 100644
--- a/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/base/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -203,10 +203,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                 } else {
                     mInfo.type = Display.TYPE_HDMI;
                     mInfo.flags |= DisplayDeviceInfo.FLAG_PRESENTATION;
+					
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_hdmi_display_name);
                     mInfo.touch = DisplayDeviceInfo.TOUCH_EXTERNAL;
                     mInfo.setAssumedDensityForExternalDisplay(mPhys.width, mPhys.height);
+					
+					mInfo.rotation=Surface.ROTATION_90;
 
                     // For demonstration purposes, allow rotation of the external display.
                     // In the future we might allow the user to configure this directly.
diff --git a/base/services/core/java/com/android/server/display/LogicalDisplay.java b/base/services/core/java/com/android/server/display/LogicalDisplay.java
index c3c25f4..950b08d 100755
--- a/base/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/base/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -235,6 +235,14 @@ final class LogicalDisplay {
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
+			
+            if(mDisplayId!=Display.DEFAULT_DISPLAY){
+                mBaseDisplayInfo.appWidth = deviceInfo.height;
+                mBaseDisplayInfo.appHeight = deviceInfo.width;
+                mBaseDisplayInfo.logicalWidth = deviceInfo.height;
+                mBaseDisplayInfo.logicalHeight = deviceInfo.width;
+            }
+			
         }
     }
 
@@ -322,6 +330,13 @@ final class LogicalDisplay {
         mTempDisplayRect.set(displayRectLeft, displayRectTop,
                 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
 
+        if(device.getDisplayDeviceInfoLocked().type!=Display.TYPE_BUILT_IN){
+             mTempDisplayRect.left=0;
+             mTempDisplayRect.right=physWidth;
+             mTempDisplayRect.top=0;
+             mTempDisplayRect.bottom=physHeight;
+        }
+				
         device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
     }
 
diff --git a/base/services/core/java/com/android/server/wm/WindowManagerService.java b/base/services/core/java/com/android/server/wm/WindowManagerService.java
index efbbb94..43b740d 100755
--- a/base/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/base/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -8570,8 +8570,8 @@ public class WindowManagerService extends IWindowManager.Stub
              rotation = Surface.ROTATION_90;
         }
         /* $_rbox_$_modify_$_huangjc , force android rotation according to 0 */
-        if("box".equals(SystemProperties.get("ro.target.product","tablet")))
-        rotation = Surface.ROTATION_0; 
+ //       if("box".equals(SystemProperties.get("ro.target.product","tablet")))
+ //       rotation = Surface.ROTATION_0; 
         /* $_rbox_$_modify_$ end */
 
         //djw:add for 3d functions
@@ -10050,6 +10050,7 @@ public class WindowManagerService extends IWindowManager.Stub
 		public static final int SET_MULTIWINDOW_MODE_ACTION = 41;
 		public static final int DO_TASK_DISPLAY_CHANGED = 42;
 		public static final int MULTIWINDOW_MOVE_BACK_ACTION = 43;
+		public static final int MOVE_APP_TO_DISPLAY = 44;
         @Override
         public void handleMessage(Message msg) {
             if (DEBUG_WINDOW_TRACE) {
@@ -10621,6 +10622,11 @@ public class WindowManagerService extends IWindowManager.Stub
 					} catch (RemoteException e) {
 					}
 					break;
+				case MOVE_APP_TO_DISPLAY:
+					synchronized (mWindowMap) {
+						moveAppToIdDisplay(msg.arg1, msg.arg2, (int)msg.obj);
+					}
+					break;
             }
             if (DEBUG_WINDOW_TRACE) {
                 Slog.v(TAG, "handleMessage: exit");
@@ -14494,6 +14500,216 @@ if(mCurConfiguration.enableMultiWindow()&&false){
 	Binder.restoreCallingIdentity(origId);
     }
 
+	public void moveAppToDisplay(Session session, IWindow client, int displayid) {
+		long origId = Binder.clearCallingIdentity();
+        	synchronized(mWindowMap){
+                	if(mDisplayContents == null || mDisplayContents.size() <= 1){
+                        	return;
+                	}
+                	final int displayCount = mDisplayContents.size();
+                	DisplayContent defaultContent = getDefaultDisplayContentLocked();
+                	int displayId = 0;
+			boolean hasTargetDisplay = false;
+                	for(int i = 0; i < displayCount;i++){
+                        	final DisplayContent content = mDisplayContents.valueAt(i);
+                                displayId = content.getDisplayId();
+				if (displayId == displayid) {
+					hasTargetDisplay = true;
+                                	break;
+				}
+                	}
+                	if(!hasTargetDisplay){
+                        	return;
+                	}
+                	if(!okToDisplay()){
+                        	return;
+                	}
+                	WindowState current = windowForClientLocked(session, client, false);
+                	if(isHomeWindow(current)){
+                        	return;
+                	}
+                	AppWindowToken wtoken = current.mAppToken;
+                	if(wtoken == null){
+                        	return;
+                	}
+
+			if(current.getDisplayId() == displayid) return;
+
+                	Settings.System.putInt(mContext.getContentResolver(),
+                       	Settings.System.DUAL_SCREEN_ICON_USED, 1);
+                	int groupId = wtoken.groupId;
+                	mH.sendMessage(mH.obtainMessage(H.MOVE_APP_TO_DISPLAY, groupId, displayid, current.getDisplayId()));
+        	}
+        	Binder.restoreCallingIdentity(origId);
+	}
+
+	public void syncDualDisplay() {
+		updateDisplayShowSynchronization();
+	}
+
+	// case as follow:
+	// 1. mast screen -> external screen
+	// 2. external screen -> mast screen
+	// 3. external screen -> external screen
+	private void moveAppToIdDisplay(int groupId, int displayid, int currentid) {
+		long origId = Binder.clearCallingIdentity();
+		int curMoveTaskId = -1;
+		synchronized(mWindowMap){
+                if(mDisplayContents == null || mDisplayContents.size() <= 1) {
+                        return;
+                }
+		DisplayContent defaultContent = getDefaultDisplayContentLocked();
+		int defaultDisplayId = defaultContent.getDisplayId();
+		final int displayCount = mDisplayContents.size();
+		int displayId = 0;
+		DisplayContent currentContent = null;
+		DisplayContent targetContent = null;
+		for(int i = 0; i < displayCount;i++) {
+                        final DisplayContent content = mDisplayContents.valueAt(i);
+                        if (content.getDisplayId() == displayid) {
+                                targetContent = content;
+                        }
+			if (content.getDisplayId() == currentid) {
+				currentContent = content;
+			}
+                }
+
+		if (targetContent == null) return;
+		if (currentContent == null) return;
+
+		if(!okToDisplay()){
+                        return;
+                }
+
+		WindowState win = null;
+                WindowList windows = currentContent.getWindowList();
+		try {
+                        SurfaceControl.openTransaction();
+			if (displayid == defaultDisplayId) {
+				int max = 1;
+        			int countOfTwoScreen = 0;
+				WindowList defaultWindows = defaultContent.getWindowList();
+				HashMap<Integer,AppWindowToken> visibleAppsOfTwoScreen = new HashMap<Integer,AppWindowToken>();
+				ArrayList<AppWindowToken> pendingRemoveOfTwoScreen = new ArrayList<AppWindowToken>();
+				for(int j = 0; j < windows.size(); j++) {
+					win = windows.get(j);
+					if (win == null) continue;
+					if (ignoreWindow(win,false) || win.mAppToken == null) continue;
+					if(isHomeWindow(win)) break;
+					if(!win.isDefaultDisplay()) {
+						AppWindowToken tk = win.mAppToken;
+						if(!visibleAppsOfTwoScreen.containsKey(tk.groupId)){
+                                			visibleAppsOfTwoScreen.put(tk.groupId, tk);
+							if (tk.groupId == groupId) {
+								pendingRemoveOfTwoScreen.add(tk);
+							}
+						}
+						/*if(!visibleAppsOfTwoScreen.containsKey(tk.groupId)){
+                                			visibleAppsOfTwoScreen.put(tk.groupId, tk);
+                                			countOfTwoScreen++;
+                                			if(countOfTwoScreen > max){
+                                        			pendingRemoveOfTwoScreen.add(tk);
+                                			}
+                        			}*/
+					}
+				}
+				if(pendingRemoveOfTwoScreen.size() > 0){
+					for(int k =0;k < pendingRemoveOfTwoScreen.size(); k++){
+						int removeTaskId = pendingRemoveOfTwoScreen.get(k).groupId;
+						for(int m = 0; m < windows.size(); m++){
+							WindowState ws = windows.get(m);
+							int mGroupId = ws.mAppToken.groupId;
+							if (mGroupId == removeTaskId) {
+								final ArrayList<TaskStack> stacks = defaultContent.getStacks();
+								final int numStacks = stacks.size();
+								int stackNdx = 1;
+								final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+								final int numTasks = tasks.size();
+								for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+                                                        		if (tasks.get(taskNdx).taskId != ws.taskId)  continue;
+                                                        		final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+                                                        		if (!tokens.contains(ws.mAppToken)) { // wrong happened
+                                                                		tasks.get(taskNdx).addAppToken(tokens.size(), ws.mAppToken);
+                                                        		}
+                                                        		//break;
+                                                		}
+								windows.remove(ws);
+								ws.mDisplayContent = defaultContent;
+                                        			if(ws.mWinAnimator != null){
+                                                			int layerStack = defaultContent.getDisplay().getLayerStack();
+                                                			if(ws.mWinAnimator.mSurfaceControl != null){
+                                                        			ws.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);
+                                                			}
+                                        			}
+                                        			defaultWindows.add(ws);
+							}
+						}
+					}
+				}
+			} else if (currentid == defaultDisplayId) {
+				WindowList targetDisplayAddList = new WindowList();
+	                        WindowList targetDisplayWindows = targetContent.getWindowList();
+				for(int i=windows.size()-1; i >= 0; i--){
+					win = windows.get(i);
+                        	        if(win == null){
+                                	        continue;
+	                                }
+       	                        if (win.mAppToken == null){
+                	                        continue;
+                        	        }
+					int mGroupId = win.mAppToken.groupId;
+        	                        if(mGroupId == groupId){
+
+                	                        final ArrayList<TaskStack> stacks = currentContent.getStacks();
+                        	                final int numStacks = stacks.size();
+                                	        int stackNdx = 1;
+						final ArrayList<Task> tasks = stacks.get(stackNdx).getTasks();
+
+						final int numTasks = tasks.size();
+						for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
+							if (tasks.get(taskNdx).taskId != win.taskId) continue;
+							final AppTokenList tokens = tasks.get(taskNdx).mAppTokens;
+							for (int n = 0; n<tokens.size();) {
+								AppWindowToken awt = tokens.get(n);
+								if (tokens.contains(awt) || awt.removed) {  // no useful
+									tasks.get(taskNdx).removeAppToken(awt);
+								}
+							}
+						}
+                        	                windows.remove(win);
+                                	        win.mDisplayContent = targetContent;
+
+	                                        if(win.mWinAnimator != null){
+        	                                        int layerStack = targetContent.getDisplay().getLayerStack();
+                	                                if(win.mWinAnimator.mSurfaceControl!= null){
+                        	                                win.mWinAnimator.mSurfaceControl.setLayerStack(layerStack);
+                                	                }
+	                                        }
+        	                                targetDisplayAddList.add(0, win);
+                	                }
+				}
+				targetDisplayWindows.addAll(targetDisplayAddList);
+			} else {
+				// external screen -> external screen
+			}
+
+			for (int i = 0; i < displayCount; i++) {
+                                final DisplayContent content = mDisplayContents.valueAt(i);
+                                assignLayersLocked(content.getWindowList());
+                                content.layoutNeeded = true;
+                        }
+			updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES, false);
+                        mAppTransition.setReady();
+                        performLayoutAndPlaceSurfacesLocked();
+			
+                }finally {
+                        SurfaceControl.closeTransaction();
+                }
+
+		}
+		Binder.restoreCallingIdentity(origId);
+	}
+	
 	public void moveWindowToSecondDisplay() {
 		int topId = -100;
 		int mCurAnimLayer = -100;
diff --git a/native/services/surfaceflinger/DisplayDevice.cpp b/native/services/surfaceflinger/DisplayDevice.cpp
index d473bb7..3b3e1ee 100755
--- a/native/services/surfaceflinger/DisplayDevice.cpp
+++ b/native/services/surfaceflinger/DisplayDevice.cpp
@@ -522,6 +522,12 @@ void DisplayDevice::setProjection(int orientation,
         orientation = (mHardwareOrientation + orientation) % 4;
     }
 
+	if (mType == DisplayDevice::DISPLAY_EXTERNAL) {
+		mClientOrientation = orientation;
+		if (orientation %2 == 1)
+			frame = Rect(0,0,getHeight(),getWidth());
+	}
+		
     const int w = mDisplayWidth;
     const int h = mDisplayHeight;
 

注意 副屏分辨率 y轴不能超过 1080,如果超过 就会显示拉伸。需要调整 framewrok 和下面的代码


diff --git a/rockchip/hwcomposer/rk_hwcomposer.cpp b/rockchip/hwcomposer/rk_hwcomposer.cpp
old mode 100755
new mode 100644
index c9a9cd2..9103934
--- a/rockchip/hwcomposer/rk_hwcomposer.cpp
+++ b/rockchip/hwcomposer/rk_hwcomposer.cpp
@@ -9825,8 +9825,8 @@ int hotplug_set_config()
                 ctxp->dpyAttr[dType].xres,ctxp->dpyAttr[dType].yres,
                 ctxe->dpyAttr[dType].xres,ctxe->dpyAttr[dType].yres);
         } else if(ctxp->dpyAttr[dType].yres > 1080) {
-            ctxp->dpyAttr[dType].xres = 1920;
-            ctxp->dpyAttr[dType].yres = 1080;
+            ctxp->dpyAttr[dType].xres = 400;
+            ctxp->dpyAttr[dType].yres = 1280;
             ctxp->mHdmiSI.NeedReDst = true;
             printf("w_s,h_s,w_d,h_d = [%d,%d,%d,%d]",
                 ctxp->dpyAttr[dType].xres,ctxp->dpyAttr[dType].yres,

如果发现副屏显示不正常。调整一下频率。

猜你喜欢

转载自blog.csdn.net/lb5761311/article/details/90024470