aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tdfxfb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tdfxfb.c')
-rw-r--r--drivers/video/tdfxfb.c267
1 files changed, 262 insertions, 5 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ee64771fbe3d..89f231dc443f 100644
--- a/drivers/video/tdfxfb.c
+++ b/drivers/video/tdfxfb.c
@@ -10,6 +10,12 @@
10 * Created : Thu Sep 23 18:17:43 1999, hmallat 10 * Created : Thu Sep 23 18:17:43 1999, hmallat
11 * Last modified: Tue Nov 2 21:19:47 1999, hmallat 11 * Last modified: Tue Nov 2 21:19:47 1999, hmallat
12 * 12 *
13 * I2C part copied from the i2c-voodoo3.c driver by:
14 * Frodo Looijaard <frodol@dds.nl>,
15 * Philip Edelbrock <phil@netroedge.com>,
16 * Ralph Metzler <rjkm@thp.uni-koeln.de>, and
17 * Mark D. Studebaker <mdsxyz123@yahoo.com>
18 *
13 * Lots of the information here comes from the Daryll Strauss' Banshee 19 * Lots of the information here comes from the Daryll Strauss' Banshee
14 * patches to the XF86 server, and the rest comes from the 3dfx 20 * patches to the XF86 server, and the rest comes from the 3dfx
15 * Banshee specification. I'm very much indebted to Daryll for his 21 * Banshee specification. I'm very much indebted to Daryll for his
@@ -481,6 +487,12 @@ static int tdfxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
481 return -EINVAL; 487 return -EINVAL;
482 } 488 }
483 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
484 var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */ 496 var->xres = (var->xres + 15) & ~15; /* could sometimes be 8 */
485 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3); 497 lpitch = var->xres * ((var->bits_per_pixel + 7) >> 3);
486 498
@@ -1167,6 +1179,207 @@ static struct fb_ops tdfxfb_ops = {
1167#endif 1179#endif
1168}; 1180};
1169 1181
1182#ifdef CONFIG_FB_3DFX_I2C
1183/* The voo GPIO registers don't have individual masks for each bit
1184 so we always have to read before writing. */
1185
1186static void tdfxfb_i2c_setscl(void *data, int val)
1187{
1188 struct tdfxfb_i2c_chan *chan = data;
1189 struct tdfx_par *par = chan->par;
1190 unsigned int r;
1191
1192 r = tdfx_inl(par, VIDSERPARPORT);
1193 if (val)
1194 r |= I2C_SCL_OUT;
1195 else
1196 r &= ~I2C_SCL_OUT;
1197 tdfx_outl(par, VIDSERPARPORT, r);
1198 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1199}
1200
1201static void tdfxfb_i2c_setsda(void *data, int val)
1202{
1203 struct tdfxfb_i2c_chan *chan = data;
1204 struct tdfx_par *par = chan->par;
1205 unsigned int r;
1206
1207 r = tdfx_inl(par, VIDSERPARPORT);
1208 if (val)
1209 r |= I2C_SDA_OUT;
1210 else
1211 r &= ~I2C_SDA_OUT;
1212 tdfx_outl(par, VIDSERPARPORT, r);
1213 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1214}
1215
1216/* The GPIO pins are open drain, so the pins always remain outputs.
1217 We rely on the i2c-algo-bit routines to set the pins high before
1218 reading the input from other chips. */
1219
1220static int tdfxfb_i2c_getscl(void *data)
1221{
1222 struct tdfxfb_i2c_chan *chan = data;
1223 struct tdfx_par *par = chan->par;
1224
1225 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
1226}
1227
1228static int tdfxfb_i2c_getsda(void *data)
1229{
1230 struct tdfxfb_i2c_chan *chan = data;
1231 struct tdfx_par *par = chan->par;
1232
1233 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
1234}
1235
1236static void tdfxfb_ddc_setscl(void *data, int val)
1237{
1238 struct tdfxfb_i2c_chan *chan = data;
1239 struct tdfx_par *par = chan->par;
1240 unsigned int r;
1241
1242 r = tdfx_inl(par, VIDSERPARPORT);
1243 if (val)
1244 r |= DDC_SCL_OUT;
1245 else
1246 r &= ~DDC_SCL_OUT;
1247 tdfx_outl(par, VIDSERPARPORT, r);
1248 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1249}
1250
1251static void tdfxfb_ddc_setsda(void *data, int val)
1252{
1253 struct tdfxfb_i2c_chan *chan = data;
1254 struct tdfx_par *par = chan->par;
1255 unsigned int r;
1256
1257 r = tdfx_inl(par, VIDSERPARPORT);
1258 if (val)
1259 r |= DDC_SDA_OUT;
1260 else
1261 r &= ~DDC_SDA_OUT;
1262 tdfx_outl(par, VIDSERPARPORT, r);
1263 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1264}
1265
1266static int tdfxfb_ddc_getscl(void *data)
1267{
1268 struct tdfxfb_i2c_chan *chan = data;
1269 struct tdfx_par *par = chan->par;
1270
1271 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
1272}
1273
1274static int tdfxfb_ddc_getsda(void *data)
1275{
1276 struct tdfxfb_i2c_chan *chan = data;
1277 struct tdfx_par *par = chan->par;
1278
1279 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
1280}
1281
1282static int __devinit tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan,
1283 const char *name, struct device *dev)
1284{
1285 int rc;
1286
1287 strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1288 chan->adapter.owner = THIS_MODULE;
1289 chan->adapter.class = I2C_CLASS_DDC;
1290 chan->adapter.algo_data = &chan->algo;
1291 chan->adapter.dev.parent = dev;
1292 chan->algo.setsda = tdfxfb_ddc_setsda;
1293 chan->algo.setscl = tdfxfb_ddc_setscl;
1294 chan->algo.getsda = tdfxfb_ddc_getsda;
1295 chan->algo.getscl = tdfxfb_ddc_getscl;
1296 chan->algo.udelay = 10;
1297 chan->algo.timeout = msecs_to_jiffies(500);
1298 chan->algo.data = chan;
1299
1300 i2c_set_adapdata(&chan->adapter, chan);
1301
1302 rc = i2c_bit_add_bus(&chan->adapter);
1303 if (rc == 0)
1304 DPRINTK("I2C bus %s registered.\n", name);
1305 else
1306 chan->par = NULL;
1307
1308 return rc;
1309}
1310
1311static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
1312 const char *name, struct device *dev)
1313{
1314 int rc;
1315
1316 strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1317 chan->adapter.owner = THIS_MODULE;
1318 chan->adapter.class = I2C_CLASS_TV_ANALOG;
1319 chan->adapter.algo_data = &chan->algo;
1320 chan->adapter.dev.parent = dev;
1321 chan->algo.setsda = tdfxfb_i2c_setsda;
1322 chan->algo.setscl = tdfxfb_i2c_setscl;
1323 chan->algo.getsda = tdfxfb_i2c_getsda;
1324 chan->algo.getscl = tdfxfb_i2c_getscl;
1325 chan->algo.udelay = 10;
1326 chan->algo.timeout = msecs_to_jiffies(500);
1327 chan->algo.data = chan;
1328
1329 i2c_set_adapdata(&chan->adapter, chan);
1330
1331 rc = i2c_bit_add_bus(&chan->adapter);
1332 if (rc == 0)
1333 DPRINTK("I2C bus %s registered.\n", name);
1334 else
1335 chan->par = NULL;
1336
1337 return rc;
1338}
1339
1340static void __devinit tdfxfb_create_i2c_busses(struct fb_info *info)
1341{
1342 struct tdfx_par *par = info->par;
1343
1344 tdfx_outl(par, VIDINFORMAT, 0x8160);
1345 tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
1346
1347 par->chan[0].par = par;
1348 par->chan[1].par = par;
1349
1350 tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
1351 tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
1352}
1353
1354static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
1355{
1356 if (par->chan[0].par)
1357 i2c_del_adapter(&par->chan[0].adapter);
1358 par->chan[0].par = NULL;
1359
1360 if (par->chan[1].par)
1361 i2c_del_adapter(&par->chan[1].adapter);
1362 par->chan[1].par = NULL;
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}
1381#endif /* CONFIG_FB_3DFX_I2C */
1382
1170/** 1383/**
1171 * tdfxfb_probe - Device Initializiation 1384 * tdfxfb_probe - Device Initializiation
1172 * 1385 *
@@ -1182,6 +1395,8 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1182 struct tdfx_par *default_par; 1395 struct tdfx_par *default_par;
1183 struct fb_info *info; 1396 struct fb_info *info;
1184 int err, lpitch; 1397 int err, lpitch;
1398 struct fb_monspecs *specs;
1399 bool found;
1185 1400
1186 err = pci_enable_device(pdev); 1401 err = pci_enable_device(pdev);
1187 if (err) { 1402 if (err) {
@@ -1284,13 +1499,49 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1284 if (hwcursor) 1499 if (hwcursor)
1285 info->fix.smem_len = (info->fix.smem_len - 1024) & 1500 info->fix.smem_len = (info->fix.smem_len - 1024) &
1286 (PAGE_MASK << 1); 1501 (PAGE_MASK << 1);
1287 1502 specs = &info->monspecs;
1288 if (!mode_option) 1503 found = false;
1504 info->var.bits_per_pixel = 8;
1505#ifdef CONFIG_FB_3DFX_I2C
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 }
1529#endif
1530 if (!mode_option && !found)
1289 mode_option = "640x480@60"; 1531 mode_option = "640x480@60";
1290 1532
1291 err = fb_find_mode(&info->var, info, mode_option, NULL, 0, NULL, 8); 1533 if (mode_option) {
1292 if (!err || err == 4) 1534 err = fb_find_mode(&info->var, info, mode_option,
1293 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 }
1294 1545
1295 /* maximize virtual vertical length */ 1546 /* maximize virtual vertical length */
1296 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);
@@ -1315,6 +1566,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1315 return 0; 1566 return 0;
1316 1567
1317out_err_iobase: 1568out_err_iobase:
1569#ifdef CONFIG_FB_3DFX_I2C
1570 tdfxfb_delete_i2c_busses(default_par);
1571#endif
1318 if (default_par->mtrr_handle >= 0) 1572 if (default_par->mtrr_handle >= 0)
1319 mtrr_del(default_par->mtrr_handle, info->fix.smem_start, 1573 mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
1320 info->fix.smem_len); 1574 info->fix.smem_len);
@@ -1379,6 +1633,9 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
1379 struct tdfx_par *par = info->par; 1633 struct tdfx_par *par = info->par;
1380 1634
1381 unregister_framebuffer(info); 1635 unregister_framebuffer(info);
1636#ifdef CONFIG_FB_3DFX_I2C
1637 tdfxfb_delete_i2c_busses(par);
1638#endif
1382 if (par->mtrr_handle >= 0) 1639 if (par->mtrr_handle >= 0)
1383 mtrr_del(par->mtrr_handle, info->fix.smem_start, 1640 mtrr_del(par->mtrr_handle, info->fix.smem_start,
1384 info->fix.smem_len); 1641 info->fix.smem_len);