最近改了个反人类的需求,就是:
当HDMI输出分辨率设置为固定的2160P后,再热拔插连接到1080P的TV,分辨率会变为1080P的分辨率,客户认为这是bug,需要改为固定。

为什么说这是反人类的需求呢?
比如说,你想固定一个4k,那你接到另一台2K的显示上,那要怎么显示呢?肯定是无显示。

所以RK平台的hdmi显示机制是这样的:
比如你设置个HDMI的分辨率,比如1920x1080p60hz,如果你接另外一台电视有这个分辨率,就会切到这个分辨率去,
如果没有支持这个分辨率,就会切到其他相近的分辨率。

当前尝试了几个办法:
一个就是直接不读EDID了,直接默认支持一堆预设好的分辨率,这些分辨率对应的vic值从drivers/gpu/drm/drm_edid.c中的edid_cea_modes结构体中获得【对应具体的整形数据】,然后随意去设置,这样的话,可以达到固定分辨率的效果,bug就是有可能会设置到有些屏不支持的分辨率,导致无显示;而且自适应分辨率的时候也会导致无法匹配到一个是当前屏最优的分辨率,只会按照def_modes中的第一个分辨率vic值来设置分辨率,此解法不妥。
修改内容如下(修改文件:drivers/gpu/drm/bridge/synopsys/dw-hdmi.c):

//主要的改动就是在def_mode 数组添加默认支持的分辨率值;edid = NULL;强制把 edid 赋为 NULL,不管有没有读到 edid 都强制按 def_modes 来显示;注释掉clock > 340MHz和clock < 340MHz的分辨率过滤
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -2533,7 +2533,9 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)connector);struct edid *edid;struct drm_display_mode *mode;
-       const u8 def_modes[6] = {4, 16, 31, 19, 17, 2};
+//     const u8 def_modes[6] = {4, 16, 31, 19, 17, 2};
+       const u8 def_modes[26] = {16, 4, 102, 101, 100, 99, 98, 97, 96, 95, 94, 93, 62, 61,
+                                       60, 34, 33, 32, 31, 21, 20, 19, 17, 6, 5, 2};struct drm_display_info *info = &connector->display_info;struct hdr_static_metadata *metedata =&connector->display_info.hdmi.hdr_panel_metadata;
@@ -2543,6 +2545,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)return 0;edid = drm_get_edid(connector, hdmi->ddc);
+       edid = NULL;if (edid) {dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]\n",edid->width_cm, edid->height_cm);
@@ -2575,6 +2578,7 @@ static int dw_hdmi_connector_get_modes(struct drm_connector *connector)info->color_formats = 0;dev_info(hdmi->dev, "failed to get edid\n");
+               dev_info(hdmi->dev, "No get edid, use def_modes resolution\n");}return ret;
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index ac8a260..532d09b 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -488,11 +488,12 @@ dw_hdmi_rockchip_mode_valid(struct drm_connector *connector,* If sink max TMDS clock < 340MHz, we should check the mode pixel* clock > 340MHz is YCbCr420 or not.*/
+#if 0if (mode->clock > 340000 &&connector->display_info.max_tmds_clock < 340000 &&!drm_mode_is_420(&connector->display_info, mode))return MODE_BAD;
-
+#endifif (!encoder) {

还需要注意一下分辨率的白名单过滤文件(在这个文件里面的分辨率上层才能识别),不然上层有可能会被过滤掉一些分辨率:
对应文件:device/rockchip/common/resolution_white.xml
通过 resolution_white.xml 定义合法分辨率,只有包含在该 xml 中的分辨率才可以设置。若不
存在该 xml 文件,不执行过滤。

还有个方法就是把def_modes这套的接口用法搬到读edid流程用法那里去,但是我觉得这个方法更加不妥。

当前采用了另外一个拙劣的方法(为什么说拙劣呢,因为还没做到零BUG):那就是在设置HDMI分辨率的时候,如果设置为自适应模式(Auto)的时候,就去设置status为detect,如果设置HDMI为固定分辨率的时候(如1080p)就设置HDMI的状态为on,即让它一直为输出HDMI信号的状态,并且分辨率固定【后来验证这种方式只能实现热拔插的时候固定分辨率,最终还是采用了def_mode的方法】。
手动测试验证:
先去Setting设置分辨率为4K的分辨率,然后串口或者adb工具敲入以下指令:
echo on > sys/class/drm/card0-HDMI-A-1/status //相当于一直使能HDMI输出
然后Setting设置为Auto,即分辨率自适应模式(会根据读到的EDID, 获取到的modes,自动匹配一个最优的mode),然后串口或者adb工具敲入以下指令:
echo off > sys/class/drm/card0-HDMI-A-1/status
echo detect > sys/class/drm/card0-HDMI-A-1/status

Android上层代码修改如下(主要是Setting apk部分的修改,即把上面的测试动作添加为代码而已,其实主要就是在设置分辨率(对应setDpMode[设置DP分辨率]和setHdmiMode[设置HDMI分辨率]接口这里,)之后,加上上面的动作):

diff --git a/src/com/android/settings/display/DrmDisplaySetting.java b/src/com/android/settings/display/DrmDisplaySetting.java
index aa8e00f..ad8b1be 100755
--- a/src/com/android/settings/display/DrmDisplaySetting.java
+++ b/src/com/android/settings/display/DrmDisplaySetting.java
@@ -17,6 +17,7 @@ import java.util.Arrays;import java.util.List;import com.android.settings.util.ReflectUtils;
+import java.io.FileWriter;* Drm Display Setting.
@@ -48,6 +49,18 @@ public class DrmDisplaySetting {Log.d(TAG, SUB_TAG + " - " + text);}+    private static int writeSysfs(String path,String value) {+               try {+                 FileWriter command = new FileWriter(path);
+                 command.write(value);
+                 command.close();
+               } catch (Exception e) {+                 e.printStackTrace();
+       return -1;
+               }
+               return 0;
+  }
+public static List<DisplayInfo> getDisplayInfoList() {List<DisplayInfo> displayInfos = new ArrayList<DisplayInfo>();Object rkDisplayOutputManager = null;
@@ -308,6 +321,15 @@ public class DrmDisplaySetting {ReflectUtils.invokeMethod(rkDisplayOutputManager, "setMode", new Class[]{int.class, int.class, String.class}, new Object[]{DISPLAY_TYPE_HDMI, currMainType, mode});}logd(" setHdmiMode 3");
+
+  if ("Auto".equals(mode)) {+      logd(" czd-Hdmi Auto setHdmiMode mode = " + mode);
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "off");
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "detect");
+  } else {+      logd(" czd-Hdmi Fix setHdmiMode mode = " + mode);
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "on");
+  }}@@ -431,6 +453,16 @@ public class DrmDisplaySetting {int currMainType = (Integer) ReflectUtils.invokeMethod(rkDisplayOutputManager, "getCurrentInterface", new Class[]{int.class}, new Object[]{DISPLAY_TYPE_DP});ReflectUtils.invokeMethod(rkDisplayOutputManager, "setMode", new Class[]{int.class, int.class, String.class}, new Object[]{DISPLAY_TYPE_DP, currMainType, reso});}
+
+  if ("Auto".equals(reso)) {+      logd(" czd-Dp Auto setHdmiMode mode = " + reso);
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "off");
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "detect");
+  } else {+      logd(" czd-Dp Fix setHdmiMode mode = " + reso);
+      writeSysfs("sys/class/drm/card0-HDMI-A-1/status", "on");
+  }
+}/**

可以单独编译apk,如果验证修改了没效果,注意在Android.mk加上以下这句:

--- a/Android.mk
+++ b/Android.mk
@@ -35,6 +35,7 @@ LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res \LOCAL_PACKAGE_NAME := SettingsLOCAL_CERTIFICATE := platform
+LOCAL_DEX_PREOPT := falseLOCAL_PRIVILEGED_MODULE := true

然后模块编译,得到更新后的apk:system/priv-app/Settings/Settings.apk:
rk3399_7.1_ind/packages/apps/Settings$ mm -j16

[100% 6/6] Install: out/target/product/rk3399_all/system/priv-app/Settings/Settings.apk
make: Leaving directory `/work/czd/rk3399_7.1_ind'#### make completed successfully (07:09 (mm:ss)) ####

然后push进机器验证:
替换apk可验证。
adb root
adb remount
adb push Settings.apk system/priv-app/Settings/Settings.apk
adb shell chmod 644 system/priv-app/Settings/Settings.apk
adb shell sync
adb reboot

kernel 驱动也要做修改: 在热拔插hdmi的时候,不能去刷新edid的数据,modes等,不然会重新读取edid的数据,自动切换分辨率:

--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
@@ -359,6 +359,12 @@ static bool check_hdmi_irq(struct dw_hdmi *hdmi, int intr_stat,if (!(intr_stat & HDMI_IH_PHY_STAT0_HPD))return false;+       /* add by czd for ne4k fix hdmi resolution
+        * ignore hdmi plug in or out, default plug in
+        */
+       if (hdmi->force == DRM_FORCE_ON)
+               return true;
+if (phy_int_pol & HDMI_PHY_HPD) {dev_dbg(hdmi->dev, "dw hdmi plug in\n");

验证情况(操作设置分辨率,然后看log打印):

rk3399_all:/ # logcat | grep czd
01-01 00:45:35.054   757   757 D DrmDisplaySetting: DrmDisplaySetting -  czd-Dp Fix setHdmiMode mode = 1920x1080p60.00-0
01-01 00:56:10.987   757   757 D DrmDisplaySetting: DrmDisplaySetting -  czd-Dp Auto setHdmiMode mode = Auto

如果您有更优的方法,请不吝赐教!

rk3399_android7.1的HDMI显示实现固定分辨率相关推荐

  1. 嵌入式linux hdmi分辨率,【Firefly3399Pro】rk3399pro在Framebuffer状态命令行模式中强制HDMI输出固定分辨率...

    环境 Ubuntu虚拟机做交叉编译环境 firefly3399pro-JD4核心板 + 配套Firefly底板 Linux-SDK官方 需求 固定HDMI不论显示器的大小,输出固定的分辨率 解决办法 ...

  2. 【正点原子FPGA连载】第四十四章MT9V034摄像头HDMI显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

    1)实验平台:正点原子新起点V2开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码+手册+视频下载地址:ht ...

  3. FPGA 20个例程篇:19.OV7725摄像头实时采集送HDMI显示(一)

    第七章 实战项目提升,完善简历 19.OV7725摄像头实时采集送HDMI显示(一) 在例程"OV7725摄像头实时采集送HDMI显示"中,我们将走近FPGA图像处理的世界,图像处 ...

  4. activiti高亮显示图片_【正点原子FPGA连载】第二十章SD卡读BMP图片HDMI显示实验领航者 ZYNQ 之嵌入式开发指南...

    1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下 ...

  5. 关于UnityPC端打包参数设置及发布PC端时固定分辨率

    UnityPC端打包参数设置 主要设置都在PlayerSettings里面 Company Name:设置公司名称 Product Name:设置项目名称,这个获取窗体句柄的时候用的到 Default ...

  6. NXP i.MX6Q 双屏同显hdmi显示闪烁解决方案

    项目场景: 在眺望电子TW-IMX6DL-EVM开发板上采用NXP i.MX6Q四核核心板可以实现LVDS+HDMI双屏同显. 编译环境及开发包: 主机:ubuntu18.04 交叉编译器:arm-l ...

  7. 基于FPGA的HDMI显示(二)

    基于FPGA的720P HDMI显示 1.4.1 HDMI 硬件电路分析   本次设计采用了 IO 模拟的方式实现 HDMI 的功能.与采用专用 HDMI 芯片相比,此方案具有成本更低.效果不输于采用 ...

  8. zynq 7000 的HDMI 显示实验

    用了很多年的zynq 7000,一直就没做hdmi 显示实验.前几天终于做了这个实验,也就做一个总结. 我的实验是在微相的z7-lite下根据他们的教程完成的.平台是windows 10 , Viva ...

  9. HDMI系列之一:基于Nios II的HDMI显示图片

    一休哥将在本文中介绍一个基于Nios II的HDMI显示图片的工程.我将主要分三个部分来介绍这一工程,从而实现工程效果. 1. Nios II的常规使用套路 2. 自定义HDMI IP核的制作 3. ...

  10. FPGA虚拟三阶魔方(HDMI显示版)

    目录 ​编辑 一.设计概述 二.设计模块 1.三阶魔方建模 (1)魔方基本操作: (2)魔方建模: 2.魔方转动控制: (1)控制概述: (2)按键消抖: (3)魔方控制: 3.HDMI显示模块: ( ...

最新文章

  1. leetcode算法题--二叉树的最近公共祖先
  2. Markdown 如何实现空行、空格?
  3. applicationContext配置文件模板1
  4. 关于使用ModelSim中编写testbench模板问题
  5. 【原】opencv中cvCopy()和cvCloneImage()的区别:
  6. 十大办法帮助传统产业数字化转型
  7. 超出部分用省略号代替的样式
  8. javascript版的等额本息计算器
  9. C++名称查找与ADL
  10. PHP根据生日计算年龄(周岁)
  11. No module named ‘service‘
  12. 【微信小程序】微信小程序开发(一)
  13. 安卓系统培训!系统盘点Android开发者必须掌握的知识点,BAT大厂面试总结
  14. 动态规划之TSP(Travel Salesman Problem)算法
  15. 没装oracle plsql,64位WIN7系统,未装ORACLE,我用PLSQLDEV 远程连接数据库时报错ORA-12560:TNS:protocol adapter error...
  16. 中国电信大数据价值挖掘:聚焦商业模式探索
  17. C++一本通基础算法:广度优先搜索(BFS)
  18. C语言基础:翁恺笔记
  19. sql查询没有选修课程编号为’3’的学员姓名和所属单位
  20. 【基础练习】【模拟】Uva489 - Hangman Judge题解

热门文章

  1. 使用Python进行描述性统计
  2. javascript高级程序设计笔记-第八章(BOM)
  3. Discuz = 7.2 SQL注入漏洞详情
  4. Trip to Canvas(1)
  5. 自学Python6个月,你能找到工作吗?
  6. ACL2021 Findings | 挖掘label的语义来增强few-shot问题
  7. 【ACL2020】最新效果显著的关系抽取框架了解一下?
  8. 谁是杨强?首位AAAI华人主席,身兼5大顶级组织Fellow,也是华为诺亚方舟实验室开创者...
  9. 大神带你实现 NLP 从入门到获奖,还有免费算力可以薅
  10. 【论文笔记】基于LSTM的问答对排序