diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-08-25 10:15:14 -0400 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2011-09-30 09:17:23 -0400 |
commit | dc891fab115380d9dfddcd252df45a941ff9cb4e (patch) | |
tree | 054f47c26b61bdad4a29d90ad1b2e23f99d5b7a0 /drivers/video/omap2 | |
parent | fcca719430086fb64b3586582646579f8ffaf47c (diff) |
OMAPFB: find best mode from edid
Use the new read_edid() function to get EDID information from the
display (when available), and use the information to use a suitable mode
at initialization time.
Hot-plug is not yet supported, so the timings selected at init time will
stay even if the monitor would be changed.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Diffstat (limited to 'drivers/video/omap2')
-rw-r--r-- | drivers/video/omap2/omapfb/omapfb-main.c | 109 |
1 files changed, 99 insertions, 10 deletions
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index cd2cae8e96ff..c84cc2964154 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2276,6 +2276,87 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev) | |||
2276 | return r; | 2276 | return r; |
2277 | } | 2277 | } |
2278 | 2278 | ||
2279 | static void fb_videomode_to_omap_timings(struct fb_videomode *m, | ||
2280 | struct omap_video_timings *t) | ||
2281 | { | ||
2282 | t->x_res = m->xres; | ||
2283 | t->y_res = m->yres; | ||
2284 | t->pixel_clock = PICOS2KHZ(m->pixclock); | ||
2285 | t->hsw = m->hsync_len; | ||
2286 | t->hfp = m->right_margin; | ||
2287 | t->hbp = m->left_margin; | ||
2288 | t->vsw = m->vsync_len; | ||
2289 | t->vfp = m->lower_margin; | ||
2290 | t->vbp = m->upper_margin; | ||
2291 | } | ||
2292 | |||
2293 | static int omapfb_find_best_mode(struct omap_dss_device *display, | ||
2294 | struct omap_video_timings *timings) | ||
2295 | { | ||
2296 | struct fb_monspecs *specs; | ||
2297 | u8 *edid; | ||
2298 | int r, i, best_xres, best_idx, len; | ||
2299 | |||
2300 | if (!display->driver->read_edid) | ||
2301 | return -ENODEV; | ||
2302 | |||
2303 | len = 0x80 * 2; | ||
2304 | edid = kmalloc(len, GFP_KERNEL); | ||
2305 | |||
2306 | r = display->driver->read_edid(display, edid, len); | ||
2307 | if (r < 0) | ||
2308 | goto err1; | ||
2309 | |||
2310 | specs = kzalloc(sizeof(*specs), GFP_KERNEL); | ||
2311 | |||
2312 | fb_edid_to_monspecs(edid, specs); | ||
2313 | |||
2314 | if (edid[126] > 0) | ||
2315 | fb_edid_add_monspecs(edid + 0x80, specs); | ||
2316 | |||
2317 | best_xres = 0; | ||
2318 | best_idx = -1; | ||
2319 | |||
2320 | for (i = 0; i < specs->modedb_len; ++i) { | ||
2321 | struct fb_videomode *m; | ||
2322 | struct omap_video_timings t; | ||
2323 | |||
2324 | m = &specs->modedb[i]; | ||
2325 | |||
2326 | if (m->pixclock == 0) | ||
2327 | continue; | ||
2328 | |||
2329 | /* skip repeated pixel modes */ | ||
2330 | if (m->xres == 2880 || m->xres == 1440) | ||
2331 | continue; | ||
2332 | |||
2333 | fb_videomode_to_omap_timings(m, &t); | ||
2334 | |||
2335 | r = display->driver->check_timings(display, &t); | ||
2336 | if (r == 0 && best_xres < m->xres) { | ||
2337 | best_xres = m->xres; | ||
2338 | best_idx = i; | ||
2339 | } | ||
2340 | } | ||
2341 | |||
2342 | if (best_xres == 0) { | ||
2343 | r = -ENOENT; | ||
2344 | goto err2; | ||
2345 | } | ||
2346 | |||
2347 | fb_videomode_to_omap_timings(&specs->modedb[best_idx], timings); | ||
2348 | |||
2349 | r = 0; | ||
2350 | |||
2351 | err2: | ||
2352 | fb_destroy_modedb(specs->modedb); | ||
2353 | kfree(specs); | ||
2354 | err1: | ||
2355 | kfree(edid); | ||
2356 | |||
2357 | return r; | ||
2358 | } | ||
2359 | |||
2279 | static int omapfb_init_display(struct omapfb2_device *fbdev, | 2360 | static int omapfb_init_display(struct omapfb2_device *fbdev, |
2280 | struct omap_dss_device *dssdev) | 2361 | struct omap_dss_device *dssdev) |
2281 | { | 2362 | { |
@@ -2404,9 +2485,27 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2404 | for (i = 0; i < fbdev->num_managers; i++) | 2485 | for (i = 0; i < fbdev->num_managers; i++) |
2405 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); | 2486 | fbdev->managers[i] = omap_dss_get_overlay_manager(i); |
2406 | 2487 | ||
2488 | /* gfx overlay should be the default one. find a display | ||
2489 | * connected to that, and use it as default display */ | ||
2490 | ovl = omap_dss_get_overlay(0); | ||
2491 | if (ovl->manager && ovl->manager->device) { | ||
2492 | def_display = ovl->manager->device; | ||
2493 | } else { | ||
2494 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
2495 | def_display = NULL; | ||
2496 | } | ||
2497 | |||
2407 | if (def_mode && strlen(def_mode) > 0) { | 2498 | if (def_mode && strlen(def_mode) > 0) { |
2408 | if (omapfb_parse_def_modes(fbdev)) | 2499 | if (omapfb_parse_def_modes(fbdev)) |
2409 | dev_warn(&pdev->dev, "cannot parse default modes\n"); | 2500 | dev_warn(&pdev->dev, "cannot parse default modes\n"); |
2501 | } else if (def_display && def_display->driver->set_timings && | ||
2502 | def_display->driver->check_timings) { | ||
2503 | struct omap_video_timings t; | ||
2504 | |||
2505 | r = omapfb_find_best_mode(def_display, &t); | ||
2506 | |||
2507 | if (r == 0) | ||
2508 | def_display->driver->set_timings(def_display, &t); | ||
2410 | } | 2509 | } |
2411 | 2510 | ||
2412 | r = omapfb_create_framebuffers(fbdev); | 2511 | r = omapfb_create_framebuffers(fbdev); |
@@ -2423,16 +2522,6 @@ static int omapfb_probe(struct platform_device *pdev) | |||
2423 | 2522 | ||
2424 | DBG("mgr->apply'ed\n"); | 2523 | DBG("mgr->apply'ed\n"); |
2425 | 2524 | ||
2426 | /* gfx overlay should be the default one. find a display | ||
2427 | * connected to that, and use it as default display */ | ||
2428 | ovl = omap_dss_get_overlay(0); | ||
2429 | if (ovl->manager && ovl->manager->device) { | ||
2430 | def_display = ovl->manager->device; | ||
2431 | } else { | ||
2432 | dev_warn(&pdev->dev, "cannot find default display\n"); | ||
2433 | def_display = NULL; | ||
2434 | } | ||
2435 | |||
2436 | if (def_display) { | 2525 | if (def_display) { |
2437 | r = omapfb_init_display(fbdev, def_display); | 2526 | r = omapfb_init_display(fbdev, def_display); |
2438 | if (r) { | 2527 | if (r) { |