涉及文件
kernel/drivers/gpu/drm/drm_edid.c
kernel/drivers/gpu/drm/rockchip/inno_hdmi.c
kernel/drivers/gpu/drm/rockchip/inno_hdmi.h
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
kernel/drivers/video/rockchip/hdmi/rockchip-hdmi.h
kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
device/rockchip/rk3399/rk3399_all/system.prop
frameworks/base/services/core/jni/com_android_server_rkdisplay_RkDisplayModes.cpp
kernel部分代码
edid相关代码
kernel/drivers/gpu/drm/drm_edid.c
/*
* Probably taken from CEA-861 spec.
* This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
*
* Index using the VIC.
*/
static const struct drm_display_mode edid_cea_modes[] = {
...
/* 5 - 1920x1080i@60Hz */
{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
...
------------------
drm_add_edid_modes
add_detailed_modes
do_detailed_mode
drm_mode_detailed
include/drm/drm_edid.h
struct edid {
u8 header[8];
/* Vendor & product info */
u8 mfg_id[2];
u8 prod_code[2];
u32 serial; /* FIXME: byte order */
u8 mfg_week;
u8 mfg_year;
/* EDID version */
u8 version;
u8 revision;
/* Display info: */
u8 input;
u8 width_cm;
u8 height_cm;
u8 gamma;
u8 features;
/* Color characteristics */
u8 red_green_lo;
u8 black_white_lo;
u8 red_x;
u8 red_y;
u8 green_x;
u8 green_y;
u8 blue_x;
u8 blue_y;
u8 white_x;
u8 white_y;
/* Est. timings and mfg rsvd timings*/
struct est_timings established_timings;
/* Standard timings 1-8*/
struct std_timing standard_timings[8];
/* Detailing timings 1-4 */
struct detailed_timing detailed_timings[4];
/* Number of 128 byte ext. blocks */
u8 extensions;
/* Checksum */
u8 checksum;
} __attribute__((packed));
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
struct edid *edid;
struct drm_display_mode *mode;
const u8 def_modes[6] = {97, 16, 31, 19, 17, 2};
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;
if (edid) {
dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]n",
edid->width_cm, edid->height_cm);
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(connector, edid);
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
ret = drm_add_edid_modes(connector, edid);
/* Store the ELD */
drm_edid_to_eld(connector, edid);
drm_mode_connector_update_hdr_property(connector, metedata);
kfree(edid);
} else {
hdmi->sink_is_hdmi = true;
hdmi->sink_has_audio = true;
for (i = 0; i < sizeof(def_modes); i++) {
mode = drm_display_mode_from_vic_index(connector,
def_modes,
31, i);
if (mode) {
if (!i)
mode->type = DRM_MODE_TYPE_PREFERRED;
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 edidn");
}
return ret;
}
HDMI 纵横比
查看edid_cea_modes[],我们发现同一个分辨率会对应几个不同的参数结构体,例如:
/* 97 - 3840x2160p@60Hz 16:9 */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
/* 107 - 3840x2160p@60Hz 64:27 */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
显示参数基本相同,唯一的区别在于图像纵横比picture_aspect_ratio,一般有如下几种配置:
HDMI_PICTURE_ASPECT_4_3
HDMI_PICTURE_ASPECT_16_9
HDMI_PICTURE_ASPECT_256_135
HDMI_PICTURE_ASPECT_64_27
该参数需要与屏幕的纵横比相匹配。
热插拔处理逻辑
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
dw_hdmi_rockchip_bind
dw_hdmi_bind
kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
int dw_hdmi_bind(struct device *dev, struct device *master,
void *data, struct drm_encoder *encoder,
struct resource *iores, int irq,
const struct dw_hdmi_plat_data *plat_data)
init_hpd_work(hdmi);
initialize_hdmi_ih_mutes(hdmi);
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
dw_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
init_hpd_work
INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event);
repo_hpd_event
devm_request_threaded_irq
dw_hdmi_hardirq
dw_hdmi_irq
check_hdmi_irq
Android部分代码
persist.sys.resolution.main
persist.sys.resolution.aux
static void nativeSaveConfig(JNIEnv* env, jobject obj) {
char buf[BUFFER_LENGTH];
bool isMainHdmiConnected=false;
bool isAuxHdmiConnected = false;
int foundMainIdx=-1,foundAuxIdx=-1;
struct file_base_paramer base_paramer;
if (primary != NULL) {
std::vector mModes = primary->modes();
char resolution[PROPERTY_VALUE_MAX];
unsigned int w=0,h=0,hsync_start=0,hsync_end=0,htotal=0;
unsigned int vsync_start=0,vsync_end=0,vtotal=0,flags=0;
float vfresh=0.0000;
property_get("persist.sys.resolution.main", resolution, "0x0@0.00-0-0-0-0-0-0-0");
if (strncmp(resolution, "Auto", 4) != 0 && strncmp(resolution, "0x0p0-0", 7) !=0)
sscanf(resolution,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x", &w, &h, &vfresh, &hsync_start,&hsync_end,
&htotal,&vsync_start,&vsync_end, &vtotal, &flags);
for (size_t c = 0; c < mModes.size(); ++c){
const DrmMode& info = mModes[c];
char curDrmModeRefresh[16];
char curRefresh[16];
float mModeRefresh;
if (info.flags() & DRM_MODE_FLAG_INTERLACE)
mModeRefresh = info.clock()*2 / (float)(info.v_total()* info.h_total()) * 1000.0f;
else
mModeRefresh = info.clock()/ (float)(info.v_total()* info.h_total()) * 1000.0f;
sprintf(curDrmModeRefresh, "%.2f", mModeRefresh);
sprintf(curRefresh, "%.2f", vfresh);
if (info.h_display() == w &&
info.v_display() == h &&
info.h_sync_start() == hsync_start &&
info.h_sync_end() == hsync_end &&
info.h_total() == htotal &&
info.v_sync_start() == vsync_start &&
info.v_sync_end() == vsync_end &&
info.v_total()==vtotal &&
atof(curDrmModeRefresh)==atof(curRefresh)) {
ALOGD("***********************found main idx %d ****************", (int)c);
foundMainIdx = c;
sprintf(buf, "display=%d,iface=%d,enable=%d,mode=%sn",
primary->display(), primary->get_type(), primary->state(), resolution);
break;
}
}
}
if (extend != NULL) {
std::vector mModes = extend->modes();
char resolution[PROPERTY_VALUE_MAX];
unsigned int w=0,h=0,hsync_start=0,hsync_end=0,htotal=0;
unsigned int vsync_start=0,vsync_end=0,vtotal=0,flags;
float vfresh=0;
property_get("persist.sys.resolution.aux", resolution, "0x0@0.00-0-0-0-0-0-0-0");
if (strncmp(resolution, "Auto", 4) != 0 && strncmp(resolution, "0x0p0-0", 7) !=0)
sscanf(resolution,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x", &w, &h, &vfresh, &hsync_start,&hsync_end,&htotal,&vsync_start,&vsync_end,
&vtotal, &flags);
for (size_t c = 0; c < mModes.size(); ++c){
const DrmMode& info = mModes[c];
char curDrmModeRefresh[16];
char curRefresh[16];
float mModeRefresh;
if (info.flags() & DRM_MODE_FLAG_INTERLACE)
mModeRefresh = info.clock()*2 / (float)(info.v_total()* info.h_total()) * 1000.0f;
else
mModeRefresh = info.clock()/ (float)(info.v_total()* info.h_total()) * 1000.0f;
sprintf(curDrmModeRefresh, "%.2f", mModeRefresh);
sprintf(curRefresh, "%.2f", vfresh);
if (info.h_display() == w &&
info.v_display() == h &&
info.h_sync_start() == hsync_start &&
info.h_sync_end() == hsync_end &&
info.h_total() == htotal &&
info.v_sync_start() == vsync_start &&
info.v_sync_end() == vsync_end &&
info.v_total()==vtotal &&
atof(curDrmModeRefresh)==atoi(curRefresh)) {
ALOGD("***********************found aux idx %d ****************", (int)c);
foundAuxIdx = c;
break;
}
}
}
...
...
static void nativeSetMode(JNIEnv* env, jobject obj, jint dpy,jint iface_type, jstring mode)
{
int display = dpy;
int type = iface_type;
const char* mMode = env->GetStringUTFChars(mode, NULL);
ALOGD("nativeSetMode %s display %d iface_type %d", mMode, display, type);
if (display == HWC_DISPLAY_PRIMARY){
property_set("persist.sys.resolution.main", mMode);
} else if (display == HWC_DISPLAY_EXTERNAL) {
property_set("persist.sys.resolution.aux", mMode);
}
}
device/rockchip/rk3399/rk3399_all/system.prop
persist.sys.resolution.aux=3840x2160p30
文件系统显示接口
查看当前HDMI屏分辨率支持列表
# cat /sys/class/drm/card0-HDMI-A-1/modes
3840x2160p60
3840x2160p60
3840x2160p60
3840x2160p50
3840x2160p30
3840x2160p30
3840x2160p30
3840x2160p25
3840x2160p24
3840x2160p24
1920x2160p60
2560x1440p60
1920x1080p60
1920x1080p60
1920x1080p50
1680x1050p60
1280x1024p75
1280x1024p60
1440x900p60
1280x960p60
1280x720p60
1280x720p60
1280x720p50
1024x768p75
1024x768p70
1024x768p60
832x624p75
800x600p75
800x600p72
800x600p60
800x600p56
720x576p50
720x480p60
720x480p60
640x480p75
640x480p73
640x480p67
640x480p60
640x480p60
720x400p70
当前的显示分辨率
# cat /sys/class/drm/card0-HDMI-A-1/mode
3840x2160p60
查看EDID信息
# cat sys/class/drm/card0-HDMI-A-1/edid | busybox hexdump
0000000 ff00 ffff ffff 00ff e305 2790 8b64 0000
0000010 1d11 0301 3c80 7822 672a a5a1 4d55 27a2
0000020 500e bf54 00ef c0d1 00b3 0095 8081 4081
0000030 c081 0101 0101 d04d a000 70f0 803e 2030
0000040 0035 5055 0021 1a00 66a3 a000 70f0 801f
0000050 2030 0035 5055 0021 1a00 0000 fc00 5500
0000060 3732 3039 0a42 2020 2020 2020 0000 fd00
0000070 1700 1e50 3ca0 0a00 2020 2020 2020 c901
0000080 0302 f133 904c 0304 131f 1201 5e5d 605f
0000090 2361 0709 8307 0001 6d00 0c03 1000 3800
00000a0 2078 6000 0201 6703 5dd8 01c4 8078 e303
00000b0 000f 560c 005e a0a0 29a0 3050 3520 5500
00000c0 2150 0000 021e 803a 7118 2d38 5840 452c
00000d0 5500 2150 0000 011e 001d 5172 1ed0 6e20
00000e0 5528 5500 2150 0000 4d1e 806c 70a0 3e70
00000f0 3080 3a20 5500 2150 0000 001a 0000 4e00
0000100
强行开关显示设备
关HDMI: echo off > /sys/class/drm/card0-HDMI-A-1/status
开HDMI: echo on > /sys/class/drm/card0-HDMI-A-1/status
VOP的状态
# cat /sys/kernel/debug/dri/0/summary
VOP [ff900000.vop]: ACTIVE
Connector: HDMI-A
overlay_mode[1] bus_format[2025] output_mode[f] color_space[3]
Display mode: 3840x2160p60
clk[533250] real_clk[533250] type[48] flag[9]
H: 3840 3888 3920 4000
V: 2160 2163 2168 2222
win0-0: ACTIVE
format: AR24 little-endian (0x34325241) SDR[0] color_space[0]
csc: y2r[0] r2r[0] r2y[1] csc mode[1]
zpos: 0
src: pos[0x0] rect[3840x2160]
dst: pos[0x0] rect[3840x2160]
buf[0]: addr: 0x0000000004000000 pitch: 15360 offset: 0
win1-0: DISABLED
win2-0: DISABLED
win2-1: DISABLED
win2-2: DISABLED
win2-3: DISABLED
win3-0: DISABLED
win3-1: DISABLED
win3-2: DISABLED
win3-3: DISABLED
post: sdr2hdr[0] hdr2sdr[0]
pre : sdr2hdr[0]
post CSC: r2y[0] y2r[0] CSC mode[1]
VOP [ff8f0000.vop]: DISABLED
HDMI当前输出状态
# cat /sys/kernel/debug/dw-hdmi/status
PHY: enabled Mode: HDMI
Pixel Clk: 533250000Hz TMDS Clk: 133312500Hz
Color Format: YUV444 Color Depth: 8 bit
Colorimetry: ITU.BT709 EOTF: Off
其他功能接口
xrandr指令配置HDMI
$ xrandr
Screen 0: minimum 320 x 200, current 3840 x 2160, maximum 8192 x 8192
HDMI-1 connected primary 3840x2160+0+0 (normal left inverted right x axis y axis) 597mm x 336mm
3840x2160 60.00*+ 60.00 50.00 59.94 30.00 25.00 24.00 29.97 23.98 29.98
1920x2160 59.99
2560x1440 59.95
1920x1080 60.00 50.00 59.94
1680x1050 59.88
1280x1024 75.02 60.02
1440x900 59.90
1280x960 60.00
1280x720 60.00 50.00 59.94
1024x768 75.03 70.07 60.00
832x624 74.55
800x600 72.19 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 72.81 66.67 60.00 59.94
720x400 70.08
使用 xrandr 设置不同的分辨率
$ xrandr --output HDMI-1 --mode 3840x2160
$ xrandr --output HDMI-1 --mode 3840x2160 --rate 30
$ xrandr
Screen 0: minimum 320 x 200, current 3840 x 2160, maximum 8192 x 8192
HDMI-1 connected primary 3840x2160+0+0 (normal left inverted right x axis y axis) 597mm x 336mm
3840x2160 60.00 + 60.00 50.00 59.94 30.00* 25.00 24.00 29.97 23.98 29.98
1920x2160 59.99
2560x1440 59.95
1920x1080 60.00 50.00 59.94
1680x1050 59.88
1280x1024 75.02 60.02
1440x900 59.90
1280x960 60.00
1280x720 60.00 50.00 59.94
1024x768 75.03 70.07 60.00
832x624 74.55
800x600 72.19 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 72.81 66.67 60.00 59.94
720x400 70.08
运行gtf或者cvt,查询某分辨率的有效扫描频率
$ gtf 3840 2160 30
# 3840x2160 @ 30.00 Hz (GTF) hsync: 65.91 kHz; pclk: 339.57 MHz
Modeline "3840x2160_30.00" 339.57 3840 4080 4496 5152 2160 2161 2164 2197 -HSync +Vsync
$ cvt 3840 2160 30
# 3840x2160 29.98 Hz (CVT) hsync: 65.96 kHz; pclk: 338.75 MHz
Modeline "3840x2160_30.00" 338.75 3840 4080 4488 5136 2160 2163 2168 2200 -hsync +vsync
通过–newmode参数新建一种xrandr模式
$ xrandr --newmode "3840x2160_30.00" 338.75 3840 4080 4488 5136 2160 2163 2168 2200 -hsync +vsync
新建模式后,我们需要把这模式添加到当前的输出设备HDMI-1
$ xrandr --addmode HDMI-1 3840x2160_30.00
设置该模式输出
$ xrandr --output HDMI-1 --mode 3840x2160_30.00
涉及文件
kernel/drivers/gpu/drm/drm_edid.c
kernel/drivers/gpu/drm/rockchip/inno_hdmi.c
kernel/drivers/gpu/drm/rockchip/inno_hdmi.h
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
kernel/drivers/video/rockchip/hdmi/rockchip-hdmi.h
kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
device/rockchip/rk3399/rk3399_all/system.prop
frameworks/base/services/core/jni/com_android_server_rkdisplay_RkDisplayModes.cpp
kernel部分代码
edid相关代码
kernel/drivers/gpu/drm/drm_edid.c
/*
* Probably taken from CEA-861 spec.
* This table is converted from xorg's hw/xfree86/modes/xf86EdidModes.c.
*
* Index using the VIC.
*/
static const struct drm_display_mode edid_cea_modes[] = {
...
/* 5 - 1920x1080i@60Hz */
{ DRM_MODE("1920x1080i", DRM_MODE_TYPE_DRIVER, 74250, 1920, 2008,
2052, 2200, 0, 1080, 1084, 1094, 1125, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC |
DRM_MODE_FLAG_INTERLACE),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
...
------------------
drm_add_edid_modes
add_detailed_modes
do_detailed_mode
drm_mode_detailed
include/drm/drm_edid.h
struct edid {
u8 header[8];
/* Vendor & product info */
u8 mfg_id[2];
u8 prod_code[2];
u32 serial; /* FIXME: byte order */
u8 mfg_week;
u8 mfg_year;
/* EDID version */
u8 version;
u8 revision;
/* Display info: */
u8 input;
u8 width_cm;
u8 height_cm;
u8 gamma;
u8 features;
/* Color characteristics */
u8 red_green_lo;
u8 black_white_lo;
u8 red_x;
u8 red_y;
u8 green_x;
u8 green_y;
u8 blue_x;
u8 blue_y;
u8 white_x;
u8 white_y;
/* Est. timings and mfg rsvd timings*/
struct est_timings established_timings;
/* Standard timings 1-8*/
struct std_timing standard_timings[8];
/* Detailing timings 1-4 */
struct detailed_timing detailed_timings[4];
/* Number of 128 byte ext. blocks */
u8 extensions;
/* Checksum */
u8 checksum;
} __attribute__((packed));
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
static int dw_hdmi_connector_get_modes(struct drm_connector *connector)
{
struct dw_hdmi *hdmi = container_of(connector, struct dw_hdmi,
connector);
struct edid *edid;
struct drm_display_mode *mode;
const u8 def_modes[6] = {97, 16, 31, 19, 17, 2};
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;
if (edid) {
dev_dbg(hdmi->dev, "got edid: width[%d] x height[%d]n",
edid->width_cm, edid->height_cm);
hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
drm_mode_connector_update_edid_property(connector, edid);
cec_notifier_set_phys_addr_from_edid(hdmi->cec_notifier, edid);
ret = drm_add_edid_modes(connector, edid);
/* Store the ELD */
drm_edid_to_eld(connector, edid);
drm_mode_connector_update_hdr_property(connector, metedata);
kfree(edid);
} else {
hdmi->sink_is_hdmi = true;
hdmi->sink_has_audio = true;
for (i = 0; i < sizeof(def_modes); i++) {
mode = drm_display_mode_from_vic_index(connector,
def_modes,
31, i);
if (mode) {
if (!i)
mode->type = DRM_MODE_TYPE_PREFERRED;
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 edidn");
}
return ret;
}
HDMI 纵横比
查看edid_cea_modes[],我们发现同一个分辨率会对应几个不同的参数结构体,例如:
/* 97 - 3840x2160p@60Hz 16:9 */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9, },
/* 107 - 3840x2160p@60Hz 64:27 */
{ DRM_MODE("3840x2160", DRM_MODE_TYPE_DRIVER, 594000, 3840, 4016,
4104, 4400, 0, 2160, 2168, 2178, 2250, 0,
DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC),
.vrefresh = 60, .picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27, },
显示参数基本相同,唯一的区别在于图像纵横比picture_aspect_ratio,一般有如下几种配置:
HDMI_PICTURE_ASPECT_4_3
HDMI_PICTURE_ASPECT_16_9
HDMI_PICTURE_ASPECT_256_135
HDMI_PICTURE_ASPECT_64_27
该参数需要与屏幕的纵横比相匹配。
热插拔处理逻辑
kernel/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
dw_hdmi_rockchip_bind
dw_hdmi_bind
kernel/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
int dw_hdmi_bind(struct device *dev, struct device *master,
void *data, struct drm_encoder *encoder,
struct resource *iores, int irq,
const struct dw_hdmi_plat_data *plat_data)
init_hpd_work(hdmi);
initialize_hdmi_ih_mutes(hdmi);
ret = devm_request_threaded_irq(dev, irq, dw_hdmi_hardirq,
dw_hdmi_irq, IRQF_SHARED,
dev_name(dev), hdmi);
init_hpd_work
INIT_DELAYED_WORK(&hdmi->work, repo_hpd_event);
repo_hpd_event
devm_request_threaded_irq
dw_hdmi_hardirq
dw_hdmi_irq
check_hdmi_irq
Android部分代码
persist.sys.resolution.main
persist.sys.resolution.aux
static void nativeSaveConfig(JNIEnv* env, jobject obj) {
char buf[BUFFER_LENGTH];
bool isMainHdmiConnected=false;
bool isAuxHdmiConnected = false;
int foundMainIdx=-1,foundAuxIdx=-1;
struct file_base_paramer base_paramer;
if (primary != NULL) {
std::vector mModes = primary->modes();
char resolution[PROPERTY_VALUE_MAX];
unsigned int w=0,h=0,hsync_start=0,hsync_end=0,htotal=0;
unsigned int vsync_start=0,vsync_end=0,vtotal=0,flags=0;
float vfresh=0.0000;
property_get("persist.sys.resolution.main", resolution, "0x0@0.00-0-0-0-0-0-0-0");
if (strncmp(resolution, "Auto", 4) != 0 && strncmp(resolution, "0x0p0-0", 7) !=0)
sscanf(resolution,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x", &w, &h, &vfresh, &hsync_start,&hsync_end,
&htotal,&vsync_start,&vsync_end, &vtotal, &flags);
for (size_t c = 0; c < mModes.size(); ++c){
const DrmMode& info = mModes[c];
char curDrmModeRefresh[16];
char curRefresh[16];
float mModeRefresh;
if (info.flags() & DRM_MODE_FLAG_INTERLACE)
mModeRefresh = info.clock()*2 / (float)(info.v_total()* info.h_total()) * 1000.0f;
else
mModeRefresh = info.clock()/ (float)(info.v_total()* info.h_total()) * 1000.0f;
sprintf(curDrmModeRefresh, "%.2f", mModeRefresh);
sprintf(curRefresh, "%.2f", vfresh);
if (info.h_display() == w &&
info.v_display() == h &&
info.h_sync_start() == hsync_start &&
info.h_sync_end() == hsync_end &&
info.h_total() == htotal &&
info.v_sync_start() == vsync_start &&
info.v_sync_end() == vsync_end &&
info.v_total()==vtotal &&
atof(curDrmModeRefresh)==atof(curRefresh)) {
ALOGD("***********************found main idx %d ****************", (int)c);
foundMainIdx = c;
sprintf(buf, "display=%d,iface=%d,enable=%d,mode=%sn",
primary->display(), primary->get_type(), primary->state(), resolution);
break;
}
}
}
if (extend != NULL) {
std::vector mModes = extend->modes();
char resolution[PROPERTY_VALUE_MAX];
unsigned int w=0,h=0,hsync_start=0,hsync_end=0,htotal=0;
unsigned int vsync_start=0,vsync_end=0,vtotal=0,flags;
float vfresh=0;
property_get("persist.sys.resolution.aux", resolution, "0x0@0.00-0-0-0-0-0-0-0");
if (strncmp(resolution, "Auto", 4) != 0 && strncmp(resolution, "0x0p0-0", 7) !=0)
sscanf(resolution,"%dx%d@%f-%d-%d-%d-%d-%d-%d-%x", &w, &h, &vfresh, &hsync_start,&hsync_end,&htotal,&vsync_start,&vsync_end,
&vtotal, &flags);
for (size_t c = 0; c < mModes.size(); ++c){
const DrmMode& info = mModes[c];
char curDrmModeRefresh[16];
char curRefresh[16];
float mModeRefresh;
if (info.flags() & DRM_MODE_FLAG_INTERLACE)
mModeRefresh = info.clock()*2 / (float)(info.v_total()* info.h_total()) * 1000.0f;
else
mModeRefresh = info.clock()/ (float)(info.v_total()* info.h_total()) * 1000.0f;
sprintf(curDrmModeRefresh, "%.2f", mModeRefresh);
sprintf(curRefresh, "%.2f", vfresh);
if (info.h_display() == w &&
info.v_display() == h &&
info.h_sync_start() == hsync_start &&
info.h_sync_end() == hsync_end &&
info.h_total() == htotal &&
info.v_sync_start() == vsync_start &&
info.v_sync_end() == vsync_end &&
info.v_total()==vtotal &&
atof(curDrmModeRefresh)==atoi(curRefresh)) {
ALOGD("***********************found aux idx %d ****************", (int)c);
foundAuxIdx = c;
break;
}
}
}
...
...
static void nativeSetMode(JNIEnv* env, jobject obj, jint dpy,jint iface_type, jstring mode)
{
int display = dpy;
int type = iface_type;
const char* mMode = env->GetStringUTFChars(mode, NULL);
ALOGD("nativeSetMode %s display %d iface_type %d", mMode, display, type);
if (display == HWC_DISPLAY_PRIMARY){
property_set("persist.sys.resolution.main", mMode);
} else if (display == HWC_DISPLAY_EXTERNAL) {
property_set("persist.sys.resolution.aux", mMode);
}
}
device/rockchip/rk3399/rk3399_all/system.prop
persist.sys.resolution.aux=3840x2160p30
文件系统显示接口
查看当前HDMI屏分辨率支持列表
# cat /sys/class/drm/card0-HDMI-A-1/modes
3840x2160p60
3840x2160p60
3840x2160p60
3840x2160p50
3840x2160p30
3840x2160p30
3840x2160p30
3840x2160p25
3840x2160p24
3840x2160p24
1920x2160p60
2560x1440p60
1920x1080p60
1920x1080p60
1920x1080p50
1680x1050p60
1280x1024p75
1280x1024p60
1440x900p60
1280x960p60
1280x720p60
1280x720p60
1280x720p50
1024x768p75
1024x768p70
1024x768p60
832x624p75
800x600p75
800x600p72
800x600p60
800x600p56
720x576p50
720x480p60
720x480p60
640x480p75
640x480p73
640x480p67
640x480p60
640x480p60
720x400p70
当前的显示分辨率
# cat /sys/class/drm/card0-HDMI-A-1/mode
3840x2160p60
查看EDID信息
# cat sys/class/drm/card0-HDMI-A-1/edid | busybox hexdump
0000000 ff00 ffff ffff 00ff e305 2790 8b64 0000
0000010 1d11 0301 3c80 7822 672a a5a1 4d55 27a2
0000020 500e bf54 00ef c0d1 00b3 0095 8081 4081
0000030 c081 0101 0101 d04d a000 70f0 803e 2030
0000040 0035 5055 0021 1a00 66a3 a000 70f0 801f
0000050 2030 0035 5055 0021 1a00 0000 fc00 5500
0000060 3732 3039 0a42 2020 2020 2020 0000 fd00
0000070 1700 1e50 3ca0 0a00 2020 2020 2020 c901
0000080 0302 f133 904c 0304 131f 1201 5e5d 605f
0000090 2361 0709 8307 0001 6d00 0c03 1000 3800
00000a0 2078 6000 0201 6703 5dd8 01c4 8078 e303
00000b0 000f 560c 005e a0a0 29a0 3050 3520 5500
00000c0 2150 0000 021e 803a 7118 2d38 5840 452c
00000d0 5500 2150 0000 011e 001d 5172 1ed0 6e20
00000e0 5528 5500 2150 0000 4d1e 806c 70a0 3e70
00000f0 3080 3a20 5500 2150 0000 001a 0000 4e00
0000100
强行开关显示设备
关HDMI: echo off > /sys/class/drm/card0-HDMI-A-1/status
开HDMI: echo on > /sys/class/drm/card0-HDMI-A-1/status
VOP的状态
# cat /sys/kernel/debug/dri/0/summary
VOP [ff900000.vop]: ACTIVE
Connector: HDMI-A
overlay_mode[1] bus_format[2025] output_mode[f] color_space[3]
Display mode: 3840x2160p60
clk[533250] real_clk[533250] type[48] flag[9]
H: 3840 3888 3920 4000
V: 2160 2163 2168 2222
win0-0: ACTIVE
format: AR24 little-endian (0x34325241) SDR[0] color_space[0]
csc: y2r[0] r2r[0] r2y[1] csc mode[1]
zpos: 0
src: pos[0x0] rect[3840x2160]
dst: pos[0x0] rect[3840x2160]
buf[0]: addr: 0x0000000004000000 pitch: 15360 offset: 0
win1-0: DISABLED
win2-0: DISABLED
win2-1: DISABLED
win2-2: DISABLED
win2-3: DISABLED
win3-0: DISABLED
win3-1: DISABLED
win3-2: DISABLED
win3-3: DISABLED
post: sdr2hdr[0] hdr2sdr[0]
pre : sdr2hdr[0]
post CSC: r2y[0] y2r[0] CSC mode[1]
VOP [ff8f0000.vop]: DISABLED
HDMI当前输出状态
# cat /sys/kernel/debug/dw-hdmi/status
PHY: enabled Mode: HDMI
Pixel Clk: 533250000Hz TMDS Clk: 133312500Hz
Color Format: YUV444 Color Depth: 8 bit
Colorimetry: ITU.BT709 EOTF: Off
其他功能接口
xrandr指令配置HDMI
$ xrandr
Screen 0: minimum 320 x 200, current 3840 x 2160, maximum 8192 x 8192
HDMI-1 connected primary 3840x2160+0+0 (normal left inverted right x axis y axis) 597mm x 336mm
3840x2160 60.00*+ 60.00 50.00 59.94 30.00 25.00 24.00 29.97 23.98 29.98
1920x2160 59.99
2560x1440 59.95
1920x1080 60.00 50.00 59.94
1680x1050 59.88
1280x1024 75.02 60.02
1440x900 59.90
1280x960 60.00
1280x720 60.00 50.00 59.94
1024x768 75.03 70.07 60.00
832x624 74.55
800x600 72.19 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 72.81 66.67 60.00 59.94
720x400 70.08
使用 xrandr 设置不同的分辨率
$ xrandr --output HDMI-1 --mode 3840x2160
$ xrandr --output HDMI-1 --mode 3840x2160 --rate 30
$ xrandr
Screen 0: minimum 320 x 200, current 3840 x 2160, maximum 8192 x 8192
HDMI-1 connected primary 3840x2160+0+0 (normal left inverted right x axis y axis) 597mm x 336mm
3840x2160 60.00 + 60.00 50.00 59.94 30.00* 25.00 24.00 29.97 23.98 29.98
1920x2160 59.99
2560x1440 59.95
1920x1080 60.00 50.00 59.94
1680x1050 59.88
1280x1024 75.02 60.02
1440x900 59.90
1280x960 60.00
1280x720 60.00 50.00 59.94
1024x768 75.03 70.07 60.00
832x624 74.55
800x600 72.19 75.00 60.32 56.25
720x576 50.00
720x480 60.00 59.94
640x480 75.00 72.81 66.67 60.00 59.94
720x400 70.08
运行gtf或者cvt,查询某分辨率的有效扫描频率
$ gtf 3840 2160 30
# 3840x2160 @ 30.00 Hz (GTF) hsync: 65.91 kHz; pclk: 339.57 MHz
Modeline "3840x2160_30.00" 339.57 3840 4080 4496 5152 2160 2161 2164 2197 -HSync +Vsync
$ cvt 3840 2160 30
# 3840x2160 29.98 Hz (CVT) hsync: 65.96 kHz; pclk: 338.75 MHz
Modeline "3840x2160_30.00" 338.75 3840 4080 4488 5136 2160 2163 2168 2200 -hsync +vsync
通过–newmode参数新建一种xrandr模式
$ xrandr --newmode "3840x2160_30.00" 338.75 3840 4080 4488 5136 2160 2163 2168 2200 -hsync +vsync
新建模式后,我们需要把这模式添加到当前的输出设备HDMI-1
$ xrandr --addmode HDMI-1 3840x2160_30.00
设置该模式输出
$ xrandr --output HDMI-1 --mode 3840x2160_30.00
举报