summaryrefslogtreecommitdiffstats
path: root/hwc/hwc.c
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-10-10 23:29:21 -0500
committerErik Gilling <konkers@android.com>2011-12-08 14:19:06 -0800
commite14d52936107e390e2464df1e6653efde5409096 (patch)
tree8422dbb2b7ec364ff489c19f7d772679f2679e5a /hwc/hwc.c
parent3837de4ff6b7562965758dd2a7af5550af1bd869 (diff)
downloadhardware_ti_omap4xxx-e14d52936107e390e2464df1e6653efde5409096.zip
hardware_ti_omap4xxx-e14d52936107e390e2464df1e6653efde5409096.tar.gz
hardware_ti_omap4xxx-e14d52936107e390e2464df1e6653efde5409096.tar.bz2
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
Diffstat (limited to 'hwc/hwc.c')
-rw-r--r--hwc/hwc.c73
1 files changed, 49 insertions, 24 deletions
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;
}