完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
**
Platform: ROCKCHIP Chip: RK3399 OS: Android7.1.2 Kernel: 4.4.126* ** 【接上篇】上篇虽然HDMI能正常输出4K,但是帧率却达不到60帧,只能30帧,具体分析如下 按网上和官方的分别试了下修改,均没成功kernel/driversideo/rockchipmi/rockchip-hdmiv2 中的 rockchip-hdmi.h 文件, /* HDMI default vide mode */ #define HDMI_VIDEO_DEFAULT_MODE HDMI_1280X720P_60HZ 又在dtsi中加入 rockchip,defaultmode = <4>;也没有成功。 以上是开机那时候的分辨率。 修改与现象 将输出特殊分辨率的方法输出 相关文件: kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c kernel/drivers/gpu/drm/drm_edid.c 如上修改: 1、在edid_cea_modes数据的最后定义特殊的分辨率(drm_edid.c文件中)。 2、把def_mode数组的第一个值改成特殊分辨率对应的 vic(vic在drivers/gpu/drm/drm_edid.c文件中edid_cea_modes结构体中). 3、edid = NULL;强制把edid赋为NULL,不管有没有读到edid都强制按def_modes来显示。 kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c下的函数dw_hdmi_connector_get_modes(),修改def_modes def_modes[1] = {97};//3840x2160P60 烧录设备结果:hdmi输出显示屏黑屏 cat 设备结果如下 在这里插入图片描述 特殊分辨率 def_modes[1] = {108};//特殊分辨率 800x1280P60 /* 108 - 800x1280@60Hz */ kernel/drivers/gpu/drm/drm_edid.c里edid_cea_modes[]:新增如下特殊分辨率: { DRM_MODE(“800x1280”, DRM_MODE_TYPE_DRIVER, 76000, 800, 848, 880, 960, 0, 1280, 1300, 1304, 1314, 0, DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC), .vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, }, 烧录设备结果:出图正常 cat 设备结果如下 在这里插入图片描述 在这里插入图片描述 原因:显示屏不支持4K60hz,支支持4K30hz,所以导致设备分辨率为60hz时黑屏 其工作流程:底层通过edid,读取到显示器的分辨率列表,然后反馈给Android系统,在系统界面里显示出来 设置分辨率的流程分析 先通过i2c获取屏的edid信息。 EDID的全称是Extended Display Identification Data(扩展显示标识数据),共有128字节。其中包含有关显示器及其性能的参数,包括供应商信息、最大图像大小、颜色设置、厂商预设置、 频率范围的限制以及显示器名和序列号的字符串等等。 如何查看edid信息? cat sys/class/drm/card0-HDMI-A-1/edid > /data/edid.bin //然后把edid.bin拷贝出来 或者:cat sys/class/drm/card0-HDMI-A-1/edid |busybox hexdump 驱动文件清单 通用屏配置驱动: drivers/gpu/drm/panel/panel-simple.c //.c文件里面包含mipi的时序参数配置和mipi一些接口还有背光的使能关闭等,配置屏参可以在此文件或者dts Core: drivers/gpu/drm/rockchip/rockchip_drm_drv.c framebuffer drivers/gpu/drm/rockchip/rockchip_drm_fb.c gem drivers/gpu/drm/rockchip/rockchip_drm_gem.c vop: drivers/gpu/drm/rockchip/rockchip_drm_vop.c drivers/gpu/drm/rockchip/rockchip_vop_reg.c lvds: drivers/gpu/drm/rockchip/rockchip_lvds.c rga: drivers/gpu/drm/rockchip/rockchip_drm_rga.c mipi: drivers/gpu/drm/rockchip/dw-mipi-dsi.c hdmi: drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c drivers/gpu/drm/bridge/dw-hdmi.c inno hdmi: drivers/gpu/drm/rockchip/inno_hdmi.c edp: drivers/gpu/drm/rockchip/analogix_dp-rockchip.c drivers/gpu/drm/bridge/analogix/analogix_dp_core.c drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c dp: drivers/gpu/drm/rockchip/cdn-dp-core.c drivers/gpu/drm/rockchip/cdn-dp-reg.c 具体相关接口分析: 基于component框架, 在probe阶段解析dts中各个设备的信息, 加到component match 列表中, 等所有设备加 载完毕后, 就会引发master设备的bind. Rockchip drm主设备驱动:drivers/gpu/drm/rockchip/rockchip_drm_drv.c drivers/gpu/drm/rockchip/rockchip_drm_drv.h VOP驱动:drivers/gpu/drm/rockchip/rockchip_drm_vop.c drivers/gpu/drm/rockchip/rockchip_vop_reg.c 图层接口: static const struct drm_plane_helper_funcs plane_helper_funcs = { // 预先对图层进行处理 .prepare_fb = vop_plane_prepare_fb, // 图层显示完成后的处理 .cleanup_fb = vop_plane_cleanup_fb, // 在显示前进行参数检查 .atomic_check = vop_plane_atomic_check, // 更新图层参数 .atomic_update = vop_plane_atomic_update, // 关闭图层 .atomic_disable = vop_plane_atomic_disable, }; VOP接口: static const struct drm_crtc_helper_funcs vop_crtc_helper_funcs = { // 使能vop, 在这里面会将timing配好 .enable = vop_crtc_enable, // 关闭vop .disable = vop_crtc_disable, // 对timing进行检查修正 .mode_fixup = vop_crtc_mode_fixup, // 在一帧显示开始前做的处理 .atomic_begin = vop_crtc_atomic_begin, // 检查显示的参数 .atomic_check = vop_crtc_atomic_check, // 提交硬件显示 .atomic_flush = vop_crtc_atomic_flush, }; 接口执行顺序: vop_plane_atomic_check //在显示前进行参数检查 vop_plane_prepare_fb //预先对图层进行处理 vop_plane_atomic_update //更新图层参数 vop_crtc_atomic_flush //提交硬件显示 vop_plane_cleanup_fb //图层显示完成后的处理 对应文件: drivers/gpu/drm/bridge/synopsys/dw-hdmi.c ./drivers/gpu/drm/drm_edid.c 调用get_modes获取分辨率的时候会去调用 .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)) 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);分配和复制现有模式, 返回:成功时指向复制模式的指针,错误时为空。 |
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
基于米尔瑞芯微RK3576核心板/开发板的人脸疲劳检测应用方案
808 浏览 0 评论
1024 浏览 1 评论
887 浏览 1 评论
2113 浏览 1 评论
3373 浏览 1 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-26 15:52 , Processed in 0.785168 second(s), Total 72, Slave 56 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号