我采用的开发环境是OK3399-C开发板,默认的HDMI输出频率是720P,而我使用的屏幕是800x600的分辨率,需改成固定分辨率。
在源码文件kernel/drivers/gpu/drm/drm_edid.c中的edid_cea_modes结构体中包含着各种分辨率,如果里面有你需要的就不用改,如果没有,需自己新加,例如800x600-60Hz。
/* 108 - 800x600p@60Hz 4:3 */
{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
968, 1056, 0, 600, 601, 605, 628, 0, /* 800x600@60Hz从上面的edid_est_modes结构体拷贝过来 */
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) ,
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3, },
在源码文件kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c的2569行dw_hdmi_connector_get_modes函数中,
struct edid *edid;
struct drm_display_mode *mode;
//const u8 def_modes[6] = {4, 16, 31, 19, 17, 2};
const u8 def_modes[1] = {108}; //将默认模式改为自己新加的108项
struct drm_display_info *info = &connector->display_info;
struct hdr_static_metadata *metedata =
&connector->display_info.hdmi.hdr_panel_metadata;
int i, ret = 0;
if (!hdmi->ddc)
return 0;
edid = drm_get_edid(connector, hdmi->ddc);
edid = NULL; //要把edid强制输出为空,否则就跟随edid了。
if (edid) {
在源码文件kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c文件中493行,去掉如下选项
/*
if (mode->clock > 340000 &&
connector->display_info.max_tmds_clock < 340000 &&
(!drm_mode_is_420(&connector->display_info, mode) ||
!connector->ycbcr_420_allowed))
return MODE_BAD;
*/
在源码文件kernel/drivers/video/rockchip/hdmi/rockchip-hdm.h文件中hdmi_video_information_code结构体中加入新增的分辨率
HDMI_800X600P_60HZ_4_3,
在570行,修改默认的分辨率
/* HDMI default vide mode */
#define HDMI_VIDEO_DEFAULT_MODE HDMI_800X600P_60HZ_4_3 //HDMI_1280X720P_60HZ
我用的OK3399-C开发板的HDMI不支持热插拔,造成的原因是拔下后,系统切换成其它视频输出接口。权宜之计,驱动中一直挂着HDMI。在源码文件kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c文件中第1645行
enum drm_connector_status dw_hdmi_phy_read_hpd(struct dw_hdmi *hdmi,
void *data)
{
return hdmi_readb(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD ?
connector_status_connected : connector_status_connected;
//connector_status_connected : connector_status_disconnected;
}
修改上面的文件后,重新编译系统内核,并更新到开发板上,可以看到分辨率变成了800x600。