patch-2.1.126 linux/drivers/video/atyfb.c
Next file: linux/drivers/video/fbcon.c
Previous file: linux/drivers/video/Makefile
Back to the patch index
Back to the overall index
- Lines: 372
- Date:
Thu Oct 15 15:24:18 1998
- Orig file:
v2.1.125/linux/drivers/video/atyfb.c
- Orig date:
Mon Oct 5 13:13:41 1998
diff -u --recursive --new-file v2.1.125/linux/drivers/video/atyfb.c linux/drivers/video/atyfb.c
@@ -1,4 +1,4 @@
-/* $Id: atyfb.c,v 1.77 1998/09/14 08:01:46 jj Exp $
+/* $Id: atyfb.c,v 1.81 1998/10/14 16:45:38 ecd Exp $
* linux/drivers/video/atyfb.c -- Frame buffer device for ATI Mach64
*
* Copyright (C) 1997-1998 Geert Uytterhoeven
@@ -28,6 +28,8 @@
- 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).
(Anyone to help with this?)
@@ -60,7 +62,7 @@
#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 <video/macmodes.h>
@@ -83,7 +85,7 @@
/*
* Debug flags.
*/
-#undef PLL_DEBUG
+#undef DEBUG
#define GUI_RESERVE 0x00001000
@@ -322,7 +324,7 @@
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
+#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,
@@ -366,7 +368,7 @@
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
@@ -401,7 +403,7 @@
static const u32 ref_clk_per = 1000000000000ULL/14318180;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
static int default_vmode = VMODE_NVRAM;
static int default_cmode = CMODE_NVRAM;
#endif
@@ -445,6 +447,14 @@
{ 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
};
+static const char *aty_gx_ram[8] __initdata = {
+ "DRAM", "VRAM", "VRAM", "DRAM", "GDRAM", "EVRAM", "EVRAM", "RESV"
+};
+
+static const char *aty_ct_ram[8] __initdata = {
+ "OFF", "DRAM", "EDO", "HPDRAM", "SDRAM", "SGRAM", "WRAM", "RESV"
+};
+
static inline u32 aty_ld_le32(volatile unsigned int regindex,
const struct fb_info_aty *info)
@@ -670,7 +680,7 @@
aty_st_8(CLOCK_CNTL + 1, (offset << 2) & ~PLL_WR_EN, info);
}
-#ifdef PLL_DEBUG
+#if defined(__sparc__) || defined(DEBUG)
static u8 aty_ld_pll(int offset, const struct fb_info_aty *info)
{
u8 res;
@@ -685,7 +695,7 @@
}
#endif
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
/*
* Apple monitor sense
@@ -725,7 +735,7 @@
return sense;
}
-#endif /* defined(CONFIG_PMAC) || defined(CONFIG_CHRP) */
+#endif /* defined(CONFIG_PPC) */
/* ------------------------------------------------------------------------- */
@@ -2289,6 +2299,78 @@
}
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_REGS + 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__ */
/*
@@ -2302,9 +2384,9 @@
int j, k;
struct fb_var_screeninfo var;
struct display *disp;
- const char *chipname = NULL;
+ const char *chipname = NULL, *ramname = NULL;
int pll, mclk;
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#if defined(CONFIG_PPC)
int sense;
#endif
@@ -2325,6 +2407,7 @@
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;
@@ -2339,6 +2422,7 @@
} 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)) {
@@ -2454,17 +2538,34 @@
info->total_vram += 0x400000;
}
- printk("%d%c %d MHz PLL, %d Mhz MCLK\n",
+ 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', pll, mclk);
-
+ info->total_vram == 0x80000 ? 'K' : 'M', ramname, pll, 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)
@@ -2487,9 +2588,9 @@
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 */
+#endif /* !CONFIG_PPC */
if (noaccel)
var.accel_flags &= ~FB_ACCELF_TEXT;
else
@@ -2520,6 +2621,9 @@
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];
@@ -2555,6 +2659,7 @@
struct fb_info_aty *info;
unsigned long addr;
#ifdef __sparc__
+ extern void (*prom_palette) (int);
extern int con_is_present(void);
struct pcidev_cookie *pcp;
char prop[128];
@@ -2703,6 +2808,9 @@
struct fb_var_screeninfo *var = &default_var;
u32 v_total, h_total;
struct crtc crtc;
+ u8 pll_regs[16];
+ u8 clock_cntl;
+ unsigned int N, P, Q, M, T;
crtc.vxres = prom_getintdefault(node, "width", 1024);
crtc.vyres = prom_getintdefault(node, "height", 768);
@@ -2715,15 +2823,59 @@
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);
+
+ /*
+ * 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);
+ /* printk("atyfb: PLL %2d: %02x\n", i, pll_regs[i]); */
+ }
+ /*
+ * PLL Reference Devider M:
+ */
+ M = pll_regs[2];
+ /* printk("atyfb: M: %02x\n", M); */
+
+ /*
+ * PLL Feedback Devider N (Dependant on CLOCK_CNTL):
+ */
+ N = pll_regs[7 + (clock_cntl & 3)];
+ /* printk("atyfb: N: %02x\n", N); */
+
+ /*
+ * PLL Post Devider P (Dependant on CLOCK_CNTL):
+ */
+ P = 1 << (pll_regs[6] >> ((clock_cntl & 3) << 1));
+ /* printk("atyfb: P: %2d\n", P); */
+
+ /*
+ * PLL Devider Q:
+ */
+ Q = N / P;
+ /* printk("atyfb: Q: %d\n", Q); */
+
+ /*
+ * Target Frequency:
+ *
+ * T * M
+ * Q = -------
+ * 2 * R
+ *
+ * where R is XTALIN (= 14318 kHz).
+ */
+ T = 2 * Q * 14318 / M;
+ /* printk("atyfb: T: %d\n", T); */
+
+ default_var.pixclock =
+ ((1000000000000ULL / v_total) * 1000) / (T * h_total);
+ /* printk("atyfb: pixclock: %d\n", default_var.pixclock); */
}
#else /* __sparc__ */
@@ -2764,6 +2916,9 @@
}
#ifdef __sparc__
+ if (!prom_palette)
+ prom_palette = atyfb_palette;
+
/*
* Add /dev/fb mmap values.
*/
@@ -2920,7 +3075,7 @@
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
}
-#if defined(CONFIG_PMAC) || defined(CONFIG_CHRP)
+#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)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov