aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tdfxfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2009-04-06 22:01:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-07 11:31:08 -0400
commitfeff3880d06da0cc8fc65b9e40f518fea7594674 (patch)
tree0feb97f54ac1af23056070576fe68e954a44b9a2 /drivers/video/tdfxfb.c
parent8f9b15286a8ea49e997e845d02d357ed33ebd090 (diff)
tdfxfb: move I2C functionality into the tdfxfb
The I2C functionality provided by the i2c-voodoo3 driver is moved into the tdfxfb (frame buffer driver for Voodoo3 cards). This way there is no conflict between the i2c driver and the fb driver. The tdfxfb does not make use from the DDC functionality yet but provides all the functionality of the i2c-voodoo3 driver. Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Acked-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>
Diffstat (limited to 'drivers/video/tdfxfb.c')
-rw-r--r--drivers/video/tdfxfb.c200
1 files changed, 199 insertions, 1 deletions
diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c
index ee64771fbe3d..bc6f916c53be 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
@@ -1167,6 +1173,190 @@ static struct fb_ops tdfxfb_ops = {
1167#endif 1173#endif
1168}; 1174};
1169 1175
1176#ifdef CONFIG_FB_3DFX_I2C
1177/* The voo GPIO registers don't have individual masks for each bit
1178 so we always have to read before writing. */
1179
1180static void tdfxfb_i2c_setscl(void *data, int val)
1181{
1182 struct tdfxfb_i2c_chan *chan = data;
1183 struct tdfx_par *par = chan->par;
1184 unsigned int r;
1185
1186 r = tdfx_inl(par, VIDSERPARPORT);
1187 if (val)
1188 r |= I2C_SCL_OUT;
1189 else
1190 r &= ~I2C_SCL_OUT;
1191 tdfx_outl(par, VIDSERPARPORT, r);
1192 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1193}
1194
1195static void tdfxfb_i2c_setsda(void *data, int val)
1196{
1197 struct tdfxfb_i2c_chan *chan = data;
1198 struct tdfx_par *par = chan->par;
1199 unsigned int r;
1200
1201 r = tdfx_inl(par, VIDSERPARPORT);
1202 if (val)
1203 r |= I2C_SDA_OUT;
1204 else
1205 r &= ~I2C_SDA_OUT;
1206 tdfx_outl(par, VIDSERPARPORT, r);
1207 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1208}
1209
1210/* The GPIO pins are open drain, so the pins always remain outputs.
1211 We rely on the i2c-algo-bit routines to set the pins high before
1212 reading the input from other chips. */
1213
1214static int tdfxfb_i2c_getscl(void *data)
1215{
1216 struct tdfxfb_i2c_chan *chan = data;
1217 struct tdfx_par *par = chan->par;
1218
1219 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SCL_IN));
1220}
1221
1222static int tdfxfb_i2c_getsda(void *data)
1223{
1224 struct tdfxfb_i2c_chan *chan = data;
1225 struct tdfx_par *par = chan->par;
1226
1227 return (0 != (tdfx_inl(par, VIDSERPARPORT) & I2C_SDA_IN));
1228}
1229
1230static void tdfxfb_ddc_setscl(void *data, int val)
1231{
1232 struct tdfxfb_i2c_chan *chan = data;
1233 struct tdfx_par *par = chan->par;
1234 unsigned int r;
1235
1236 r = tdfx_inl(par, VIDSERPARPORT);
1237 if (val)
1238 r |= DDC_SCL_OUT;
1239 else
1240 r &= ~DDC_SCL_OUT;
1241 tdfx_outl(par, VIDSERPARPORT, r);
1242 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1243}
1244
1245static void tdfxfb_ddc_setsda(void *data, int val)
1246{
1247 struct tdfxfb_i2c_chan *chan = data;
1248 struct tdfx_par *par = chan->par;
1249 unsigned int r;
1250
1251 r = tdfx_inl(par, VIDSERPARPORT);
1252 if (val)
1253 r |= DDC_SDA_OUT;
1254 else
1255 r &= ~DDC_SDA_OUT;
1256 tdfx_outl(par, VIDSERPARPORT, r);
1257 tdfx_inl(par, VIDSERPARPORT); /* flush posted write */
1258}
1259
1260static int tdfxfb_ddc_getscl(void *data)
1261{
1262 struct tdfxfb_i2c_chan *chan = data;
1263 struct tdfx_par *par = chan->par;
1264
1265 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SCL_IN));
1266}
1267
1268static int tdfxfb_ddc_getsda(void *data)
1269{
1270 struct tdfxfb_i2c_chan *chan = data;
1271 struct tdfx_par *par = chan->par;
1272
1273 return (0 != (tdfx_inl(par, VIDSERPARPORT) & DDC_SDA_IN));
1274}
1275
1276static int __devinit tdfxfb_setup_ddc_bus(struct tdfxfb_i2c_chan *chan,
1277 const char *name, struct device *dev)
1278{
1279 int rc;
1280
1281 strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1282 chan->adapter.owner = THIS_MODULE;
1283 chan->adapter.class = I2C_CLASS_DDC;
1284 chan->adapter.algo_data = &chan->algo;
1285 chan->adapter.dev.parent = dev;
1286 chan->algo.setsda = tdfxfb_ddc_setsda;
1287 chan->algo.setscl = tdfxfb_ddc_setscl;
1288 chan->algo.getsda = tdfxfb_ddc_getsda;
1289 chan->algo.getscl = tdfxfb_ddc_getscl;
1290 chan->algo.udelay = 10;
1291 chan->algo.timeout = msecs_to_jiffies(500);
1292 chan->algo.data = chan;
1293
1294 i2c_set_adapdata(&chan->adapter, chan);
1295
1296 rc = i2c_bit_add_bus(&chan->adapter);
1297 if (rc == 0)
1298 DPRINTK("I2C bus %s registered.\n", name);
1299 else
1300 chan->par = NULL;
1301
1302 return rc;
1303}
1304
1305static int __devinit tdfxfb_setup_i2c_bus(struct tdfxfb_i2c_chan *chan,
1306 const char *name, struct device *dev)
1307{
1308 int rc;
1309
1310 strlcpy(chan->adapter.name, name, sizeof(chan->adapter.name));
1311 chan->adapter.owner = THIS_MODULE;
1312 chan->adapter.class = I2C_CLASS_TV_ANALOG;
1313 chan->adapter.algo_data = &chan->algo;
1314 chan->adapter.dev.parent = dev;
1315 chan->algo.setsda = tdfxfb_i2c_setsda;
1316 chan->algo.setscl = tdfxfb_i2c_setscl;
1317 chan->algo.getsda = tdfxfb_i2c_getsda;
1318 chan->algo.getscl = tdfxfb_i2c_getscl;
1319 chan->algo.udelay = 10;
1320 chan->algo.timeout = msecs_to_jiffies(500);
1321 chan->algo.data = chan;
1322
1323 i2c_set_adapdata(&chan->adapter, chan);
1324
1325 rc = i2c_bit_add_bus(&chan->adapter);
1326 if (rc == 0)
1327 DPRINTK("I2C bus %s registered.\n", name);
1328 else
1329 chan->par = NULL;
1330
1331 return rc;
1332}
1333
1334static void __devinit tdfxfb_create_i2c_busses(struct fb_info *info)
1335{
1336 struct tdfx_par *par = info->par;
1337
1338 tdfx_outl(par, VIDINFORMAT, 0x8160);
1339 tdfx_outl(par, VIDSERPARPORT, 0xcffc0020);
1340
1341 par->chan[0].par = par;
1342 par->chan[1].par = par;
1343
1344 tdfxfb_setup_ddc_bus(&par->chan[0], "Voodoo3-DDC", info->dev);
1345 tdfxfb_setup_i2c_bus(&par->chan[1], "Voodoo3-I2C", info->dev);
1346}
1347
1348static void tdfxfb_delete_i2c_busses(struct tdfx_par *par)
1349{
1350 if (par->chan[0].par)
1351 i2c_del_adapter(&par->chan[0].adapter);
1352 par->chan[0].par = NULL;
1353
1354 if (par->chan[1].par)
1355 i2c_del_adapter(&par->chan[1].adapter);
1356 par->chan[1].par = NULL;
1357}
1358#endif /* CONFIG_FB_3DFX_I2C */
1359
1170/** 1360/**
1171 * tdfxfb_probe - Device Initializiation 1361 * tdfxfb_probe - Device Initializiation
1172 * 1362 *
@@ -1284,7 +1474,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1284 if (hwcursor) 1474 if (hwcursor)
1285 info->fix.smem_len = (info->fix.smem_len - 1024) & 1475 info->fix.smem_len = (info->fix.smem_len - 1024) &
1286 (PAGE_MASK << 1); 1476 (PAGE_MASK << 1);
1287 1477#ifdef CONFIG_FB_3DFX_I2C
1478 tdfxfb_create_i2c_busses(info);
1479#endif
1288 if (!mode_option) 1480 if (!mode_option)
1289 mode_option = "640x480@60"; 1481 mode_option = "640x480@60";
1290 1482
@@ -1315,6 +1507,9 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
1315 return 0; 1507 return 0;
1316 1508
1317out_err_iobase: 1509out_err_iobase:
1510#ifdef CONFIG_FB_3DFX_I2C
1511 tdfxfb_delete_i2c_busses(default_par);
1512#endif
1318 if (default_par->mtrr_handle >= 0) 1513 if (default_par->mtrr_handle >= 0)
1319 mtrr_del(default_par->mtrr_handle, info->fix.smem_start, 1514 mtrr_del(default_par->mtrr_handle, info->fix.smem_start,
1320 info->fix.smem_len); 1515 info->fix.smem_len);
@@ -1379,6 +1574,9 @@ static void __devexit tdfxfb_remove(struct pci_dev *pdev)
1379 struct tdfx_par *par = info->par; 1574 struct tdfx_par *par = info->par;
1380 1575
1381 unregister_framebuffer(info); 1576 unregister_framebuffer(info);
1577#ifdef CONFIG_FB_3DFX_I2C
1578 tdfxfb_delete_i2c_busses(par);
1579#endif
1382 if (par->mtrr_handle >= 0) 1580 if (par->mtrr_handle >= 0)
1383 mtrr_del(par->mtrr_handle, info->fix.smem_start, 1581 mtrr_del(par->mtrr_handle, info->fix.smem_start,
1384 info->fix.smem_len); 1582 info->fix.smem_len);