summaryrefslogtreecommitdiffstats
path: root/drivers/video/atyfb.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
committerRalf Baechle <ralf@linux-mips.org>1999-01-04 16:03:48 +0000
commit78c388aed2b7184182c08428db1de6c872d815f5 (patch)
tree4b2003b1b4ceb241a17faa995da8dd1004bb8e45 /drivers/video/atyfb.c
parenteb7a5bf93aaa4be1d7c6181100ab7639e74d67f7 (diff)
Merge with Linux 2.1.131 and more MIPS goodies.
(Did I mention that CVS is buggy ...)
Diffstat (limited to 'drivers/video/atyfb.c')
-rw-r--r--drivers/video/atyfb.c1188
1 files changed, 773 insertions, 415 deletions
diff --git a/drivers/video/atyfb.c b/drivers/video/atyfb.c
index 7d271bc29..e3f1b1d8d 100644
--- a/drivers/video/atyfb.c
+++ b/drivers/video/atyfb.c
@@ -1,9 +1,9 @@
-/*
+/* $Id: atyfb.c,v 1.90 1998/11/20 12:27:03 geert Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
- * Copyright (C) 1997-1998 Geert Uytterhoeven
- * Copyright (C) 1998 Bernd Harries
- * Copyright (C) 1998 Eddie C. Dost
+ * Copyright (C) 1997-1998 Geert Uytterhoeven
+ * Copyright (C) 1998 Bernd Harries
+ * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
*
* This driver is partly based on the PowerMac console driver:
*
@@ -26,15 +26,12 @@
TODO:
- (ecd):
-
- - fix initialization of cursor timer.
-
- - add code to support cursor on all cards and all ramdacs.
+ - cursor support on all cards and all ramdacs.
+ - cursor parameters controlable via ioctl()s.
+ - guess PLL and MCLK based on the original PLL register values initialized
+ by the BIOS or Open Firmware (if they are initialized).
- - make cursor parameters controllable via ioctl()s.
-
- (Anyone to help with all this?)
+ (Anyone to help with this?)
******************************************************************************/
@@ -65,29 +62,33 @@
#include <asm/io.h>
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
#include <asm/prom.h>
#include <asm/pci-bridge.h>
-#include "macmodes.h"
+#include <video/macmodes.h>
#endif
#ifdef __sparc__
#include <asm/pbm.h>
+#include <asm/fbio.h>
+#include <asm/uaccess.h>
#endif
+#include <video/fbcon.h>
+#include <video/fbcon-cfb8.h>
+#include <video/fbcon-cfb16.h>
+#include <video/fbcon-cfb24.h>
+#include <video/fbcon-cfb32.h>
+
#include "aty.h"
-#include "fbcon.h"
-#include "fbcon-cfb8.h"
-#include "fbcon-cfb16.h"
-#include "fbcon-cfb24.h"
-#include "fbcon-cfb32.h"
-#define GUI_RESERVE 0x00001000
+/*
+ * Debug flags.
+ */
+#undef DEBUG
-#define CLASS_GX 1
-#define CLASS_CT 2
-#define CLASS_VT 3
-#define CLASS_GT 4
+
+#define GUI_RESERVE 0x00001000
#ifndef __powerpc__
@@ -166,6 +167,7 @@ struct pci_mmap_map {
};
#define DEFAULT_CURSOR_BLINK_RATE (20)
+#define CURSOR_DRAW_DELAY (2)
struct aty_cursor {
int enable;
@@ -179,6 +181,7 @@ struct aty_cursor {
u32 color[2];
u8 bits[8][64];
u8 mask[8][64];
+ u8 *ram;
struct timer_list *timer;
};
@@ -188,8 +191,6 @@ struct fb_info_aty {
unsigned long ati_regbase;
unsigned long frame_buffer_phys;
unsigned long frame_buffer;
- struct display disp;
- struct display_switch dispsw;
struct pci_mmap_map *mmap_map;
struct aty_cursor *cursor;
struct aty_cmap_regs *aty_cmap_regs;
@@ -208,6 +209,19 @@ struct fb_info_aty {
u8 dac_type;
u8 clk_type;
u8 mem_refresh_rate;
+ struct display disp;
+ struct display_switch dispsw;
+ union {
+#ifdef FBCON_HAS_CFB16
+ u16 cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB24
+ u32 cfb24[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u32 cfb32[16];
+#endif
+ } fbcon_cmap;
#ifdef __sparc__
u8 open;
u8 mmaped;
@@ -299,6 +313,7 @@ static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
*/
static int aty_init(struct fb_info_aty *info, const char *name);
+static struct aty_cursor *aty_init_cursor(struct fb_info_aty *fb);
#ifdef CONFIG_ATARI
static int store_video_par(char *videopar, unsigned char m64_num);
static char *strtoke(char *s, const char *ct);
@@ -309,6 +324,9 @@ static void init_engine(const struct atyfb_par *par,
const struct fb_info_aty *info);
static void aty_st_514(int offset, u8 val, const struct fb_info_aty *info);
static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info);
+#if defined(__sparc__) || defined(DEBUG)
+static u8 aty_ld_pll(int offset, const struct fb_info_aty *info);
+#endif
static void aty_set_crtc(const struct fb_info_aty *info,
const struct crtc *crtc);
static int aty_var_to_crtc(const struct fb_info_aty *info,
@@ -319,22 +337,17 @@ static int aty_crtc_to_var(const struct crtc *crtc,
struct fb_var_screeninfo *var);
static void aty_set_pll_gx(const struct fb_info_aty *info,
const struct pll_gx *pll);
-static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
- struct pll_gx *pll);
-static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
- struct pll_gx *pll);
-static int aty_pll_gx_to_var(const struct pll_gx *pll,
- struct fb_var_screeninfo *var);
+static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll);
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll);
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per);
static void aty_set_pll_ct(const struct fb_info_aty *info,
const struct pll_ct *pll);
static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
u8 mclk_post_div, u8 vclk_fb_div, u8 vclk_post_div,
u8 bpp, struct pll_ct *pll);
-static int aty_var_to_pll_ct(const struct fb_info_aty *info,
- const struct fb_var_screeninfo *var,
- struct pll_ct *pll);
-static int aty_pll_ct_to_var(const struct pll_ct *pll,
- struct fb_var_screeninfo *var);
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ u8 bpp, struct pll_ct *pll);
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per);
static void atyfb_set_par(const struct atyfb_par *par,
struct fb_info_aty *info);
static int atyfb_decode_var(const struct fb_var_screeninfo *var,
@@ -348,12 +361,14 @@ static void set_off_pitch(struct atyfb_par *par,
static int encode_fix(struct fb_fix_screeninfo *fix,
const struct atyfb_par *par,
const struct fb_info_aty *info);
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel);
static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *fb);
static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *fb);
static void do_install_cmap(int con, struct fb_info *info);
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
static int read_aty_sense(const struct fb_info_aty *info);
#endif
@@ -383,12 +398,17 @@ static struct fb_ops atyfb_ops = {
static char atyfb_name[16] = "ATY Mach64";
static char fontname[40] __initdata = { 0 };
+static char curblink __initdata = 1;
+static char noaccel __initdata = 0;
+static u32 default_vram __initdata = 0;
+static int default_pll __initdata = 0;
+static int default_mclk __initdata = 0;
static const u32 ref_clk_per = 1000000000000ULL/14318180;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
-static int default_vmode = VMODE_NVRAM;
-static int default_cmode = CMODE_NVRAM;
+#if defined(CONFIG_PPC)
+static int default_vmode __initdata = VMODE_NVRAM;
+static int default_cmode __initdata = CMODE_NVRAM;
#endif
#ifdef CONFIG_ATARI
@@ -415,14 +435,20 @@ static struct aty_features {
/* mach64CT family / mach64VT class */
{ 0x5654, 0x5654, "mach64VT (ATI264VT)" },
{ 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
-/* { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" }, */
+ { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
/* mach64CT family / mach64GT (3D RAGE) class */
+ { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
+ { 0x4c42, 0x4c44, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c47, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c49, "3D RAGE LT PRO" },
+ { 0x4c42, 0x4c50, "3D RAGE LT PRO" },
{ 0x4c54, 0x4c54, "3D RAGE LT" },
- { 0x4c47, 0x4c47, "3D RAGE LG" },
{ 0x4754, 0x4754, "3D RAGE (GT)" },
{ 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
-/* { 0x4756, 0x4756, "3D RAGE IIC" }, */
+ { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
+ { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
+ { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
{ 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
{ 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
{ 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
@@ -430,6 +456,14 @@ static struct aty_features {
{ 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
};
+static const char *aty_gx_ram[8] __initdata = {
+ "DRAM", "VRAM", "VRAM", "DRAM", "DRAM", "VRAM", "VRAM", "RESV"
+};
+
+static const char *aty_ct_ram[8] __initdata = {
+ "OFF", "DRAM", "EDO", "EDO", "SDRAM", "SGRAM", "WRAM", "RESV"
+};
+
static inline u32 aty_ld_le32(volatile unsigned int regindex,
const struct fb_info_aty *info)
@@ -620,6 +654,12 @@ static void init_engine(const struct atyfb_par *par,
aty_st_le32(DP_PIX_WIDTH, par->crtc.dp_pix_width, info);
aty_st_le32(DP_CHAIN_MASK, par->crtc.dp_chain_mask, info);
+ wait_for_fifo(5, info);
+ aty_st_le32(SCALE_3D_CNTL, 0, info);
+ aty_st_le32(Z_CNTL, 0, info);
+ aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL, info) & ~0x20, info);
+ aty_st_le32(GUI_TRAJ_CNTL, 0x100023, info);
+
/* insure engine is idle before leaving */
wait_for_idle(info);
}
@@ -648,22 +688,22 @@ static void aty_st_pll(int offset, u8 val, const struct fb_info_aty *info)
aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
}
-#if 0 /* ecd debug */
+#if defined(__sparc__) || defined(DEBUG)
static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
{
- u8 val;
+ u8 res;
/* write addr byte */
aty_st_8(CLOCK_CNTL + 1, (offset << 2), info);
eieio();
/* read the register value */
- val = aty_ld_8(CLOCK_CNTL + 2, info);
+ res = aty_ld_8(CLOCK_CNTL + 2, info);
eieio();
- return val;
+ return res;
}
-#endif /* ecd debug */
+#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
/*
* Apple monitor sense
@@ -703,7 +743,7 @@ static int read_aty_sense(const struct fb_info_aty *info)
return sense;
}
-#endif /* defined(CONFIG_PMAC) || defined(CONFIG_CHRP) */
+#endif /* defined(CONFIG_PPC) */
/* ------------------------------------------------------------------------- */
@@ -768,8 +808,7 @@ aty_set_cursor_shape(struct fb_info_aty *fb)
return;
#endif
- ram = (u8 *)(fb->frame_buffer + c->offset);
-
+ ram = c->ram;
for (y = 0; y < c->size.y; y++) {
for (x = 0; x < c->size.x >> 2; x++) {
m = c->mask[x][y];
@@ -788,8 +827,9 @@ aty_set_cursor_shape(struct fb_info_aty *fb)
}
static void
-aty_set_cursor(struct fb_info_aty *fb)
+aty_set_cursor(struct fb_info_aty *fb, int on)
{
+ struct atyfb_par *par = &fb->current_par;
struct aty_cursor *c = fb->cursor;
u16 xoff, yoff;
int x, y;
@@ -802,8 +842,8 @@ aty_set_cursor(struct fb_info_aty *fb)
return;
#endif
- if (c->on) {
- x = c->pos.x - c->hot.x;
+ if (on) {
+ x = c->pos.x - c->hot.x - par->crtc.xoffset;
if (x < 0) {
xoff = -x;
x = 0;
@@ -811,7 +851,7 @@ aty_set_cursor(struct fb_info_aty *fb)
xoff = 0;
}
- y = c->pos.y - c->hot.y;
+ y = c->pos.y - c->hot.y - par->crtc.yoffset;
if (y < 0) {
yoff = -y;
y = 0;
@@ -827,11 +867,12 @@ aty_set_cursor(struct fb_info_aty *fb)
aty_st_le32(GEN_TEST_CNTL, aty_ld_le32(GEN_TEST_CNTL, fb)
| HWCURSOR_ENABLE, fb);
} else {
- wait_for_fifo(4, fb);
+ wait_for_fifo(1, fb);
aty_st_le32(GEN_TEST_CNTL,
aty_ld_le32(GEN_TEST_CNTL, fb) & ~HWCURSOR_ENABLE,
fb);
}
+ wait_for_idle(fb);
}
static void
@@ -847,7 +888,7 @@ aty_cursor_timer_handler(unsigned long dev_addr)
if (fb->cursor->vbl_cnt && --fb->cursor->vbl_cnt == 0) {
fb->cursor->on ^= 1;
- aty_set_cursor(fb);
+ aty_set_cursor(fb, fb->cursor->on);
fb->cursor->vbl_cnt = fb->cursor->blink_rate;
}
@@ -857,9 +898,9 @@ out:
}
static void
-atyfb_cursor(struct display *d, int mode, int x, int y)
+atyfb_cursor(struct display *p, int mode, int x, int y)
{
- struct fb_info_aty *fb = (struct fb_info_aty *)d->fb_info;
+ struct fb_info_aty *fb = (struct fb_info_aty *)p->fb_info;
struct aty_cursor *c = fb->cursor;
if (!c)
@@ -870,44 +911,82 @@ atyfb_cursor(struct display *d, int mode, int x, int y)
return;
#endif
- x *= d->fontwidth;
- y *= d->fontheight;
- if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->on)
+ x *= fontwidth(p);
+ y *= fontheight(p);
+ if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
return;
c->enable = 0;
+ if (c->on)
+ aty_set_cursor(fb, 0);
c->pos.x = x;
c->pos.y = y;
switch (mode) {
case CM_ERASE:
c->on = 0;
- aty_set_cursor(fb);
break;
case CM_DRAW:
case CM_MOVE:
- c->on = 1;
- aty_set_cursor(fb);
+ if (c->on)
+ aty_set_cursor(fb, 1);
+ else
+ c->vbl_cnt = CURSOR_DRAW_DELAY;
+ c->enable = 1;
+ break;
+ }
+}
- if (!c->timer) {
- c->timer = kmalloc(sizeof(*c->timer), GFP_KERNEL);
- if (!c->timer)
- return;
+__initfunc(static struct aty_cursor *
+aty_init_cursor(struct fb_info_aty *fb))
+{
+ struct aty_cursor *cursor;
+ unsigned long addr;
- c->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
+ if (!cursor)
+ return 0;
+ memset(cursor, 0, sizeof(*cursor));
- init_timer(c->timer);
- c->timer->expires = jiffies + (HZ / 50);
- c->timer->data = (unsigned long)fb;
- c->timer->function = aty_cursor_timer_handler;
- add_timer(c->timer);
- }
+ cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+ if (!cursor->timer) {
+ kfree(cursor);
+ return 0;
+ }
+ memset(cursor->timer, 0, sizeof(*cursor->timer));
- c->vbl_cnt = c->blink_rate;
- c->enable = 1;
- break;
+ cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
+ fb->total_vram -= PAGE_SIZE;
+ cursor->offset = fb->total_vram;
+
+#ifdef __sparc__
+ addr = fb->frame_buffer - 0x800000 + cursor->offset;
+ cursor->ram = (u8 *)addr;
+#else
+#ifdef __BIG_ENDIAN
+ addr = fb->frame_buffer_phys - 0x800000 + cursor->offset;
+ cursor->ram = (u8 *)ioremap(addr, 1024);
+#else
+ addr = fb->frame_buffer + cursor->offset;
+ cursor->ram = (u8 *)addr;
+#endif
+#endif
+
+ if (! cursor->ram) {
+ kfree(cursor);
+ return NULL;
+ }
+
+ if (curblink) {
+ init_timer(cursor->timer);
+ cursor->timer->expires = jiffies + (HZ / 50);
+ cursor->timer->data = (unsigned long)fb;
+ cursor->timer->function = aty_cursor_timer_handler;
+ add_timer(cursor->timer);
}
+
+ return cursor;
}
static int
@@ -923,7 +1002,6 @@ atyfb_set_font(struct display *d, int width, int height)
height = 16;
}
- c->offset = fb->total_vram - 0x1000;
c->hot.x = 0;
c->hot.y = 0;
c->size.x = width;
@@ -972,7 +1050,7 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
u32 left, right, upper, lower, hslen, vslen, sync, vmode;
u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
- u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol;
+ u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width, dp_pix_width, dp_chain_mask;
/* input */
@@ -1029,6 +1107,8 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
FAIL("v_total too large");
v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? CRTC_CSYNC_EN : 0;
+
if (bpp <= 8) {
bpp = 8;
pix_width = CRTC_PIX_WIDTH_8BPP;
@@ -1073,10 +1153,9 @@ static int aty_var_to_crtc(const struct fb_info_aty *info,
crtc->v_tot_disp = v_total | (v_disp<<16);
crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21);
crtc->off_pitch = ((yoffset*vxres+xoffset)*bpp/64) | (vxres<<19);
- crtc->gen_cntl = pix_width | CRTC_EXT_DISP_EN | CRTC_ENABLE;
+ crtc->gen_cntl = pix_width | c_sync | CRTC_EXT_DISP_EN | CRTC_ENABLE;
if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID) ||
- ((Gx == VT_CHIP_ID) && !(Rev & 0x03)) ||
- ((Gx == GT_CHIP_ID) && !(Rev & 0x03))) {
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07))) {
/* Not VTB/GTB */
/* FIXME: magic FIFO values */
crtc->gen_cntl |= aty_ld_le32(CRTC_GEN_CNTL, info) & 0x000e0000;
@@ -1129,7 +1208,7 @@ static int aty_crtc_to_var(const struct crtc *crtc,
{
u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync;
u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol;
- u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol;
+ u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
u32 pix_width;
/* input */
@@ -1145,19 +1224,21 @@ static int aty_crtc_to_var(const struct crtc *crtc,
v_sync_strt = crtc->v_sync_strt_wid & 0x7ff;
v_sync_wid = (crtc->v_sync_strt_wid>>16) & 0x1f;
v_sync_pol = (crtc->v_sync_strt_wid>>21) & 0x1;
+ c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
/* convert */
xres = (h_disp+1)*8;
yres = v_disp+1;
left = (h_total-h_sync_strt-h_sync_wid)*8-h_sync_dly;
- right = (h_sync_strt-h_disp)*8;
+ right = (h_sync_strt-h_disp)*8+h_sync_dly;
hslen = h_sync_wid*8;
upper = v_total-v_sync_strt-v_sync_wid;
lower = v_sync_strt-v_disp;
vslen = v_sync_wid;
sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) |
- (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT);
+ (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) |
+ (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
switch (pix_width) {
#if 0
@@ -1277,13 +1358,12 @@ static void aty_set_pll_gx(const struct fb_info_aty *info,
aty_st_514(0x03, 0x00, info); /* Sync Control */
aty_st_514(0x05, 0x00, info); /* Power Management */
aty_st_514(0x20, pll->m, info); /* F0 / M0 */
- aty_st_514(0x21, pll->m, info); /* F1 / N0 */
+ aty_st_514(0x21, pll->n, info); /* F1 / N0 */
break;
}
}
-static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
- struct pll_gx *pll)
+static int aty_var_to_pll_18818(u32 vclk_per, struct pll_gx *pll)
{
/*
* FIXME: use real calculations instead of using fixed values from the old
@@ -1329,7 +1409,7 @@ static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
for (set = 0; set < sizeof(ATI18818_clocks)/sizeof(*ATI18818_clocks);
set++)
- if (var->pixclock <= ATI18818_clocks[set].ps_lim) {
+ if (vclk_per <= ATI18818_clocks[set].ps_lim) {
pll->m = ATI18818_clocks[set].mode;
pll->n = ATI18818_clocks[set].prog;
return 0;
@@ -1337,8 +1417,7 @@ static int aty_var_to_pll_18818(const struct fb_var_screeninfo *var,
return -EINVAL;
}
-static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
- struct pll_gx *pll)
+static int aty_var_to_pll_514(u32 vclk_per, struct pll_gx *pll)
{
/*
* FIXME: use real calculations instead of using fixed values from the old
@@ -1360,7 +1439,7 @@ static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
int i;
for (i = 0; i < sizeof(RGB514_clocks)/sizeof(*RGB514_clocks); i++)
- if (var->pixclock <= RGB514_clocks[i].limit) {
+ if (vclk_per <= RGB514_clocks[i].limit) {
pll->m = RGB514_clocks[i].m;
pll->n = RGB514_clocks[i].n;
return 0;
@@ -1370,8 +1449,7 @@ static int aty_var_to_pll_514(const struct fb_var_screeninfo *var,
/* FIXME: ATI18818?? */
-static int aty_pll_gx_to_var(const struct pll_gx *pll,
- struct fb_var_screeninfo *var)
+static int aty_pll_gx_to_var(const struct pll_gx *pll, u32 *vclk_per)
{
u8 df, vco_div_count, ref_div_count;
@@ -1379,7 +1457,7 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll,
vco_div_count = pll->m & 0x3f;
ref_div_count = pll->n;
- var->pixclock = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
+ *vclk_per = (ref_clk_per*(vco_div_count+65)/ref_div_count)>>(3-df);
return 0;
}
@@ -1392,22 +1470,6 @@ static int aty_pll_gx_to_var(const struct pll_gx *pll,
static void aty_set_pll_ct(const struct fb_info_aty *info,
const struct pll_ct *pll)
{
-#if 0 /* ecd debug */
-printk("PLL_REF_DIV: %02x (%02x)\n",
- pll->pll_ref_div, aty_ld_pll(PLL_REF_DIV, info));
-printk("PLL_GEN_CNTL: %02x (%02x)\n",
- pll->pll_gen_cntl, aty_ld_pll(PLL_GEN_CNTL, info));
-printk("MCLK_FB_DIV: %02x (%02x)\n",
- pll->mclk_fb_div, aty_ld_pll(MCLK_FB_DIV, info));
-printk("PLL_VCLK_CNTL: %02x (%02x)\n",
- pll->pll_vclk_cntl, aty_ld_pll(PLL_VCLK_CNTL, info));
-printk("VCLK_POST_DIV: %02x (%02x)\n",
- pll->vclk_post_div, aty_ld_pll(VCLK_POST_DIV, info));
-printk("VCLK0_FB_DIV: %02x (%02x)\n",
- pll->vclk_fb_div, aty_ld_pll(VCLK0_FB_DIV, info));
-printk("PLL_EXT_CNTL: %02x (%02x)\n",
- pll->pll_ext_cntl, aty_ld_pll(PLL_EXT_CNTL, info));
-#endif /* ecd debug */
aty_st_pll(PLL_REF_DIV, pll->pll_ref_div, info);
aty_st_pll(PLL_GEN_CNTL, pll->pll_gen_cntl, info);
aty_st_pll(MCLK_FB_DIV, pll->mclk_fb_div, info);
@@ -1416,10 +1478,9 @@ printk("PLL_EXT_CNTL: %02x (%02x)\n",
aty_st_pll(VCLK0_FB_DIV, pll->vclk_fb_div, info);
aty_st_pll(PLL_EXT_CNTL, pll->pll_ext_cntl, info);
- if (((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
- (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
- (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
- (Gx == VU_CHIP_ID)) {
+ if (!(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)))) {
if (info->ram_type >= SDRAM)
aty_st_pll(DLL_CNTL, 0xa6, info);
else
@@ -1442,7 +1503,15 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
(vclk_fb_div*mclk_post_div*bpp);
if (xclks_per_row < (1<<11))
FAIL("Dotclock to high");
- fifo_size = 24;
+ if (Gx == GT_CHIP_ID || Gx == GU_CHIP_ID || Gx == VT_CHIP_ID ||
+ Gx == VU_CHIP_ID || Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+ Gx == GZ_CHIP_ID) {
+ fifo_size = 24;
+ dsp_loop_latency = 0;
+ } else {
+ fifo_size = 32;
+ dsp_loop_latency = 2;
+ }
dsp_precision = 0;
y = (xclks_per_row*fifo_size)>>11;
while (y) {
@@ -1456,21 +1525,21 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
if (info->total_vram > 1*1024*1024) {
if (info->ram_type >= SDRAM) {
/* >1 MB SDRAM */
- dsp_loop_latency = 8;
+ dsp_loop_latency += 8;
page_size = 8;
} else {
/* >1 MB DRAM */
- dsp_loop_latency = 6;
+ dsp_loop_latency += 6;
page_size = 9;
}
} else {
if (info->ram_type >= SDRAM) {
/* <2 MB SDRAM */
- dsp_loop_latency = 9;
+ dsp_loop_latency += 9;
page_size = 10;
} else {
/* <2 MB DRAM */
- dsp_loop_latency = 8;
+ dsp_loop_latency += 8;
page_size = 10;
}
}
@@ -1491,11 +1560,10 @@ static int aty_dsp_gt(const struct fb_info_aty *info, u8 mclk_fb_div,
return 0;
}
-static int aty_var_to_pll_ct(const struct fb_info_aty *info,
- const struct fb_var_screeninfo *var,
- struct pll_ct *pll)
+static int aty_var_to_pll_ct(const struct fb_info_aty *info, u32 vclk_per,
+ u8 bpp, struct pll_ct *pll)
{
- u32 vclk_per, q, x; /* x is a workaround for sparc64-linux-gcc */
+ u32 q, x; /* x is a workaround for sparc64-linux-gcc */
u8 pll_ref_div, pll_gen_cntl, pll_ext_cntl;
u8 mclk_fb_div, mclk_post_div, mpostdiv = 0;
u8 vclk_fb_div, vclk_post_div, vpostdiv = 0;
@@ -1505,7 +1573,6 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
pll->pll_vclk_cntl = 0x03; /* VCLK = PLL_VCLK/VCLKx_POST */
- vclk_per = var->pixclock;
pll_ref_div = info->pll_per*2*255/ref_clk_per;
/* FIXME: use the VTB/GTB /3 post divider if it's better suited */
@@ -1537,7 +1604,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
vclk_fb_div = q*vclk_post_div/8;
if ((err = aty_dsp_gt(info, mclk_fb_div, mclk_post_div, vclk_fb_div,
- vclk_post_div, var->bits_per_pixel, pll)))
+ vclk_post_div, bpp, pll)))
return err;
if ((((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
@@ -1609,8 +1676,7 @@ static int aty_var_to_pll_ct(const struct fb_info_aty *info,
return 0;
}
-static int aty_pll_ct_to_var(const struct pll_ct *pll,
- struct fb_var_screeninfo *var)
+static int aty_pll_ct_to_var(const struct pll_ct *pll, u32 *vclk_per)
{
u8 pll_ref_div = pll->pll_ref_div;
u8 vclk_fb_div = pll->vclk_fb_div;
@@ -1624,7 +1690,7 @@ static int aty_pll_ct_to_var(const struct pll_ct *pll,
(vclk_post_div & 3)];
if (vpostdiv == 0)
return -EINVAL;
- var->pixclock = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
+ *vclk_per = pll_ref_div*vpostdiv*ref_clk_per/vclk_fb_div/2;
return 0;
}
@@ -1657,7 +1723,7 @@ static void atyfb_set_par(const struct atyfb_par *par,
aty_set_pll_ct(info, &par->pll.ct);
i = aty_ld_le32(MEM_CNTL, info) & 0xf30fffff;
if (!(Gx == VT_CHIP_ID && (Rev == 0x40 || Rev == 0x48)))
- i |= info->mem_refresh_rate << 20;
+ i |= info->mem_refresh_rate << 20;
switch (par->crtc.bpp) {
case 8:
case 24:
@@ -1680,7 +1746,8 @@ static void atyfb_set_par(const struct atyfb_par *par,
/* GT */
aty_st_le32(DAC_CNTL, 0x86010102, info);
aty_st_le32(BUS_CNTL, 0x7b23a040, info);
- aty_st_le32(EXT_MEM_CNTL, 0x5000001, info);
+ aty_st_le32(EXT_MEM_CNTL,
+ aty_ld_le32(EXT_MEM_CNTL, info) | 0x5000001, info);
}
aty_st_le32(MEM_CNTL, i, info);
}
@@ -1720,17 +1787,18 @@ static int atyfb_decode_var(const struct fb_var_screeninfo *var,
if ((err = aty_var_to_crtc(info, var, &par->crtc)))
return err;
- if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID))
+ if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
switch (info->clk_type) {
case CLK_ATI18818_1:
- err = aty_var_to_pll_18818(var, &par->pll.gx);
+ err = aty_var_to_pll_18818(var->pixclock, &par->pll.gx);
break;
case CLK_IBMRGB514:
- err = aty_var_to_pll_514(var, &par->pll.gx);
+ err = aty_var_to_pll_514(var->pixclock, &par->pll.gx);
break;
}
else
- err = aty_var_to_pll_ct(info, var, &par->pll.ct);
+ err = aty_var_to_pll_ct(info, var->pixclock, par->crtc.bpp,
+ &par->pll.ct);
if (err)
return err;
@@ -1740,7 +1808,7 @@ static int atyfb_decode_var(const struct fb_var_screeninfo *var,
par->accel_flags = 0;
#if 0
- if (!fbmon_valid_timings(pixclock, htotal, vtotal, info))
+ if (!fbmon_valid_timings(var->pixclock, htotal, vtotal, info))
return -EINVAL;
#endif
@@ -1757,10 +1825,10 @@ static int atyfb_encode_var(struct fb_var_screeninfo *var,
if ((err = aty_crtc_to_var(&par->crtc, var)))
return err;
- if ((Gx == GX_PCI_ID) || (Gx == CX_PCI_ID))
- err = aty_pll_gx_to_var(&par->pll.gx, var);
+ if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
+ err = aty_pll_gx_to_var(&par->pll.gx, &var->pixclock);
else
- err = aty_pll_ct_to_var(&par->pll.ct, var);
+ err = aty_pll_ct_to_var(&par->pll.ct, &var->pixclock);
if (err)
return err;
@@ -1853,15 +1921,15 @@ static int encode_fix(struct fb_fix_screeninfo *fix,
* Reg Block 0 (CT-compatible block) is at ati_regbase_phys
* Reg Block 1 (multimedia extensions) is at ati_regbase_phys-0x400
*/
- if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
+ if (Gx == GX_CHIP_ID || Gx == CX_CHIP_ID) {
fix->mmio_start = (char *)info->ati_regbase_phys;
fix->mmio_len = 0x400;
fix->accel = FB_ACCEL_ATI_MACH64GX;
- } else if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
+ } else if (Gx == CT_CHIP_ID || Gx == ET_CHIP_ID) {
fix->mmio_start = (char *)info->ati_regbase_phys;
fix->mmio_len = 0x400;
fix->accel = FB_ACCEL_ATI_MACH64CT;
- } else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID)) {
+ } else if (Gx == VT_CHIP_ID || Gx == VU_CHIP_ID || Gx == VV_CHIP_ID) {
fix->mmio_start = (char *)(info->ati_regbase_phys-0x400);
fix->mmio_len = 0x800;
fix->accel = FB_ACCEL_ATI_MACH64VT;
@@ -1891,32 +1959,6 @@ struct fb_var_screeninfo default_var = {
0, FB_VMODE_NONINTERLACED
};
-#ifdef __sparc__
-struct fb_var_screeninfo default_var_1024x768 __initdata = {
- /* 1024x768, 75 Hz, Non-Interlaced (78.75 MHz dotclock) */
- 1024, 768, 1024, 768, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 12699, 176, 16, 28, 1, 96, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1152x900 __initdata = {
- /* 1152x900, 76 Hz, Non-Interlaced (110.0 MHz dotclock) */
- 1152, 900, 1152, 900, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 9091, 234, 24, 34, 3, 100, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-
-struct fb_var_screeninfo default_var_1280x1024 __initdata = {
- /* 1280x1024, 75 Hz, Non-Interlaced (135.00 MHz dotclock) */
- 1280, 1024, 1280, 1024, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 7408, 248, 16, 38, 1, 144, 3,
- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
-};
-#endif
-
/*
* Get the Fixed Part of the Display
@@ -1954,6 +1996,47 @@ static int atyfb_get_var(struct fb_var_screeninfo *var, int con,
}
+static void atyfb_set_disp(struct display *disp, struct fb_info_aty *info,
+ int bpp, int accel)
+{
+ switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ info->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
+ disp->dispsw = &info->dispsw;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ info->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb16;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ info->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb24;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ info->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
+ disp->dispsw = &info->dispsw;
+ disp->dispsw_data = info->fbcon_cmap.cfb32;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ }
+ if (info->cursor) {
+ info->dispsw.cursor = atyfb_cursor;
+ info->dispsw.set_font = atyfb_set_font;
+ }
+}
+
+
/*
* Set the User Defined Part of the Display
*/
@@ -2001,38 +2084,13 @@ static int atyfb_set_var(struct fb_var_screeninfo *var, int con,
display->can_soft_blank = 1;
display->inverse = 0;
accel = var->accel_flags & FB_ACCELF_TEXT;
- switch (par.crtc.bpp) {
-#ifdef FBCON_HAS_CFB8
- case 8:
- *display->dispsw = accel ? fbcon_aty8 : fbcon_cfb8;
- break;
-#endif
-#ifdef FBCON_HAS_CFB16
- case 16:
- *display->dispsw = accel ? fbcon_aty16 : fbcon_cfb16;
- break;
-#endif
-#ifdef FBCON_HAS_CFB24
- case 24:
- *display->dispsw = accel ? fbcon_aty24 : fbcon_cfb24;
- break;
-#endif
-#ifdef FBCON_HAS_CFB32
- case 32:
- *display->dispsw = accel ? fbcon_aty32 : fbcon_cfb32;
- break;
-#endif
- default:
- display->dispsw = NULL;
- break;
- }
- display->scrollmode = accel ? 0 : SCROLL_YREDRAW;
+ atyfb_set_disp(display, info, par.crtc.bpp, accel);
+ if (accel)
+ display->scrollmode = (info->bus_type == PCI) ? SCROLL_YNOMOVE : 0;
+ else
+ display->scrollmode = SCROLL_YREDRAW;
if (info->fb_info.changevar)
(*info->fb_info.changevar)(con);
- if (info->cursor) {
- display->dispsw->cursor = atyfb_cursor;
- display->dispsw->set_font = atyfb_set_font;
- }
}
if (con == currcon)
atyfb_set_par(&par, info);
@@ -2080,8 +2138,7 @@ static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
struct fb_info *info)
{
if (con == currcon) /* current console? */
- return fb_get_cmap(cmap, &fb_display[con].var, kspc, atyfb_getcolreg,
- info);
+ return fb_get_cmap(cmap, kspc, atyfb_getcolreg, info);
else if (fb_display[con].cmap.len) /* non default colormap? */
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else {
@@ -2106,8 +2163,7 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
return err;
}
if (con == currcon) /* current console? */
- return fb_set_cmap(cmap, &fb_display[con].var, kspc, atyfb_setcolreg,
- info);
+ return fb_set_cmap(cmap, kspc, atyfb_setcolreg, info);
else
fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);
return 0;
@@ -2117,7 +2173,27 @@ static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd,
u_long arg, int con, struct fb_info *info)
{
+#ifdef __sparc__
+ struct fb_info_aty *fb = (struct fb_info_aty *)info;
+ struct fbtype fbtyp;
+
+ switch (cmd) {
+ case FBIOGTYPE:
+ fbtyp.fb_type = FBTYPE_PCI_GENERIC;
+ fbtyp.fb_width = fb->current_par.crtc.vxres;
+ fbtyp.fb_height = fb->current_par.crtc.vyres;
+ fbtyp.fb_depth = fb->current_par.crtc.bpp;
+ fbtyp.fb_cmsize = fb_display[con].cmap.len;
+ fbtyp.fb_size = fb->total_vram;
+ copy_to_user_ret((struct fbtype *)arg, &fbtyp, sizeof(fbtyp), -EFAULT);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+#else
return -EINVAL;
+#endif
}
#ifdef __sparc__
@@ -2139,10 +2215,15 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
/* To stop the swapper from even considering these pages. */
vma->vm_flags |= (VM_SHM | VM_LOCKED);
+ if (((vma->vm_offset == 0) && (size == fb->total_vram)) ||
+ ((vma->vm_offset == fb->total_vram) && (size == PAGE_SIZE)))
+ vma->vm_offset += 0x8000000000000000UL;
+
#ifdef __sparc_v9__
/* Align it as much as desirable */
{
- int j, max = -1, align;
+ unsigned long j, align;
+ int max = -1;
map_offset = vma->vm_offset+size;
for (i = 0; fb->mmap_map[i].size; i++) {
@@ -2193,7 +2274,7 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
if (start > offset)
continue;
- if (offset > end)
+ if (offset >= end)
continue;
map_size = fb->mmap_map[i].size - (offset - start);
@@ -2237,6 +2318,78 @@ static int atyfb_mmap(struct fb_info *info, struct file *file,
}
return 0;
}
+
+static struct {
+ u32 yoffset;
+ u8 r[2][256];
+ u8 g[2][256];
+ u8 b[2][256];
+} atyfb_save;
+
+static void atyfb_save_palette(struct fb_info *fb, int enter)
+{
+ struct fb_info_aty *info = (struct fb_info_aty *)fb;
+ int i, tmp, scale;
+
+ for (i = 0; i < 256; i++) {
+ tmp = aty_ld_8(DAC_CNTL, info) & 0xfc;
+ if ((Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
+ (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) ||
+ (Gx == GD_CHIP_ID) || (Gx == GI_CHIP_ID) ||
+ (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+ tmp |= 0x2;
+ aty_st_8(DAC_CNTL, tmp, info);
+ aty_st_8(DAC_MASK, 0xff, info);
+ eieio();
+ scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
+ (info->current_par.crtc.bpp == 16)) ? 3 : 0;
+ info->aty_cmap_regs->rindex = i << scale;
+ eieio();
+ atyfb_save.r[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ atyfb_save.g[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ atyfb_save.b[enter][i] = info->aty_cmap_regs->lut;
+ eieio();
+ info->aty_cmap_regs->windex = i << scale;
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.r[1-enter][i];
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.g[1-enter][i];
+ eieio();
+ info->aty_cmap_regs->lut = atyfb_save.b[1-enter][i];
+ eieio();
+ }
+}
+
+static void atyfb_palette(int enter)
+{
+ struct fb_info_aty *info;
+ struct atyfb_par *par;
+ struct display *d;
+ int i;
+
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ d = &fb_display[i];
+ if (d->fb_info &&
+ d->fb_info->fbops == &atyfb_ops &&
+ d->fb_info->display_fg &&
+ d->fb_info->display_fg->vc_num == i) {
+ atyfb_save_palette(d->fb_info, enter);
+ info = (struct fb_info_aty *)d->fb_info;
+ par = &info->current_par;
+ if (enter) {
+ atyfb_save.yoffset = par->crtc.yoffset;
+ par->crtc.yoffset = 0;
+ set_off_pitch(par, info);
+ } else {
+ par->crtc.yoffset = atyfb_save.yoffset;
+ set_off_pitch(par, info);
+ }
+ break;
+ }
+ }
+}
#endif /* __sparc__ */
/*
@@ -2250,9 +2403,9 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
int j, k;
struct fb_var_screeninfo var;
struct display *disp;
- const char *chipname = NULL;
- int pll, mclk;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+ const char *chipname = NULL, *ramname = NULL;
+ int pll, mclk, gtb_memsize;
+#if defined(CONFIG_PPC)
int sense;
#endif
@@ -2269,10 +2422,11 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
printk("atyfb: Unknown mach64 0x%04x\n", Gx);
return 0;
} else
- printk("atyfb: %s [0x%04x rev 0x%2x] ", chipname, Gx, Rev);
+ printk("atyfb: %s [0x%04x rev 0x%02x] ", chipname, Gx, Rev);
if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID)) {
info->bus_type = (aty_ld_le32(CONFIG_STAT0, info) >> 0) & 0x07;
info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) >> 3) & 0x07;
+ ramname = aty_gx_ram[info->ram_type];
/* FIXME: clockchip/RAMDAC probing? */
#ifdef CONFIG_ATARI
info->dac_type = DAC_ATI68860_B;
@@ -2287,6 +2441,7 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
} else {
info->bus_type = PCI;
info->ram_type = (aty_ld_le32(CONFIG_STAT0, info) & 0x07);
+ ramname = aty_ct_ram[info->ram_type];
info->dac_type = DAC_INTERNAL;
info->clk_type = CLK_INTERNAL;
if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID)) {
@@ -2315,10 +2470,14 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
(Gx == GU_CHIP_ID)) {
/* RAGE II+ */
pll = 200;
- } else if ((Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
- (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) ||
- (Gx == GQ_CHIP_ID)) {
- /* RAGE PRO */
+ } else if (Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
+ Gx == GI_CHIP_ID || Gx == GP_CHIP_ID ||
+ Gx == GQ_CHIP_ID || Gx == VV_CHIP_ID ||
+ Gx == GV_CHIP_ID || Gx == GW_CHIP_ID ||
+ Gx == GZ_CHIP_ID || Gx == LD_CHIP_ID ||
+ Gx == LG_CHIP_ID || Gx == LB_CHIP_ID ||
+ Gx == LI_CHIP_ID || Gx == LP_CHIP_ID) {
+ /* RAGE PRO or IIC */
pll = 230;
} else {
/* other RAGE */
@@ -2327,31 +2486,12 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
}
}
}
- if (mclk < 44)
- info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
- else if (mclk < 50)
- info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
- else if (mclk < 55)
- info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
- else if (mclk < 66)
- info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
- else if (mclk < 75)
- info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
- else if (mclk < 80)
- info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
- else if (mclk < 100)
- info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
- else
- info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
- printk("%d MHz PLL, %d Mhz MCLK\n", pll, mclk);
- info->pll_per = 1000000/pll;
- info->mclk_per = 1000000/mclk;
i = aty_ld_le32(MEM_CNTL, info);
- if (((Gx == GT_CHIP_ID) && (Rev & 0x03)) || (Gx == GU_CHIP_ID) ||
- ((Gx == VT_CHIP_ID) && (Rev & 0x01)) || (Gx == VU_CHIP_ID) ||
- (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
- (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
+ gtb_memsize = !(Gx == GX_CHIP_ID || Gx == CX_CHIP_ID || Gx == CT_CHIP_ID ||
+ Gx == ET_CHIP_ID ||
+ ((Gx == VT_CHIP_ID || Gx == GT_CHIP_ID) && !(Rev & 0x07)));
+ if (gtb_memsize)
switch (i & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */
case MEM_SIZE_512K:
info->total_vram = 0x80000;
@@ -2398,21 +2538,93 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
info->total_vram = 0x80000;
}
+ if (Gx == GI_CHIP_ID) {
+ if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
+ info->total_vram += 0x400000;
+ }
+
+ if (default_vram) {
+ info->total_vram = default_vram*1024;
+ i = i & ~(gtb_memsize ? 0xF : MEM_SIZE_ALIAS);
+ if (info->total_vram <= 0x80000)
+ i |= MEM_SIZE_512K;
+ else if (info->total_vram <= 0x100000)
+ i |= MEM_SIZE_1M;
+ else if (info->total_vram <= 0x200000)
+ i |= gtb_memsize ? MEM_SIZE_2M_GTB : MEM_SIZE_2M;
+ else if (info->total_vram <= 0x400000)
+ i |= gtb_memsize ? MEM_SIZE_4M_GTB : MEM_SIZE_4M;
+ else if (info->total_vram <= 0x600000)
+ i |= gtb_memsize ? MEM_SIZE_6M_GTB : MEM_SIZE_6M;
+ else
+ i |= gtb_memsize ? MEM_SIZE_8M_GTB : MEM_SIZE_8M;
+ aty_st_le32(MEM_CNTL, i, info);
+ }
+ if (default_pll)
+ pll = default_pll;
+ if (default_mclk)
+ mclk = default_mclk;
+
+ printk("%d%c %s, %d MHz PLL, %d Mhz MCLK\n",
+ info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
+ info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, mclk);
+
+ if (mclk < 44)
+ info->mem_refresh_rate = 0; /* 000 = 10 Mhz - 43 Mhz */
+ else if (mclk < 50)
+ info->mem_refresh_rate = 1; /* 001 = 44 Mhz - 49 Mhz */
+ else if (mclk < 55)
+ info->mem_refresh_rate = 2; /* 010 = 50 Mhz - 54 Mhz */
+ else if (mclk < 66)
+ info->mem_refresh_rate = 3; /* 011 = 55 Mhz - 65 Mhz */
+ else if (mclk < 75)
+ info->mem_refresh_rate = 4; /* 100 = 66 Mhz - 74 Mhz */
+ else if (mclk < 80)
+ info->mem_refresh_rate = 5; /* 101 = 75 Mhz - 79 Mhz */
+ else if (mclk < 100)
+ info->mem_refresh_rate = 6; /* 110 = 80 Mhz - 100 Mhz */
+ else
+ info->mem_refresh_rate = 7; /* 111 = 100 Mhz and above */
+ info->pll_per = 1000000/pll;
+ info->mclk_per = 1000000/mclk;
+
+#ifdef DEBUG
+ if ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID)) {
+ int i;
+ printk("BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL "
+ "DSP_CONFIG DSP_ON_OFF\n"
+ "%08x %08x %08x %08x %08x %08x %08x\n"
+ "PLL",
+ aty_ld_le32(BUS_CNTL, info), aty_ld_le32(DAC_CNTL, info),
+ aty_ld_le32(MEM_CNTL, info), aty_ld_le32(EXT_MEM_CNTL, info),
+ aty_ld_le32(CRTC_GEN_CNTL, info), aty_ld_le32(DSP_CONFIG, info),
+ aty_ld_le32(DSP_ON_OFF, info));
+ for (i = 0; i < 16; i++)
+ printk(" %02x", aty_ld_pll(i, info));
+ printk("\n");
+ }
+#endif
+
if (info->bus_type == ISA)
if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
/* protect GUI-regs if complete Aperture is VRAM */
info->total_vram -= GUI_RESERVE;
}
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
if (default_vmode == VMODE_NVRAM) {
default_vmode = nvram_read_byte(NV_VMODE);
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_CHOOSE;
}
if (default_vmode == VMODE_CHOOSE) {
- sense = read_aty_sense(info);
- default_vmode = mac_map_monitor_sense(sense);
+ if (Gx == LG_CHIP_ID)
+ /* G3 PowerBook with 1024x768 LCD */
+ default_vmode = VMODE_1024_768_60;
+ else {
+ sense = read_aty_sense(info);
+ default_vmode = mac_map_monitor_sense(sense);
+ }
}
if (default_vmode <= 0 || default_vmode > VMODE_MAX)
default_vmode = VMODE_640_480_60;
@@ -2422,24 +2634,26 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
default_cmode = CMODE_8;
if (mac_vmode_to_var(default_vmode, default_cmode, &var))
var = default_var;
-#else /* !CONFIG_PMAC && !CONFIG_CHRP */
+#else /* !CONFIG_PPC */
var = default_var;
-#endif /* !CONFIG_PMAC && !CONFIG_CHRP */
- var.accel_flags |= FB_ACCELF_TEXT;
+#endif /* !CONFIG_PPC */
+ if (noaccel)
+ var.accel_flags &= ~FB_ACCELF_TEXT;
+ else
+ var.accel_flags |= FB_ACCELF_TEXT;
+
+ if (var.yres == var.yres_virtual) {
+ u32 vram = (info->total_vram - (PAGE_SIZE << 2));
+ var.yres_virtual = ((vram * 8) / var.bits_per_pixel) / var.xres_virtual;
+ if (var.yres_virtual < var.yres)
+ var.yres_virtual = var.yres;
+ }
+
if (atyfb_decode_var(&var, &info->default_par, info)) {
printk("atyfb: can't set default video mode\n");
return 0;
}
- if ((Gx == GX_CHIP_ID) || (Gx == CX_CHIP_ID))
- strcat(atyfb_name, "GX");
- else if ((Gx == CT_CHIP_ID) || (Gx == ET_CHIP_ID))
- strcat(atyfb_name, "CT");
- else if ((Gx == VT_CHIP_ID) || (Gx == VU_CHIP_ID))
- strcat(atyfb_name, "VT");
- else
- strcat(atyfb_name, "GT");
-
disp = &info->disp;
strcpy(info->fb_info.modename, atyfb_name);
@@ -2451,7 +2665,11 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
info->fb_info.switch_con = &atyfbcon_switch;
info->fb_info.updatevar = &atyfbcon_updatevar;
info->fb_info.blank = &atyfbcon_blank;
+ info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+#ifdef __sparc__
+ atyfb_save_palette(&info->fb_info, 0);
+#endif
for (j = 0; j < 16; j++) {
k = color_table[j];
info->palette[j].red = default_red[k];
@@ -2459,16 +2677,14 @@ __initfunc(static int aty_init(struct fb_info_aty *info, const char *name))
info->palette[j].blue = default_blu[k];
}
- if ((Gx == VT_CHIP_ID) || (Gx == GT_CHIP_ID) || (Gx == GU_CHIP_ID) ||
- (Gx == LG_CHIP_ID) || (Gx == GB_CHIP_ID) || (Gx == GD_CHIP_ID) ||
- (Gx == GI_CHIP_ID) || (Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID) ||
- (Gx == VU_CHIP_ID)) {
- info->cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
- if (info->cursor)
- memset(info->cursor, 0, sizeof(*info->cursor));
+ if (Gx != GX_CHIP_ID && Gx != CX_CHIP_ID) {
+ info->cursor = aty_init_cursor(info);
+ if (info->cursor) {
+ info->dispsw.cursor = atyfb_cursor;
+ info->dispsw.set_font = atyfb_set_font;
+ }
}
-
- disp->dispsw = &info->dispsw;
+
atyfb_set_var(&var, -1, &info->fb_info);
if (register_framebuffer(&info->fb_info) < 0)
@@ -2489,8 +2705,12 @@ __initfunc(void atyfb_init(void))
struct fb_info_aty *info;
unsigned long addr;
#ifdef __sparc__
+ extern void (*prom_palette) (int);
extern int con_is_present(void);
- u32 chip_id;
+ struct pcidev_cookie *pcp;
+ char prop[128];
+ int node, len;
+ u32 mem, chip_id;
int i, j;
/* Do not attach when we have a serial console. */
@@ -2536,16 +2756,17 @@ __initfunc(void atyfb_init(void))
*/
for (i = 0; i < 6 && pdev->base_address[i]; i++)
/* nothing */;
- j = i + 1;
+ j = i + 3;
info->mmap_map = kmalloc(j * sizeof(*info->mmap_map), GFP_ATOMIC);
if (!info->mmap_map) {
printk("atyfb_init: can't alloc mmap_map\n");
kfree(info);
+ return;
}
-
memset(info->mmap_map, 0, j * sizeof(*info->mmap_map));
- for (i = j = 0; i < 6 && pdev->base_address[i]; i++) {
+
+ for (i = 0, j = 2; i < 6 && pdev->base_address[i]; i++) {
int io, breg = PCI_BASE_ADDRESS_0 + (i << 2);
unsigned long base;
u32 size, pbase;
@@ -2564,8 +2785,7 @@ __initfunc(void atyfb_init(void))
size = ~(size) + 1;
if (base == addr) {
- info->mmap_map[j].voff = (pbase + 0x800000)
- & PAGE_MASK;
+ info->mmap_map[j].voff = (pbase + 0x800000) & PAGE_MASK;
info->mmap_map[j].poff = __pa((base + 0x800000)
& PAGE_MASK);
info->mmap_map[j].size = 0x800000;
@@ -2586,9 +2806,10 @@ __initfunc(void atyfb_init(void))
/*
* Fix PROMs idea of MEM_CNTL settings...
*/
- chip_id = aty_ld_le32(CONFIG_CHIP_ID, info) & CFG_CHIP_TYPE;
- if ((chip_id & 0xffff) == VT_CHIP_ID && !((chip_id >> 24) & 1)) {
- u32 mem = aty_ld_le32(MEM_CNTL, info);
+ mem = aty_ld_le32(MEM_CNTL, info);
+ chip_id = aty_ld_le32(CONFIG_CHIP_ID, info);
+ if (((chip_id & CFG_CHIP_TYPE) == VT_CHIP_ID) &&
+ !((chip_id >> 24) & 1)) {
switch (mem & 0x0f) {
case 3:
mem = (mem & ~(0x0f)) | 2;
@@ -2606,53 +2827,93 @@ __initfunc(void atyfb_init(void))
break;
}
if ((aty_ld_le32(CONFIG_STAT0, info) & 7) >= SDRAM)
- mem &= ~(0x00f00000);
- aty_st_le32(MEM_CNTL, mem, info);
+ mem &= ~(0x00700000);
}
+ mem &= ~(0xcf80e000); /* Turn off all undocumented bits. */
+ aty_st_le32(MEM_CNTL, mem, info);
/*
- * Set default vmode and cmode from PROM properties.
+ * If this is the console device, we will set default video
+ * settings to what the PROM left us with.
*/
- {
- struct pcidev_cookie *cookie = pdev->sysdata;
- int node = cookie->prom_node;
- int width = prom_getintdefault(node, "width", 1024);
- int height = prom_getintdefault(node, "height", 768);
- int depth = prom_getintdefault(node, "depth", 8);
-
- switch (width) {
- case 1024:
- if (height == 768)
- default_var = default_var_1024x768;
- break;
- case 1152:
- if (height == 900)
- default_var = default_var_1152x900;
- break;
- case 1280:
- if (height == 1024)
- default_var = default_var_1280x1024;
- break;
- default:
- break;
+ node = prom_getchild(prom_root_node);
+ node = prom_searchsiblings(node, "aliases");
+ if (node) {
+ len = prom_getproperty(node, "screen", prop, sizeof(prop));
+ if (len > 0) {
+ prop[len] = '\0';
+ node = prom_finddevice(prop);
+ } else {
+ node = 0;
}
+ }
- switch (depth) {
- case 8:
- default_var.bits_per_pixel = 8;
- break;
- case 16:
- default_var.bits_per_pixel = 16;
- break;
- case 24:
- default_var.bits_per_pixel = 24;
- break;
- case 32:
- default_var.bits_per_pixel = 32;
- break;
- default:
- break;
- }
+ pcp = pdev->sysdata;
+ if (node == pcp->prom_node) {
+
+ struct fb_var_screeninfo *var = &default_var;
+ unsigned int N, P, Q, M, T;
+ u32 v_total, h_total;
+ struct crtc crtc;
+ u8 pll_regs[16];
+ u8 clock_cntl;
+
+ crtc.vxres = prom_getintdefault(node, "width", 1024);
+ crtc.vyres = prom_getintdefault(node, "height", 768);
+ crtc.bpp = prom_getintdefault(node, "depth", 8);
+ crtc.xoffset = crtc.yoffset = 0;
+ crtc.h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, info);
+ crtc.h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, info);
+ crtc.v_tot_disp = aty_ld_le32(CRTC_V_TOTAL_DISP, info);
+ crtc.v_sync_strt_wid = aty_ld_le32(CRTC_V_SYNC_STRT_WID, info);
+ crtc.gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, info);
+ aty_crtc_to_var(&crtc, var);
+
+ h_total = var->xres + var->right_margin +
+ var->hsync_len + var->left_margin;
+ v_total = var->yres + var->lower_margin +
+ var->vsync_len + var->upper_margin;
+
+ /*
+ * Read the PLL to figure actual Refresh Rate.
+ */
+ clock_cntl = aty_ld_8(CLOCK_CNTL, info);
+ /* printk("atyfb: CLOCK_CNTL: %02x\n", clock_cntl); */
+ for (i = 0; i < 16; i++)
+ pll_regs[i] = aty_ld_pll(i, info);
+
+ /*
+ * PLL Reference Devider M:
+ */
+ M = pll_regs[2];
+
+ /*
+ * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
+ */
+ N = pll_regs[7 + (clock_cntl & 3)];
+
+ /*
+ * PLL Post Devider P (Dependant on CLOCK_CNTL):
+ */
+ P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+
+ /*
+ * PLL Devider Q:
+ */
+ Q = N / P;
+
+ /*
+ * Target Frequency:
+ *
+ * T * M
+ * Q = -------
+ * 2 * R
+ *
+ * where R is XTALIN (= 14318 kHz).
+ */
+ T = 2 * Q * 14318 / M;
+
+ default_var.pixclock = 1000000000 / T;
}
#else /* __sparc__ */
@@ -2661,6 +2922,11 @@ __initfunc(void atyfb_init(void))
info->ati_regbase = (unsigned long)
ioremap(info->ati_regbase_phys, 0x1000);
+ if(!info->ati_regbase) {
+ kfree(info);
+ return;
+ }
+
info->ati_regbase_phys += 0xc00;
info->ati_regbase += 0xc00;
@@ -2683,13 +2949,38 @@ __initfunc(void atyfb_init(void))
info->frame_buffer_phys = addr;
info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+ if(!info->frame_buffer) {
+ kfree(info);
+ return;
+ }
+
#endif /* __sparc__ */
if (!aty_init(info, "PCI")) {
if (info->mmap_map)
kfree(info->mmap_map);
kfree(info);
+ return;
}
+
+#ifdef __sparc__
+ if (!prom_palette)
+ prom_palette = atyfb_palette;
+
+ /*
+ * Add /dev/fb mmap values.
+ */
+ info->mmap_map[0].voff = 0x8000000000000000UL;
+ info->mmap_map[0].poff = __pa(info->frame_buffer & PAGE_MASK);
+ info->mmap_map[0].size = info->total_vram;
+ info->mmap_map[0].prot_mask = _PAGE_CACHE;
+ info->mmap_map[0].prot_flag = _PAGE_E;
+ info->mmap_map[1].voff = info->mmap_map[0].voff + info->total_vram;
+ info->mmap_map[1].poff = __pa(info->ati_regbase & PAGE_MASK);
+ info->mmap_map[1].size = PAGE_SIZE;
+ info->mmap_map[1].prot_mask = _PAGE_CACHE;
+ info->mmap_map[1].prot_flag = _PAGE_E;
+#endif /* __sparc__ */
}
}
#elif defined(CONFIG_ATARI)
@@ -2705,6 +2996,11 @@ __initfunc(void atyfb_init(void))
}
info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+ if (!info) {
+ printk("atyfb_init: can't alloc fb_info_aty\n");
+ return;
+ }
+ memset(info, 0, sizeof(struct fb_info_aty));
/*
* Map the video memory (physical address given) to somewhere in the
@@ -2736,63 +3032,78 @@ __initfunc(void atyfb_of_init(struct device_node *dp))
struct fb_info_aty *info;
int i;
- for (; dp; dp = dp->next) {
- switch (dp->n_addrs) {
- case 1:
- case 3:
- addr = dp->addrs[0].address;
- break;
- case 4:
- addr = dp->addrs[1].address;
- break;
- default:
- printk("Warning: got %d adresses for ATY:\n", dp->n_addrs);
- for (i = 0; i < dp->n_addrs; i++)
- printk(" %08x-%08x", dp->addrs[i].address,
- dp->addrs[i].address+dp->addrs[i].size-1);
- if (dp->n_addrs)
- printk("\n");
- continue;
- }
+ switch (dp->n_addrs) {
+ case 1:
+ case 2:
+ case 3:
+ addr = dp->addrs[0].address;
+ break;
+ case 4:
+ addr = dp->addrs[1].address;
+ break;
+ default:
+ printk("Warning: got %d adresses for ATY:\n", dp->n_addrs);
+ for (i = 0; i < dp->n_addrs; i++)
+ printk(" %08x-%08x", dp->addrs[i].address,
+ dp->addrs[i].address+dp->addrs[i].size-1);
+ if (dp->n_addrs)
+ printk("\n");
+ return;
+ }
- info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+ info = kmalloc(sizeof(struct fb_info_aty), GFP_ATOMIC);
+ if (!info) {
+ printk("atyfb_of_init: can't alloc fb_info_aty\n");
+ return;
+ }
+ memset(info, 0, sizeof(struct fb_info_aty));
- info->ati_regbase = (unsigned long)ioremap(0x7ff000+addr,
- 0x1000)+0xc00;
- info->ati_regbase_phys = 0x7ff000+addr;
- info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
+ info->ati_regbase_phys = 0x7ff000+addr;
+ info->ati_regbase = (unsigned long)ioremap(info->ati_regbase_phys,
0x1000);
- info->ati_regbase_phys += 0xc00;
- info->ati_regbase += 0xc00;
-
- /* enable memory-space accesses using config-space command register */
- if (pci_device_loc(dp, &bus, &devfn) == 0) {
- pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
- if (cmd != 0xffff) {
- cmd |= PCI_COMMAND_MEMORY;
- pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
- }
+
+ if(! info->ati_regbase) {
+ printk("atyfb_init: ioremap() returned NULL\n");
+ kfree(info);
+ return;
+ }
+
+ info->ati_regbase_phys += 0xc00;
+ info->ati_regbase += 0xc00;
+
+ /* enable memory-space accesses using config-space command register */
+ if (pci_device_loc(dp, &bus, &devfn) == 0) {
+ pcibios_read_config_word(bus, devfn, PCI_COMMAND, &cmd);
+ if (cmd != 0xffff) {
+ cmd |= PCI_COMMAND_MEMORY;
+ pcibios_write_config_word(bus, devfn, PCI_COMMAND, cmd);
}
+ }
#ifdef __BIG_ENDIAN
- /* Use the big-endian aperture */
- addr += 0x800000;
+ /* Use the big-endian aperture */
+ addr += 0x800000;
#endif
- /* Map in frame buffer */
- info->frame_buffer_phys = addr;
- info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
+ /* Map in frame buffer */
+ info->frame_buffer_phys = addr;
+ info->frame_buffer = (unsigned long)ioremap(addr, 0x800000);
- if (!aty_init(info, dp->full_name)) {
+ if(! info->frame_buffer) {
+ printk("atyfb_init: ioremap() returned NULL\n");
kfree(info);
return;
- }
+ }
+
+ if (!aty_init(info, dp->full_name)) {
+ kfree(info);
+ return;
+ }
#ifdef CONFIG_FB_COMPAT_XPMAC
- if (!console_fb_info)
- console_fb_info = &info->fb_info;
+ if (!console_fb_info)
+ console_fb_info = &info->fb_info;
#endif /* CONFIG_FB_COMPAT_XPMAC */
- }
}
#endif /* CONFIG_FB_OF */
@@ -2816,25 +3127,35 @@ __initfunc(void atyfb_setup(char *options, int *ints))
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
- }
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
- if (!strncmp(this_opt, "vmode:", 6)) {
- int vmode = simple_strtoul(this_opt+6, NULL, 0);
+ } else if (!strncmp(this_opt, "noblink", 7)) {
+ curblink = 0;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ } else if (!strncmp(this_opt, "vram:", 5))
+ default_vram = simple_strtoul(this_opt+5, NULL, 0);
+ else if (!strncmp(this_opt, "pll:", 4))
+ default_pll = simple_strtoul(this_opt+4, NULL, 0);
+ else if (!strncmp(this_opt, "mclk:", 5))
+ default_mclk = simple_strtoul(this_opt+5, NULL, 0);
+#if defined(CONFIG_PPC)
+ else if (!strncmp(this_opt, "vmode:", 6)) {
+ unsigned int vmode = simple_strtoul(this_opt+6, NULL, 0);
if (vmode > 0 && vmode <= VMODE_MAX)
default_vmode = vmode;
} else if (!strncmp(this_opt, "cmode:", 6)) {
- int depth = simple_strtoul(this_opt+6, NULL, 0);
- switch (depth) {
+ unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+ switch (cmode) {
+ case 0:
case 8:
- default_cmode = 0;
+ default_cmode = CMODE_8;
break;
case 15:
case 16:
- default_cmode = 1;
+ default_cmode = CMODE_16;
break;
case 24:
case 32:
- default_cmode = 2;
+ default_cmode = CMODE_32;
break;
}
}
@@ -2844,7 +3165,7 @@ __initfunc(void atyfb_setup(char *options, int *ints))
* Why do we need this silly Mach64 argument?
* We are already here because of mach64= so its redundant.
*/
- if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
+ else if (MACH_IS_ATARI && (!strncmp(this_opt, "Mach64:", 7))) {
static unsigned char m64_num;
static char mach64_str[80];
strncpy(mach64_str, this_opt+7, 80);
@@ -2914,8 +3235,7 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
/* Do we have to save the colormap? */
if (fb_display[currcon].cmap.len)
- fb_get_cmap(&fb_display[currcon].cmap, &fb_display[currcon].var, 1,
- atyfb_getcolreg, fb);
+ fb_get_cmap(&fb_display[currcon].cmap, 1, atyfb_getcolreg, fb);
/* Erase HW Cursor */
if (info->cursor)
@@ -2926,6 +3246,8 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
atyfb_decode_var(&fb_display[con].var, &par, info);
atyfb_set_par(&par, info);
+ atyfb_set_disp(&fb_display[con], info, par.crtc.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
/* Install new colormap */
do_install_cmap(con, fb);
@@ -2940,19 +3262,6 @@ static int atyfbcon_switch(int con, struct fb_info *fb)
}
/*
- * Update the `var' structure (called by fbcon.c)
- */
-
-static int atyfbcon_updatevar(int con, struct fb_info *fb)
-{
- struct fb_info_aty *info = (struct fb_info_aty *)fb;
-
- info->current_par.crtc.yoffset = fb_display[con].var.yoffset;
- set_off_pitch(&info->current_par, info);
- return 0;
-}
-
- /*
* Blank the display.
*/
@@ -2995,9 +3304,10 @@ static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
if (regno > 255)
return 1;
- *red = info->palette[regno].red;
- *green = info->palette[regno].green;
- *blue = info->palette[regno].blue;
+ *red = (info->palette[regno].red<<8) | info->palette[regno].red;
+ *green = (info->palette[regno].green<<8) | info->palette[regno].green;
+ *blue = (info->palette[regno].blue<<8) | info->palette[regno].blue;
+ *transp = 0;
return 0;
}
@@ -3016,6 +3326,9 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if (regno > 255)
return 1;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
info->palette[regno].red = red;
info->palette[regno].green = green;
info->palette[regno].blue = blue;
@@ -3025,30 +3338,39 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
(Gx == GP_CHIP_ID) || (Gx == GQ_CHIP_ID))
i |= 0x2; /*DAC_CNTL|0x2 turns off the extra brightness for gt*/
aty_st_8(DAC_CNTL, i, info);
- aty_st_8(DAC_REGS + DAC_MASK, 0xff, info);
+ aty_st_8(DAC_MASK, 0xff, info);
eieio();
scale = ((Gx != GX_CHIP_ID) && (Gx != CX_CHIP_ID) &&
(info->current_par.crtc.bpp == 16)) ? 3 : 0;
info->aty_cmap_regs->windex = regno << scale;
eieio();
- info->aty_cmap_regs->lut = red << scale;
+ info->aty_cmap_regs->lut = red;
eieio();
- info->aty_cmap_regs->lut = green << scale;
+ info->aty_cmap_regs->lut = green;
eieio();
- info->aty_cmap_regs->lut = blue << scale;
+ info->aty_cmap_regs->lut = blue;
eieio();
- if (regno < 16) {
+ if (regno < 16)
+ switch (info->current_par.crtc.bpp) {
#ifdef FBCON_HAS_CFB16
- fbcon_cfb16_cmap[regno] = (regno << 10) | (regno << 5) | regno;
+ case 16:
+ info->fbcon_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
+ regno;
+ break;
#endif
#ifdef FBCON_HAS_CFB24
- fbcon_cfb24_cmap[regno] = (regno << 16) | (regno << 8) | regno;
+ case 24:
+ info->fbcon_cmap.cfb24[regno] = (regno << 16) | (regno << 8) |
+ regno;
+ break;
#endif
#ifdef FBCON_HAS_CFB32
- fbcon_cfb32_cmap[regno] = (regno << 24) | (regno << 16) |
- (regno << 8) | regno;
+ case 32:
+ i = (regno << 8) | regno;
+ info->fbcon_cmap.cfb32[regno] = (i << 16) | i;
+ break;
#endif
- }
+ }
return 0;
}
@@ -3058,12 +3380,10 @@ static void do_install_cmap(int con, struct fb_info *info)
if (con != currcon)
return;
if (fb_display[con].cmap.len)
- fb_set_cmap(&fb_display[con].cmap, &fb_display[con].var, 1,
- atyfb_setcolreg, info);
+ fb_set_cmap(&fb_display[con].cmap, 1, atyfb_setcolreg, info);
else {
int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;
- fb_set_cmap(fb_default_cmap(size), &fb_display[con].var, 1,
- atyfb_setcolreg, info);
+ fb_set_cmap(fb_default_cmap(size), 1, atyfb_setcolreg, info);
}
}
@@ -3113,14 +3433,8 @@ static inline void aty_rectcopy(int srcx, int srcy, int dstx, int dsty,
} else
direction |= DST_X_LEFT_TO_RIGHT;
- wait_for_fifo(5, info);
+ wait_for_fifo(4, info);
aty_st_le32(DP_SRC, FRGD_SRC_BLIT, info);
- /*
- * ++Geert:
- * Warning: SRC_OFF_PITCH may be thrashed by writing to other registers
- * (e.g. CRTC_H_TOTAL_DISP, DP_SRC, DP_FRGD_CLR)
- */
- aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22, info);
aty_st_le32(SRC_Y_X, (srcx << 16) | srcy, info);
aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height, info);
aty_st_le32(DST_CNTL, direction, info);
@@ -3149,6 +3463,50 @@ static inline void aty_rectfill(int dstx, int dsty, u_int width, u_int height,
draw_rect(dstx, dsty, width, height, info);
}
+ /*
+ * Update the `var' structure (called by fbcon.c)
+ */
+
+static int atyfbcon_updatevar(int con, struct fb_info *fb)
+{
+ struct fb_info_aty *info = (struct fb_info_aty *)fb;
+ struct atyfb_par *par = &info->current_par;
+ struct display *p = &fb_display[con];
+ struct vc_data *conp = p->conp;
+ u32 yres, yoffset, sy, height;
+
+ yres = ((par->crtc.v_tot_disp >> 16) & 0x7ff) + 1;
+ yoffset = fb_display[con].var.yoffset;
+
+ sy = (conp->vc_rows + p->yscroll) * fontheight(p);
+ height = yres - conp->vc_rows * fontheight(p);
+
+ if (height && (yoffset + yres > sy)) {
+ u32 xres, xoffset;
+ u32 bgx;
+
+ xres = (((par->crtc.h_tot_disp >> 16) & 0xff) + 1) * 8;
+ xoffset = fb_display[con].var.xoffset;
+
+
+ bgx = attr_bgcol_ec(p, conp);
+ bgx |= (bgx << 8);
+ bgx |= (bgx << 16);
+
+ if (sy + height > par->crtc.vyres) {
+ wait_for_fifo(1, info);
+ aty_st_le32(SC_BOTTOM, sy + height - 1, info);
+ }
+ aty_rectfill(xoffset, sy, xres, height, bgx, info);
+ }
+
+ if (info->cursor && (yoffset + yres <= sy))
+ atyfb_cursor(p, CM_ERASE, info->cursor->pos.x, info->cursor->pos.y);
+
+ info->current_par.crtc.yoffset = yoffset;
+ set_off_pitch(&info->current_par, info);
+ return 0;
+}
/*
* Text console acceleration
@@ -3164,12 +3522,12 @@ static void fbcon_aty_bmove(struct display *p, int sy, int sx, int dy, int dx,
return;
#endif
- sx *= p->fontwidth;
- sy *= p->fontheight;
- dx *= p->fontwidth;
- dy *= p->fontheight;
- width *= p->fontwidth;
- height *= p->fontheight;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ dx *= fontwidth(p);
+ dy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
aty_rectcopy(sx, sy, dx, dy, width, height,
(struct fb_info_aty *)p->fb_info);
@@ -3190,10 +3548,10 @@ static void fbcon_aty_clear(struct vc_data *conp, struct display *p, int sy,
bgx |= (bgx << 8);
bgx |= (bgx << 16);
- sx *= p->fontwidth;
- sy *= p->fontheight;
- width *= p->fontwidth;
- height *= p->fontheight;
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
aty_rectfill(sx, sy, width, height, bgx,
(struct fb_info_aty *)p->fb_info);