diff options
Diffstat (limited to 'drivers/video/cyber2000fb.c')
-rw-r--r-- | drivers/video/cyber2000fb.c | 289 |
1 files changed, 216 insertions, 73 deletions
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index c24288124..d342304a3 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -121,7 +121,7 @@ static const struct res cyber2000_res[] = { 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 @@ static void cyber2000_init_hw(const struct res *res) 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_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx, 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 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 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 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, 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 @@ static int cyber2000fb_set_timing(struct fb_var_screeninfo *var) 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 @@ cyber2000fb_update_start(struct fb_var_screeninfo *var) 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 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, int *visual) break; #endif #ifdef FBCON_HAS_CFB16 + case 15: case 16: *visual = FB_VISUAL_DIRECTCOLOR; break; @@ -737,6 +847,10 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info } 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 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info 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 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info 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 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info 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 @@ static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con, 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 @@ cyber2000fb_init_fbinfo(void)) 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 @@ cyber2000fb_init_fbinfo(void)) 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 @@ cyber2000fb_init_fbinfo(void)) 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; |