aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/omap2
diff options
context:
space:
mode:
authorTomi Valkeinen <tomi.valkeinen@ti.com>2011-08-25 10:15:14 -0400
committerTomi Valkeinen <tomi.valkeinen@ti.com>2011-09-30 09:17:23 -0400
commitdc891fab115380d9dfddcd252df45a941ff9cb4e (patch)
tree054f47c26b61bdad4a29d90ad1b2e23f99d5b7a0 /drivers/video/omap2
parentfcca719430086fb64b3586582646579f8ffaf47c (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.c109
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
2279static 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
2293static 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
2351err2:
2352 fb_destroy_modedb(specs->modedb);
2353 kfree(specs);
2354err1:
2355 kfree(edid);
2356
2357 return r;
2358}
2359
2279static int omapfb_init_display(struct omapfb2_device *fbdev, 2360static 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) {