From c63364590d5df4837438ba69b4ba7dad66af3321 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Thu, 12 Apr 2012 14:53:30 -0700 Subject: DO NOT MERGE HDMI: update mode selection logic The kernel now passes all of the modes to user space with flags to specify whether or not it is preferred or not and if the hardware actually supports the mode. With this, we can try to pick modes that match the 'preferred' mode as specified in the EDID from the panel. If the preferred mode is masked due to the driver, the logic will try to favor available modes that match the resolution of the preferred mode. If none of these options are available, fall back to the older logic of trying to find the best mode to match what the current framebuffer is set to. Change-Id: I289fd36ee5b8151739942832d9ff3fd876e8d3ee --- hwc/hwc.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/hwc/hwc.c b/hwc/hwc.c index 26d38b17..d1dd1cf5 100644 --- a/hwc/hwc.c +++ b/hwc/hwc.c @@ -927,6 +927,21 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, ext->yres = 480; } + /* + * copy the xres/yres from the preferred mode + */ + __u32 preferred_mode_xres = 0; + __u32 preferred_mode_yres = 0; + for (i = 0; i < d.dis.modedb_len; i++) { + if (d.modedb[i].flag & FB_FLAG_PREFERRED) { + preferred_mode_xres = d.modedb[i].xres; + preferred_mode_yres = d.modedb[i].yres; + LOGD("preferred mode %d: xres %u yres %u\n", + i, d.modedb[i].xres, d.modedb[i].yres); + break; + } + } + __u32 ext_fb_xres, ext_fb_yres; for (i = 0; i < d.dis.modedb_len; i++) { __u32 score = 0; @@ -935,6 +950,10 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 ext_width = d.dis.width_in_mm; __u32 ext_height = d.dis.height_in_mm; + /* reject it because the hw says it can't actually use this mode */ + if ((d.modedb[i].flag & FB_FLAG_HW_CAPABLE) == 0) + continue; + if (d.modedb[i].flag & FB_FLAG_RATIO_4_3) { ext_width = 4; ext_height = 3; @@ -959,7 +978,17 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, /* prefer CEA modes */ if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) - score = 1; + score += 1; + + /* prefer modes that match the preferred mode's resolution */ + if (d.modedb[i].xres == preferred_mode_xres && + d.modedb[i].yres == preferred_mode_yres) { + score += 1; + } + + /* prefer modes the kernel has hinted is the correct mode */ + if (d.modedb[i].flag & FB_FLAG_PREFERRED) + score += 1; /* prefer the same mode as we use for mirroring to avoid mode change */ score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); @@ -967,7 +996,8 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, score = add_scaling_score(score, xres, yres, 60, ext_fb_xres, ext_fb_yres, mode_xres, mode_yres, d.modedb[i].refresh ? : 1); - LOGD("#%d: %dx%d %dHz", i, mode_xres, mode_yres, d.modedb[i].refresh); + LOGD("#%d: %dx%d %dHz flag 0x%x vmode 0x%x", i, mode_xres, mode_yres, + d.modedb[i].refresh, d.modedb[i].flag, d.modedb[i].vmode); if (debug) LOGD(" score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); if (best_score < score) { -- cgit v1.2.3