aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/savage
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2005-09-09 16:04:35 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-09 16:57:59 -0400
commit13776711ce4b234b5ad153e55e8b5d6703c6b1ef (patch)
tree478de15a8709545fab36ca1d60cf7ab09018eacd /drivers/video/savage
parent5e518d7672dea4cd7c60871e40d0490c52f01d13 (diff)
[PATCH] savagefb: Driver updates
- Fallback to firmware EDID if chipset has no DDC/I2C support or if I2C probing failed - Add fb_blank hook - Fix savagefb_suspend/resume to enable driver to successfully suspend and resume from S3, memory or disk Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/video/savage')
-rw-r--r--drivers/video/savage/savagefb-i2c.c16
-rw-r--r--drivers/video/savage/savagefb.h13
-rw-r--r--drivers/video/savage/savagefb_driver.c139
3 files changed, 147 insertions, 21 deletions
diff --git a/drivers/video/savage/savagefb-i2c.c b/drivers/video/savage/savagefb-i2c.c
index 847698b5cfe7..959404ad68f4 100644
--- a/drivers/video/savage/savagefb-i2c.c
+++ b/drivers/video/savage/savagefb-i2c.c
@@ -259,8 +259,9 @@ static u8 *savage_do_probe_i2c_edid(struct savagefb_i2c_chan *chan)
259 return buf; 259 return buf;
260} 260}
261 261
262int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid) 262int savagefb_probe_i2c_connector(struct fb_info *info, u8 **out_edid)
263{ 263{
264 struct savagefb_par *par = info->par;
264 u8 *edid = NULL; 265 u8 *edid = NULL;
265 int i; 266 int i;
266 267
@@ -270,12 +271,19 @@ int savagefb_probe_i2c_connector(struct savagefb_par *par, u8 **out_edid)
270 if (edid) 271 if (edid)
271 break; 272 break;
272 } 273 }
274
275 if (!edid) {
276 /* try to get from firmware */
277 edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
278 if (edid)
279 memcpy(edid, fb_firmware_edid(info->device),
280 EDID_LENGTH);
281 }
282
273 if (out_edid) 283 if (out_edid)
274 *out_edid = edid; 284 *out_edid = edid;
275 if (!edid)
276 return 1;
277 285
278 return 0; 286 return (edid) ? 0 : 1;
279} 287}
280 288
281MODULE_LICENSE("GPL"); 289MODULE_LICENSE("GPL");
diff --git a/drivers/video/savage/savagefb.h b/drivers/video/savage/savagefb.h
index 8594b1e42d71..d6f94742c9f2 100644
--- a/drivers/video/savage/savagefb.h
+++ b/drivers/video/savage/savagefb.h
@@ -60,6 +60,7 @@
60 60
61#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000)) 61#define S3_SAVAGE_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE2000))
62 62
63#define S3_MOBILE_TWISTER_SERIES(chip) ((chip==S3_TWISTER) || (chip == S3_PROSAVAGEDDR))
63 64
64/* Chip tags. These are used to group the adapters into 65/* Chip tags. These are used to group the adapters into
65 * related families. 66 * related families.
@@ -73,6 +74,8 @@ typedef enum {
73 S3_PROSAVAGE, 74 S3_PROSAVAGE,
74 S3_SUPERSAVAGE, 75 S3_SUPERSAVAGE,
75 S3_SAVAGE2000, 76 S3_SAVAGE2000,
77 S3_PROSAVAGEDDR,
78 S3_TWISTER,
76 S3_LAST 79 S3_LAST
77} savage_chipset; 80} savage_chipset;
78 81
@@ -128,6 +131,10 @@ typedef enum {
128#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16)) 131#define BCI_CMD_SET_ROP(cmd, rop) ((cmd) |= ((rop & 0xFF) << 16))
129#define BCI_CMD_SEND_COLOR 0x00008000 132#define BCI_CMD_SEND_COLOR 0x00008000
130 133
134#define DISP_CRT 1
135#define DISP_LCD 2
136#define DISP_DFP 3
137
131struct xtimings { 138struct xtimings {
132 unsigned int Clock; 139 unsigned int Clock;
133 unsigned int HDisplay; 140 unsigned int HDisplay;
@@ -166,6 +173,10 @@ struct savagefb_par {
166 struct savagefb_i2c_chan chan; 173 struct savagefb_i2c_chan chan;
167 unsigned char *edid; 174 unsigned char *edid;
168 u32 pseudo_palette[16]; 175 u32 pseudo_palette[16];
176 int pm_state;
177 int display_type;
178 int dvi;
179 int crtonly;
169 int dacSpeedBpp; 180 int dacSpeedBpp;
170 int maxClock; 181 int maxClock;
171 int minClock; 182 int minClock;
@@ -338,7 +349,7 @@ do { \
338 } \ 349 } \
339} 350}
340 351
341extern int savagefb_probe_i2c_connector(struct savagefb_par *par, 352extern int savagefb_probe_i2c_connector(struct fb_info *info,
342 u8 **out_edid); 353 u8 **out_edid);
343extern void savagefb_create_i2c_busses(struct fb_info *info); 354extern void savagefb_create_i2c_busses(struct fb_info *info);
344extern void savagefb_delete_i2c_busses(struct fb_info *info); 355extern void savagefb_delete_i2c_busses(struct fb_info *info);
diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c
index 117ad42f120d..abad90a3702c 100644
--- a/drivers/video/savage/savagefb_driver.c
+++ b/drivers/video/savage/savagefb_driver.c
@@ -1400,6 +1400,58 @@ static int savagefb_pan_display (struct fb_var_screeninfo *var,
1400 return 0; 1400 return 0;
1401} 1401}
1402 1402
1403static int savagefb_blank(int blank, struct fb_info *info)
1404{
1405 struct savagefb_par *par = info->par;
1406 u8 sr8 = 0, srd = 0;
1407
1408 if (par->display_type == DISP_CRT) {
1409 vga_out8(0x3c4, 0x08);
1410 sr8 = vga_in8(0x3c5);
1411 sr8 |= 0x06;
1412 vga_out8(0x3c5, sr8);
1413 vga_out8(0x3c4, 0x0d);
1414 srd = vga_in8(0x3c5);
1415 srd &= 0x03;
1416
1417 switch (blank) {
1418 case FB_BLANK_UNBLANK:
1419 case FB_BLANK_NORMAL:
1420 break;
1421 case FB_BLANK_VSYNC_SUSPEND:
1422 srd |= 0x10;
1423 break;
1424 case FB_BLANK_HSYNC_SUSPEND:
1425 srd |= 0x40;
1426 break;
1427 case FB_BLANK_POWERDOWN:
1428 srd |= 0x50;
1429 break;
1430 }
1431
1432 vga_out8(0x3c4, 0x0d);
1433 vga_out8(0x3c5, srd);
1434 }
1435
1436 if (par->display_type == DISP_LCD ||
1437 par->display_type == DISP_DFP) {
1438 switch(blank) {
1439 case FB_BLANK_UNBLANK:
1440 case FB_BLANK_NORMAL:
1441 vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
1442 vga_out8(0x3c5, vga_in8(0x3c5) | 0x10);
1443 break;
1444 case FB_BLANK_VSYNC_SUSPEND:
1445 case FB_BLANK_HSYNC_SUSPEND:
1446 case FB_BLANK_POWERDOWN:
1447 vga_out8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
1448 vga_out8(0x3c5, vga_in8(0x3c5) & ~0x10);
1449 break;
1450 }
1451 }
1452
1453 return (blank == FB_BLANK_NORMAL) ? 1 : 0;
1454}
1403 1455
1404static struct fb_ops savagefb_ops = { 1456static struct fb_ops savagefb_ops = {
1405 .owner = THIS_MODULE, 1457 .owner = THIS_MODULE,
@@ -1407,6 +1459,7 @@ static struct fb_ops savagefb_ops = {
1407 .fb_set_par = savagefb_set_par, 1459 .fb_set_par = savagefb_set_par,
1408 .fb_setcolreg = savagefb_setcolreg, 1460 .fb_setcolreg = savagefb_setcolreg,
1409 .fb_pan_display = savagefb_pan_display, 1461 .fb_pan_display = savagefb_pan_display,
1462 .fb_blank = savagefb_blank,
1410#if defined(CONFIG_FB_SAVAGE_ACCEL) 1463#if defined(CONFIG_FB_SAVAGE_ACCEL)
1411 .fb_fillrect = savagefb_fillrect, 1464 .fb_fillrect = savagefb_fillrect,
1412 .fb_copyarea = savagefb_copyarea, 1465 .fb_copyarea = savagefb_copyarea,
@@ -1583,8 +1636,7 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
1583 static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 }; 1636 static unsigned char RamSavage4[] = { 2, 4, 8, 12, 16, 32, 64, 32 };
1584 static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 }; 1637 static unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
1585 static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 }; 1638 static unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 2, 2 };
1586 1639 int videoRam, videoRambytes, dvi;
1587 int videoRam, videoRambytes;
1588 1640
1589 DBG("savage_init_hw"); 1641 DBG("savage_init_hw");
1590 1642
@@ -1705,6 +1757,30 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
1705 printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n", 1757 printk (KERN_INFO "savagefb: Detected current MCLK value of %d kHz\n",
1706 par->MCLK); 1758 par->MCLK);
1707 1759
1760 /* check for DVI/flat panel */
1761 dvi = 0;
1762
1763 if (par->chip == S3_SAVAGE4) {
1764 unsigned char sr30 = 0x00;
1765
1766 vga_out8(0x3c4, 0x30);
1767 /* clear bit 1 */
1768 vga_out8(0x3c5, vga_in8(0x3c5) & ~0x02);
1769 sr30 = vga_in8(0x3c5);
1770 if (sr30 & 0x02 /*0x04 */) {
1771 dvi = 1;
1772 printk("savagefb: Digital Flat Panel Detected\n");
1773 }
1774 }
1775
1776 if (S3_SAVAGE_MOBILE_SERIES(par->chip) ||
1777 (S3_MOBILE_TWISTER_SERIES(par->chip) && !par->crtonly))
1778 par->display_type = DISP_LCD;
1779 else if (dvi || (par->chip == S3_SAVAGE4 && par->dvi))
1780 par->display_type = DISP_DFP;
1781 else
1782 par->display_type = DISP_CRT;
1783
1708 /* Check LCD panel parrmation */ 1784 /* Check LCD panel parrmation */
1709 1785
1710 if (par->chip == S3_SAVAGE_MX) { 1786 if (par->chip == S3_SAVAGE_MX) {
@@ -1759,7 +1835,8 @@ static int __devinit savage_init_hw (struct savagefb_par *par)
1759 par->SavagePanelWidth = panelX; 1835 par->SavagePanelWidth = panelX;
1760 par->SavagePanelHeight = panelY; 1836 par->SavagePanelHeight = panelY;
1761 1837
1762 } 1838 } else
1839 par->display_type = DISP_CRT;
1763 } 1840 }
1764 1841
1765 savage_get_default_par (par); 1842 savage_get_default_par (par);
@@ -1845,15 +1922,15 @@ static int __devinit savage_init_fb_info (struct fb_info *info,
1845 snprintf (info->fix.id, 16, "ProSavageKM"); 1922 snprintf (info->fix.id, 16, "ProSavageKM");
1846 break; 1923 break;
1847 case FB_ACCEL_S3TWISTER_P: 1924 case FB_ACCEL_S3TWISTER_P:
1848 par->chip = S3_PROSAVAGE; 1925 par->chip = S3_TWISTER;
1849 snprintf (info->fix.id, 16, "TwisterP"); 1926 snprintf (info->fix.id, 16, "TwisterP");
1850 break; 1927 break;
1851 case FB_ACCEL_S3TWISTER_K: 1928 case FB_ACCEL_S3TWISTER_K:
1852 par->chip = S3_PROSAVAGE; 1929 par->chip = S3_TWISTER;
1853 snprintf (info->fix.id, 16, "TwisterK"); 1930 snprintf (info->fix.id, 16, "TwisterK");
1854 break; 1931 break;
1855 case FB_ACCEL_PROSAVAGE_DDR: 1932 case FB_ACCEL_PROSAVAGE_DDR:
1856 par->chip = S3_PROSAVAGE; 1933 par->chip = S3_PROSAVAGEDDR;
1857 snprintf (info->fix.id, 16, "ProSavageDDR"); 1934 snprintf (info->fix.id, 16, "ProSavageDDR");
1858 break; 1935 break;
1859 case FB_ACCEL_PROSAVAGE_DDRK: 1936 case FB_ACCEL_PROSAVAGE_DDRK:
@@ -1959,7 +2036,8 @@ static int __devinit savagefb_probe (struct pci_dev* dev,
1959 INIT_LIST_HEAD(&info->modelist); 2036 INIT_LIST_HEAD(&info->modelist);
1960#if defined(CONFIG_FB_SAVAGE_I2C) 2037#if defined(CONFIG_FB_SAVAGE_I2C)
1961 savagefb_create_i2c_busses(info); 2038 savagefb_create_i2c_busses(info);
1962 savagefb_probe_i2c_connector(par, &par->edid); 2039 savagefb_probe_i2c_connector(info, &par->edid);
2040 kfree(par->edid);
1963 fb_edid_to_monspecs(par->edid, &info->monspecs); 2041 fb_edid_to_monspecs(par->edid, &info->monspecs);
1964 fb_videomode_to_modelist(info->monspecs.modedb, 2042 fb_videomode_to_modelist(info->monspecs.modedb,
1965 info->monspecs.modedb_len, 2043 info->monspecs.modedb_len,
@@ -2111,13 +2189,30 @@ static int savagefb_suspend (struct pci_dev* dev, pm_message_t state)
2111 2189
2112 DBG("savagefb_suspend"); 2190 DBG("savagefb_suspend");
2113 2191
2192
2193 par->pm_state = state.event;
2194
2195 /*
2196 * For PM_EVENT_FREEZE, do not power down so the console
2197 * can remain active.
2198 */
2199 if (state.event == PM_EVENT_FREEZE) {
2200 dev->dev.power.power_state = state;
2201 return 0;
2202 }
2203
2114 acquire_console_sem(); 2204 acquire_console_sem();
2115 fb_set_suspend(info, pci_choose_state(dev, state)); 2205 fb_set_suspend(info, 1);
2116 savage_disable_mmio(par);
2117 release_console_sem();
2118 2206
2207 if (info->fbops->fb_sync)
2208 info->fbops->fb_sync(info);
2209
2210 savagefb_blank(FB_BLANK_POWERDOWN, info);
2211 savage_disable_mmio(par);
2212 pci_save_state(dev);
2119 pci_disable_device(dev); 2213 pci_disable_device(dev);
2120 pci_set_power_state(dev, pci_choose_state(dev, state)); 2214 pci_set_power_state(dev, pci_choose_state(dev, state));
2215 release_console_sem();
2121 2216
2122 return 0; 2217 return 0;
2123} 2218}
@@ -2127,22 +2222,34 @@ static int savagefb_resume (struct pci_dev* dev)
2127 struct fb_info *info = 2222 struct fb_info *info =
2128 (struct fb_info *)pci_get_drvdata(dev); 2223 (struct fb_info *)pci_get_drvdata(dev);
2129 struct savagefb_par *par = (struct savagefb_par *)info->par; 2224 struct savagefb_par *par = (struct savagefb_par *)info->par;
2225 int cur_state = par->pm_state;
2130 2226
2131 DBG("savage_resume"); 2227 DBG("savage_resume");
2132 2228
2133 pci_set_power_state(dev, 0); 2229 par->pm_state = PM_EVENT_ON;
2134 pci_restore_state(dev);
2135 if(pci_enable_device(dev))
2136 DBG("err");
2137 2230
2138 SavagePrintRegs(); 2231 /*
2232 * The adapter was not powered down coming back from a
2233 * PM_EVENT_FREEZE.
2234 */
2235 if (cur_state == PM_EVENT_FREEZE) {
2236 pci_set_power_state(dev, PCI_D0);
2237 return 0;
2238 }
2139 2239
2140 acquire_console_sem(); 2240 acquire_console_sem();
2141 2241
2242 pci_set_power_state(dev, PCI_D0);
2243 pci_restore_state(dev);
2244
2245 if(pci_enable_device(dev))
2246 DBG("err");
2247
2248 pci_set_master(dev);
2142 savage_enable_mmio(par); 2249 savage_enable_mmio(par);
2143 savage_init_hw(par); 2250 savage_init_hw(par);
2144 savagefb_set_par (info); 2251 savagefb_set_par (info);
2145 2252 savagefb_blank(FB_BLANK_UNBLANK, info);
2146 fb_set_suspend (info, 0); 2253 fb_set_suspend (info, 0);
2147 release_console_sem(); 2254 release_console_sem();
2148 2255