From e14d52936107e390e2464df1e6653efde5409096 Mon Sep 17 00:00:00 2001 From: Lajos Molnar Date: Mon, 10 Oct 2011 23:29:21 -0500 Subject: hwc: extract HDMI mode scoring function Separate HDMI mode scoring function so that it is easier to modify. Also changed scoring function to be cumulative instead of absolute, so that priorities of the sub-scores can be easily changed. Change-Id: I3f803c13c1482653b8a3fb26a47a8fefecc51b4b --- hwc/hwc.c | 73 ++++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 24 deletions(-) (limited to 'hwc') diff --git a/hwc/hwc.c b/hwc/hwc.c index 95dc9fe..c894b9a 100644 --- a/hwc/hwc.c +++ b/hwc/hwc.c @@ -768,6 +768,44 @@ static int omap4_hwc_is_valid_layer(omap4_hwc_device_t *hwc_dev, return omap4_hwc_can_scale_layer(hwc_dev, layer, handle); } +static __u32 add_scaling_score(__u32 score, + __u32 xres, __u32 yres, __u32 refresh, + __u32 ext_xres, __u32 ext_yres, + __u32 mode_xres, __u32 mode_yres, __u32 mode_refresh) +{ + __u32 area = xres * yres; + __u32 ext_area = ext_xres * ext_yres; + __u32 mode_area = mode_xres * mode_yres; + + /* prefer to upscale (1% tolerance) [0..1] (insert after 1st bit) */ + int upscale = (ext_xres >= xres * 99 / 100 && ext_yres >= yres * 99 / 100); + score = (((score & ~1) | upscale) << 1) | (score & 1); + + /* pick minimum scaling [0..16] */ + if (ext_area > area) + score = (score << 5) | (16 * area / ext_area); + else + score = (score << 5) | (16 * ext_area / area); + + /* pick smallest leftover area [0..16] */ + score = (score << 5) | ((16 * ext_area + (mode_area >> 1)) / mode_area); + + /* adjust mode refresh rate */ + mode_refresh += mode_refresh % 6 == 5; + + /* prefer same or higher frame rate */ + upscale = (mode_refresh >= refresh); + score = (score << 1) | upscale; + + /* pick closest frame rate */ + if (mode_refresh > refresh) + score = (score << 8) | (240 * refresh / mode_refresh); + else + score = (score << 8) | (240 * mode_refresh / refresh); + + return score; +} + static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 yres, float xpy) { @@ -801,8 +839,8 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, __u32 ext_fb_xres, ext_fb_yres; for (i = 0; i < d.dis.modedb_len; i++) { __u32 score = 0; - __u32 area = xres * yres; - __u32 mode_area = d.modedb[i].xres * d.modedb[i].yres; + __u32 mode_xres = d.modedb[i].xres; + __u32 mode_yres = d.modedb[i].yres; __u32 ext_width = d.dis.width_in_mm; __u32 ext_height = d.dis.height_in_mm; @@ -814,10 +852,10 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, ext_height = 9; } - if (mode_area == 0) + if (!mode_xres || !mode_yres) continue; - get_max_dimensions(xres, yres, xpy, d.modedb[i].xres, d.modedb[i].yres, + get_max_dimensions(xres, yres, xpy, mode_xres, mode_yres, ext_width, ext_height, &ext_fb_xres, &ext_fb_yres); /* we need to ensure that even TILER2D buffers can be scaled */ @@ -832,33 +870,20 @@ static int omap4_hwc_set_best_hdmi_mode(omap4_hwc_device_t *hwc_dev, __u32 xres, if (d.modedb[i].flag & (FB_FLAG_RATIO_4_3 | FB_FLAG_RATIO_16_9)) score = 1; - /* prefer to upscale (1% tolerance) */ - __u32 upscaling = (ext_fb_xres >= xres * 99 / 100 && ext_fb_yres >= yres * 99 / 100); - score = (score << 1) | upscaling; - /* prefer the same mode as we use for mirroring to avoid mode change */ - score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); - - /* pick closest screen size */ - if (ext_fb_xres * ext_fb_yres > area) - score = (score << 5) | (16 * area / ext_fb_xres / ext_fb_yres); - else - score = (score << 5) | (16 * ext_fb_xres * ext_fb_yres / area); - - /* pick smallest leftover area */ - score = (score << 5) | ((16 * ext_fb_xres * ext_fb_yres + (mode_area >> 1)) / mode_area); + score = (score << 1) | (i == ~ext->mirror_mode && ext->avoid_mode_change); - /* pick highest frame rate */ - score = (score << 8) | d.modedb[i].refresh; + 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, d.modedb[i].xres, d.modedb[i].yres, d.modedb[i].refresh); + LOGD("#%d: %dx%d %dHz", i, mode_xres, mode_yres, d.modedb[i].refresh); if (debug) - LOGD(" score=%u adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); + LOGD(" score=0x%x adj.res=%dx%d", score, ext_fb_xres, ext_fb_yres); if (best_score < score) { ext->width = ext_width; ext->height = ext_height; - ext->xres = d.modedb[i].xres; - ext->yres = d.modedb[i].yres; + ext->xres = mode_xres; + ext->yres = mode_yres; best = i; best_score = score; } -- cgit v1.1