patch-2.1.124 linux/drivers/video/atyfb.c
Next file: linux/drivers/video/bwtwofb.c
Previous file: linux/drivers/video/ati-vt.h
Back to the patch index
Back to the overall index
- Lines: 1451
- Date:
Thu Oct 1 10:02:21 1998
- Orig file:
v2.1.123/linux/drivers/video/atyfb.c
- Orig date:
Tue Jul 28 14:21:09 1998
diff -u --recursive --new-file v2.1.123/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
@@ -1,9 +1,9 @@
-/*
+/* $Id: atyfb.c,v 1.77 1998/09/14 08:01:46 jj 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,10 @@
TODO:
- (ecd):
-
- - fix initialization of cursor timer.
-
- - add code to support cursor on all cards and all ramdacs.
-
- - make cursor parameters controllable via ioctl()s.
+ - cursor support on all cards and all ramdacs.
+ - cursor parameters controlable via ioctl()s.
- (Anyone to help with all this?)
+ (Anyone to help with this?)
******************************************************************************/
@@ -68,26 +63,30 @@
#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
#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 PLL_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 +165,7 @@
};
#define DEFAULT_CURSOR_BLINK_RATE (20)
+#define CURSOR_DRAW_DELAY (2)
struct aty_cursor {
int enable;
@@ -179,6 +179,7 @@
u32 color[2];
u8 bits[8][64];
u8 mask[8][64];
+ u8 *ram;
struct timer_list *timer;
};
@@ -188,8 +189,6 @@
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 +207,19 @@
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 +311,7 @@
*/
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 +322,9 @@
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);
+#ifdef PLL_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 +335,17 @@
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,6 +359,8 @@
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,
@@ -383,6 +396,8 @@
static char atyfb_name[16] = "ATY Mach64";
static char fontname[40] __initdata = { 0 };
+static char curblink __initdata = 1;
+static char noaccel __initdata = 0;
static const u32 ref_clk_per = 1000000000000ULL/14318180;
@@ -515,6 +530,7 @@
aty_ld_le32(GEN_TEST_CNTL, info) | GUI_ENGINE_ENABLE, info);
/* ensure engine is not locked up by clearing any FIFO or */
/* HOST errors */
+ aty_st_le32(0xf4,0xa955,info);
aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, info) | BUS_HOST_ERR_ACK |
BUS_FIFO_ERR_ACK, info);
}
@@ -620,6 +636,12 @@
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,20 +670,20 @@
aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
}
-#if 0 /* ecd debug */
+#ifdef PLL_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)
@@ -768,8 +790,7 @@
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 +809,9 @@
}
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 +824,8 @@
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 +833,7 @@
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 +849,12 @@
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 +870,7 @@
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 +880,9 @@
}
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,46 +893,79 @@
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->timer) {
- c->timer = kmalloc(sizeof(*c->timer), GFP_KERNEL);
- if (!c->timer)
- return;
-
- c->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
-
- 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);
- }
-
- c->vbl_cnt = c->blink_rate;
+ if (c->on)
+ aty_set_cursor(fb, 1);
+ else
+ c->vbl_cnt = CURSOR_DRAW_DELAY;
c->enable = 1;
break;
}
}
+__initfunc(static struct aty_cursor *
+aty_init_cursor(struct fb_info_aty *fb))
+{
+ struct aty_cursor *cursor;
+ unsigned long addr;
+
+ cursor = kmalloc(sizeof(struct aty_cursor), GFP_ATOMIC);
+ if (!cursor)
+ return 0;
+ memset(cursor, 0, sizeof(*cursor));
+
+ cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
+ if (!cursor->timer) {
+ kfree(cursor);
+ return 0;
+ }
+ memset(cursor->timer, 0, sizeof(*cursor->timer));
+
+ 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 (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
atyfb_set_font(struct display *d, int width, int height)
{
@@ -923,7 +979,6 @@
height = 16;
}
- c->offset = fb->total_vram - 0x1000;
c->hot.x = 0;
c->hot.y = 0;
c->size.x = width;
@@ -972,7 +1027,7 @@
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 +1084,8 @@
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,7 +1130,7 @@
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))) {
@@ -1129,7 +1186,7 @@
{
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 +1202,21 @@
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
@@ -1282,8 +1341,7 @@
}
}
-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 +1387,7 @@
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 +1395,7 @@
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 +1417,7 @@
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 +1427,7 @@
/* 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 +1435,7 @@
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 +1448,6 @@
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);
@@ -1491,11 +1531,10 @@
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 +1544,6 @@
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 +1575,7 @@
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 +1647,7 @@
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 +1661,7 @@
(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 +1694,7 @@
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 +1717,8 @@
/* 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 +1758,18 @@
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 +1779,7 @@
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 +1796,10 @@
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;
@@ -1891,32 +1930,6 @@
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 +1967,47 @@
}
+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 +2055,13 @@
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 +2109,7 @@
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 +2134,7 @@
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 +2144,27 @@
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 +2186,15 @@
/* 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 +2245,7 @@
if (start > offset)
continue;
- if (offset > end)
+ if (offset >= end)
continue;
map_size = fb->mmap_map[i].size - (offset - start);
@@ -2269,7 +2321,7 @@
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;
@@ -2343,7 +2395,6 @@
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;
@@ -2398,6 +2449,15 @@
info->total_vram = 0x80000;
}
+ if (Gx == GI_CHIP_ID) {
+ if (aty_ld_le32(CONFIG_STAT1, info) & 0x40000000)
+ info->total_vram += 0x400000;
+ }
+
+ printk("%d%c %d MHz PLL, %d Mhz MCLK\n",
+ info->total_vram == 0x80000 ? 512 : (info->total_vram >> 20),
+ info->total_vram == 0x80000 ? 'K' : 'M', pll, mclk);
+
if (info->bus_type == ISA)
if ((info->total_vram == 0x400000) || (info->total_vram == 0x800000)) {
/* protect GUI-regs if complete Aperture is VRAM */
@@ -2411,8 +2471,13 @@
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;
@@ -2425,21 +2490,23 @@
#else /* !CONFIG_PMAC && !CONFIG_CHRP */
var = default_var;
#endif /* !CONFIG_PMAC && !CONFIG_CHRP */
- var.accel_flags |= FB_ACCELF_TEXT;
+ 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,6 +2518,7 @@
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;
for (j = 0; j < 16; j++) {
k = color_table[j];
@@ -2459,16 +2527,14 @@
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)
@@ -2490,7 +2556,10 @@
unsigned long addr;
#ifdef __sparc__
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 +2605,17 @@
*/
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 +2634,7 @@
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 +2655,10 @@
/*
* 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 +2676,54 @@
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;
+ u32 v_total, h_total;
+ struct crtc crtc;
+
+ 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);
+
+ /*
+ * FIXME: Read the PLL to figure actual Refresh Rate.
+ * Default to 66Hz for now.
+ */
+ 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;
+ default_var.pixclock = 1000000000000ULL/(66*h_total*v_total);
}
#else /* __sparc__ */
@@ -2689,7 +2760,24 @@
if (info->mmap_map)
kfree(info->mmap_map);
kfree(info);
+ return;
}
+
+#ifdef __sparc__
+ /*
+ * 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 +2793,11 @@
}
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
@@ -2739,6 +2832,7 @@
for (; dp; dp = dp->next) {
switch (dp->n_addrs) {
case 1:
+ case 2:
case 3:
addr = dp->addrs[0].address;
break;
@@ -2756,6 +2850,11 @@
}
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;
@@ -2816,25 +2915,30 @@
break;
memcpy(fontname, this_opt + 5, i);
fontname[i] = 0;
+ } else if (!strncmp(this_opt, "noblink", 7)) {
+ curblink = 0;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
}
#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, "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 +2948,7 @@
* 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 +3018,7 @@
/* 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 +3029,8 @@
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 +3045,6 @@
}
/*
- * 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 +3087,10 @@
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 +3109,9 @@
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;
@@ -3031,24 +3127,33 @@
(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 +3163,10 @@
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);
}
}
@@ -3149,6 +3252,50 @@
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 +3311,12 @@
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 +3337,10 @@
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);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov