aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-04-06 22:01:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:09 -0400
commit215059d2421f95c30d1fca6ff31357fcae9f67dc (patch)
tree7eadb76ba99372f4674e46c8553639ba11a529cf
parentfeff3880d06da0cc8fc65b9e40f518fea7594674 (diff)
tdfxfb: make use of DDC information about connected monitor
Read DDC information from a connected monitor and use it to select initial mode (if the mode is not specified). Also, use the information to protect against modes outside the monitor specs. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Tested-by: Jean Delvare <khali@linux-fr.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/video/tdfxfb.c67
1 files changed, 63 insertions, 4 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index bc6f916c53be..89f231dc443f 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -487,6 +487,12 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
487 return -EINVAL; 487 return -EINVAL;
488 } 488 }
489 489
490 if (info->monspecs.hfmax && info->monspecs.vfmax &&
491 info->monspecs.dclkmax && fb_validate_mode(var, info) < 0) {
492 DPRINTK("mode outside monitor's specs\n");
493 return -EINVAL;
494 }
495
490 var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */ 496 var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
491 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); 497 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
492 498
@@ -1355,6 +1361,23 @@ static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
1355 i2c_del_adapter(&par->chan[1].adapter); 1361 i2c_del_adapter(&par->chan[1].adapter);
1356 par->chan[1].par = NULL; 1362 par->chan[1].par = NULL;
1357} 1363}
1364
1365static int tdfxfb_probe_i2c_connector(struct tdfx_par *par,
1366 struct fb_monspecs *specs)
1367{
1368 u8 *edid = NULL;
1369
1370 DPRINTK("Probe DDC Bus\n");
1371 if (par->chan[0].par)
1372 edid = fb_ddc_read(&par->chan[0].adapter);
1373
1374 if (edid) {
1375 fb_edid_to_monspecs(edid, specs);
1376 kfree(edid);
1377 return 0;
1378 }
1379 return 1;
1380}
1358#endif /* CONFIG_FB_3DFX_I2C */ 1381#endif /* CONFIG_FB_3DFX_I2C */
1359 1382
1360/** 1383/**
@@ -1372,6 +1395,8 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1372 struct tdfx_par *default_par; 1395 struct tdfx_par *default_par;
1373 struct fb_info *info; 1396 struct fb_info *info;
1374 int err, lpitch; 1397 int err, lpitch;
1398 struct fb_monspecs *specs;
1399 bool found;
1375 1400
1376 err = pci_enable_device(pdev); 1401 err = pci_enable_device(pdev);
1377 if (err) { 1402 if (err) {
@@ -1474,15 +1499,49 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1474 if (hwcursor) 1499 if (hwcursor)
1475 info->fix.smem_len = (info->fix.smem_len - 1024) & 1500 info->fix.smem_len = (info->fix.smem_len - 1024) &
1476 (PAGE_MASK << 1); 1501 (PAGE_MASK << 1);
1502 specs = &info->monspecs;
1503 found = false;
1504 info->var.bits_per_pixel = 8;
1477#ifdef CONFIG_FB_3DFX_I2C 1505#ifdef CONFIG_FB_3DFX_I2C
1478 tdfxfb_create_i2c_busses(info); 1506 tdfxfb_create_i2c_busses(info);
1507 err = tdfxfb_probe_i2c_connector(default_par, specs);
1508
1509 if (!err) {
1510 if (specs->modedb == NULL)
1511 DPRINTK("Unable to get Mode Database\n");
1512 else {
1513 const struct fb_videomode *m;
1514
1515 fb_videomode_to_modelist(specs->modedb,
1516 specs->modedb_len,
1517 &info->modelist);
1518 m = fb_find_best_display(specs, &info->modelist);
1519 if (m) {
1520 fb_videomode_to_var(&info->var, m);
1521 /* fill all other info->var's fields */
1522 if (tdfxfb_check_var(&info->var, info) < 0)
1523 info->var = tdfx_var;
1524 else
1525 found = true;
1526 }
1527 }
1528 }
1479#endif 1529#endif
1480 if (!mode_option) 1530 if (!mode_option && !found)
1481 mode_option = "640x480@60"; 1531 mode_option = "640x480@60";
1482 1532
1483 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 1533 if (mode_option) {
1484 if (!err || err == 4) 1534 err = fb_find_mode(&info->var, info, mode_option,
1485 info->var = tdfx_var; 1535 specs->modedb, specs->modedb_len,
1536 NULL, info->var.bits_per_pixel);
1537 if (!err || err == 4)
1538 info->var = tdfx_var;
1539 }
1540
1541 if (found) {
1542 fb_destroy_modedb(specs->modedb);
1543 specs->modedb = NULL;
1544 }
1486 1545
1487 /* maximize virtual vertical length */ 1546 /* maximize virtual vertical length */
1488 lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3); 1547 lpitch = info->var.xres_virtual * ((info->var.bits_per_pixel + 7) >> 3);