patch-2.2.14 linux/drivers/video/atyfb.c

Next file: linux/drivers/video/bwtwofb.c
Previous file: linux/drivers/video/Config.in
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.13/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/*  $Id: atyfb.c,v 1.106.2.4 1999/09/02 06:34:46 paulus Exp $
+/*  $Id: atyfb.c,v 1.106.2.6 1999/10/14 08:44:47 davem Exp $
  *  linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
  *
  *	Copyright (C) 1997-1998  Geert Uytterhoeven
@@ -89,7 +89,6 @@
  */
 #undef DEBUG
 
-
 #define GUI_RESERVE	0x00001000
 
 
@@ -227,8 +226,8 @@
     } fbcon_cmap;
     u8 blitter_may_be_busy;
 #ifdef __sparc__
-    u8 open;
     u8 mmaped;
+    int open;
     int vtconsole;
     int consolecnt;
 #endif
@@ -1896,10 +1895,8 @@
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	if (fb->open)
-	    return -EBUSY;
+	fb->open++;
 	fb->mmaped = 0;
-	fb->open = 1;
 	fb->vtconsole = -1;
     } else {
 	fb->consolecnt++;
@@ -1909,17 +1906,54 @@
     return(0);
 }
 
+struct fb_var_screeninfo default_var = {
+    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+    640, 480, 640, 480, 0, 0, 8, 0,
+    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+    0, FB_VMODE_NONINTERLACED
+};
+
 static int atyfb_release(struct fb_info *info, int user)
 {
 #ifdef __sparc__
     struct fb_info_aty *fb = (struct fb_info_aty *)info;
 
     if (user) {
-	if (fb->vtconsole != -1)
-	    vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
-	fb->open = 0;
-	fb->mmaped = 0;
-	fb->vtconsole = -1;
+	fb->open--;
+	udelay(1000);
+	wait_for_idle(fb);
+	if (!fb->open) {
+		int was_mmaped = fb->mmaped;
+
+		fb->mmaped = 0;
+		if (fb->vtconsole != -1)
+			vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;
+		fb->vtconsole = -1;
+
+		if (was_mmaped) {
+			struct fb_var_screeninfo var;
+
+			/* Now reset the default display config, we have no
+			 * idea what the program(s) which mmap'd the chip did
+			 * to the configuration, nor whether it restored it
+			 * correctly.
+			 */
+			var = default_var;
+			if (noaccel)
+				var.accel_flags &= ~FB_ACCELF_TEXT;
+			else
+				var.accel_flags |= FB_ACCELF_TEXT;
+			if (var.yres == var.yres_virtual) {
+				u32 vram = (fb->total_vram - (PAGE_SIZE << 2));
+				var.yres_virtual = ((vram * 8) / var.bits_per_pixel) /
+					var.xres_virtual;
+				if (var.yres_virtual < var.yres)
+					var.yres_virtual = var.yres;
+			}
+			atyfb_set_var(&var, -1, &fb->fb_info);
+		}
+	}
     } else {
 	fb->consolecnt--;
     }
@@ -1982,15 +2016,6 @@
 }
 
 
-struct fb_var_screeninfo default_var = {
-    /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
-    640, 480, 640, 480, 0, 0, 8, 0,
-    {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
-    0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
-    0, FB_VMODE_NONINTERLACED
-};
-
-
     /*
      *  Get the Fixed Part of the Display
      */
@@ -3909,47 +3934,65 @@
 {
 	struct fb_info_aty *info;
  	unsigned int pm;
- 	
+
 	for (info = first_display; info != NULL; info = info->next) {
 		struct fb_fix_screeninfo fix;
 		int nb;
-		
+
 		atyfb_get_fix(&fix, fg_console, (struct fb_info *)info);
 		nb = fb_display[fg_console].var.yres * fix.line_length;
 
 		switch (when) {
+		case PBOOK_SLEEP_REQUEST:
+			info->save_framebuffer = vmalloc(nb);
+			break;
+		case PBOOK_SLEEP_REJECT:
+			if (info->save_framebuffer) {
+				vfree(info->save_framebuffer);
+				info->save_framebuffer = 0;
+			}
+			break;
 		case PBOOK_SLEEP_NOW:
+			if (info->blitter_may_be_busy)
+				wait_for_idle(info);
 			/* Stop accel engine (stop bus mastering) */
 			if (info->current_par.accel_flags & FB_ACCELF_TEXT)
 				reset_engine(info);
-#if 1
+
 			/* Backup fb content */	
-			info->save_framebuffer = vmalloc(nb);
 			if (info->save_framebuffer)
 				memcpy(info->save_framebuffer,
 				       (void *)info->frame_buffer, nb);
-#endif
-			/* Blank display and LCD */				       
-			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);			
-			
-			/* Set chip to "suspend" mode. Note: There's an HW bug in the
-			   chip which prevents proper resync on wakeup with automatic
-			   power management, we handle suspend manually using the
-			   following (weird) sequence described by ATI. Note2:
+
+			/* Blank display and LCD */
+			atyfbcon_blank(VESA_POWERDOWN+1, (struct fb_info *)info);
+
+			/* Set chip to "suspend" mode. Note: There's a HW bug
+			   in the chip which prevents proper resync on wakeup
+			   with automatic power management, we handle suspend
+			   manually using the following (weird) sequence
+			   described by ATI.
+			   Note2:
 			   We could enable this for all Rage LT Pro chip ids */
-			if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID) || (Gx == LP_CHIP_ID)) {
+			if ((Gx == LG_CHIP_ID) || (Gx == LT_CHIP_ID)
+			    || (Gx == LP_CHIP_ID)) {
 				pm = aty_ld_le32(POWER_MANAGEMENT, info);
 				pm &= ~PWR_MGT_ON;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				mdelay(1);
 				pm &= ~(PWR_BLON | AUTO_PWR_UP);
 				pm |= SUSPEND_NOW;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				mdelay(1);
 				pm |= PWR_MGT_ON;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				do {
 					pm = aty_ld_le32(POWER_MANAGEMENT, info);
+					/* Fix a problem with revision 4c50 of the chip */
+					if (Gx == LP_CHIP_ID)
+						break;
 				} while ((pm & PWR_MGT_STATUS_MASK) != PWR_MGT_STATUS_SUSPEND);
 				mdelay(500);
 			}
@@ -3961,18 +4004,23 @@
 				pm &= ~PWR_MGT_ON;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				mdelay(1);
 				pm |=  (PWR_BLON | AUTO_PWR_UP);
 				pm &= ~SUSPEND_NOW;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				pm = aty_ld_le32(POWER_MANAGEMENT, info);
+				mdelay(1);
 				pm |= PWR_MGT_ON;
 				aty_st_le32(POWER_MANAGEMENT, pm, info);
 				do {
 					pm = aty_ld_le32(POWER_MANAGEMENT, info);
+					/* Fix a problem with revision 4c50 of the chip */
+					if (Gx == LP_CHIP_ID)
+						break;
 				} while ((pm & PWR_MGT_STATUS_MASK) != 0);
 				mdelay(500);
 			}
-#if 1
+
 			/* Restore fb content */			
 			if (info->save_framebuffer) {
 				memcpy((void *)info->frame_buffer,
@@ -3980,7 +4028,7 @@
 				vfree(info->save_framebuffer);
 				info->save_framebuffer = 0;
 			}
-#endif
+
 			/* Restore display */			
 			atyfb_set_par(&info->current_par, info);
 			atyfbcon_blank(0, (struct fb_info *)info);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)