aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/tridentfb.c
diff options
context:
space:
mode:
authorKrzysztof Helt <krzysztof.h1@wp.pl>2008-03-04 17:28:39 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-03-04 19:35:12 -0500
commite8ed857c64e3ae62e27606ae58bc7371b5daccb1 (patch)
tree1cd65f3b9151e245fc89abe31eaf7d4cccef91fe /drivers/video/tridentfb.c
parent00f0b8259e48979c37212995d798f3fbd0374690 (diff)
tridentfb: resource management fixes in probe function
Correct error paths in probe function. The probe function enables mmio mode so it important to disable the mmio mode before exiting the probe function. Otherwise, the console is left in unusable state (garbled fonts at least, lock up at worst). [akpm@linux-foundation.org: cleanups] Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl> Cc: "Antonino A. Daplas" <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/video/tridentfb.c')
-rw-r--r--drivers/video/tridentfb.c65
1 files changed, 48 insertions, 17 deletions
diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c
index 70fb4ee2b421..919ce75db9e2 100644
--- a/drivers/video/tridentfb.c
+++ b/drivers/video/tridentfb.c
@@ -564,19 +564,46 @@ static inline void write3CE(int reg, unsigned char val)
564 t_outb(val, 0x3CF); 564 t_outb(val, 0x3CF);
565} 565}
566 566
567static inline void enable_mmio(void) 567static void enable_mmio(void)
568{ 568{
569 unsigned char tmp;
570
569 /* Goto New Mode */ 571 /* Goto New Mode */
570 outb(0x0B, 0x3C4); 572 outb(0x0B, 0x3C4);
571 inb(0x3C5); 573 inb(0x3C5);
572 574
573 /* Unprotect registers */ 575 /* Unprotect registers */
574 outb(NewMode1, 0x3C4); 576 outb(NewMode1, 0x3C4);
577 tmp = inb(0x3C5);
575 outb(0x80, 0x3C5); 578 outb(0x80, 0x3C5);
576 579
577 /* Enable MMIO */ 580 /* Enable MMIO */
578 outb(PCIReg, 0x3D4); 581 outb(PCIReg, 0x3D4);
579 outb(inb(0x3D5) | 0x01, 0x3D5); 582 outb(inb(0x3D5) | 0x01, 0x3D5);
583
584 t_outb(NewMode1, 0x3C4);
585 t_outb(tmp, 0x3C5);
586}
587
588static void disable_mmio(void)
589{
590 unsigned char tmp;
591
592 /* Goto New Mode */
593 t_outb(0x0B, 0x3C4);
594 t_inb(0x3C5);
595
596 /* Unprotect registers */
597 t_outb(NewMode1, 0x3C4);
598 tmp = t_inb(0x3C5);
599 t_outb(0x80, 0x3C5);
600
601 /* Disable MMIO */
602 t_outb(PCIReg, 0x3D4);
603 t_outb(t_inb(0x3D5) & ~0x01, 0x3D5);
604
605 outb(NewMode1, 0x3C4);
606 outb(tmp, 0x3C5);
580} 607}
581 608
582#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F) 609#define crtc_unlock() write3X4(CRTVSyncEnd, read3X4(CRTVSyncEnd) & 0x7F)
@@ -1239,9 +1266,9 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
1239 default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); 1266 default_par.io_virt = ioremap_nocache(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1240 1267
1241 if (!default_par.io_virt) { 1268 if (!default_par.io_virt) {
1242 release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1243 debug("ioremap failed\n"); 1269 debug("ioremap failed\n");
1244 return -1; 1270 err = -1;
1271 goto out_unmap1;
1245 } 1272 }
1246 1273
1247 enable_mmio(); 1274 enable_mmio();
@@ -1252,25 +1279,21 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
1252 1279
1253 if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) { 1280 if (!request_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len, "tridentfb")) {
1254 debug("request_mem_region failed!\n"); 1281 debug("request_mem_region failed!\n");
1282 disable_mmio();
1255 err = -1; 1283 err = -1;
1256 goto out_unmap; 1284 goto out_unmap1;
1257 } 1285 }
1258 1286
1259 fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start, 1287 fb_info.screen_base = ioremap_nocache(tridentfb_fix.smem_start,
1260 tridentfb_fix.smem_len); 1288 tridentfb_fix.smem_len);
1261 1289
1262 if (!fb_info.screen_base) { 1290 if (!fb_info.screen_base) {
1263 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
1264 debug("ioremap failed\n"); 1291 debug("ioremap failed\n");
1265 err = -1; 1292 err = -1;
1266 goto out_unmap; 1293 goto out_unmap2;
1267 } 1294 }
1268 1295
1269 output("%s board found\n", pci_name(dev)); 1296 output("%s board found\n", pci_name(dev));
1270#if 0
1271 output("Trident board found : mem = %X, io = %X, mem_v = %X, io_v = %X\n",
1272 tridentfb_fix.smem_start, tridentfb_fix.mmio_start, fb_info.screen_base, default_par.io_virt);
1273#endif
1274 displaytype = get_displaytype(); 1297 displaytype = get_displaytype();
1275 1298
1276 if (flatpanel) 1299 if (flatpanel)
@@ -1288,9 +1311,12 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
1288 1311
1289 if (!fb_find_mode(&default_var, &fb_info, mode, NULL, 0, NULL, bpp)) { 1312 if (!fb_find_mode(&default_var, &fb_info, mode, NULL, 0, NULL, bpp)) {
1290 err = -EINVAL; 1313 err = -EINVAL;
1291 goto out_unmap; 1314 goto out_unmap2;
1292 } 1315 }
1293 fb_alloc_cmap(&fb_info.cmap, 256, 0); 1316 err = fb_alloc_cmap(&fb_info.cmap, 256, 0);
1317 if (err < 0)
1318 goto out_unmap2;
1319
1294 if (defaultaccel && acc) 1320 if (defaultaccel && acc)
1295 default_var.accel_flags |= FB_ACCELF_TEXT; 1321 default_var.accel_flags |= FB_ACCELF_TEXT;
1296 else 1322 else
@@ -1300,19 +1326,24 @@ static int __devinit trident_pci_probe(struct pci_dev * dev,
1300 fb_info.device = &dev->dev; 1326 fb_info.device = &dev->dev;
1301 if (register_framebuffer(&fb_info) < 0) { 1327 if (register_framebuffer(&fb_info) < 0) {
1302 printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n"); 1328 printk(KERN_ERR "tridentfb: could not register Trident framebuffer\n");
1329 fb_dealloc_cmap(&fb_info.cmap);
1303 err = -EINVAL; 1330 err = -EINVAL;
1304 goto out_unmap; 1331 goto out_unmap2;
1305 } 1332 }
1306 output("fb%d: %s frame buffer device %dx%d-%dbpp\n", 1333 output("fb%d: %s frame buffer device %dx%d-%dbpp\n",
1307 fb_info.node, fb_info.fix.id, default_var.xres, 1334 fb_info.node, fb_info.fix.id, default_var.xres,
1308 default_var.yres, default_var.bits_per_pixel); 1335 default_var.yres, default_var.bits_per_pixel);
1309 return 0; 1336 return 0;
1310 1337
1311out_unmap: 1338out_unmap2:
1312 if (default_par.io_virt)
1313 iounmap(default_par.io_virt);
1314 if (fb_info.screen_base) 1339 if (fb_info.screen_base)
1315 iounmap(fb_info.screen_base); 1340 iounmap(fb_info.screen_base);
1341 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
1342 disable_mmio();
1343out_unmap1:
1344 if (default_par.io_virt)
1345 iounmap(default_par.io_virt);
1346 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1316 return err; 1347 return err;
1317} 1348}
1318 1349
@@ -1323,7 +1354,7 @@ static void __devexit trident_pci_remove(struct pci_dev *dev)
1323 iounmap(par->io_virt); 1354 iounmap(par->io_virt);
1324 iounmap(fb_info.screen_base); 1355 iounmap(fb_info.screen_base);
1325 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len); 1356 release_mem_region(tridentfb_fix.smem_start, tridentfb_fix.smem_len);
1326 release_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len); 1357 release_mem_region(tridentfb_fix.mmio_start, tridentfb_fix.mmio_len);
1327} 1358}
1328 1359
1329/* List of boards that we are trying to support */ 1360/* List of boards that we are trying to support */