aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/video/Kconfig9
-rw-r--r--drivers/video/tdfxfb.c200
-rw-r--r--include/video/tdfx.h26
3 files changed, 234 insertions, 1 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index ffe2f2796e29..7826bdce4bbe 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1550,6 +1550,7 @@ config FB_3DFX
1550 select FB_CFB_IMAGEBLIT 1550 select FB_CFB_IMAGEBLIT
1551 select FB_CFB_FILLRECT 1551 select FB_CFB_FILLRECT
1552 select FB_CFB_COPYAREA 1552 select FB_CFB_COPYAREA
1553 select FB_MODE_HELPERS
1553 help 1554 help
1554 This driver supports graphics boards with the 3Dfx Banshee, 1555 This driver supports graphics boards with the 3Dfx Banshee,
1555 Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have 1556 Voodoo3 or VSA-100 (aka Voodoo4/5) chips. Say Y if you have
@@ -1565,6 +1566,14 @@ config FB_3DFX_ACCEL
1565 This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer 1566 This will compile the 3Dfx Banshee/Voodoo3/VSA-100 frame buffer
1566 device driver with acceleration functions. 1567 device driver with acceleration functions.
1567 1568
1569config FB_3DFX_I2C
1570 bool "Enable DDC/I2C support"
1571 depends on FB_3DFX && EXPERIMENTAL
1572 select FB_DDC
1573 default y
1574 help
1575 Say Y here if you want DDC/I2C support for your 3dfx Voodoo3.
1576
1568config FB_VOODOO1 1577config FB_VOODOO1
1569 tristate "3Dfx Voodoo Graphics (sst1) support" 1578 tristate "3Dfx Voodoo Graphics (sst1) support"
1570 depends on FB && PCI 1579 depends on FB && PCI
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);
diff --git a/include/video/tdfx.h b/include/video/tdfx.h
index 7431d9681e57..befbaf0a92d8 100644
--- a/include/video/tdfx.h
+++ b/include/video/tdfx.h
@@ -1,6 +1,9 @@
1#ifndef _TDFX_H 1#ifndef _TDFX_H
2#define _TDFX_H 2#define _TDFX_H
3 3
4#include <linux/i2c.h>
5#include <linux/i2c-algo-bit.h>
6
4/* membase0 register offsets */ 7/* membase0 register offsets */
5#define STATUS 0x00 8#define STATUS 0x00
6#define PCIINIT0 0x04 9#define PCIINIT0 0x04
@@ -123,6 +126,18 @@
123#define VIDCFG_PIXFMT_SHIFT 18 126#define VIDCFG_PIXFMT_SHIFT 18
124#define DACMODE_2X BIT(0) 127#define DACMODE_2X BIT(0)
125 128
129/* I2C bit locations in the VIDSERPARPORT register */
130#define DDC_ENAB 0x00040000
131#define DDC_SCL_OUT 0x00080000
132#define DDC_SDA_OUT 0x00100000
133#define DDC_SCL_IN 0x00200000
134#define DDC_SDA_IN 0x00400000
135#define I2C_ENAB 0x00800000
136#define I2C_SCL_OUT 0x01000000
137#define I2C_SDA_OUT 0x02000000
138#define I2C_SCL_IN 0x04000000
139#define I2C_SDA_IN 0x08000000
140
126/* VGA rubbish, need to change this for multihead support */ 141/* VGA rubbish, need to change this for multihead support */
127#define MISC_W 0x3c2 142#define MISC_W 0x3c2
128#define MISC_R 0x3cc 143#define MISC_R 0x3cc
@@ -168,12 +183,23 @@ struct banshee_reg {
168 unsigned long miscinit0; 183 unsigned long miscinit0;
169}; 184};
170 185
186struct tdfx_par;
187
188struct tdfxfb_i2c_chan {
189 struct tdfx_par *par;
190 struct i2c_adapter adapter;
191 struct i2c_algo_bit_data algo;
192};
193
171struct tdfx_par { 194struct tdfx_par {
172 u32 max_pixclock; 195 u32 max_pixclock;
173 u32 palette[16]; 196 u32 palette[16];
174 void __iomem *regbase_virt; 197 void __iomem *regbase_virt;
175 unsigned long iobase; 198 unsigned long iobase;
176 int mtrr_handle; 199 int mtrr_handle;
200#ifdef CONFIG_FB_3DFX_I2C
201 struct tdfxfb_i2c_chan chan[2];
202#endif
177}; 203};
178 204
179#endif /* __KERNEL__ */ 205#endif /* __KERNEL__ */