RK3568 HDMI EDID处理过程

2023-11-05

一.简介

EDID是什么?

EDID的全称是Extended Display Identification Data(扩展显示标识数据),VGA、DVI的EDID由主块128字节组成,HDMI的EDID增加扩展块(128字节),扩展块的内容主要是和音频属性相关的,DVI和VGA没有音频,HDMI自带音频,扩展块数据规范按照CEA-861x标准定义,未来可能增加到512或256的整数倍。其中包含有关显示器及其性能的参数,包括供应商信息、最大图像大小、颜色设置、厂商预设置、频率范围的限制以及显示器名和序列号的字符串等等。形象地说,EDID就是显示器的身份证、户口本、技能证书等证件的集合,目的就是告诉别人我是谁,我从哪来,我能干什么。

为什么要使用EDID?

为了能让PC或其他的图像输出设备更好的识别显示器属性

EDID并非古而有之,在古老的CRT时期是没有EDID这个概念的,那为什么后来会有呢?因为随着显示设备的发展,显示器的种类越来越多,模拟的、数字的、普屏的、宽屏的、17寸、19寸、22寸……这让PC傻了眼,分辨率和时序的种类太多了,而每种显示器又不可能支持所有的分辨率,那怎么知道该给显示器一个什么样的分辨率啊?显示出的效果是最佳效果吗?不仅如此,随便输出一个分辨率还有损坏显示器硬件的可能,这可太危险了。于是,EDID临危受命,担当起显示器和PC之前的传话筒。“PC你好,我是A显示器,我能显示N种分辨率,最佳分辨率是XXX”。“显示器你好,收到你的信息,现在就按最佳分辨率给你输出”。这下大家明白了吧,EDID就是为了能让PC或其他的图像输出设备更好的识别显示器属性而出现的。

二.EDID的调用流程

对应文件:
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
./drivers/gpu/drm/drm_edid.c

.get_modes = dw_hdmi_connector_get_modes
									->edid = drm_get_edid(connector, hdmi->ddc); //获取edid
										->drm_do_get_edid
											->drm_do_probe_ddc_edid //尝试通过i2获取edid信息,成功时为0,失败时为-1。
												->drm_get_displayid //如果edid存在,则获取显示id

如果获取到edid,则调用:

				 hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid); //检测显示器是否是HDMI,是就返回true,否则return false;
					->drm_find_cea_extension //
						->drm_find_edid_extension //在edid中搜索CEA扩展块
							->if (cea_db_is_hdmi_vsdb(&edid_ext[i]))
									return true; //因为HDMI标识符在特定于供应商的块中,所以从CEA扩展的所有数据块中搜索它。
				 
                 hdmi->sink_has_audio = drm_detect_monitor_audio(edid); //检测显示器audio音频功能,如果显示器支持音频,就返回true,否则return false;
				 
                 drm_mode_connector_update_edid_property(connector, edid); //更新连接器的edid属性
				 
                 cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid); 
				 
                 ret = drm_add_edid_modes(connector, edid); //从连接的显示器中读取到的edid数据添加分辨率[mode](如果mode可用),
*edid spec说 mode(分辨率)应该按以下顺序优先选择:

	*-首选 详细 mode(分辨率)

	*-来自基础块的其他详细 mode(分辨率)

	*-扩展块的详细 mode(分辨率)

	*-CVT 3字节代码 mode(分辨率)

	*-标准定时代码

	*-已建立的时间代码

	*-根据GTF或CVT范围信息推断的 mode(分辨率)


     /* Store the ELD */
    drm_edid_to_eld(connector, edid); //从edid构建ELD, 填充ELD(类似于edid的数据)缓冲区以传递给音频驱动程序。这个HDCP和端口字段留给图形驱动程序填写。

    drm_mode_connector_update_hdr_property(connector, metedata); //原子替换现有blob属性

如果获取不到edid,则调用:

				 hdmi->sink_is_hdmi = true;
				 hdmi->sink_has_audio = true;			 
				 for (i = 0; i < sizeof(def_modes); i++) { //去遍历def_mode数组的值,他们对应在edid_cea_modes里面的分辨率[mode]-->取自CEA-861规范。
					mode = drm_display_mode_from_vic_index(connector, def_modes, 31, i); //调用该接口来设置def_modes数组中第一个分辨率值
						->调用vic = svd_to_vic(video_db[video_index]); // vic值对应 edid_cea_modes 中的分辨率参数
							->if (!drm_valid_cea_vic(vic))
								->vic > 0 && vic < ARRAY_SIZE(edid_cea_modes); 则设置 edid_cea_modes 里面相应的分辨率
									->newmode = drm_mode_duplicate(dev, &edid_cea_modes[vic]);
										->drm_mode_copy(nmode, mode);分配和复制现有模式, 返回:成功时指向复制模式的指针,错误时为空。

三.尝试修改HDMI的屏幕分辨率

尝试修改kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c下的函数dw_hdmi_connector_get_modes()。

static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
	struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
					     connector);
	struct hdr_static_metadata *metedata =
			&connector->hdr_sink_metadata.hdmi_type1;
	struct edid *edid;
	struct drm_display_mode *mode;
	struct drm_display_info *info = &connector->display_info;
	int i, ret = 0;

	memset(metedata, 0, sizeof(*metedata));
	if (!hdmi->ddc)
		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);

		hdmi->support_hdmi = drm_detect_hdmi_monitor(edid);
		hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
		hdmi->rgb_quant_range_selectable = drm_rgb_quant_range_selectable(edid);
		drm_connector_update_edid_property(connector, edid);
		cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
		ret = drm_add_edid_modes(connector, edid);
		dw_hdmi_update_hdr_property(connector);
		kfree(edid);
	} else {
		hdmi->support_hdmi = true;
		hdmi->sink_has_audio = true;
		hdmi->rgb_quant_range_selectable = false;

		for (i = 0; i < ARRAY_SIZE(dw_hdmi_default_modes); i++) {
			struct drm_display_mode *ptr =
				&dw_hdmi_default_modes[i];

				struct student hdmi1;

+				ptr->hdisplay = hdmi1.hdisplay_m;
+	            ptr->vdisplay = hdmi1.vdisplay_m;
+	            ptr->hsync_start = hdmi1.hsync_start_m;
+	            ptr->hsync_end = hdmi1.hsync_end_m;
+	            ptr->htotal = hdmi1.htotal_m;
+	            ptr->vsync_start = hdmi1.vsync_start_m;
+	            ptr->vsync_end = hdmi1.vsync_end_m;
+	            ptr->vtotal = hdmi1.vtotal_m;
+	            ptr->clock = hdmi1.clock_m;

+				printk("drm_mode_duplicate ptr->hdisplay:%d\n",ptr->hdisplay);
+				printk("drm_mode_duplicate ptr->vdisplay:%d\n",ptr->vdisplay);
+				printk("drm_mode_duplicate ptr->hsync_start:%d\n",ptr->hsync_start);
+				printk("drm_mode_duplicate ptr->hsync_end:%d\n",ptr->hsync_end);
+				printk("drm_mode_duplicate ptr->htotal:%d\n",ptr->htotal);
+				printk("drm_mode_duplicate ptr->vsync_start:%d\n",ptr->vsync_start);
+				printk("drm_mode_duplicate ptr->vsync_end:%d\n",ptr->vsync_end);
+				printk("drm_mode_duplicate ptr->vtotal:%d\n",ptr->vtotal);
+				printk("drm_mode_duplicate ptr->clock:%d\n",ptr->clock);

			mode = drm_mode_duplicate(connector->dev, ptr);
			if (mode) {
				if (!i) {
					mode->type = DRM_MODE_TYPE_PREFERRED;
					mode->picture_aspect_ratio =
						HDMI_PICTURE_ASPECT_NONE;
				}
				drm_mode_probed_add(connector, mode);
				ret++;
			}
		}
		info->edid_hdmi_dc_modes = 0;
		info->hdmi.y420_dc_modes = 0;
		info->color_formats = 0;

		dev_info(hdmi->dev, "failed to get edid\n");
	}
	dw_hdmi_check_output_type_changed(hdmi);

	return ret;
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

RK3568 HDMI EDID处理过程 的相关文章

随机推荐

  • Android使用ProgressBar实现加载动画

    项目需要做一个加载转圈的效果 给了一张菊花图 首先想到的是使用补间动画的旋转效果 在anim目录中创建loading xml
  • WPF加载大量控件的优化

    WPF 应用程序从两个线程开始 一个用于处理呈现 一个用于管理 UI 呈现线程有效地隐藏在后台运行 而 UI 线程则接收输入 处理事件 绘制屏幕以及运行应用程序代码 UI 线程对一个名为 Dispatcher 的对象内的工作项进行排队 Di
  • 如何快速掌握Redis跳跃表源码技巧?阿里架构师让你秒懂

    我们再来学习如何从跳跃表中查询数据 跳跃表本质上是一个链表 但它允许我们像数组一样定位某个索引区间内的节点 并且与数组不同的是 跳跃表允许我们将头节点L0层的前驱节点 即跳跃表分值最小的节点 zsl gt header level 0 fo
  • php 微信支付V3接口

    注意事项 1 请求接口签名方式 RSA 用到了API证书序列号 后缀为key pem的密钥文件 cert文件要用java自己生成 具体参考 https developers weixin qq com community develop d
  • mysql安装图解 mysql图文安装教程(详细说明)

    下面的是MySQL安装的图解 用的可执行文件安装的 详细说明了一下 打开下载的mysql安装文件mysql 5 0 27 win32 zip 双击解压缩 运行 setup exe 出现如下界面 mysql安装图文教程1 mysql安装向导启
  • Linux——信号的发送,自己实现结束进程的kill命令

    信号的发送 Linux提供了一种系统调用 2 不是kill命令 kill 可以向指定的进程发送指定的信号 int kill pid t pid int signType signType是要发送的信号 kill方法的pid参数有四种不同的情
  • PID 控制保姆级培训教程下-全国大学生电子设计大赛赛前必备

    紧接上回 PID 控制保姆级培训教程上 全国大学生电子设计大赛赛前必备 http t csdn cn TY4eB 上回介绍到 书接上回 实操设计 干货满满 3 数字控制器的模拟化设计 3 1 数字PID 3 1 1 DDC系统的组成原理 D
  • FastAPI从入门到实战(6)——请求体与嵌套模型

    前面记录的是路径参数和查询参数的内容 那两种形式的数据都不算的发送的数据 都是存在路径中的数据 请求体是客户端发给接口的参数 不存在于路径中 本文就主要记录FastAPI中的请求体应用内容 一个发送请求体的接口 创建一个数据模型 class
  • Linux 使用rpm方式安装最新mysql(5.7.16)步骤以及常见问题解决

    前几天在阿里云买了个服务器 准备自己玩玩 现将最新版mysql 5 7 16 安装步骤 以及遇到问题及解决过程分享如下 第一步 下载rpm包 mysql官网下载 http dev mysql com downloads mysql 但如果你
  • 2021年网络安全省赛--web隐藏信息探索解析(中职组)

    2021年省赛web隐藏信息探索 解析 任务环境说明 Web20200529 服务器场景操作系统 未知 关闭连接 1 通过本地PC中渗透测试平台Kali对服务器场景Web20200529中的网站进行访问 找到登录界面中的FLAG 并将FLA
  • 专属于程序员的知识仓库:开发者导航

    一个专属于开发者的导航网站 收录丰富 内容详实 更新频繁 废话不多说 先上几张图吧 网站还收录了很多惊喜类目 比如最近很火的ChatGPT和AI绘画 开发者导航网至少收录了20多个 大部分都是免魔法 国内直接可以访问的 娱乐区还包括很多影视
  • 金蝶显示服务器异常,金蝶连接云服务器异常怎么回事

    金蝶连接云服务器异常怎么回事 内容精选 换一换 华为云帮助中心 为用户提供产品简介 价格说明 购买指南 用户指南 API参考 最佳实践 常见问题 视频帮助等技术文档 帮助您快速上手使用华为云服务 ELB的常见异常返回码有400 403 50
  • 派查查 :一个WearOS智能手表系统上的快递查询应用

    目录 前言 项目概述 设计背景 系统架构 接口介绍 即时查询请求 即时查询回复 前言 在学习面向对象程序设计课程的时候 收获颇多 最后的课程报告选题选择了 Android开发 但是安卓手机上好的应用数不胜数 自己不想重蹈覆辙做别人做过不知道
  • 前端常用工具库整理

    功能库 lt lt lt Axios 一个基于 promise 的 HTTP 库 可以用在浏览器和 node js 中 http www axios js com Lodash 一个一致性 模块化 高性能的 JavaScript 实用工具库
  • 小程序使用 svg

    封装组件 components下新建svgIcon文件 wxml
  • node内置模块——Buffer模块(缓冲区)

    文章目录 Buffer 缓冲区 创建Buffer 利用字符串创建buffer Buffer from 使用Buffer方法创建buffer Buffer alloc Buffer allocUnsafe size Buffer元素的操作 B
  • CSS选择器(nth-child)

    nth child 这个选择符括号内可以写 an b a b均为整数 或者关键字 因为工作中有遇到要隐藏列表第三个子元素之后的所有子元素 所以有用到这个选择器 记录一下 1 nth child a 当括号里只写一个数字 比如 list li
  • OSI七层参考模型和数据封装

    OSI七层参考模型和数据封装 一 网络基础原理 1 分层思想 二 OSI七层参考模型 三 TCP IP协议簇和OSI参考模型 1 TCP IP五层模型常见协议 2 ARP是地址解析协议 3 RARP是反地址解析协议 四 PDU协议数据单元数
  • Flash概念简述

    1 Flash全名叫做Flash Memory Flash存储芯片的一种 通过特定的程序可以修改里面的数据 Flash属于非易失性存储设备 Non volatile Memory Device 与此相对应的是易失性存储设备 Volatile
  • RK3568 HDMI EDID处理过程

    一 简介 EDID是什么 EDID的全称是Extended Display Identification Data 扩展显示标识数据 VGA DVI的EDID由主块128字节组成 HDMI的EDID增加扩展块 128字节 扩展块的内容主要是