patch-2.1.132 linux/drivers/video/imsttfb.c
Next file: linux/drivers/video/macfb.c
Previous file: linux/drivers/video/font_sun12x22.c
Back to the patch index
Back to the overall index
- Lines: 1083
- Date:
Mon Dec 21 14:48:04 1998
- Orig file:
v2.1.131/linux/drivers/video/imsttfb.c
- Orig date:
Thu Nov 19 09:56:28 1998
diff -u --recursive --new-file v2.1.131/linux/drivers/video/imsttfb.c linux/drivers/video/imsttfb.c
@@ -51,11 +51,6 @@
#define eieio() /* Enforce In-order Execution of I/O */
#endif
-enum {
- IBM = 0x00,
- TVP = 0x01
-};
-
/* TwinTurbo (Cosmo) registers */
enum {
S1SA = 0, /* 0x00 */
@@ -63,7 +58,8 @@
SP = 2, /* 0x08 */
DSA = 3, /* 0x0C */
CNT = 4, /* 0x10 */
- DP_OCTRL= 5, /* 0x14 */
+ DP_OCTL = 5, /* 0x14 */
+ CLR = 6, /* 0x18 */
BI = 8, /* 0x20 */
MBC = 9, /* 0x24 */
BLTCTL = 10, /* 0x28 */
@@ -113,7 +109,7 @@
#endif
};
-/* IBM ramdac direct registers */
+/* IBM 624 RAMDAC Direct Registers */
enum {
PADDRW = 0x00,
PDATA = 0x04,
@@ -125,7 +121,7 @@
PIDXCTL = 0x1c
};
-/* IBM ramdac indirect registers */
+/* IBM 624 RAMDAC Indirect Registers */
enum {
CLKCTL = 0x02, /* (0x01) Miscellaneous Clock Control */
SYNCCTL = 0x03, /* (0x00) Sync Control */
@@ -255,7 +251,7 @@
* used in the 2MB and 4MB cards, at least.
*/
{ BPP8, 0x00 },
- { BPP16, 0x00 },
+ { BPP16, 0x01 },
{ BPP24, 0x00 },
{ BPP32, 0x00 },
@@ -265,7 +261,7 @@
{ SYSCLKM, 0x4f },
{ SYSCLKP, 0x00 },
{ SYSCLKC, 0x00 },
- { CURSCTL, 0x02 },
+ { CURSCTL, 0x00 },
{ CURSACCTL, 0x01 },
{ CURSACATTR, 0xa8 },
{ CURS1R, 0xff },
@@ -287,24 +283,24 @@
};
static struct initvalues tvp_initregs[] __initdata = {
- { 0x6, 0x00 },
- { 0x7, 0xe4 },
- { 0xf, 0x06 },
- { 0x18, 0x80 },
- { 0x19, 0x4d },
- { 0x1a, 0x05 },
- { 0x1c, 0x00 },
- { 0x1d, 0x00 },
- { 0x1e, 0x08 },
- { 0x30, 0xff },
- { 0x31, 0xff },
- { 0x32, 0xff },
- { 0x33, 0xff },
- { 0x34, 0xff },
- { 0x35, 0xff },
- { 0x36, 0xff },
- { 0x37, 0xff },
- { 0x38, 0x00 },
+ { TVPIRICC, 0x00 },
+ { TVPIRBRC, 0xe4 },
+ { TVPIRLAC, 0x06 },
+ { TVPIRTCC, 0x80 },
+ { TVPIRMXC, 0x4d },
+ { TVPIRCLS, 0x05 },
+ { TVPIRPPG, 0x00 },
+ { TVPIRGEC, 0x00 },
+ { TVPIRMIC, 0x08 },
+ { TVPIRCKL, 0xff },
+ { TVPIRCKH, 0xff },
+ { TVPIRCRL, 0xff },
+ { TVPIRCRH, 0xff },
+ { TVPIRCGL, 0xff },
+ { TVPIRCGH, 0xff },
+ { TVPIRCBL, 0xff },
+ { TVPIRCBH, 0xff },
+ { TVPIRCKC, 0x00 },
{ TVPIRPLA, 0x00 },
{ TVPIRPPD, 0xc0 },
{ TVPIRPPD, 0xd5 },
@@ -358,13 +354,18 @@
} palette[256];
struct imstt_regvals init;
struct imstt_cursor cursor;
- volatile __u8 *frame_buffer_phys, *frame_buffer;
- volatile __u32 *dc_regs_phys, *dc_regs;
- volatile __u8 *cmap_regs_phys, *cmap_regs;
+ __u8 *frame_buffer_phys, *frame_buffer;
+ __u32 *dc_regs_phys, *dc_regs;
+ __u8 *cmap_regs_phys, *cmap_regs;
__u32 total_vram;
__u32 ramdac;
};
+enum {
+ IBM = 0,
+ TVP = 1
+};
+
#define USE_NV_MODES 1
#define INIT_BPP 8
#define INIT_XRES 640
@@ -379,6 +380,9 @@
#if defined(CONFIG_PPC)
static signed char init_vmode __initdata = -1, init_cmode __initdata = -1;
#endif
+#ifdef MODULE
+static struct fb_info_imstt *fb_info_imstt_p[FB_MAX] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+#endif
static struct imstt_regvals tvp_reg_init_2 = {
512,
@@ -619,7 +623,12 @@
lckl_p = init->lckl_p[1];
break;
case 24:
- /* ?!? */
+ tcc = 0x5e;
+ mxc = 0x5d;
+ lckl_n = 0xf1;
+ mlc = init->mlc[2];
+ lckl_p = init->lckl_p[2];
+ break;
case 32:
tcc = 0x46;
mxc = 0x5d;
@@ -666,7 +675,7 @@
set_imstt_regvals (struct fb_info_imstt *p, u_int bpp)
{
struct imstt_regvals *init = &p->init;
- __u32 ctl, pitch, byteswap, scr, line_pitch = init->pitch * (bpp >> 3);
+ __u32 ctl, pitch, byteswap, scr;
if (p->ramdac == IBM)
set_imstt_regvals_ibm(p, bpp);
@@ -682,7 +691,6 @@
* ========== ===== =====
* 8bpp 0 0
* 16bpp 0 1
- * 24bpp 1 0
* 32bpp 1 1
*/
switch (bpp) {
@@ -737,64 +745,97 @@
}
switch (p->total_vram) {
- case 0x00200000:
+ case 0x200000:
scr = 0x059d | byteswap;
break;
- case 0x00400000:
- case 0x00800000:
- pitch /= 2;
+ /* case 0x400000:
+ case 0x800000: */
+ default:
+ pitch >>= 1;
scr = 0x150dd | byteswap;
break;
}
out_le32(&p->dc_regs[SCR], scr);
out_le32(&p->dc_regs[SPR], pitch);
- out_le32(&p->dc_regs[SP], (line_pitch << 16) | line_pitch);
- out_le32(&p->dc_regs[DP_OCTRL], line_pitch);
-
out_le32(&p->dc_regs[STGCTL], ctl);
}
-static void
-set_16 (struct fb_info_imstt *p, __u8 x)
+static inline void
+set_offset (struct display *disp, struct fb_info_imstt *p)
+{
+ __u32 off = disp->var.yoffset * (disp->line_length >> 3)
+ + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
+ out_le32(&p->dc_regs[SSR], off);
+}
+
+static inline void
+set_555 (struct fb_info_imstt *p)
{
if (p->ramdac == IBM) {
p->cmap_regs[PIDXHI] = 0; eieio();
p->cmap_regs[PIDXLO] = BPP16; eieio();
- p->cmap_regs[PIDXDATA] = x; eieio();
+ p->cmap_regs[PIDXDATA] = 0x01; eieio();
} else {
- /* ?!? */
+ p->cmap_regs[TVPADDRW] = TVPIRTCC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x44; eieio();
}
}
-#define set_555(_p) set_16(_p, 0x01)
-#define set_565(_p) set_16(_p, 0x03)
+static inline void
+set_565 (struct fb_info_imstt *p)
+{
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = BPP16; eieio();
+ p->cmap_regs[PIDXDATA] = 0x03; eieio();
+ } else {
+ p->cmap_regs[TVPADDRW] = TVPIRTCC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x45; eieio();
+ }
+}
static void
imstt_set_cursor (struct fb_info_imstt *p, int on)
{
struct imstt_cursor *c = &p->cursor;
- p->cmap_regs[PIDXHI] = 0;
- if (!on) {
- p->cmap_regs[PIDXLO] = CURSCTL; eieio();
- p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ if (!on) {
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ } else {
+ p->cmap_regs[PIDXLO] = CURSXHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->x >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSXLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->x & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSYHI; eieio();
+ p->cmap_regs[PIDXDATA] = c->y >> 8; eieio();
+ p->cmap_regs[PIDXLO] = CURSYLO; eieio();
+ p->cmap_regs[PIDXDATA] = c->y & 0xff; eieio();
+ p->cmap_regs[PIDXLO] = CURSCTL; eieio();
+ p->cmap_regs[PIDXDATA] = 0x02; eieio();
+ }
} else {
- p->cmap_regs[PIDXLO] = CURSXHI; eieio();
- p->cmap_regs[PIDXDATA] = c->x >> 8; eieio();
- p->cmap_regs[PIDXLO] = CURSXLO; eieio();
- p->cmap_regs[PIDXDATA] = c->x & 0xff; eieio();
- p->cmap_regs[PIDXLO] = CURSYHI; eieio();
- p->cmap_regs[PIDXDATA] = c->y >> 8; eieio();
- p->cmap_regs[PIDXLO] = CURSYLO; eieio();
- p->cmap_regs[PIDXDATA] = c->y & 0xff; eieio();
- p->cmap_regs[PIDXLO] = CURSCTL; eieio();
- p->cmap_regs[PIDXDATA] = 0x02; eieio();
+ if (!on) {
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x00; eieio();
+ } else {
+ __u16 x = c->x + 0x40, y = c->y + 0x40;
+
+ p->cmap_regs[TVPCXPOH] = x >> 8; eieio();
+ p->cmap_regs[TVPCXPOL] = x & 0xff; eieio();
+ p->cmap_regs[TVPCYPOH] = y >> 8; eieio();
+ p->cmap_regs[TVPCYPOL] = y & 0xff; eieio();
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] = 0x02; eieio();
+ }
}
}
static void
-imsttfb_cursor (struct display *disp, int mode, int x, int y)
+imsttfbcon_cursor (struct display *disp, int mode, int x, int y)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
struct imstt_cursor *c = &p->cursor;
@@ -827,11 +868,12 @@
}
static int
-imsttfb_set_font (struct display *disp, int width, int height)
+imsttfbcon_set_font (struct display *disp, int width, int height)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
struct imstt_cursor *c = &p->cursor;
u_int x, y;
+ __u8 fgc;
if (width > 32 || height > 32)
return -EINVAL;
@@ -839,17 +881,68 @@
c->height = height;
c->width = width;
- p->cmap_regs[PIDXHI] = 1; eieio();
- for (x = 0; x < 0x100; x++) {
- p->cmap_regs[PIDXLO] = x; eieio();
- p->cmap_regs[PIDXDATA] = 0x00; eieio();
- }
- p->cmap_regs[PIDXHI] = 1; eieio();
- for (y = 0; y < height; y++)
- for (x = 0; x < width >> 2; x++) {
- p->cmap_regs[PIDXLO] = x + y * 8; eieio();
- p->cmap_regs[PIDXDATA] = 0xff; eieio();
+ fgc = ~attr_bgcol_ec(disp, disp->conp);
+
+ if (p->ramdac == IBM) {
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (x = 0; x < 0x100; x++) {
+ p->cmap_regs[PIDXLO] = x; eieio();
+ p->cmap_regs[PIDXDATA] = 0x00; eieio();
+ }
+ p->cmap_regs[PIDXHI] = 1; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 2; x++) {
+ p->cmap_regs[PIDXLO] = x + y * 8; eieio();
+ p->cmap_regs[PIDXDATA] = 0xff; eieio();
+ }
+ p->cmap_regs[PIDXHI] = 0; eieio();
+ p->cmap_regs[PIDXLO] = CURS1R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS1G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS1B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS2B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3R; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3G; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ p->cmap_regs[PIDXLO] = CURS3B; eieio();
+ p->cmap_regs[PIDXDATA] = fgc; eieio();
+ } else {
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] &= 0x03; eieio();
+ p->cmap_regs[TVPADDRW] = 0; eieio();
+ for (x = 0; x < 0x200; x++) {
+ p->cmap_regs[TVPCRDAT] = 0x00; eieio();
}
+ for (x = 0; x < 0x200; x++) {
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] &= 0x03; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 3; x++) {
+ p->cmap_regs[TVPADDRW] = x + y * 8; eieio();
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPADDRW] = TVPIRICC; eieio();
+ p->cmap_regs[TVPIDATA] |= 0x08; eieio();
+ for (y = 0; y < height; y++)
+ for (x = 0; x < width >> 3; x++) {
+ p->cmap_regs[TVPADDRW] = x + y * 8; eieio();
+ p->cmap_regs[TVPCRDAT] = 0xff; eieio();
+ }
+ p->cmap_regs[TVPCADRW] = 0x00; eieio();
+ for (x = 0; x < 12; x++) {
+ p->cmap_regs[TVPCDATA] = fgc; eieio();
+ }
+ }
return 1;
}
@@ -879,7 +972,7 @@
{
struct imstt_cursor *c = &p->cursor;
- imsttfb_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
+ imsttfbcon_set_font(&p->disp, fontwidth(&p->disp), fontheight(&p->disp));
c->enable = 1;
c->on = 1;
@@ -898,75 +991,152 @@
}
static void
-imsttfb_rectcopy (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
- __u32 Bpp = disp->var.bits_per_pixel >> 3,
- line_pitch = disp->line_length,
- fb_offset_old, fb_offset_new;
+ __u32 Bpp, line_pitch,
+ fb_offset_old, fb_offset_new,
+ sp, dp_octl, cnt, bltctl;
- fb_offset_old = sy * line_pitch + sx * Bpp;
- fb_offset_new = dy * line_pitch + dx * Bpp;
+ Bpp = disp->var.bits_per_pixel >> 3,
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
- out_le32(&p->dc_regs[CNT], ((height - 1) << 16) | (width * Bpp - 1));
+ sy *= fontheight(disp);
+ sx *= fontwidth(disp);
+ sx *= Bpp;
+ dy *= fontheight(disp);
+ dx *= fontwidth(disp);
+ dx *= Bpp;
+ height *= fontheight(disp);
+ height--;
+ width *= fontwidth(disp);
+ width *= Bpp;
+ width--;
+
+ line_pitch = disp->line_length;
+ bltctl = 0x05;
+ sp = line_pitch << 16;
+ cnt = height << 16;
+
+ if (sy < dy) {
+ sy += height;
+ dy += height;
+ sp |= -(line_pitch) & 0xffff;
+ dp_octl = -(line_pitch) & 0xffff;
+ } else {
+ sp |= line_pitch;
+ dp_octl = line_pitch;
+ }
+ if (sx < dx) {
+ sx += width;
+ dx += width;
+ bltctl |= 0x80;
+ cnt |= -(width) & 0xffff;
+ } else {
+ cnt |= width;
+ }
+ fb_offset_old = sy * line_pitch + sx;
+ fb_offset_new = dy * line_pitch + dx;
+
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
out_le32(&p->dc_regs[S1SA], fb_offset_old);
- /* out_le32(&p->dc_regs[S2SA], fb_offset_new); */
+ out_le32(&p->dc_regs[SP], sp);
out_le32(&p->dc_regs[DSA], fb_offset_new);
- out_le32(&p->dc_regs[BLTCTL], 0xc0000005);
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x80);
- while (in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+ out_le32(&p->dc_regs[CNT], cnt);
+ out_le32(&p->dc_regs[DP_OCTL], dp_octl);
+ out_le32(&p->dc_regs[BLTCTL], bltctl);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
}
static void
-imsttfbcon_bmove (struct display *disp, int sy, int sx, int dy, int dx, int height, int width)
+imsttfbcon_clear (struct vc_data *conp, struct display *disp,
+ int sy, int sx, int height, int width)
{
- /* XXX .. */
- if (sy < dy || (sy == dy && sx < dx)) {
- switch (disp->var.bits_per_pixel) {
- case 8: fbcon_cfb8_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 16: fbcon_cfb16_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 24: fbcon_cfb24_bmove(disp, sy, sx, dy, dx, height, width); break;
- case 32: fbcon_cfb32_bmove(disp, sy, sx, dy, dx, height, width); break;
- }
- return;
- }
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ __u32 Bpp, line_pitch, bgc;
+
+ bgc = attr_bgcol_ec(disp, conp);
+ bgc |= (bgc << 8);
+ bgc |= (bgc << 16);
+
+ Bpp = disp->var.bits_per_pixel >> 3,
+ line_pitch = disp->line_length;
sy *= fontheight(disp);
+ sy *= line_pitch;
sx *= fontwidth(disp);
- dy *= fontheight(disp);
- dx *= fontwidth(disp);
+ sx *= Bpp;
height *= fontheight(disp);
+ height--;
width *= fontwidth(disp);
+ width *= Bpp;
+ width--;
+
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ out_le32(&p->dc_regs[DSA], sy + sx);
+ out_le32(&p->dc_regs[CNT], (height << 16) | width);
+ out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+ out_le32(&p->dc_regs[BI], 0xffffffff);
+ out_le32(&p->dc_regs[MBC], 0xffffffff);
+ out_le32(&p->dc_regs[CLR], bgc);
+ out_le32(&p->dc_regs[BLTCTL], 0x200000);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
+}
+
+static void
+imsttfbcon_revc (struct display *disp, int sx, int sy)
+{
+ struct fb_info_imstt *p = (struct fb_info_imstt *)disp->fb_info;
+ __u32 Bpp, line_pitch, height, width;
+
+ Bpp = disp->var.bits_per_pixel >> 3,
+ line_pitch = disp->line_length;
- imsttfb_rectcopy(disp, sy, sx, dy, dx, height, width);
+ height = fontheight(disp);
+ width = fontwidth(disp) * Bpp;
+ sy *= height;
+ sy *= line_pitch;
+ sx *= width;
+ height--;
+ width--;
+
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ out_le32(&p->dc_regs[DSA], sy + sx);
+ out_le32(&p->dc_regs[S1SA], sy + sx);
+ out_le32(&p->dc_regs[CNT], (height << 16) | width);
+ out_le32(&p->dc_regs[DP_OCTL], line_pitch);
+ out_le32(&p->dc_regs[SP], line_pitch);
+ out_le32(&p->dc_regs[BLTCTL], 0x40005);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x80);
+ while(in_le32(&p->dc_regs[SSTATUS]) & 0x40);
}
#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_imstt8 = {
- fbcon_cfb8_setup, imsttfbcon_bmove, fbcon_cfb8_clear, fbcon_cfb8_putc,
- fbcon_cfb8_putcs, fbcon_cfb8_revc, NULL, NULL, fbcon_cfb8_clear_margins,
+ fbcon_cfb8_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb8_putc,
+ fbcon_cfb8_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb8_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB16
static struct display_switch fbcon_imstt16 = {
- fbcon_cfb16_setup, imsttfbcon_bmove, fbcon_cfb16_clear, fbcon_cfb16_putc,
- fbcon_cfb16_putcs, fbcon_cfb16_revc, NULL, NULL, fbcon_cfb16_clear_margins,
+ fbcon_cfb16_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb16_putc,
+ fbcon_cfb16_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb16_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB24
static struct display_switch fbcon_imstt24 = {
- fbcon_cfb24_setup, imsttfbcon_bmove, fbcon_cfb24_clear, fbcon_cfb24_putc,
- fbcon_cfb24_putcs, fbcon_cfb24_revc, NULL, NULL, fbcon_cfb24_clear_margins,
+ fbcon_cfb24_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb24_putc,
+ fbcon_cfb24_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb24_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
#ifdef FBCON_HAS_CFB32
static struct display_switch fbcon_imstt32 = {
- fbcon_cfb32_setup, imsttfbcon_bmove, fbcon_cfb32_clear, fbcon_cfb32_putc,
- fbcon_cfb32_putcs, fbcon_cfb32_revc, NULL, NULL, fbcon_cfb32_clear_margins,
+ fbcon_cfb32_setup, imsttfbcon_bmove, imsttfbcon_clear, fbcon_cfb32_putc,
+ fbcon_cfb32_putcs, imsttfbcon_revc, imsttfbcon_cursor, imsttfbcon_set_font, fbcon_cfb32_clear_margins,
FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
@@ -1049,11 +1219,12 @@
p->palette[regno].blue = blue;
/* PADDRW/PDATA are the same as TVPPADDRW/TVPPDATA */
- if (bpp == 16 && p->ramdac == TVP && fb_display[currcon].var.green.length == 5) {
- p->cmap_regs[PADDRW] = regno << 3; eieio();
- } else {
- p->cmap_regs[PADDRW] = regno; eieio();
- }
+ if (0 && bpp == 16) /* screws up X */
+ p->cmap_regs[PADDRW] = regno << 3;
+ else
+ p->cmap_regs[PADDRW] = regno;
+ eieio();
+
p->cmap_regs[PDATA] = red; eieio();
p->cmap_regs[PDATA] = green; eieio();
p->cmap_regs[PDATA] = blue; eieio();
@@ -1129,10 +1300,13 @@
}
static void
-set_disp (struct display *disp, struct fb_info_imstt *p)
+set_dispsw (struct display *disp, struct fb_info_imstt *p)
{
u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+ if (disp->conp && disp->conp->vc_sw && disp->conp->vc_sw->con_cursor)
+ disp->conp->vc_sw->con_cursor(disp->conp, CM_ERASE);
+
p->dispsw = fbcon_dummy;
disp->dispsw = &p->dispsw;
disp->dispsw_data = 0;
@@ -1150,7 +1324,7 @@
p->dispsw = accel ? fbcon_imstt8 : fbcon_cfb8;
#endif
break;
- case 16: /* RGB 555 */
+ case 16: /* RGB 555 or 565 */
if (disp->var.green.length != 6)
disp->var.red.offset = 10;
disp->var.red.length = 5;
@@ -1196,11 +1370,25 @@
break;
}
- if (p->ramdac == IBM) {
- p->dispsw.cursor = imsttfb_cursor;
- p->dispsw.set_font = imsttfb_set_font;
+ if (accel && p->ramdac != IBM) {
+ p->dispsw.cursor = 0;
+ p->dispsw.set_font = 0;
}
+#ifdef CONFIG_FB_COMPAT_XPMAC
+ set_display_info(disp);
+#endif
+}
+
+static void
+set_disp (struct display *disp, struct fb_info_imstt *p)
+{
+ u_int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+ disp->fb_info = &p->info;
+
+ set_dispsw(disp, p);
+
disp->visual = disp->var.bits_per_pixel == 8 ? FB_VISUAL_PSEUDOCOLOR
: FB_VISUAL_DIRECTCOLOR;
disp->screen_base = (__u8 *)p->frame_buffer;
@@ -1222,8 +1410,6 @@
}
} else {
disp->scrollmode = SCROLL_YREDRAW;
- disp->var.yoffset = disp->var.xoffset = 0;
- out_le32(&p->dc_regs[SSR], 0);
}
disp->var.activate = 0;
@@ -1237,10 +1423,6 @@
disp->var.left_margin = disp->var.right_margin = 16;
disp->var.upper_margin = disp->var.lower_margin = 16;
disp->var.hsync_len = disp->var.vsync_len = 8;
-
-#ifdef CONFIG_FB_COMPAT_XPMAC
- set_display_info(disp);
-#endif
}
static int
@@ -1248,7 +1430,7 @@
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp;
- u_int oldbpp, oldxres, oldyres, oldgreenlen;
+ u_int oldbpp, oldxres, oldyres, oldgreenlen, oldaccel;
disp = &fb_display[con];
@@ -1273,6 +1455,7 @@
oldxres = disp->var.xres;
oldyres = disp->var.yres;
oldgreenlen = disp->var.green.length;
+ oldaccel = disp->var.accel_flags;
disp->var.bits_per_pixel = var->bits_per_pixel;
disp->var.xres = var->xres;
@@ -1306,6 +1489,7 @@
return err;
do_install_cmap(con, info);
}
+ *var = disp->var;
return 0;
}
@@ -1315,7 +1499,6 @@
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp = &fb_display[con];
- __u32 off;
if (var->xoffset + disp->var.xres > disp->var.xres_virtual
|| var->yoffset + disp->var.yres > disp->var.yres_virtual)
@@ -1323,11 +1506,8 @@
disp->var.xoffset = var->xoffset;
disp->var.yoffset = var->yoffset;
- if (con == currcon) {
- off = var->yoffset * (disp->line_length >> 3)
- + ((var->xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
- }
+ if (con == currcon)
+ set_offset(disp, p);
return 0;
}
@@ -1377,48 +1557,48 @@
u_long arg, int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
- __u8 init[2];
+ __u8 idx[2];
__u32 reg[2];
switch (cmd) {
case FBIMSTT_SETREG:
- if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
out_le32(&p->dc_regs[reg[0]], reg[1]);
return 0;
case FBIMSTT_GETREG:
- if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x40000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
reg[1] = in_le32(&p->dc_regs[reg[0]]);
if (copy_to_user((void *)(arg + 4), ®[1], 4))
return -EFAULT;
return 0;
case FBIMSTT_SETCMAPREG:
- if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 8) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
out_le32(&((u_int *)p->cmap_regs)[reg[0]], reg[1]);
return 0;
case FBIMSTT_GETCMAPREG:
- if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x17c0000 - sizeof(reg[0])) / sizeof(reg[0]))
+ if (copy_from_user(reg, (void *)arg, 4) || reg[0] > (0x1000 - sizeof(reg[0])) / sizeof(reg[0]))
return -EFAULT;
reg[1] = in_le32(&((u_int *)p->cmap_regs)[reg[0]]);
if (copy_to_user((void *)(arg + 4), ®[1], 4))
return -EFAULT;
return 0;
case FBIMSTT_SETIDXREG:
- if (copy_from_user(init, (void *)arg, 2))
+ if (copy_from_user(idx, (void *)arg, 2))
return -EFAULT;
p->cmap_regs[PIDXHI] = 0; eieio();
- p->cmap_regs[PIDXLO] = init[0]; eieio();
- p->cmap_regs[PIDXDATA] = init[1]; eieio();
+ p->cmap_regs[PIDXLO] = idx[0]; eieio();
+ p->cmap_regs[PIDXDATA] = idx[1]; eieio();
return 0;
case FBIMSTT_GETIDXREG:
- if (copy_from_user(init, (void *)arg, 1))
+ if (copy_from_user(idx, (void *)arg, 1))
return -EFAULT;
p->cmap_regs[PIDXHI] = 0; eieio();
- p->cmap_regs[PIDXLO] = init[0]; eieio();
- init[1] = p->cmap_regs[PIDXDATA];
- if (copy_to_user((void *)(arg + 1), &init[1], 1))
+ p->cmap_regs[PIDXLO] = idx[0]; eieio();
+ idx[1] = p->cmap_regs[PIDXDATA];
+ if (copy_to_user((void *)(arg + 1), &idx[1], 1))
return -EFAULT;
return 0;
default:
@@ -1443,21 +1623,21 @@
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *old = &fb_display[currcon], *new = &fb_display[con];
- __u32 off;
if (old->cmap.len)
fb_get_cmap(&old->cmap, 1, imsttfb_getcolreg, info);
-
- if (p->ramdac == IBM)
- imsttfb_cursor(old, CM_ERASE, p->cursor.x, p->cursor.y);
+
+ if (old->conp && old->conp->vc_sw && old->conp->vc_sw->con_cursor)
+ old->conp->vc_sw->con_cursor(old->conp, CM_ERASE);
currcon = con;
if (old->var.xres != new->var.xres
|| old->var.yres != new->var.yres
|| old->var.bits_per_pixel != new->var.bits_per_pixel
- || old->var.green.length != new->var.green.length) {
- set_disp(new, p);
+ || old->var.green.length != new->var.green.length
+ || old->var.accel_flags != new->var.accel_flags) {
+ set_dispsw(new, p);
if (!compute_imstt_regvals(p, new->var.xres, new->var.yres))
return -1;
if (new->var.bits_per_pixel == 16) {
@@ -1468,53 +1648,28 @@
}
set_imstt_regvals(p, new->var.bits_per_pixel);
}
- if (old->var.yoffset != new->var.yoffset || old->var.xoffset != new->var.xoffset) {
- off = new->var.yoffset * (new->line_length >> 3)
- + ((new->var.xoffset * (new->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
- }
+ set_offset(new, p);
+
+ imsttfbcon_set_font(new, fontwidth(new), fontheight(new));
do_install_cmap(con, info);
return 0;
}
-static inline void
-imsttfb_rectfill (struct display *disp, u_int sy, u_int sx, u_int height, u_int width, __u32 bgx)
-{
- memset(disp->screen_base + sy + sx, bgx, height * width * (disp->var.bits_per_pixel >> 3));
-}
-
static int
imsttfbcon_updatevar (int con, struct fb_info *info)
{
struct fb_info_imstt *p = (struct fb_info_imstt *)info;
struct display *disp = &fb_display[con];
- struct vc_data *conp = disp->conp;
- __u32 off, yres, yoffset, sy, height;
if (con != currcon)
goto out;
- yres = disp->var.yres;
- yoffset = disp->var.yoffset;
- sy = (conp->vc_rows + disp->yscroll) * fontheight(disp);
- height = yres - conp->vc_rows * fontheight(disp);
-
- if (height && (yoffset + yres > sy)) {
- __u32 bgx = attr_bgcol_ec(disp, conp);
-
- if (sy + height > disp->var.yres_virtual)
- printk("updatevar: %u + %u > %u\n", sy, height, disp->var.yres_virtual);
- imsttfb_rectfill(disp, sy, disp->var.xoffset, height, disp->var.xres, bgx);
- }
-
- if (p->ramdac == IBM && (yoffset + yres <= sy))
- imsttfb_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
+ if (p->ramdac == IBM)
+ imsttfbcon_cursor(disp, CM_ERASE, p->cursor.x, p->cursor.y);
- off = disp->var.yoffset * (disp->line_length >> 3)
- + ((disp->var.xoffset * (disp->var.bits_per_pixel >> 3)) >> 3);
- out_le32(&p->dc_regs[SSR], off);
+ set_offset(disp, p);
out:
return 0;
@@ -1581,9 +1736,9 @@
tmp = in_le32(&p->dc_regs[PRC]);
if (p->ramdac == IBM)
- p->total_vram = (tmp & 0x0004) ? 0x00400000 : 0x00200000;
+ p->total_vram = (tmp & 0x0004) ? 0x400000 : 0x200000;
else
- p->total_vram = 0x00800000;
+ p->total_vram = 0x800000;
ip = (__u32 *)p->frame_buffer;
end = (__u32 *)(p->frame_buffer + p->total_vram);
@@ -1660,7 +1815,7 @@
p->disp.var.accel_flags = noaccel ? 0 : FB_ACCELF_TEXT;
set_disp(&p->disp, p);
- if (p->ramdac == IBM)
+ if (!noaccel && p->ramdac == IBM)
imstt_cursor_init(p);
if (p->disp.var.green.length == 6)
set_565(p);
@@ -1693,64 +1848,65 @@
return;
}
+ i = GET_FB_IDX(p->info.node);
tmp = (in_le32(&p->dc_regs[SSTATUS]) & 0x0f00) >> 8;
- printk("fb%d: %s frame buffer; %uMB vram; chip version %u\n",
- GET_FB_IDX(p->info.node), p->fix.id, p->total_vram >> 20, tmp);
+ printk("fb%u: %s frame buffer; %uMB vram; chip version %u\n",
+ i, p->fix.id, p->total_vram >> 20, tmp);
+#ifdef MODULE
+ fb_info_imstt_p[i] = p;
+#endif
#ifdef CONFIG_FB_COMPAT_XPMAC
strncpy(display_info.name, "IMS,tt128mb", sizeof(display_info.name));
display_info.fb_address = (__u32)p->frame_buffer_phys;
display_info.cmap_adr_address = (__u32)&p->cmap_regs_phys[PADDRW];
display_info.cmap_data_address = (__u32)&p->cmap_regs_phys[PDATA];
display_info.disp_reg_address = (__u32)p->dc_regs_phys;
- set_display_info(&p->disp);
if (!console_fb_info)
console_fb_info = &p->info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
}
-#if defined(CONFIG_FB_OF)
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
__initfunc(void
imsttfb_of_init(struct device_node *dp))
{
struct fb_info_imstt *p;
int i;
- __u32 addr, size = 0;
+ __u32 addr = 0;
__u8 bus, devfn;
__u16 cmd;
for (i = 0; i < dp->n_addrs; i++) {
- if (dp->addrs[i].size >= 0x02000000) {
+ if (dp->addrs[i].size >= 0x02000000)
addr = dp->addrs[i].address;
- size = dp->addrs[i].size;
- }
}
- if (!size)
+ if (!addr)
return;
+ if (!pci_device_loc(dp, &bus, &devfn)) {
+ if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd) && !(cmd & PCI_COMMAND_MEMORY)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
+ }
+ }
+
p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
if (!p)
return;
-
memset(p, 0, sizeof(struct fb_info_imstt));
- p->frame_buffer_phys = (__u8 *)addr;
- p->frame_buffer = (__u8 *)ioremap(addr, size);
- p->dc_regs_phys = (__u32 *)(p->frame_buffer_phys + 0x00800000);
- p->dc_regs = (__u32 *)(p->frame_buffer + 0x00800000);
- p->cmap_regs_phys = (__u8 *)(p->frame_buffer_phys + 0x00840000);
- p->cmap_regs = (__u8 *)(p->frame_buffer + 0x00840000);
- if (dp->name[11] == '8')
+ if (dp->name[11] == '8' || (dp->name[6] == '3' && dp->name[7] == 'd'))
p->ramdac = TVP;
else
p->ramdac = IBM;
- if (!pci_device_loc(dp, &bus, &devfn)) {
- if (!pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd)) {
- cmd |= PCI_COMMAND_MEMORY;
- pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
- }
- }
+ p->frame_buffer_phys = (__u8 *)addr;
+ p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+ p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+ p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+ p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+ p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
init_imstt(p);
}
@@ -1759,11 +1915,60 @@
__initfunc(void
imsttfb_init(void))
{
-#if !defined(CONFIG_FB_OF)
- /* ... */
-#endif
+#if defined(CONFIG_FB_OF) && !defined(MODULE)
+ /* We don't want to be called like this. */
+ /* We rely on Open Firmware (offb) instead. */
+#elif defined(CONFIG_PCI)
+ struct pci_dev *pdev;
+ struct fb_info_imstt *p;
+ __u32 addr;
+ __u16 cmd;
+
+ for (pdev = pci_devices; pdev; pdev = pdev->next) {
+ if (!(((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ && (pdev->vendor == PCI_VENDOR_ID_IMS)))
+ continue;
+
+ pci_read_config_word(pdev, PCI_COMMAND, &cmd);
+ if (!(cmd & PCI_COMMAND_MEMORY)) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pci_write_config_word(pdev, PCI_COMMAND, cmd);
+ }
+
+ addr = pdev->base_address[0] & PCI_BASE_ADDRESS_MEM_MASK;
+ if (!addr)
+ continue;
+
+ p = kmalloc(sizeof(struct fb_info_imstt), GFP_ATOMIC);
+ if (!p)
+ return;
+ memset(p, 0, sizeof(struct fb_info_imstt));
+
+ printk("imsttfb: device=%04x\n", pdev->device);
+
+ switch (pdev->device) {
+ case 0x9128: /* IMS,tt128mbA */
+ p->ramdac = IBM;
+ break;
+ case 0x9135: /* IMS,tt3d */
+ default:
+ p->ramdac = TVP;
+ break;
+ }
+
+ p->frame_buffer_phys = (__u8 *)addr;
+ p->frame_buffer = (__u8 *)ioremap(addr, p->ramdac == IBM ? 0x400000 : 0x800000);
+ p->dc_regs_phys = (__u32 *)(addr + 0x800000);
+ p->dc_regs = (__u32 *)ioremap(addr + 0x800000, 0x1000);
+ p->cmap_regs_phys = (__u8 *)(addr + 0x840000);
+ p->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
+
+ init_imstt(p);
+ }
+#endif /* CONFIG_PCI */
}
+#ifndef MODULE
__initfunc(void
imsttfb_setup(char *options, int *ints))
{
@@ -1816,3 +2021,42 @@
#endif
}
}
+
+#else /* MODULE */
+
+int
+init_module (void)
+{
+ struct fb_info_imstt *p;
+ __u32 i;
+
+ imsttfb_init();
+
+ for (i = 0; i < FB_MAX; i++) {
+ p = fb_info_imstt_p[i];
+ if (p)
+ return 0;
+ }
+
+ return -ENXIO;
+}
+
+void
+cleanup_module (void)
+{
+ struct fb_info_imstt *p;
+ __u32 i;
+
+ for (i = 0; i < FB_MAX; i++) {
+ p = fb_info_imstt_p[i];
+ if (!p)
+ continue;
+ iounmap(p->cmap_regs);
+ iounmap(p->dc_regs);
+ iounmap(p->frame_buffer);
+ kfree(p);
+ }
+}
+
+#include "macmodes.c"
+#endif /* MODULE */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov