patch-2.4.13 linux/drivers/video/cyber2000fb.c
Next file: linux/drivers/video/cyber2000fb.h
Previous file: linux/drivers/video/creatorfb.c
Back to the patch index
Back to the overall index
- Lines: 828
- Date:
Thu Oct 11 09:43:30 2001
- Orig file:
v2.4.12/linux/drivers/video/cyber2000fb.c
- Orig date:
Sun Sep 23 11:41:00 2001
diff -u --recursive --new-file v2.4.12/linux/drivers/video/cyber2000fb.c linux/drivers/video/cyber2000fb.c
@@ -3,6 +3,9 @@
*
* Copyright (C) 1998-2000 Russell King
*
+ * MIPS and 50xx clock support
+ * Copyright (C) 2001 Bradley D. LaRonde <brad@ltc.com>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
@@ -53,14 +56,14 @@
*/
/*#define CFB16_IS_CFB15*/
-static char *CyberRegs;
-
#include "cyber2000fb.h"
struct cfb_info {
struct fb_info fb;
struct display_switch *dispsw;
struct pci_dev *dev;
+ unsigned char *region;
+ unsigned char *regs;
signed int currcon;
int func_use_count;
u_long ref_ps;
@@ -80,19 +83,67 @@
u_char mclk_div;
};
+static char default_font_storage[40];
+static char *default_font = "Acorn8x8";
+MODULE_PARM(default_font, "s");
+MODULE_PARM_DESC(default_font, "Default font name");
+
+/*
+ * Our access methods.
+ */
+#define cyber2000fb_writel(val,reg,cfb) writel(val, (cfb)->regs + (reg))
+#define cyber2000fb_writew(val,reg,cfb) writew(val, (cfb)->regs + (reg))
+#define cyber2000fb_writeb(val,reg,cfb) writeb(val, (cfb)->regs + (reg))
+
+#define cyber2000fb_readb(reg,cfb) readb((cfb)->regs + (reg))
+
+static inline void
+cyber2000_crtcw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3d4, cfb);
+}
+
+static inline void
+cyber2000_grphw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3ce, cfb);
+}
+
+static inline unsigned int
+cyber2000_grphr(unsigned int reg, struct cfb_info *cfb)
+{
+ cyber2000fb_writeb(reg, 0x3ce, cfb);
+ return cyber2000fb_readb(0x3cf, cfb);
+}
+
+static inline void
+cyber2000_attrw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_readb(0x3da, cfb);
+ cyber2000fb_writeb(reg, 0x3c0, cfb);
+ cyber2000fb_readb(0x3c1, cfb);
+ cyber2000fb_writeb(val, 0x3c0, cfb);
+}
+
+static inline void
+cyber2000_seqw(unsigned int reg, unsigned int val, struct cfb_info *cfb)
+{
+ cyber2000fb_writew((reg & 255) | val << 8, 0x3c4, cfb);
+}
+
/* -------------------- Hardware specific routines ------------------------- */
/*
* Hardware Cyber2000 Acceleration
*/
-static void cyber2000_accel_wait(void)
+static void cyber2000_accel_wait(struct cfb_info *cfb)
{
int count = 100000;
- while (cyber2000_inb(CO_REG_CONTROL) & 0x80) {
+ while (cyber2000fb_readb(CO_REG_CONTROL, cfb) & 0x80) {
if (!count--) {
debug_printf("accel_wait timed out\n");
- cyber2000_outb(0, CO_REG_CONTROL);
+ cyber2000fb_writeb(0, CO_REG_CONTROL, cfb);
return;
}
udelay(1);
@@ -110,6 +161,7 @@
cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
+ struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
u_long src, dst;
u_int fh, fw;
@@ -142,29 +194,30 @@
src = sx + sy * var->xres_virtual;
dst = dx + dy * var->xres_virtual;
- cyber2000_accel_wait();
- cyber2000_outb(0x00, CO_REG_CONTROL);
- cyber2000_outb(0x03, CO_REG_FORE_MIX);
- cyber2000_outw(width, CO_REG_WIDTH);
+ cyber2000_accel_wait(cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
+ cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
if (var->bits_per_pixel != 24) {
- cyber2000_outl(dst, CO_REG_DEST_PTR);
- cyber2000_outl(src, CO_REG_SRC_PTR);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writel(src, CO_REG_SRC_PTR, cfb);
} else {
- cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
- cyber2000_outb(dst, CO_REG_X_PHASE);
- cyber2000_outl(src * 3, CO_REG_SRC_PTR);
+ cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
+ cyber2000fb_writel(src * 3, CO_REG_SRC_PTR, cfb);
}
- cyber2000_outw(height, CO_REG_HEIGHT);
- cyber2000_outw(cmd, CO_REG_CMD_L);
- cyber2000_outw(0x2800, CO_REG_CMD_H);
+ cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
+ cyber2000fb_writew(cmd, CO_REG_CMD_L, cfb);
+ cyber2000fb_writew(0x2800, CO_REG_CMD_H, cfb);
}
static void
cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
+ struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
struct fb_var_screeninfo *var = &p->fb_info->var;
u_long dst;
u_int fw, fh;
@@ -177,30 +230,30 @@
width = width * fw - 1;
height = height * fh - 1;
- cyber2000_accel_wait();
- cyber2000_outb(0x00, CO_REG_CONTROL);
- cyber2000_outb(0x03, CO_REG_FORE_MIX);
- cyber2000_outw(width, CO_REG_WIDTH);
- cyber2000_outw(height, CO_REG_HEIGHT);
+ cyber2000_accel_wait(cfb);
+ cyber2000fb_writeb(0x00, CO_REG_CONTROL, cfb);
+ cyber2000fb_writeb(0x03, CO_REG_FORE_MIX, cfb);
+ cyber2000fb_writew(width, CO_REG_WIDTH, cfb);
+ cyber2000fb_writew(height, CO_REG_HEIGHT, cfb);
switch (var->bits_per_pixel) {
case 15:
case 16:
bgx = ((u16 *)p->dispsw_data)[bgx];
case 8:
- cyber2000_outl(dst, CO_REG_DEST_PTR);
+ cyber2000fb_writel(dst, CO_REG_DEST_PTR, cfb);
break;
case 24:
- cyber2000_outl(dst * 3, CO_REG_DEST_PTR);
- cyber2000_outb(dst, CO_REG_X_PHASE);
+ cyber2000fb_writel(dst * 3, CO_REG_DEST_PTR, cfb);
+ cyber2000fb_writeb(dst, CO_REG_X_PHASE, cfb);
bgx = ((u32 *)p->dispsw_data)[bgx];
break;
}
- cyber2000_outl(bgx, CO_REG_FOREGROUND);
- cyber2000_outw(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L);
- cyber2000_outw(0x0800, CO_REG_CMD_H);
+ cyber2000fb_writel(bgx, CO_REG_FOREGROUND, cfb);
+ cyber2000fb_writew(CO_CMD_L_PATTERN_FGCOL, CO_REG_CMD_L, cfb);
+ cyber2000fb_writew(0x0800, CO_REG_CMD_H, cfb);
}
static void
@@ -209,7 +262,7 @@
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->putc(conp, p, c, yy, xx);
}
@@ -219,7 +272,7 @@
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->putcs(conp, p, s, count, yy, xx);
}
@@ -227,7 +280,7 @@
{
struct cfb_info *cfb = (struct cfb_info *)p->fb_info;
- cyber2000_accel_wait();
+ cyber2000_accel_wait(cfb);
cfb->dispsw->revc(p, xx, yy);
}
@@ -274,10 +327,10 @@
switch (cfb->fb.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);
+ cyber2000fb_writeb(regno, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
break;
#endif
@@ -286,18 +339,18 @@
#ifndef CFB16_IS_CFB15
if (regno < 64) {
/* write green */
- cyber2000_outb(regno << 2, 0x3c8);
- cyber2000_outb(cfb->palette[regno >> 1].red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(cfb->palette[regno >> 1].blue, 0x3c9);
+ cyber2000fb_writeb(regno << 2, 0x3c8, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno >> 1].blue, 0x3c9, cfb);
}
if (regno < 32) {
/* write red,blue */
- cyber2000_outb(regno << 3, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(cfb->palette[regno << 1].green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[regno << 1].green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
}
if (regno < 16)
@@ -308,10 +361,10 @@
case 15:
if (regno < 32) {
- cyber2000_outb(regno << 3, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno << 3, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
}
if (regno < 16)
((u16 *)cfb->fb.pseudo_palette)[regno] =
@@ -322,10 +375,10 @@
#ifdef FBCON_HAS_CFB24
case 24:
- cyber2000_outb(regno, 0x3c8);
- cyber2000_outb(red, 0x3c9);
- cyber2000_outb(green, 0x3c9);
- cyber2000_outb(blue, 0x3c9);
+ cyber2000fb_writeb(regno, 0x3c8, cfb);
+ cyber2000fb_writeb(red, 0x3c9, cfb);
+ cyber2000fb_writeb(green, 0x3c9, cfb);
+ cyber2000fb_writeb(blue, 0x3c9, cfb);
if (regno < 16)
((u32 *)cfb->fb.pseudo_palette)[regno] =
@@ -375,92 +428,92 @@
* Blank palette
*/
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
- }
-
- cyber2000_outb(0xef, 0x3c2);
- cyber2000_crtcw(0x11, 0x0b);
- cyber2000_attrw(0x11, 0x00);
-
- cyber2000_seqw(0x00, 0x01);
- cyber2000_seqw(0x01, 0x01);
- cyber2000_seqw(0x02, 0x0f);
- cyber2000_seqw(0x03, 0x00);
- cyber2000_seqw(0x04, 0x0e);
- cyber2000_seqw(0x00, 0x03);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ }
+
+ cyber2000fb_writeb(0xef, 0x3c2, cfb);
+ cyber2000_crtcw(0x11, 0x0b, cfb);
+ cyber2000_attrw(0x11, 0x00, cfb);
+
+ cyber2000_seqw(0x00, 0x01, cfb);
+ cyber2000_seqw(0x01, 0x01, cfb);
+ cyber2000_seqw(0x02, 0x0f, cfb);
+ cyber2000_seqw(0x03, 0x00, cfb);
+ cyber2000_seqw(0x04, 0x0e, cfb);
+ cyber2000_seqw(0x00, 0x03, cfb);
for (i = 0; i < sizeof(crtc_idx); i++)
- cyber2000_crtcw(crtc_idx[i], hw->crtc[i]);
+ cyber2000_crtcw(crtc_idx[i], hw->crtc[i], cfb);
for (i = 0x0a; i < 0x10; i++)
- cyber2000_crtcw(i, 0);
+ cyber2000_crtcw(i, 0, cfb);
- cyber2000_grphw(0x11, hw->crtc_ofl);
- cyber2000_grphw(0x00, 0x00);
- 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);
+ cyber2000_grphw(0x11, hw->crtc_ofl, cfb);
+ cyber2000_grphw(0x00, 0x00, cfb);
+ cyber2000_grphw(0x01, 0x00, cfb);
+ cyber2000_grphw(0x02, 0x00, cfb);
+ cyber2000_grphw(0x03, 0x00, cfb);
+ cyber2000_grphw(0x04, 0x00, cfb);
+ cyber2000_grphw(0x05, 0x60, cfb);
+ cyber2000_grphw(0x06, 0x05, cfb);
+ cyber2000_grphw(0x07, 0x0f, cfb);
+ cyber2000_grphw(0x08, 0xff, cfb);
/* Attribute controller registers */
for (i = 0; i < 16; i++)
- cyber2000_attrw(i, i);
+ cyber2000_attrw(i, i, cfb);
- cyber2000_attrw(0x10, 0x01);
- cyber2000_attrw(0x11, 0x00);
- cyber2000_attrw(0x12, 0x0f);
- cyber2000_attrw(0x13, 0x00);
- cyber2000_attrw(0x14, 0x00);
+ cyber2000_attrw(0x10, 0x01, cfb);
+ cyber2000_attrw(0x11, 0x00, cfb);
+ cyber2000_attrw(0x12, 0x0f, cfb);
+ cyber2000_attrw(0x13, 0x00, cfb);
+ cyber2000_attrw(0x14, 0x00, cfb);
/* woody: set the interlaced bit... */
/* FIXME: what about doublescan? */
- cyber2000_outb(0x11, 0x3ce);
- i = cyber2000_inb(0x3cf);
+ cyber2000fb_writeb(0x11, 0x3ce, cfb);
+ i = cyber2000fb_readb(0x3cf, cfb);
if (hw->vmode == FB_VMODE_INTERLACED)
i |= 0x20;
else
i &= ~0x20;
- cyber2000_outb(i, 0x3cf);
+ cyber2000fb_writeb(i, 0x3cf, cfb);
/* PLL registers */
- cyber2000_grphw(DCLK_MULT, hw->clock_mult);
- cyber2000_grphw(DCLK_DIV, hw->clock_div);
- cyber2000_grphw(MCLK_MULT, cfb->mclk_mult);
- cyber2000_grphw(MCLK_DIV, cfb->mclk_div);
- cyber2000_grphw(0x90, 0x01);
- cyber2000_grphw(0xb9, 0x80);
- cyber2000_grphw(0xb9, 0x00);
-
- cyber2000_outb(0x56, 0x3ce);
- i = cyber2000_inb(0x3cf);
- cyber2000_outb(i | 4, 0x3cf);
- cyber2000_outb(hw->palette_ctrl, 0x3c6);
- cyber2000_outb(i, 0x3cf);
+ cyber2000_grphw(DCLK_MULT, hw->clock_mult, cfb);
+ cyber2000_grphw(DCLK_DIV, hw->clock_div, cfb);
+ cyber2000_grphw(MCLK_MULT, cfb->mclk_mult, cfb);
+ cyber2000_grphw(MCLK_DIV, cfb->mclk_div, cfb);
+ cyber2000_grphw(0x90, 0x01, cfb);
+ cyber2000_grphw(0xb9, 0x80, cfb);
+ cyber2000_grphw(0xb9, 0x00, cfb);
+
+ cyber2000fb_writeb(0x56, 0x3ce, cfb);
+ i = cyber2000fb_readb(0x3cf, cfb);
+ cyber2000fb_writeb(i | 4, 0x3cf, cfb);
+ cyber2000fb_writeb(hw->palette_ctrl, 0x3c6, cfb);
+ cyber2000fb_writeb(i, 0x3cf, cfb);
- cyber2000_outb(0x20, 0x3c0);
- cyber2000_outb(0xff, 0x3c6);
+ cyber2000fb_writeb(0x20, 0x3c0, cfb);
+ cyber2000fb_writeb(0xff, 0x3c6, cfb);
- cyber2000_grphw(0x14, hw->fetch);
+ cyber2000_grphw(0x14, hw->fetch, cfb);
cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) |
- ((hw->pitch >> 4) & 0x30));
- cyber2000_grphw(0x77, hw->visualid);
+ ((hw->pitch >> 4) & 0x30), cfb);
+ cyber2000_grphw(0x77, hw->visualid, cfb);
/* make sure we stay in linear mode */
- cyber2000_grphw(0x33, 0x0d);
+ cyber2000_grphw(0x33, 0x0d, cfb);
/*
* Set up accelerator registers
*/
- cyber2000_outw(hw->width, CO_REG_SRC_WIDTH);
- cyber2000_outw(hw->width, CO_REG_DEST_WIDTH);
- cyber2000_outb(hw->pixformat, CO_REG_PIX_FORMAT);
+ cyber2000fb_writew(hw->width, CO_REG_SRC_WIDTH, cfb);
+ cyber2000fb_writew(hw->width, CO_REG_DEST_WIDTH, cfb);
+ cyber2000fb_writeb(hw->pixformat, CO_REG_PIX_FORMAT, cfb);
}
static inline int
@@ -475,9 +528,9 @@
if (base >= 1 << 20)
return -EINVAL;
- cyber2000_grphw(0x10, base >> 16 | 0x10);
- cyber2000_crtcw(0x0c, base >> 8);
- cyber2000_crtcw(0x0d, base);
+ cyber2000_grphw(0x10, base >> 16 | 0x10, cfb);
+ cyber2000_crtcw(0x0c, base >> 8, cfb);
+ cyber2000_crtcw(0x0d, base, cfb);
return 0;
}
@@ -623,6 +676,7 @@
const u_long ref_ps = cfb->ref_ps;
u_int div2, t_div1, best_div1, best_mult;
int best_diff;
+ int vco;
/*
* Step 1:
@@ -697,6 +751,11 @@
hw->clock_mult = best_mult - 1;
hw->clock_div = div2 << 6 | (best_div1 - 1);
+ vco = ref_ps * best_div1 / best_mult;
+ if ((ref_ps == 40690) && (vco < 5556))
+ /* Set VFSEL when VCO > 180MHz (5.556 ps). */
+ hw->clock_div |= DCLK_DIV_VFSEL;
+
return 0;
}
@@ -1057,30 +1116,30 @@
switch (blank) {
case 4: /* powerdown - both sync lines down */
- cyber2000_grphw(0x16, 0x05);
+ cyber2000_grphw(0x16, 0x05, cfb);
break;
case 3: /* hsync off */
- cyber2000_grphw(0x16, 0x01);
+ cyber2000_grphw(0x16, 0x01, cfb);
break;
case 2: /* vsync off */
- cyber2000_grphw(0x16, 0x04);
+ cyber2000_grphw(0x16, 0x04, cfb);
break;
case 1: /* soft blank */
- cyber2000_grphw(0x16, 0x00);
+ cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
- cyber2000_outb(0, 0x3c9);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
+ cyber2000fb_writeb(0, 0x3c9, cfb);
}
break;
default: /* unblank */
- cyber2000_grphw(0x16, 0x00);
+ cyber2000_grphw(0x16, 0x00, cfb);
for (i = 0; i < NR_PALETTE; i++) {
- cyber2000_outb(i, 0x3c8);
- cyber2000_outb(cfb->palette[i].red, 0x3c9);
- cyber2000_outb(cfb->palette[i].green, 0x3c9);
- cyber2000_outb(cfb->palette[i].blue, 0x3c9);
+ cyber2000fb_writeb(i, 0x3c8, cfb);
+ cyber2000fb_writeb(cfb->palette[i].red, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[i].green, 0x3c9, cfb);
+ cyber2000fb_writeb(cfb->palette[i].blue, 0x3c9, cfb);
}
break;
}
@@ -1136,8 +1195,8 @@
if (cfb->func_use_count == 1) {
int old;
- old = cyber2000_grphr(FUNC_CTL);
- cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL);
+ old = cyber2000_grphr(FUNC_CTL, cfb);
+ cyber2000_grphw(FUNC_CTL, old | FUNC_CTL_EXTREGENBL, cfb);
}
}
@@ -1149,8 +1208,8 @@
if (cfb->func_use_count == 1) {
int old;
- old = cyber2000_grphr(FUNC_CTL);
- cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL);
+ old = cyber2000_grphr(FUNC_CTL, cfb);
+ cyber2000_grphw(FUNC_CTL, old & ~FUNC_CTL_EXTREGENBL, cfb);
}
cfb->func_use_count -= 1;
@@ -1170,7 +1229,7 @@
{
if (int_cfb_info != NULL) {
info->dev = int_cfb_info->dev;
- info->regs = CyberRegs;
+ info->regs = int_cfb_info->regs;
info->fb = int_cfb_info->fb.screen_base;
info->fb_size = int_cfb_info->fb.fix.smem_len;
info->enable_extregs = cyber2000fb_enable_extregs;
@@ -1281,14 +1340,14 @@
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT);
- cfb->mclk_div = cyber2000_grphr(MCLK_DIV);
+ cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
+ cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
/*
- * x86 is simple, we just do regular outb's instead of
- * cyber2000_outb.
+ * x86 and MIPS are simple, we just do regular
+ * outb's instead of cyber2000fb_writeb.
*/
outb(0x18, 0x46e8);
outb(0x01, 0x102);
@@ -1302,16 +1361,16 @@
* initialising this card for the first time.
* FIXME: what about hotplug?
*/
- cfb->mclk_mult = cyber2000_grphr(MCLK_MULT);
- cfb->mclk_div = cyber2000_grphr(MCLK_DIV);
+ cfb->mclk_mult = cyber2000_grphr(MCLK_MULT, cfb);
+ cfb->mclk_div = cyber2000_grphr(MCLK_DIV, cfb);
}
#endif
#ifdef __arm__
- cyber2000_outb(0x18, 0x46e8);
- cyber2000_outb(0x01, 0x102);
- cyber2000_outb(0x08, 0x46e8);
- cyber2000_outb(0x33, 0x3ce);
- cyber2000_outb(0x01, 0x3cf);
+ cyber2000fb_writeb(0x18, 0x46e8, cfb);
+ cyber2000fb_writeb(0x01, 0x102, cfb);
+ cyber2000fb_writeb(0x08, 0x46e8, cfb);
+ cyber2000fb_writeb(0x33, 0x3ce, cfb);
+ cyber2000fb_writeb(0x01, 0x3cf, cfb);
/*
* MCLK on the NetWinder and the Shark is fixed at 75MHz
@@ -1324,7 +1383,7 @@
* Initialise the CyberPro
*/
for (i = 0; i < sizeof(igs_regs); i += 2)
- cyber2000_grphw(igs_regs[i], igs_regs[i+1]);
+ cyber2000_grphw(igs_regs[i], igs_regs[i+1], cfb);
if (at_boot) {
/*
@@ -1332,14 +1391,14 @@
* This should have been already initialised by the BIOS,
* but if it's garbage, claim default 1MB VRAM (woody)
*/
- cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1);
- cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2);
+ cfb->mem_ctl1 = cyber2000_grphr(MEM_CTL1, cfb);
+ cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2, cfb);
} else {
/*
* Reprogram the MEM_CTL1 and MEM_CTL2 registers
*/
- cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1);
- cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2);
+ cyber2000_grphw(MEM_CTL1, cfb->mem_ctl1, cfb);
+ cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2, cfb);
}
/*
@@ -1347,8 +1406,8 @@
* (CyberPro 5000's may be programmed to use
* an additional set of PLLs.
*/
- cyber2000_outb(0xba, 0x3ce);
- cyber2000_outb(cyber2000_inb(0x3cf) & 0x80, 0x3cf);
+ cyber2000fb_writeb(0xba, 0x3ce, cfb);
+ cyber2000fb_writeb(cyber2000fb_readb(0x3cf, cfb) & 0x80, 0x3cf, cfb);
}
static struct cfb_info * __devinit
@@ -1366,15 +1425,20 @@
cfb->currcon = -1;
cfb->dev = dev;
- cfb->ref_ps = 69842;
+
+ if (id->driver_data == FB_ACCEL_IGS_CYBER5000)
+ cfb->ref_ps = 40690; // 24.576 MHz
+ else
+ cfb->ref_ps = 69842; // 14.31818 MHz (69841?)
+
cfb->divisors[0] = 1;
cfb->divisors[1] = 2;
cfb->divisors[2] = 4;
- if (id->driver_data == FB_ACCEL_IGS_CYBER2010)
- cfb->divisors[3] = 6;
- else
+ if (id->driver_data == FB_ACCEL_IGS_CYBER2000)
cfb->divisors[3] = 8;
+ else
+ cfb->divisors[3] = 6;
strcpy(cfb->fb.fix.id, name);
@@ -1392,7 +1456,7 @@
cfb->fb.var.accel_flags = FB_ACCELF_TEXT;
strcpy(cfb->fb.modename, cfb->fb.fix.id);
- strcpy(cfb->fb.fontname, "Acorn8x8");
+ strcpy(cfb->fb.fontname, default_font);
cfb->fb.fbops = &cyber2000fb_ops;
cfb->fb.changevar = NULL;
@@ -1422,69 +1486,32 @@
}
/*
- * Map in the registers
- */
-static int __devinit
-cyberpro_map_mmio(struct cfb_info *cfb, struct pci_dev *dev)
-{
- u_long mmio_base;
-
- mmio_base = pci_resource_start(dev, 0) + MMIO_OFFSET;
-
- cfb->fb.fix.mmio_start = mmio_base;
- cfb->fb.fix.mmio_len = MMIO_SIZE;
-
- CyberRegs = ioremap(mmio_base, MMIO_SIZE);
- if (!CyberRegs) {
- printk("%s: unable to map memory mapped IO\n",
- cfb->fb.fix.id);
- return -ENOMEM;
- }
- return 0;
-}
-
-/*
- * Unmap registers
+ * Parse Cyber2000fb options. Usage:
+ * video=cyber2000:font:fontname
*/
-static void __devinit cyberpro_unmap_mmio(struct cfb_info *cfb)
+int
+cyber2000fb_setup(char *options)
{
- if (cfb && CyberRegs) {
- iounmap(CyberRegs);
- CyberRegs = NULL;
- }
-}
+ char *opt;
-/*
- * Map in screen memory
- */
-static int __devinit
-cyberpro_map_smem(struct cfb_info *cfb, struct pci_dev *dev, u_long smem_len)
-{
- u_long smem_base;
+ if (!options || !*options)
+ return 0;
- smem_base = pci_resource_start(dev, 0);
+ while ((opt = strsep(&options, ",")) != NULL) {
+ if (!*opt)
+ continue;
- cfb->fb.fix.smem_start = smem_base;
- cfb->fb.fix.smem_len = smem_len;
+ if (strncmp(opt, "font:", 5) == 0) {
+ strncpy(default_font_storage, opt + 5, sizeof(default_font_storage));
+ default_font = default_font_storage;
+ continue;
+ }
- cfb->fb.screen_base = ioremap(smem_base, smem_len);
- if (!cfb->fb.screen_base) {
- printk("%s: unable to map screen memory\n",
- cfb->fb.fix.id);
- return -ENOMEM;
+ printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", opt);
}
-
return 0;
}
-static void __devinit cyberpro_unmap_smem(struct cfb_info *cfb)
-{
- if (cfb && cfb->fb.screen_base) {
- iounmap(cfb->fb.screen_base);
- cfb->fb.screen_base = NULL;
- }
-}
-
static int __devinit
cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
@@ -1507,11 +1534,14 @@
err = -ENOMEM;
cfb = cyberpro_alloc_fb_info(dev, id, name);
if (!cfb)
- goto failed;
+ goto failed_release;
- err = cyberpro_map_mmio(cfb, dev);
- if (err)
- goto failed;
+ cfb->region = ioremap(pci_resource_start(dev, 0),
+ pci_resource_len(dev, 0));
+ if (!cfb->region)
+ goto failed_ioremap;
+
+ cfb->regs = cfb->region + MMIO_OFFSET;
cyberpro_init_hw(cfb, 1);
@@ -1521,9 +1551,15 @@
default: smem_size = 0x00100000; break;
}
- err = cyberpro_map_smem(cfb, dev, smem_size);
- if (err)
- goto failed;
+ /*
+ * Hmm, we _need_ a portable way of finding the address for
+ * the remap stuff, both for mmio and for smem.
+ */
+ cfb->fb.fix.mmio_start = pci_resource_start(dev, 0) + MMIO_OFFSET;
+ cfb->fb.fix.smem_start = pci_resource_start(dev, 0);
+ cfb->fb.fix.mmio_len = MMIO_SIZE;
+ cfb->fb.fix.smem_len = smem_size;
+ cfb->fb.screen_base = cfb->region;
if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0,
&cyber2000fb_default_mode, 8)) {
@@ -1570,11 +1606,10 @@
return 0;
failed:
- cyberpro_unmap_smem(cfb);
- cyberpro_unmap_mmio(cfb);
+ iounmap(cfb->region);
+failed_ioremap:
cyberpro_free_fb_info(cfb);
-
-release:
+failed_release:
pci_release_regions(dev);
return err;
@@ -1594,8 +1629,7 @@
printk(KERN_WARNING "%s: danger Will Robinson, "
"danger danger! Oopsen imminent!\n",
cfb->fb.fix.id);
- cyberpro_unmap_smem(cfb);
- cyberpro_unmap_mmio(cfb);
+ iounmap(cfb->region);
cyberpro_free_fb_info(cfb);
/*
@@ -1673,7 +1707,10 @@
}
#ifdef MODULE
-MODULE_LICENSE("GPL");
module_init(cyber2000fb_init);
#endif
module_exit(cyberpro_exit);
+
+MODULE_AUTHOR("Russell King");
+MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver");
+MODULE_LICENSE("GPL");
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)