版权声明:本文为博主原创文章,未经博主允许不得转载。 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,
®_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,
如果发现副屏显示不正常。调整一下频率。