RK3368 Edp屏调试,利用EDID做兼容

本文档详细介绍了如何针对RK3368平台进行EDP屏的调试,通过分析和利用EDID信息来实现屏幕的兼容性。在kernel部分,主要涉及了Edid信息打印、lcdc驱动、rk_screen、dts和rk32_dp驱动的修改。而在uboot部分,着重阐述了代码的调整和配置文件中Edp设置的添加。
摘要由CSDN通过智能技术生成

RK3368 Edp屏调试,利用EDID做兼容

Platform: RK3368
OS: Android 6.0
Kernel: 3.10.0


最近采购经常换显示面板,而RK的Edp屏相关的配置都是在dts里面写死的,一个屏幕需要写一个dts配置,所以就想做个Edp屏兼容.原理就是将Edp屏里面的EDID读取出来,提取时序相关信息,然后覆盖掉原来从dts中获取的屏幕配置.

1. kernel部分修改

1.1 Edp EDID信息打印:

在调试阶段,可以在drivers/video/fbmon.c里面将DEBUG打开,这样内核会将EDID信息直接打印出来.

1.2 修改lcdc驱动

修改rk3368_lcdc,如果屏幕是Edp类型的就将Edp屏的最佳时序从EDID中提取出来,然后覆盖rk_screen从dts中获取的屏幕时序配置.

diff --git a/drivers/video/rockchip/lcdc/rk3368_lcdc.c b/drivers/video/rockchip/lcdc/rk3368_lcdc.c
index 17cdd3a..84eb89e 100755
--- a/drivers/video/rockchip/lcdc/rk3368_lcdc.c
+++ b/drivers/video/rockchip/lcdc/rk3368_lcdc.c
@@ -2288,6 +2288,22 @@ static int rk3368_lcdc_open(struct rk_lcdc_driver *dev_drv, int win_id,
                rk3368_lcdc_reg_restore(lcdc_dev);
                /*if (dev_drv->iommu_enabled)
                   rk3368_lcdc_mmu_en(dev_drv); */
+
+               //if current screen type is eDP, then overlay videomode by EDID.
+               if(dev_drv->cur_screen->type==SCREEN_EDP &&
+                       dev_drv->trsm_ops && dev_drv->trsm_ops->enable &&
+                       strstr(saved_command_line,"edp.edid=1")!= NULL){
+                       if(!support_uboot_display()){
+                               dev_drv->trsm_ops->enable();
+                       }
+                       if(rk32_edp_get_screen_info_from_edid(dev_drv->cur_screen)==0){
+                               rk_fb_set_prmry_screen_specs(dev_drv->cur_screen);
+                       }
+                       if(!support_uboot_display()){
+                               dev_drv->trsm_ops->disable();
+                       }
+               }
+
                if ((support_uboot_display() && (lcdc_dev->prop == PRMRY))) {
                        rk3368_lcdc_set_dclk(dev_drv, 0);
                        /*rk3368_lcdc_enable_irq(dev_drv);*/

1.3 修改rk_screen

添加一个函数rk_fb_set_prmry_screen_specs,用来覆盖原来从dts中读取的显示配置.

diff --git a/drivers/video/rockchip/screen/rk_screen.c b/drivers/video/rockchip/screen/rk_screen.c
index d5e3b15..f5d27a0 100755
--- a/drivers/video/rockchip/screen/rk_screen.c
+++ b/drivers/video/rockchip/screen/rk_screen.c
@@ -44,6 +44,27 @@ int rk_fb_set_prmry_screen(struct rk_screen *screen)
        return 0;
 }
 
+int rk_fb_set_prmry_screen_specs(struct rk_screen *screen)
+{
+       if (unlikely(!rk_screen) || unlikely(!screen))
+               return -1;
+
+       rk_screen->mode.xres = screen->mode.xres;
+       rk_screen->mode.yres = screen->mode.yres;
+       rk_screen->mode.pixclock = screen->mode.pixclock;
+       rk_screen->mode.left_margin = screen->mode.left_margin;
+       rk_screen->mode.right_margin = screen->mode.right_margin;
+       rk_screen->mode.upper_margin = screen->mode.upper_margin;
+       rk_screen->mode.lower_margin = screen->mode.lower_margin;
+       rk_screen->mode.hsync_len = screen->mode.hsync_len;
+       rk_screen->mode.vsync_len = screen->mode.vsync_len;
+       rk_screen->pin_hsync = screen->mode.sync & FB_SYNC_HOR_HIGH_ACT ? 1 : 0;
+       rk_screen->pin_vsync = screen->mode.sync & FB_SYNC_VERT_HIGH_ACT ? 1 : 0;
+       rk_screen->width = screen->width;
+       rk_screen->height= screen->height;
+       return 0;
+}
+
 size_t get_fb_size(u8 reserved_fb)
 {
        size_t size = 0;

1.4 修改dts

从EDID中提取显示时序,以及dts中的自定义配置解析:

dts文件配置:

&edp{
	status = "okay";
	enhanced-mode;
	//bist-mode;
	scramble-enable;
};

1.5 修改rk32_dp驱动

diff --git a/drivers/video/rockchip/transmitter/rk32_dp.c b/drivers/video/rockchip/transmitter/rk32_dp.c
index 2b3457c..021188d 100755
--- a/drivers/video/rockchip/transmitter/rk32_dp.c
+++ b/drivers/video/rockchip/transmitter/rk32_dp.c
@@ -39,9 +39,10 @@
 
 #include "rk32_dp.h"
 
-/*#define EDP_BIST_MODE*/
 /*#define SW_LT*/
 
+static int rk32_edp_enable_scramble(struct rk32_edp *edp, bool enable);
+
 #define RK3368_GRF_SOC_CON4    0x410
 
 static struct rk32_edp *rk32_edp;
@@ -293,8 +294,7 @@ static int rk32_edp_read_edid(struct rk32_edp *edp)
        dev_err(edp->dev, "EDID Read success!\n");
        return 0;
 }
-#define open_t 0
-#if open_t
+
 static int rk32_edp_handle_edid(struct rk32_edp *edp)
 {
        u8 buf[12];
@@ -306,8 +306,8 @@ static int rk32_edp_handle_edid(struct rk32_edp *edp)
        if (retval < 0)
                return retval;
 
-       for (i = 0; i < 12; i++)
-               dev_info(edp->dev, "%d:>>0x%02x\n", i, buf[i]);
+       //for (i = 0; i < 12; i++)
+       //      dev_info(edp->dev, "%d:>>0x%02x\n", i, buf[i]);
        /* Read EDID */
        for (i = 0; i < 3; i++) {
                retval = rk32_edp_read_edid(edp);
@@ -407,7 +407,6 @@ static int rk32_edp_set_enhanced_mode(struct rk32_edp *edp)
 
        return 0;
 }
-#endif
 
 
 #if defined(SW_LT)
@@ -1097,9 +1096,9 @@ static int rk32_edp_config_video(struct rk32_edp *edp,
        rk32_edp_set_video_cr_mn(edp, CALCULATED_M, 0, 0);
 
        /* For video bist, Video timing must be generated by register */
-#ifndef EDP_BIST_MODE
-       rk32_edp_set_video_timing_mode(edp, VIDEO_TIMING_FROM_CAPTURE);
-#endif
+       if(edp->bist_mode){
+               rk32_edp_set_video_timing_mode(edp, VIDEO_TIMING_FROM_CAPTURE);
+       }
        /* Disable video mute */
        rk32_edp_enable_video_mute(edp, 0);
 
@@ -1165,6 +1164,59 @@ static irqreturn_t rk32_edp_isr(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+static struct fb_videomode *rk32_edp_get_preferred_mode(struct fb_monspecs *spec)
+{
+       int i;
+
+       if (!spec || !spec->modedb || !(spec->misc & FB_MISC_1ST_DETAIL))
+               return NULL;
+
+       for (i = 0; i < spec->modedb_len; i++) {
+               if (spec->modedb[i].flag & FB_MODE_IS_FIRST &&
+                       spec->modedb[i].flag & FB_MODE_IS_DETAILED)
+                       return &spec->modedb[i];
+       }
+
+       return NULL;
+}
+
+int rk32_edp_get_screen_info_from_edid(struct rk_screen *screen)
+{
+       struct rk32_edp *edp = rk32_edp;
+
+       int ret = rk32_edp_handle_edid(edp);
+       if (ret) {
+               dev_err(edp->dev, "unable to handle edid\n");
+               return -1;
+       }
+       dev_info(edp->dev, "EDID Version %d.%d\n", (int) edp->specs.version, (int) edp->specs.revision);
+       dev_info(edp->dev, "      Manufacturer: %s, Model: %x\n", edp->specs.manufacturer, edp->specs.model);
+       dev_info(edp->dev, "      Year: %u Week %u\n", edp->specs.year, edp->specs.week);
+
+       struct fb_videomode *preferred_mode = rk32_edp_get_preferred_mode(&edp->specs);
+
+       if(preferred_mode!=NULL){
+               dev_info(edp->dev, "      Preferred Timing: %ld MHz\n",  PICOS2KHZ(preferred_mode->pixclock)/1000);
+
+               screen->mode.xres = preferred_mode->xres;
+               screen->mode.yres = preferred_mode->yres;
+               screen->mode.pixclock = PICOS2KHZ(preferred_mode->pixclock)*1000;
+               screen->mode.left_margin = preferred_mode->left_margin;
+               screen->mode.right_margin = preferred_mode->right_margin;
+               screen->mode.upper_margin = preferred_mode->upper_margin;
+               screen->mode.lower_margin = preferred_mode->lower_margin;
+               screen->mode.hsync_len = preferred_mode->hsync_len;
+               screen->mode.vsync_len = preferred_mode->vsync_len;
+               screen->mode.sync = preferred_mode->sync;
+
+               screen->width = edp->specs.max_x*10;
+               screen->height= edp->specs.max_y*10;
+               return 0;
+       }
+       pr_info("EDID preferred mode not found!\n");
+       return -1;
+}
+
 static int rk32_edp_enable(void)
 {
        int ret = 0;
@@ -1175,24 +1227,23 @@ static int rk32_edp_enable(void)
                rk32_edp_pre_init(edp);
                rk32_edp_init_edp(edp);
                enable_irq(edp->irq);
-               /*ret = rk32_edp_handle_edid(edp);
+/*
+               ret = rk32_edp_handle_edid(edp);
                if (ret) {
                        dev_err(edp->dev, "unable to handle edid\n");
-                       //goto out;
                }
-
-               ret = rk32_edp_enable_scramble(edp, 0);
+*/
+               ret = rk32_edp_enable_scramble(edp, edp->scramble_enable);
                if (ret) {
                        dev_err(edp->dev, "unable to set scramble\n");
-                       //goto out;
                }
 
-               ret = rk32_edp_enable_rx_to_enhanced_mode(edp, 0);
+               ret = rk32_edp_enable_rx_to_enhanced_mode(edp, edp->enhanced_mode);
                if (ret) {
                        dev_err(edp->dev, "unable to set enhanced mode\n");
-                       //goto out;
                }
-               rk32_edp_enable_enhanced_mode(edp, 1);*/
+               rk32_edp_enable_enhanced_mode(edp, edp->enhanced_mode);
+
 
                ret = rk32_edp_set_link_train(edp);
                if (ret)
@@ -1204,9 +1255,10 @@ static int rk32_edp_enable(void)
                rk32_edp_set_link_bandwidth(edp, edp->link_train.link_rate);
                rk32_edp_init_video(edp);
 
-#ifdef EDP_BIST_MODE
-               rk32_edp_bist_cfg(edp);
-#endif
+               if(edp->bist_mode){
+                       rk32_edp_bist_cfg(edp);
+               }
+
                ret = rk32_edp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值