[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Debian support for the lastest Powerbook 12" (1,33Ghz)



On Wed, Jul 07, 2004 at 02:48:29PM +0200, Guido Guenther wrote:
> On Mon, Jul 05, 2004 at 01:18:22PM +0200, Djoumé SALVETTI wrote:
> > Guido Guenther do you know about this patch? If you need it, I will be
> > happy to give you some additionnal information or perform some test, I
> > think it would be nice if this patch or an equivalent would be included
> > in the kernel.
> The patch isn't the problem, the broken rivafb in 2.6.7 is.
The attached patch brings rivafb back to live in 2.6.7 on my pbook
(NV17). It's basically current linus tree + more fixes, cleanups and
backlight control. Console switching is still broken though.
Cheers,
 -- Guido
--- ../linux-2.6.7.orig/drivers/video/riva/fbdev.c	2004-06-16 07:19:43.000000000 +0200
+++ drivers/video/riva/fbdev.c	2004-07-08 11:42:51.000000000 +0200
@@ -48,6 +48,9 @@
 #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #endif
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 #include "rivafb.h"
 #include "nvreg.h"
@@ -64,15 +67,16 @@
  * various helpful macros and constants
  *
  * ------------------------------------------------------------------------- */
-
-#undef RIVAFBDEBUG
-#ifdef RIVAFBDEBUG
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
+#ifdef CONFIG_FB_RIVA_DEBUG
+#define NVTRACE          printk
 #else
-#define DPRINTK(fmt, args...)
+#define NVTRACE          if(0) printk
 #endif
 
-#ifndef RIVA_NDEBUG
+#define NVTRACE_ENTER(...)  NVTRACE("%s START\n", __FUNCTION__)
+#define NVTRACE_LEAVE(...)  NVTRACE("%s END\n", __FUNCTION__)
+
+#ifdef CONFIG_FB_RIVA_DEBUG
 #define assert(expr) \
 	if(!(expr)) { \
 	printk( "Assertion failed! %s,%s,%s,line=%d\n",\
@@ -173,18 +177,18 @@
 	{ "GeForce2-GTS", NV_ARCH_10 },
 	{ "GeForce2-ULTRA", NV_ARCH_10 },
 	{ "Quadro2-PRO", NV_ARCH_10 },
-	{ "GeForce4-MX-460", NV_ARCH_20 },
-	{ "GeForce4-MX-440", NV_ARCH_20 },
-	{ "GeForce4-MX-420", NV_ARCH_20 },
-	{ "GeForce4-440-GO", NV_ARCH_20 },
-	{ "GeForce4-420-GO", NV_ARCH_20 },
-	{ "GeForce4-420-GO-M32", NV_ARCH_20 },
-	{ "Quadro4-500-XGL", NV_ARCH_20 },
-	{ "GeForce4-440-GO-M64", NV_ARCH_20 },
-	{ "Quadro4-200", NV_ARCH_20 },
-	{ "Quadro4-550-XGL", NV_ARCH_20 },
-	{ "Quadro4-500-GOGL", NV_ARCH_20 },
-	{ "GeForce2", NV_ARCH_20 },
+	{ "GeForce4-MX-460", NV_ARCH_10 },
+	{ "GeForce4-MX-440", NV_ARCH_10 },
+	{ "GeForce4-MX-420", NV_ARCH_10 },
+	{ "GeForce4-440-GO", NV_ARCH_10 },
+	{ "GeForce4-420-GO", NV_ARCH_10 },
+	{ "GeForce4-420-GO-M32", NV_ARCH_10 },
+	{ "Quadro4-500-XGL", NV_ARCH_10 },
+	{ "GeForce4-440-GO-M64", NV_ARCH_10 },
+	{ "Quadro4-200", NV_ARCH_10 },
+	{ "Quadro4-550-XGL", NV_ARCH_10 },
+	{ "Quadro4-500-GOGL", NV_ARCH_10 },
+	{ "GeForce2", NV_ARCH_10 },
 	{ "GeForce3", NV_ARCH_20 }, 
 	{ "GeForce3 Ti 200", NV_ARCH_20 },
 	{ "GeForce3 Ti 500", NV_ARCH_20 },
@@ -296,9 +300,8 @@
 static int nomtrr __initdata = 0;
 #endif
 
-#ifndef MODULE
 static char *mode_option __initdata = NULL;
-#endif
+static int  strictmode       = 0;
 
 static struct fb_fix_screeninfo rivafb_fix = {
 	.id		= "nVidia",
@@ -352,6 +355,38 @@
 	0xEB							/* MISC */
 };
 
+/*
+ * Backlight control
+ */
+#ifdef CONFIG_PMAC_BACKLIGHT
+
+static int riva_backlight_levels[] = {
+    0x158,
+    0x192,
+    0x1c6,
+    0x200,
+    0x234,
+    0x268,
+    0x2a2,
+    0x2d6,
+    0x310,
+    0x344,
+    0x378,
+    0x3b2,
+    0x3e6,
+    0x41a,
+    0x454,
+    0x534,
+};
+
+static int riva_set_backlight_enable(int on, int level, void *data);
+static int riva_set_backlight_level(int level, void *data);
+static struct backlight_controller riva_backlight_controller = {
+	riva_set_backlight_enable,
+	riva_set_backlight_level
+};
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
 /* ------------------------------------------------------------------------- *
  *
  * MMIO access macros
@@ -493,57 +528,35 @@
  * rivafb_cursor()
  */
 static void rivafb_load_cursor_image(struct riva_par *par, u8 *data8,
-				     u8 *mask8, u16 bg, u16 fg, u32 w, u32 h)
+				     u16 bg, u16 fg, u32 w, u32 h)
 {
 	int i, j, k = 0;
-	u32 b, m, tmp;
+	u32 b, tmp;
 	u32 *data = (u32 *)data8;
-	u32 *mask = (u32 *)mask8;
 
+	NVTRACE_ENTER();
 	for (i = 0; i < h; i++) {
 		b = *data++;
-		m = *mask++;
 		reverse_order(&b);
 		
 		for (j = 0; j < w/2; j++) {
 			tmp = 0;
 #if defined (__BIG_ENDIAN)
-			if (m & (1 << 31)) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
 			b <<= 1;
-			m <<= 1;
-
-			if (m & (1 << 31)) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp |= (b & (1 << 31)) ? fg : bg;
 			b <<= 1;
-			m <<= 1;
 #else
-			if (m & 1) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp = (b & 1) ? fg : bg;
 			b >>= 1;
-			m >>= 1;
-			
-			if (m & 1) {
-				fg |= 1 << 15;
-				bg |= 1 << 15;
-			}
 			tmp |= (b & 1) ? fg << 16 : bg << 16;
 			b >>= 1;
-			m >>= 1;
 #endif
-			writel(tmp, par->riva.CURSOR + k++);
+			writel(tmp, &par->riva.CURSOR[k++]);
 		}
 		k += (MAX_CURS - w)/2;
 	}
+	NVTRACE_LEAVE();
 }
 
 /* ------------------------------------------------------------------------- *
@@ -617,6 +630,7 @@
 {
 	int i;
 
+	NVTRACE_ENTER();
 	par->riva.LockUnlock(&par->riva, 0);
 
 	par->riva.UnloadStateExt(&par->riva, &regs->ext);
@@ -634,6 +648,7 @@
 
 	for (i = 0; i < NUM_SEQ_REGS; i++)
 		regs->seq[i] = SEQin(par, i);
+	NVTRACE_LEAVE();
 }
 
 /**
@@ -655,6 +670,7 @@
 	RIVA_HW_STATE *state = &regs->ext;
 	int i;
 
+	NVTRACE_ENTER();
 	CRTCout(par, 0x11, 0x00);
 
 	par->riva.LockUnlock(&par->riva, 0);
@@ -681,6 +697,7 @@
 
 	for (i = 0; i < NUM_SEQ_REGS; i++)
 		SEQout(par, i, regs->seq[i]);
+	NVTRACE_LEAVE();
 }
 
 /**
@@ -701,6 +718,7 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 	struct riva_regs newmode;
 	
+	NVTRACE_ENTER();
 	/* time to calculate */
 	rivafb_blank(1, info);
 
@@ -831,6 +849,27 @@
 	riva_load_state(par, &par->current_state);
 	par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
 	rivafb_blank(0, info);
+	NVTRACE_LEAVE();
+}
+
+static void riva_update_var(struct fb_var_screeninfo *var, struct fb_videomode *modedb)
+{
+	NVTRACE_ENTER();
+	var->xres = var->xres_virtual = modedb->xres;
+	var->yres = modedb->yres;
+        if (var->yres_virtual < var->yres)
+	    var->yres_virtual = var->yres;
+        var->xoffset = var->yoffset = 0;
+        var->pixclock = modedb->pixclock;
+        var->left_margin = modedb->left_margin;
+        var->right_margin = modedb->right_margin;
+        var->upper_margin = modedb->upper_margin;
+        var->lower_margin = modedb->lower_margin;
+        var->hsync_len = modedb->hsync_len;
+        var->vsync_len = modedb->vsync_len;
+        var->sync = modedb->sync;
+        var->vmode = modedb->vmode;
+	NVTRACE_LEAVE();
 }
 
 /**
@@ -866,19 +905,20 @@
 	};
 	int i;
 
+	NVTRACE_ENTER();
 	/* use highest possible virtual resolution */
 	if (var->xres_virtual == -1 && var->yres_virtual == -1) {
 		printk(KERN_WARNING PFX
 		       "using maximum available virtual resolution\n");
 		for (i = 0; modes[i].xres != -1; i++) {
 			if (modes[i].xres * nom / den * modes[i].yres <
-			    info->fix.smem_len / 2)
+			    info->fix.smem_len)
 				break;
 		}
 		if (modes[i].xres == -1) {
 			printk(KERN_ERR PFX
 			       "could not find a virtual resolution that fits into video memory!!\n");
-			DPRINTK("EXIT - EINVAL error\n");
+			NVTRACE("EXIT - EINVAL error\n");
 			return -EINVAL;
 		}
 		var->xres_virtual = modes[i].xres;
@@ -889,13 +929,13 @@
 		       var->xres_virtual, var->yres_virtual);
 	} else if (var->xres_virtual == -1) {
 		var->xres_virtual = (info->fix.smem_len * den /
-			(nom * var->yres_virtual * 2)) & ~15;
+			(nom * var->yres_virtual)) & ~15;
 		printk(KERN_WARNING PFX
 		       "setting virtual X resolution to %d\n", var->xres_virtual);
 	} else if (var->yres_virtual == -1) {
 		var->xres_virtual = (var->xres_virtual + 15) & ~15;
 		var->yres_virtual = info->fix.smem_len * den /
-			(nom * var->xres_virtual * 2);
+			(nom * var->xres_virtual);
 		printk(KERN_WARNING PFX
 		       "setting virtual Y resolution to %d\n", var->yres_virtual);
 	} else {
@@ -904,7 +944,7 @@
 			printk(KERN_ERR PFX
 			       "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
 			       var->xres, var->yres, var->bits_per_pixel);
-			DPRINTK("EXIT - EINVAL error\n");
+			NVTRACE("EXIT - EINVAL error\n");
 			return -EINVAL;
 		}
 	}
@@ -927,35 +967,52 @@
 		       "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
 		return -EINVAL;
 	}
+	if (var->xres_virtual > 0x7fff/nom)
+	    var->xres_virtual = 0x7fff/nom;
+	if (var->yres_virtual > 0x7fff/nom)
+	    var->yres_virtual = 0x7fff/nom;
+	NVTRACE_LEAVE();
 	return 0;
 }
 
+static void
+riva_set_pattern(struct riva_par *par, int clr0, int clr1, int pat0, int pat1)
+{
+	RIVA_FIFO_FREE(par->riva, Patt, 4);
+	par->riva.Patt->Color0        = clr0;
+	par->riva.Patt->Color1        = clr1;
+	par->riva.Patt->Monochrome[0] = pat0;
+	par->riva.Patt->Monochrome[1] = pat1;
+}
+
 /* acceleration routines */
 inline void wait_for_idle(struct riva_par *par)
 {
 	while (par->riva.Busy(&par->riva));
 }
 
-/* set copy ROP, no mask */
-static void riva_setup_ROP(struct riva_par *par)
+/*
+ * Set ROP.  Translate X rop into ROP3.  Internal routine.
+ */
+static void
+riva_set_rop_solid(struct riva_par *par, int rop)
 {
-	RIVA_FIFO_FREE(par->riva, Patt, 5);
-	par->riva.Patt->Shape = 0;
-	par->riva.Patt->Color0 = 0xffffffff;
-	par->riva.Patt->Color1 = 0xffffffff;
-	par->riva.Patt->Monochrome[0] = 0xffffffff;
-	par->riva.Patt->Monochrome[1] = 0xffffffff;
-
+	riva_set_pattern(par, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF);
 	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = 0xCC;
+        par->riva.Rop->Rop3 = rop;
+
 }
 
-void riva_setup_accel(struct riva_par *par)
+void riva_setup_accel(struct fb_info *info)
 {
+	struct riva_par *par = (struct riva_par *) info->par;
+
 	RIVA_FIFO_FREE(par->riva, Clip, 2);
 	par->riva.Clip->TopLeft     = 0x0;
-	par->riva.Clip->WidthHeight = 0x80008000;
-	riva_setup_ROP(par);
+	par->riva.Clip->WidthHeight = 0x7fff7fff;
+	par->riva.Clip->WidthHeight = (info->var.xres_virtual & 0xffff) |
+		(info->var.yres_virtual << 16);
+	riva_set_rop_solid(par, 0xcc);
 	wait_for_idle(par);
 }
 
@@ -995,6 +1052,36 @@
 
 /* ------------------------------------------------------------------------- *
  *
+ * Backlight operations
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+static int riva_set_backlight_enable(int on, int level, void *data)
+{
+	struct riva_par *par = (struct riva_par *)data;
+	U032 tmp_pcrt, tmp_pmc;
+
+	tmp_pmc = par->riva.PMC[0x10F0/4] & 0x0000FFFF;
+	tmp_pcrt = par->riva.PCRTC0[0x081C/4] & 0xFFFFFFFC;
+	if(on && (level > BACKLIGHT_OFF)) {
+		tmp_pcrt |= 0x1;
+		tmp_pmc |= (1 << 31); // backlight bit
+		tmp_pmc |= riva_backlight_levels[level-1] << 16; // level
+	}
+	par->riva.PCRTC0[0x081C/4] = tmp_pcrt;
+	par->riva.PMC[0x10F0/4] = tmp_pmc;
+	return 0;
+}
+
+static int riva_set_backlight_level(int level, void *data)
+{
+	return riva_set_backlight_enable(1, level, data);
+}
+#endif /* CONFIG_PMAC_BACKLIGHT */
+
+/* ------------------------------------------------------------------------- *
+ *
  * framebuffer operations
  *
  * ------------------------------------------------------------------------- */
@@ -1004,6 +1091,7 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 	int cnt = atomic_read(&par->ref_count);
 
+	NVTRACE_ENTER();
 	if (!cnt) {
 		memset(&par->state, 0, sizeof(struct vgastate));
 		par->state.flags = VGA_SAVE_MODE  | VGA_SAVE_FONTS;
@@ -1020,6 +1108,7 @@
 		riva_save_state(par, &par->initial_state);
 	}
 	atomic_inc(&par->ref_count);
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1028,6 +1117,7 @@
 	struct riva_par *par = (struct riva_par *) info->par;
 	int cnt = atomic_read(&par->ref_count);
 
+	NVTRACE_ENTER();
 	if (!cnt)
 		return -EINVAL;
 	if (cnt == 1) {
@@ -1038,13 +1128,17 @@
 		par->riva.LockUnlock(&par->riva, 1);
 	}
 	atomic_dec(&par->ref_count);
+	NVTRACE_LEAVE();
 	return 0;
 }
 
 static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	struct fb_monspecs *specs = &info->monspecs;
 	int nom, den;		/* translating from pixels->bytes */
+	int mode_valid = 0;
 	
+	NVTRACE_ENTER();
 	switch (var->bits_per_pixel) {
 	case 1 ... 8:
 		var->red.offset = var->green.offset = var->blue.offset = 0;
@@ -1090,10 +1184,77 @@
 		printk(KERN_ERR PFX
 		       "mode %dx%dx%d rejected...color depth not supported.\n",
 		       var->xres, var->yres, var->bits_per_pixel);
-		DPRINTK("EXIT, returning -EINVAL\n");
+		NVTRACE("EXIT, returning -EINVAL\n");
 		return -EINVAL;
 	}
 
+	if (!strictmode) {
+		if (!fb_validate_mode(var, info))
+			mode_valid = 1;
+	}
+
+	/* find best mode from modedb */
+	if (!mode_valid && specs->modedb_len) {
+		int i, best, best_refresh, best_x, best_y, diff_x, diff_y;
+
+		best_refresh = best = best_x = best_y = 0;
+		diff_x = diff_y = -1;
+
+		for (i = 0; i < specs->modedb_len; i++) {
+			if (var->xres <= specs->modedb[i].xres &&
+			    !(specs->modedb[i].flag & FB_MODE_IS_CALCULATED) &&
+			    specs->modedb[i].xres - var->xres < diff_x) {
+				best_x = specs->modedb[i].xres;
+				diff_x = best_x - var->xres;
+			}
+			if (!diff_x) break;
+		}
+
+		if (diff_x != -1) {
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (best_x == specs->modedb[i].xres &&
+				    var->yres <= specs->modedb[i].yres &&
+				    !(specs->modedb[i].flag &
+				      FB_MODE_IS_CALCULATED) &&
+				    specs->modedb[i].yres-var->yres < diff_y) {
+					best_y = specs->modedb[i].yres;
+					diff_y = best_y - var->yres;
+				}
+				if (!diff_y) break;
+			}
+		}
+
+		if (diff_y != -1) {
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (best_x == specs->modedb[i].xres &&
+				    best_y == specs->modedb[i].yres &&
+				    !(specs->modedb[i].flag &
+				      FB_MODE_IS_CALCULATED) &&
+				    specs->modedb[i].refresh > best_refresh) {
+					best_refresh=specs->modedb[i].refresh;
+					best = i;
+				}
+			}
+		}
+
+		if (best_refresh) {
+			riva_update_var(var, &specs->modedb[best]);
+			mode_valid = 1;
+		}
+	}
+
+	/* calculate modeline if supported by monitor */
+	if (!mode_valid && info->monspecs.gtf) {
+		if (!fb_get_mode(FB_MAXTIMINGS, 0, var, info))
+			mode_valid = 1;
+	}
+	if (!mode_valid && info->monspecs.modedb_len)
+		return -EINVAL;
+
+	if (var->xres_virtual < var->xres)
+		var->xres_virtual = var->xres;
+	if (var->yres_virtual <= var->yres)
+		var->yres_virtual = -1;
 	if (rivafb_do_maximize(info, var, nom, den) < 0)
 		return -EINVAL;
 
@@ -1113,6 +1274,7 @@
 	    var->green.msb_right =
 	    var->blue.msb_right =
 	    var->transp.offset = var->transp.length = var->transp.msb_right = 0;
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1120,12 +1282,21 @@
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 
+	NVTRACE_ENTER();
+	riva_common_setup(par);
+	RivaGetConfig(&par->riva, par->Chipset);
+	/* vgaHWunlock() + riva unlock (0x7F) */
+	CRTCout(par, 0x11, 0xFF);
+	par->riva.LockUnlock(&par->riva, 0);
+
 	riva_load_video_mode(info);
-	riva_setup_accel(par);
+	riva_setup_accel(info);
 	
+	memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
 	info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
 	info->fix.visual = (info->var.bits_per_pixel == 8) ?
 				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1148,6 +1319,7 @@
 	struct riva_par *par = (struct riva_par *)info->par;
 	unsigned int base;
 
+	NVTRACE_ENTER();
 	if (var->xoffset > (var->xres_virtual - var->xres))
 		return -EINVAL;
 	if (var->yoffset > (var->yres_virtual - var->yres))
@@ -1174,6 +1346,7 @@
 		info->var.vmode |= FB_VMODE_YWRAP;
 	else
 		info->var.vmode &= ~FB_VMODE_YWRAP;
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1185,6 +1358,7 @@
 	tmp = SEQin(par, 0x01) & ~0x20;	/* screen on/off */
 	vesa = CRTCin(par, 0x1a) & ~0xc0;	/* sync on/off */
 
+	NVTRACE_ENTER();
 	if (blank) {
 		tmp |= 0x20;
 		switch (blank - 1) {
@@ -1203,6 +1377,14 @@
 	}
 	SEQout(par, 0x01, tmp);
 	CRTCout(par, 0x1a, vesa);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if ( par->FlatPanel && _machine == _MACH_Pmac) {
+		set_backlight_enable(!blank);
+	}
+#endif
+
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1329,8 +1511,7 @@
 		break;
 	}
 
-	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = rop;
+	riva_set_rop_solid(par, rop);
 
 	RIVA_FIFO_FREE(par->riva, Bitmap, 1);
 	par->riva.Bitmap->Color1A = color;
@@ -1338,10 +1519,12 @@
 	RIVA_FIFO_FREE(par->riva, Bitmap, 2);
 	par->riva.Bitmap->UnclippedRectangle[0].TopLeft =
 			(rect->dx << 16) | rect->dy;
+	mb();
 	par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =
 			(rect->width << 16) | rect->height;
-	RIVA_FIFO_FREE(par->riva, Rop, 1);
-	par->riva.Rop->Rop3 = 0xCC;	// back to COPY
+	mb();
+	riva_set_rop_solid(par, 0xcc);
+
 }
 
 /**
@@ -1362,16 +1545,18 @@
 	RIVA_FIFO_FREE(par->riva, Blt, 3);
 	par->riva.Blt->TopLeftSrc  = (region->sy << 16) | region->sx;
 	par->riva.Blt->TopLeftDst  = (region->dy << 16) | region->dx;
+	mb();
 	par->riva.Blt->WidthHeight = (region->height << 16) | region->width;
-	wait_for_idle(par);
+	mb();
 }
 
 static inline void convert_bgcolor_16(u32 *col)
 {
-	*col = ((*col & 0x00007C00) << 9)
-		| ((*col & 0x000003E0) << 6)
+	*col = ((*col & 0x0000F800) << 8)
+		| ((*col & 0x00007E0) << 5)
 		| ((*col & 0x0000001F) << 3)
 		|	   0xFF000000;
+	mb();
 }
 
 /**
@@ -1478,10 +1663,10 @@
 {
 	struct riva_par *par = (struct riva_par *) info->par;
 	u8 data[MAX_CURS * MAX_CURS/8];
-	u8 mask[MAX_CURS * MAX_CURS/8];
 	u16 fg, bg;
 	int i;
 
+	NVTRACE_ENTER();
 	par->riva.ShowHideCursor(&par->riva, 0);
 
 	if (cursor->set & FB_CUR_SETPOS) {
@@ -1508,7 +1693,7 @@
 		info->cursor.image.fg_color = cursor->image.fg_color;
 	}
 
-	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP)) {
+	if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETCUR)) {
 		u32 bg_idx = info->cursor.image.bg_color;
 		u32 fg_idx = info->cursor.image.fg_color;
 		u32 s_pitch = (info->cursor.image.width+7) >> 3;
@@ -1517,39 +1702,41 @@
 		u8 *msk = (u8 *) info->cursor.mask;
 		u8 src[64];	
 		
+		info->cursor.image.data = cursor->image.data;
 		switch (info->cursor.rop) {
 		case ROP_XOR:
-			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
+			for (i = 0; i < s_pitch * info->cursor.image.height;
+			     i++)
 					src[i] = dat[i] ^ msk[i];
 			break;
 		case ROP_COPY:
 		default:
-			for (i = 0; i < s_pitch * info->cursor.image.height; i++)
-				
+			for (i = 0; i < s_pitch * info->cursor.image.height;
+			     i++)
 					src[i] = dat[i] & msk[i];
 			break;
 		}
 		
-		fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src, s_pitch, info->cursor.image.height);
-
-		fb_move_buf_aligned(info, &info->sprite, mask, d_pitch, msk, s_pitch, info->cursor.image.height);
+		fb_move_buf_aligned(info, &info->sprite, data, d_pitch, src,
+				    s_pitch, info->cursor.image.height);
 
 		bg = ((info->cmap.red[bg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[bg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3);
+		     ((info->cmap.blue[bg_idx] & 0xf8) >> 3) | 1 << 15;
 
 		fg = ((info->cmap.red[fg_idx] & 0xf8) << 7) |
 		     ((info->cmap.green[fg_idx] & 0xf8) << 2) |
-		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3);
+		     ((info->cmap.blue[fg_idx] & 0xf8) >> 3) | 1 << 15;
 
 		par->riva.LockUnlock(&par->riva, 0);
 
-		rivafb_load_cursor_image(par, data, mask, bg, fg,
+		rivafb_load_cursor_image(par, data, bg, fg,
 					 info->cursor.image.width, 
 					 info->cursor.image.height);
 	}
 	if (info->cursor.enable)
 		par->riva.ShowHideCursor(&par->riva, 1);
+	NVTRACE_LEAVE();
 	return 0;
 }
 
@@ -1586,23 +1773,22 @@
 
 static int __devinit riva_set_fbinfo(struct fb_info *info)
 {
-	struct riva_par *par = (struct riva_par *) info->par;
 	unsigned int cmap_len;
 
-	info->flags = FBINFO_FLAG_DEFAULT;
-	info->var = rivafb_default_var;
-	info->fix = rivafb_fix;
-	info->fbops = &riva_fb_ops;
-	info->pseudo_palette = pseudo_palette;
-
-#ifndef MODULE
-	if (mode_option)
-		fb_find_mode(&info->var, info, mode_option,
-			     NULL, 0, NULL, 8);
+	NVTRACE_ENTER();
+	info->flags = 0;
+#if 0
+	info->flags = FBINFO_DEFAULT
+		    | FBINFO_HWACCEL_XPAN
+		    | FBINFO_HWACCEL_YPAN
+		    | FBINFO_HWACCEL_COPYAREA
+		    | FBINFO_HWACCEL_FILLRECT
+		    | FBINFO_HWACCEL_IMAGEBLIT;
 #endif
-	if (par->use_default_var)
-		/* We will use the modified default var */
 		info->var = rivafb_default_var;
+	info->fix.visual = (info->var.bits_per_pixel == 8) ?
+				FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
+	info->pseudo_palette = pseudo_palette;
 
 	cmap_len = riva_get_cmap_len(&info->var);
 	fb_alloc_cmap(&info->cmap, cmap_len, 0);	
@@ -1611,7 +1797,9 @@
 	info->pixmap.buf_align = 4;
 	info->pixmap.scan_align = 4;
 	info->pixmap.flags = FB_PIXMAP_SYSTEM;
-	return 0;
+	info->var.yres_virtual = -1;
+	NVTRACE_LEAVE();
+	return (rivafb_check_var(&info->var, info));
 }
 
 #ifdef CONFIG_PPC_OF
@@ -1625,6 +1813,7 @@
 		"DFP,EDID", "LCD,EDID", "EDID", "EDID1", "EDID,B", "EDID,A", NULL };
 	int i;
 
+	NVTRACE_ENTER();
 	dp = pci_device_to_OF_node(pd);
 	for (; dp != NULL; dp = dp->child) {
 		disptype = (unsigned char *)get_property(dp, "display-type", NULL);
@@ -1641,104 +1830,75 @@
 			}
 		}
 	}
+	NVTRACE_LEAVE();
 		return 0;
 }
 #endif /* CONFIG_PPC_OF */
 
-static int riva_dfp_parse_EDID(struct riva_par *par)
+static void riva_update_default_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
-	unsigned char *block = par->EDID;
+	struct fb_monspecs *specs = &info->monspecs;
+	struct fb_videomode modedb;
 
-	if (!block)
-		return 0;
-
-	/* jump to detailed timing block section */
-	block += 54;
+	NVTRACE_ENTER();
+	/* respect mode options */
+	if (mode_option) {
+		fb_find_mode(var, info, mode_option,
+			     specs->modedb, specs->modedb_len,
+			     NULL, 8);
+	} else if (specs->modedb != NULL) {
+		/* get preferred timing */
+		if (info->monspecs.misc & FB_MISC_1ST_DETAIL) {
+			int i;
 
-	par->clock = (block[0] + (block[1] << 8));
-	par->panel_xres = (block[2] + ((block[4] & 0xf0) << 4));
-	par->hblank = (block[3] + ((block[4] & 0x0f) << 8));
-	par->panel_yres = (block[5] + ((block[7] & 0xf0) << 4));
-	par->vblank = (block[6] + ((block[7] & 0x0f) << 8));
-	par->hOver_plus = (block[8] + ((block[11] & 0xc0) << 2));
-	par->hSync_width = (block[9] + ((block[11] & 0x30) << 4));
-	par->vOver_plus = ((block[10] >> 4) + ((block[11] & 0x0c) << 2));
-	par->vSync_width = ((block[10] & 0x0f) + ((block[11] & 0x03) << 4));
-	par->interlaced = ((block[17] & 0x80) >> 7);
-	par->synct = ((block[17] & 0x18) >> 3);
-	par->misc = ((block[17] & 0x06) >> 1);
-	par->hAct_high = par->vAct_high = 0;
-	if (par->synct == 3) {
-		if (par->misc & 2)
-			par->hAct_high = 1;
-		if (par->misc & 1)
-			par->vAct_high = 1;
+			for (i = 0; i < specs->modedb_len; i++) {
+				if (specs->modedb[i].flag & FB_MODE_IS_FIRST) {
+					modedb = specs->modedb[i];
+					break;
 	}
-
-	printk(KERN_INFO PFX
-			"detected DFP panel size from EDID: %dx%d\n", 
-			par->panel_xres, par->panel_yres);
-	par->got_dfpinfo = 1;
-	return 1;
 }
-
-static void riva_update_default_var(struct fb_info *info)
-{
-	struct fb_var_screeninfo *var = &rivafb_default_var;
-	struct riva_par *par = (struct riva_par *) info->par;
-
-        var->xres = par->panel_xres;
-        var->yres = par->panel_yres;
-        var->xres_virtual = par->panel_xres;
-        var->yres_virtual = par->panel_yres;
-        var->xoffset = var->yoffset = 0;
+		} else {
+			/* otherwise, get first mode in database */
+			modedb = specs->modedb[0];
+		}
         var->bits_per_pixel = 8;
-        var->pixclock = 100000000 / par->clock;
-        var->left_margin = (par->hblank - par->hOver_plus - par->hSync_width);
-        var->right_margin = par->hOver_plus;
-        var->upper_margin = (par->vblank - par->vOver_plus - par->vSync_width);
-        var->lower_margin = par->vOver_plus;
-        var->hsync_len = par->hSync_width;
-        var->vsync_len = par->vSync_width;
-        var->sync = 0;
-
-        if (par->synct == 3) {
-                if (par->hAct_high)
-                        var->sync |= FB_SYNC_HOR_HIGH_ACT;
-                if (par->vAct_high)
-                        var->sync |= FB_SYNC_VERT_HIGH_ACT;
-        }
- 
-        var->vmode = 0;
-        if (par->interlaced)
-                var->vmode |= FB_VMODE_INTERLACED;
-
+		riva_update_var(var, &modedb);
+	}
 	var->accel_flags |= FB_ACCELF_TEXT;
-        
-        par->use_default_var = 1;
+	NVTRACE_LEAVE();
 }
 
 
 static void riva_get_EDID(struct fb_info *info, struct pci_dev *pdev)
 {
+	NVTRACE_ENTER();
 #ifdef CONFIG_PPC_OF
 	if (!riva_get_EDID_OF(info, pdev))
 		printk("rivafb: could not retrieve EDID from OF\n");
 #else
 	/* XXX use other methods later */
+#ifdef CONFIG_FB_RIVA_I2C
+	struct riva_par *par = (struct riva_par *) info->par;
+
+	riva_create_i2c_busses(par);
+	riva_probe_i2c_connector(par, 1, &par->EDID);
+	riva_delete_i2c_busses(par);
 #endif
+#endif
+	NVTRACE_LEAVE();
 }
 
 
-static void riva_get_dfpinfo(struct fb_info *info)
+static void riva_get_edidinfo(struct fb_info *info)
 {
+	struct fb_var_screeninfo *var = &rivafb_default_var;
 	struct riva_par *par = (struct riva_par *) info->par;
 
-	if (riva_dfp_parse_EDID(par))
-		riva_update_default_var(info);
+	fb_edid_to_monspecs(par->EDID, &info->monspecs);
+	riva_update_default_var(var, info);
 
 	/* if user specified flatpanel, we respect that */
-	if (par->got_dfpinfo == 1)
+	if (info->monspecs.input & FB_DISP_DDI)
 		par->FlatPanel = 1;
 }
 
@@ -1755,6 +1915,7 @@
 	struct riva_par *default_par;
 	struct fb_info *info;
 
+	NVTRACE_ENTER();
 	assert(pd != NULL);
 	assert(rci != NULL);
 
@@ -1768,11 +1929,21 @@
 
 	memset(info, 0, sizeof(struct fb_info));
 	memset(default_par, 0, sizeof(struct riva_par));
+	default_par->pdev = pd;
 
 	info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
 	if (info->pixmap.addr == NULL)
 		goto err_out_kfree1;
 	memset(info->pixmap.addr, 0, 64 * 1024);
+	if (pci_enable_device(pd)) {
+		printk(KERN_ERR PFX "cannot enable PCI device\n");
+		goto err_out_enable;
+	}
+
+	if (pci_request_regions(pd, "rivafb")) {
+		printk(KERN_ERR PFX "cannot request PCI regions\n");
+		goto err_out_request;
+	}
 
 	strcat(rivafb_fix.id, rci->name);
 	default_par->riva.Architecture = rci->arch_rev;
@@ -1800,12 +1971,6 @@
 	rivafb_fix.mmio_start = pci_resource_start(pd, 0);
 	rivafb_fix.smem_start = pci_resource_start(pd, 1);
 
-	if (!request_mem_region(rivafb_fix.mmio_start,
-				rivafb_fix.mmio_len, "rivafb")) {
-		printk(KERN_ERR PFX "cannot reserve MMIO region\n");
-		goto err_out_kfree2;
-	}
-
 	default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
 					 rivafb_fix.mmio_len);
 	if (!default_par->ctrl_base) {
@@ -1815,27 +1980,19 @@
 
 	info->par = default_par;
 
-	riva_get_EDID(info, pd);
-
-	riva_get_dfpinfo(info);
-
 	switch (default_par->riva.Architecture) {
 	case NV_ARCH_03:
 		/* Riva128's PRAMIN is in the "framebuffer" space
 		 * Since these cards were never made with more than 8 megabytes
 		 * we can safely allocate this separately.
 		 */
-		if (!request_mem_region(rivafb_fix.smem_start + 0x00C00000,
-					 0x00008000, "rivafb")) {
-			printk(KERN_ERR PFX "cannot reserve PRAMIN region\n");
-			goto err_out_iounmap_ctrl;
-		}
 		default_par->riva.PRAMIN = ioremap(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
 		if (!default_par->riva.PRAMIN) {
 			printk(KERN_ERR PFX "cannot ioremap PRAMIN region\n");
 			goto err_out_free_nv3_pramin;
 		}
 		rivafb_fix.accel = FB_ACCEL_NV3;
+		default_par->bus = 1;
 		break;
 	case NV_ARCH_04:
 	case NV_ARCH_10:
@@ -1843,6 +2000,7 @@
 		default_par->riva.PCRTC0 = (unsigned *)(default_par->ctrl_base + 0x00600000);
 		default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
 		rivafb_fix.accel = FB_ACCEL_NV4;
+		default_par->bus = 2;
 		break;
 	}
 
@@ -1855,12 +2013,6 @@
 	rivafb_fix.smem_len = riva_get_memlen(default_par) * 1024;
 	default_par->dclk_max = riva_get_maxdclk(default_par) * 1000;
 
-	if (!request_mem_region(rivafb_fix.smem_start,
-				rivafb_fix.smem_len, "rivafb")) {
-		printk(KERN_ERR PFX "cannot reserve FB region\n");
-		goto err_out_iounmap_nv3_pramin;
-	}
-	
 	info->screen_base = ioremap(rivafb_fix.smem_start,
 				    rivafb_fix.smem_len);
 	if (!info->screen_base) {
@@ -1883,6 +2035,11 @@
 	}
 #endif /* CONFIG_MTRR */
 
+	info->fbops = &riva_fb_ops;
+	info->fix = rivafb_fix;
+	riva_get_EDID(info, pd);
+	riva_get_edidinfo(info);
+
 	if (riva_set_fbinfo(info) < 0) {
 		printk(KERN_ERR PFX "error setting initial video mode\n");
 		goto err_out_iounmap_fb;
@@ -1903,23 +2060,27 @@
 		info->fix.id,
 		info->fix.smem_len / (1024 * 1024),
 		info->fix.smem_start);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (default_par->FlatPanel && _machine == _MACH_Pmac)
+	register_backlight_controller(&riva_backlight_controller,
+				      			default_par, "mnca");
+#endif
+	NVTRACE_LEAVE();
 	return 0;
 
 err_out_iounmap_fb:
 	iounmap(info->screen_base);
 err_out_free_base1:
-	release_mem_region(rivafb_fix.smem_start, rivafb_fix.smem_len);
-err_out_iounmap_nv3_pramin:
 	if (default_par->riva.Architecture == NV_ARCH_03) 
 		iounmap((caddr_t)default_par->riva.PRAMIN);
 err_out_free_nv3_pramin:
-	if (default_par->riva.Architecture == NV_ARCH_03)
-		release_mem_region(rivafb_fix.smem_start + 0x00C00000, 0x00008000);
-err_out_iounmap_ctrl:
 	iounmap(default_par->ctrl_base);
 err_out_free_base0:
-	release_mem_region(rivafb_fix.mmio_start, rivafb_fix.mmio_len);
-err_out_kfree2:
+	pci_release_regions(pd);
+err_out_request:
+	pci_disable_device(pd);
+err_out_enable:
 	kfree(info->pixmap.addr);
 err_out_kfree1:
 	kfree(default_par);
@@ -1934,6 +2095,7 @@
 	struct fb_info *info = pci_get_drvdata(pd);
 	struct riva_par *par = (struct riva_par *) info->par;
 	
+	NVTRACE_ENTER();
 	if (!info)
 		return;
 
@@ -1947,19 +2109,17 @@
 	iounmap(par->ctrl_base);
 	iounmap(info->screen_base);
 
-	release_mem_region(info->fix.mmio_start,
-			   info->fix.mmio_len);
-	release_mem_region(info->fix.smem_start,
-			   info->fix.smem_len);
-
 	if (par->riva.Architecture == NV_ARCH_03) {
 		iounmap((caddr_t)par->riva.PRAMIN);
-		release_mem_region(info->fix.smem_start + 0x00C00000, 0x00008000);
 	}
+	pci_release_regions(pd);
+	pci_disable_device(pd);
+	fb_destroy_modedb(info->monspecs.modedb);
 	kfree(info->pixmap.addr);
 	kfree(par);
 	kfree(info);
 	pci_set_drvdata(pd, NULL);
+	NVTRACE_LEAVE();
 }
 
 /* ------------------------------------------------------------------------- *
@@ -1973,6 +2133,7 @@
 {
 	char *this_opt;
 
+	NVTRACE_ENTER();
 	if (!options || !*options)
 		return 0;
 
@@ -1991,9 +2152,12 @@
 		} else if (!strncmp(this_opt, "nomtrr", 6)) {
 			nomtrr = 1;
 #endif
+		} else if (!strncmp(this_opt, "strictmode", 10)) {
+			strictmode = 1;
 		} else
 			mode_option = this_opt;
 	}
+	NVTRACE_LEAVE();
 	return 0;
 }
 #endif /* !MODULE */
@@ -2039,6 +2203,8 @@
 #ifdef CONFIG_MTRR
 MODULE_PARM(nomtrr, "i");
 MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
+MODULE_PARM(strictmode, "i");
+MODULE_PARM_DESC(strictmode, "Only use video modes from EDID");
 #endif
 #endif /* MODULE */
 

Attachment: signature.asc
Description: Digital signature


Reply to: