patch-2.3.7 linux/drivers/video/cyber2000fb.c

Next file: linux/drivers/video/cyber2000fb.h
Previous file: linux/drivers/video/acornfb.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.6/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
@@ -121,7 +121,7 @@
 		1600, 1200,
 		{
 			0xff, 0xc7, 0xc9, 0x9f, 0xcf, 0xa0, 0xfe, 0x10,
-			0x00, 0x40,
+ 			0x00, 0x40,
 			0xcf, 0x89, 0xaf, 0xc8, 0x00, 0xbc, 0xf1, 0xe3
 		},
 		0x1f,
@@ -154,54 +154,54 @@
 	debug_printf("init vga hw for %dx%d\n", res->xres, res->yres);
 
 	cyber2000_outb(0xef, 0x3c2);
-	cyber2000_crtcw(0x0b, 0x11);
-	cyber2000_attrw(0x00, 0x11);
+	cyber2000_crtcw(0x11, 0x0b);
+	cyber2000_attrw(0x11, 0x00);
 
-	cyber2000_seqw(0x01, 0x00);
+	cyber2000_seqw(0x00, 0x01);
 	cyber2000_seqw(0x01, 0x01);
-	cyber2000_seqw(0x0f, 0x02);
-	cyber2000_seqw(0x00, 0x03);
-	cyber2000_seqw(0x0e, 0x04);
+	cyber2000_seqw(0x02, 0x0f);
 	cyber2000_seqw(0x03, 0x00);
+	cyber2000_seqw(0x04, 0x0e);
+	cyber2000_seqw(0x00, 0x03);
 
 	for (i = 0; i < sizeof(crtc_idx); i++)
-		cyber2000_crtcw(res->crtc_regs[i], crtc_idx[i]);
+		cyber2000_crtcw(crtc_idx[i], res->crtc_regs[i]);
 
 	for (i = 0x0a; i < 0x10; i++)
-		cyber2000_crtcw(0, i);
+		cyber2000_crtcw(i, 0);
 
-	cyber2000_crtcw(0xff, 0x18);
+	cyber2000_crtcw(0x18, 0xff);
 
 	cyber2000_grphw(0x00, 0x00);
-	cyber2000_grphw(0x00, 0x01);
-	cyber2000_grphw(0x00, 0x02);
-	cyber2000_grphw(0x00, 0x03);
-	cyber2000_grphw(0x00, 0x04);
-	cyber2000_grphw(0x60, 0x05);
-	cyber2000_grphw(0x05, 0x06);
-	cyber2000_grphw(0x0f, 0x07);
-	cyber2000_grphw(0xff, 0x08);
+	cyber2000_grphw(0x01, 0x00);
+	cyber2000_grphw(0x02, 0x00);
+	cyber2000_grphw(0x03, 0x00);
+	cyber2000_grphw(0x04, 0x00);
+	cyber2000_grphw(0x05, 0x60);
+	cyber2000_grphw(0x06, 0x05);
+	cyber2000_grphw(0x07, 0x0f);
+	cyber2000_grphw(0x08, 0xff);
 
 	for (i = 0; i < 16; i++)
 		cyber2000_attrw(i, i);
 
-	cyber2000_attrw(0x01, 0x10);
-	cyber2000_attrw(0x00, 0x11);
-	cyber2000_attrw(0x0f, 0x12);
-	cyber2000_attrw(0x00, 0x13);
-	cyber2000_attrw(0x00, 0x14);
+	cyber2000_attrw(0x10, 0x01);
+	cyber2000_attrw(0x11, 0x00);
+	cyber2000_attrw(0x12, 0x0f);
+	cyber2000_attrw(0x13, 0x00);
+	cyber2000_attrw(0x14, 0x00);
 
 	for (i = 0; i < sizeof(igs_regs); i += 2)
-		cyber2000_grphw(igs_regs[i+1], igs_regs[i]);
+		cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
 
-	cyber2000_grphw(res->crtc_ofl, 0x11);
+	cyber2000_grphw(0x11, res->crtc_ofl);
 
 	for (i = 0; i < 4; i += 1)
-		cyber2000_grphw(res->clk_regs[i], 0xb0 + i);
+		cyber2000_grphw(0xb0 + i, res->clk_regs[i]);
 
-	cyber2000_grphw(0x01, 0x90);
-	cyber2000_grphw(0x80, 0xb9);
-	cyber2000_grphw(0x00, 0xb9);
+	cyber2000_grphw(0x90, 0x01);
+	cyber2000_grphw(0xb9, 0x80);
+	cyber2000_grphw(0xb9, 0x00);
 
 	cyber2000_outb(0x56, 0x3ce);
 	i = cyber2000_inb(0x3cf);
@@ -311,6 +311,7 @@
 	cyber2000_outw(height, 0xbf062);
 
 	switch (p->var.bits_per_pixel) {
+	case 15:
 	case 16:
 		bgx = ((u16 *)p->dispsw_data)[bgx];
 	case 8:
@@ -415,14 +416,27 @@
 	current_par.palette[regno].blue  = blue;
 
 	switch (fb_display[current_par.currcon].var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
 	case 8:
 		cyber2000_outb(regno, 0x3c8);
 		cyber2000_outb(red,   0x3c9);
 		cyber2000_outb(green, 0x3c9);
 		cyber2000_outb(blue,  0x3c9);
 		break;
+#endif
 
 #ifdef FBCON_HAS_CFB16
+	case 15:
+		if (regno < 32) {
+			cyber2000_outb(regno << 3, 0x3c8);
+			cyber2000_outb(red, 0x3c9);
+			cyber2000_outb(green, 0x3c9);
+			cyber2000_outb(blue, 0x3c9);
+		}
+		if (regno < 16)
+			current_par.c_table.cfb16[regno] = regno | regno << 5 | regno << 10;
+		break;
+
 	case 16:
 		if (regno < 64) {
 			/* write green */
@@ -464,36 +478,123 @@
 	return 0;
 }
 
-static int cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+static void cyber2000fb_calculate_timing(unsigned char *v, struct fb_var_screeninfo *var)
 {
-	int width = var->xres_virtual;
-	int scr_pitch, fetchrow;
-	int i;
-	char b, col;
+	int Htotal, Hdispend, Hblankstart, Hblankend, Hsyncstart, Hsyncend;
+	int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend;
+#define BIT(v,b1,m,b2) (((v >> b1) & m) << b2)
+
+	Hdispend    = var->xres;
+	Hsyncstart  = var->xres + var->right_margin;
+	Hsyncend    = var->xres + var->right_margin + var->hsync_len;
+	Htotal      = var->xres + var->right_margin + var->hsync_len + var->left_margin;
+
+	Hblankstart = var->xres;
+	Hblankend   = Htotal - 4*8;
+
+	Vdispend    = var->yres;
+	Vsyncstart  = var->yres + var->lower_margin;
+	Vsyncend    = var->yres + var->lower_margin + var->vsync_len;
+	Vtotal      = var->yres + var->lower_margin + var->vsync_len + var->upper_margin;
+
+	Vblankstart = var->yres + 7;
+	Vblankend   = Vtotal - 11;
+
+	Hdispend    >>= 3;
+	Hsyncstart  >>= 3;
+	Hsyncend    >>= 3;
+	Htotal      >>= 3;
+	Hblankstart >>= 3;
+	Hblankend   >>= 3;
+
+	Htotal      -= 5;
+	Hdispend    -= 1;
+	Vtotal	    -= 2;
+	Vdispend    -= 1;
+	Vblankstart -= 1;
+	Vblankend   -= 1;
+
+	v[0]  = Htotal;
+	v[1]  = Hdispend;
+	v[2]  = Hblankstart;
+	v[3]  = BIT(Hblankend,  0, 0x1f,  0) |
+		BIT(1,          0, 0x01,  7);
+	v[4]  = Hsyncstart;
+	v[5]  = BIT(Hsyncend,   0, 0x1f,  0) |
+	        BIT(Hblankend,  5, 0x01,  7);
+
+	v[6]  = Vtotal;
+	v[7]  = BIT(Vtotal,     8, 0x01,  0) |
+		BIT(Vdispend,   8, 0x01,  1) |
+		BIT(Vsyncstart, 8, 0x01,  2) |
+		BIT(Vblankstart,8, 0x01,  3) |
+		BIT(1,          0, 0x01,  4) |
+	        BIT(Vtotal,     9, 0x01,  5) |
+		BIT(Vdispend,   9, 0x01,  6) |
+		BIT(Vsyncstart, 9, 0x01,  7);
+	v[8]  = 0;
+	v[9]  = BIT(0,          0, 0x1f,  0) |
+	        BIT(Vblankstart,9, 0x01,  5) |
+		BIT(1,          0, 0x01,  6);
+	v[10] = Vsyncstart;
+	v[11] = BIT(Vsyncend,   0, 0x0f,  0) |
+		BIT(1,          0, 0x01,  7);
+	v[12] = Vdispend;
+	v[14] = 0;
+	v[15] = Vblankstart;
+	v[16] = Vblankend;
+	v[17] = 0xe3;
+
+	/* overflow - graphics reg 0x11 */
+	v[18] = BIT(Vtotal,     10, 0x01,  0) | /* guess */
+		BIT(Vdispend,   10, 0x01,  1) |
+		BIT(Vsyncstart, 10, 0x01,  2) | /* guess */
+		BIT(Vblankstart,10, 0x01,  3) | /* guess */
+		BIT(Hblankend,   6, 0x01,  4);  /* guess */
+}
+
+static void cyber2000fb_set_timing(struct fb_var_screeninfo *var)
+{
+	unsigned int width = var->xres_virtual;
+	unsigned int scr_pitch, fetchrow, i;
+	char b, graph_r77, crtc[32];
 
 	switch (var->bits_per_pixel) {
 	case 8:	/* PSEUDOCOLOUR, 256 */
 		b = 0;
-		col = 1;
-		scr_pitch = var->xres_virtual / 8;
+		graph_r77 = 1;
+		scr_pitch = width;
+		break;
+
+	case 15:/* DIRECTCOLOUR, 32k */
+		b = 1;
+		graph_r77 = 6;
+		scr_pitch = width * 2;
 		break;
 
 	case 16:/* DIRECTCOLOUR, 64k */
 		b = 1;
-		col = 2;
-		scr_pitch = var->xres_virtual / 8 * 2;
+		graph_r77 = 2;
+		scr_pitch = width * 2;
 		break;
+
 	case 24:/* TRUECOLOUR, 16m */
 		b = 2;
-		col = 4;
-		scr_pitch = var->xres_virtual / 8 * 3;
+		graph_r77 = 4;
 		width *= 3;
+		scr_pitch = width;
 		break;
 
 	default:
-		return 1;
+		return;
 	}
 
+	width -= 1;
+	scr_pitch >>= 3;
+	fetchrow = scr_pitch + 1;
+
+	cyber2000fb_calculate_timing(crtc, var);
+
 	for (i = 0; i < NUM_TOTAL_MODES; i++)
 		if (var->xres == cyber2000_res[i].xres &&
 		    var->yres == cyber2000_res[i].yres)
@@ -502,30 +603,41 @@
 	if (i < NUM_TOTAL_MODES)
 		cyber2000_init_hw(cyber2000_res + i);
 
-	fetchrow = scr_pitch + 1;
+	crtc[13] = scr_pitch;
 
-	debug_printf("Setting regs: pitch=%X, fetchrow=%X, col=%X, b=%X\n",
-		     scr_pitch, fetchrow, col, b);
+	/*
+	 * reprogram the CRTC with the values we calculated
+	 * above.  This should be cleaned up once we're
+	 * confident that we're generating the correct
+	 * values.  Disable this if you're having problems,
+	 * and report the values obtained from the kernel
+	 * messages.
+	 */
+#if 1
+	cyber2000_crtcw(0x11, 0x0b);
+	for (i = 0; i < sizeof(crtc_idx); i++)
+		cyber2000_crtcw(crtc_idx[i], crtc[i]);
+#else
+	cyber2000_crtcw(0x13, crtc[13]);
+#endif
 
-	cyber2000_outb(0x13, 0x3d4);
-	cyber2000_outb(scr_pitch, 0x3d5);
-	cyber2000_outb(0x14, 0x3ce);
-	cyber2000_outb(fetchrow, 0x3cf);
-	cyber2000_outb(0x15, 0x3ce);
+	cyber2000_grphw(0x14, fetchrow);
 					/* FIXME: is this the right way round? */
-	cyber2000_outb(((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f), 0x3cf);
-	cyber2000_outb(0x77, 0x3ce);
-	cyber2000_outb(col, 0x3cf);
-
-
-	cyber2000_outb(0x33, 0x3ce);
-	cyber2000_outb(0x1c, 0x3cf);
-
-	cyber2000_outw(width - 1, 0xbf018);
-	cyber2000_outw(width - 1, 0xbf218);
-	cyber2000_outb(b, 0xbf01c);
-
-	return 0;
+	cyber2000_grphw(0x15, ((fetchrow >> 4) & 0xf0) | ((scr_pitch >> 8) & 0x0f));
+	cyber2000_grphw(0x77, graph_r77);
+	cyber2000_grphw(0x33, 0x1c);
+
+	cyber2000_outw(width, 0xbf018);
+	cyber2000_outw(width, 0xbf218);
+	cyber2000_outb(b,     0xbf01c);
+
+{ int j;
+ printk(KERN_DEBUG);
+ for (j = 0; j < 19; j++) printk("%2d ", j); printk("\n"KERN_DEBUG);
+ for (j = 0; j < 19; j++) printk("%02X ", crtc[j]); printk("\n"KERN_DEBUG);
+ for (j = 0; j < 18; j++) printk("%02X ", cyber2000_res[i].crtc_regs[j]);
+ printk("%02X\n", cyber2000_res[i].crtc_ofl);
+}
 }
 
 static inline void
@@ -536,13 +648,10 @@
 
 	base = var->yoffset * var->xres_virtual + var->xoffset;
 
-	cyber2000_outb(0x0c, 0x3d4);
-	cyber2000_outb(base, 0x3d5);
-	cyber2000_outb(0x0d, 0x3d4);
-	cyber2000_outb(base >> 8, 0x3d5);
+	cyber2000_crtcw(0x0c, base);
+	cyber2000_crtcw(0x0d, base >> 8);
 	/* FIXME: need the upper bits of the start offset */
-/*	cyber2000_outb(0x??, 0x3d4);
-	cyber2000_outb(base >> 16, 0x3d5);*/
+/*	cyber2000_crtcw(0x??, base >> 16);*/
 #endif
 }
 
@@ -622,6 +731,7 @@
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
+	case 15:
 	case 16:
 		*visual = FB_VISUAL_DIRECTCOLOR;
 		break;
@@ -737,6 +847,10 @@
 	}
 
 	display->var = *var;
+	display->var.activate &= ~FB_ACTIVATE_ALL;
+
+	if (var->activate & FB_ACTIVATE_ALL)
+		global_disp.var = display->var;
 
 	display->screen_base	= (char *)current_par.screen_base;
 	display->visual		= visual;
@@ -744,8 +858,6 @@
 	display->type_aux	= 0;
 	display->ypanstep	= 0;
 	display->ywrapstep	= 0;
-	display->line_length	=
-	display->next_line	= (var->xres_virtual * var->bits_per_pixel) / 8;
 	display->can_soft_blank = 1;
 	display->inverse	= 0;
 
@@ -754,18 +866,22 @@
 	case 8:
 		dispsw = &fbcon_cfb8;
 		display->dispsw_data = NULL;
+		display->next_line = var->xres_virtual;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB16
+	case 15:
 	case 16:
 		dispsw = &fbcon_cfb16;
 		display->dispsw_data = current_par.c_table.cfb16;
+		display->next_line = var->xres_virtual * 2;
 		break;
 #endif
 #ifdef FBCON_HAS_CFB24
 	case 24:
 		dispsw = &fbcon_cfb24;
 		display->dispsw_data = current_par.c_table.cfb24;
+		display->next_line = var->xres_virtual * 3;
 		break;
 #endif
 	default:
@@ -775,6 +891,8 @@
 		break;
 	}
 
+	display->line_length = display->next_line;
+
 	if (display->var.accel_flags & FB_ACCELF_TEXT &&
 	    dispsw != &fbcon_dummy)
 		display->dispsw = &fbcon_cyber_accel;
@@ -818,6 +936,7 @@
 		return -EINVAL;
 	if (y_bottom > fb_display[con].var.yres_virtual)
 		return -EINVAL;
+/*disabled until we can update the start address properly */
 return -EINVAL;
 
 	cyber2000fb_update_start(var);
@@ -947,12 +1066,26 @@
 	init_var.yres			= DEFAULT_YRES;
 	init_var.bits_per_pixel		= DEFAULT_BPP;
 
+	/*
+	 * These parameters give
+	 * 640x480, hsync 31.5kHz, vsync 60Hz
+	 */
+	init_var.left_margin		= 56;
+	init_var.right_margin		= 16;
+	init_var.upper_margin		= 34;
+	init_var.lower_margin		= 9;
+	init_var.hsync_len		= 88;
+	init_var.vsync_len		= 2;
+	init_var.pixclock		= 39722;
+
 	init_var.red.msb_right		= 0;
 	init_var.green.msb_right	= 0;
 	init_var.blue.msb_right		= 0;
 
 	switch(init_var.bits_per_pixel) {
-	case 8:
+	default:
+		init_var.bits_per_pixel = 8;
+	case 8: /* PSEUDOCOLOUR */
 		init_var.bits_per_pixel	= 8;
 		init_var.red.offset	= 0;
 		init_var.red.length	= 8;
@@ -962,7 +1095,17 @@
 		init_var.blue.length	= 8;
 		break;
 
-	case 16:
+	case 15: /* RGB555 */
+		init_var.bits_per_pixel = 15;
+		init_var.red.offset	= 10;
+		init_var.red.length	= 5;
+		init_var.green.offset	= 5;
+		init_var.green.length	= 5;
+		init_var.blue.offset	= 0;
+		init_var.blue.length	= 5;
+		break;
+
+	case 16: /* RGB565 */
 		init_var.bits_per_pixel = 16;
 		init_var.red.offset	= 11;
 		init_var.red.length	= 5;
@@ -972,7 +1115,7 @@
 		init_var.blue.length	= 5;
 		break;
 
-	case 24:
+	case 24: /* RGB888 */
 		init_var.bits_per_pixel = 24;
 		init_var.red.offset	= 16;
 		init_var.red.length	= 8;

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