[PATCH] radeonfb ... again

Peter Horton (pdh@berserk.demon.co.uk)
Mon, 15 Apr 2002 23:14:20 +0100


More "radeonfb" patch, still against 2.4.19-pre2.

* Remove palette hacks for soft cursor by copying "revc" method.
* Added "nostretch" option to disable stretching on DFPs.
* Fast console switch (don't change PLL unless we have to).
* Added module options.
* Other fixes and cleanups.

P.

diff -ur linux-2.4.19-pre2/drivers/video/radeon.h linux.pdh/drivers/video/radeon.h
--- linux-2.4.19-pre2/drivers/video/radeon.h Sat Apr 6 16:34:27 2002
+++ linux.pdh/drivers/video/radeon.h Thu Apr 11 23:57:10 2002
@@ -379,6 +379,7 @@
#define SC_TOP_LEFT 0x16EC
#define SC_BOTTOM_RIGHT 0x16F0
#define SRC_SC_BOTTOM_RIGHT 0x16F4
+#define RB2D_DSTCACHE_MODE 0x3428
#define RB2D_DSTCACHE_CTLSTAT 0x342C
#define LVDS_GEN_CNTL 0x02d0
#define LVDS_PLL_CNTL 0x02d4
@@ -395,6 +396,7 @@
#define RADEON_BIOS_6_SCRATCH 0x0028
#define RADEON_BIOS_7_SCRATCH 0x002c

+#define HDP_SOFT_RESET (1 << 26)

#define CLK_PIN_CNTL 0x0001
#define PPLL_CNTL 0x0002
diff -ur linux-2.4.19-pre2/drivers/video/radeonfb.c linux.pdh/drivers/video/radeonfb.c
--- linux-2.4.19-pre2/drivers/video/radeonfb.c Sat Apr 6 16:34:27 2002
+++ linux.pdh/drivers/video/radeonfb.c Sun Apr 14 19:18:16 2002
@@ -22,6 +22,13 @@
*
* Special thanks to ATI DevRel team for their hardware donations.
*
+ * 2002-04-xx Added MTRR support. Fixed 8bpp acceleration. Added
+ * acceleration for 16/32bpp. Applied fix from XFree86
+ * for hard crash on accelerator reset. Fixed up the
+ * colour stuff. Made "ypan" work. Don't reload PLL
+ * unless pixel clock changes. Soft cursor improvements.
+ * Add module options. Various other fixes / cleanups.
+ * Peter Horton <pdh@colonel-panic.org>
*/


@@ -44,6 +51,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/vmalloc.h>
+#include <asm/mtrr.h>

#include <asm/io.h>
#if defined(__powerpc__)
@@ -73,18 +81,22 @@
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
-#include <video/fbcon-cfb24.h>
+/* #include <video/fbcon-cfb24.h> */
#include <video/fbcon-cfb32.h>

#include "radeon.h"


-#define DEBUG 0
+#define FIX_DEPTH_15 1
+
+#define DEBUG 0
+
+#define _RTRACE(f,a...) do{printk(KERN_DEBUG "radeonfb: " f "\n", ##a);}while(0)

#if DEBUG
-#define RTRACE printk
+#define RTRACE(f,a...) _RTRACE(f,##a)
#else
-#define RTRACE if(0) printk
+#define RTRACE(f,a...)
#endif


@@ -261,6 +273,8 @@
u32 mmio_base;
u32 fb_base;

+ int mtrr_hdl;
+
struct pci_dev *pdev;

unsigned char *EDID;
@@ -270,13 +284,16 @@
int currcon;
struct display *currcon_display;

- struct { u8 red, green, blue, pad; } palette[256];
+ u8 palette_red[256];
+ u8 palette_grn[256];
+ u8 palette_blu[256];

int chipset;
int video_ram;
u8 rev;
int pitch, bpp, depth;
int xres, yres, pixclock;
+ int ppixclock;

int use_default_var;
int got_dfpinfo;
@@ -299,17 +316,16 @@

struct ram_info ram;

+#if 0
u32 hack_crtc_ext_cntl;
u32 hack_crtc_v_sync_strt_wid;
+#endif

#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
union {
#if defined(FBCON_HAS_CFB16)
u_int16_t cfb16[16];
#endif
-#if defined(FBCON_HAS_CFB24)
- u_int32_t cfb24[16];
-#endif
#if defined(FBCON_HAS_CFB32)
u_int32_t cfb32[16];
#endif
@@ -474,17 +490,15 @@
}


-static inline int var_to_depth(const struct fb_var_screeninfo *var)
+static __inline__ int var_to_depth(const struct fb_var_screeninfo *var)
{
- if (var->bits_per_pixel != 16)
- return var->bits_per_pixel;
- return (var->green.length == 6) ? 16 : 15;
+ return (var->bits_per_pixel == 16 && var->green.length == 5) ? 15 : var->bits_per_pixel;
}


static void _radeon_engine_reset(struct radeonfb_info *rinfo)
{
- u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset;
+ u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset, host_path_cntl;

radeon_engine_flush (rinfo);

@@ -498,6 +512,9 @@
FORCEON_YCLKB |
FORCEON_MC |
FORCEON_AIC));
+
+ host_path_cntl = INREG(HOST_PATH_CNTL);
+
rbbm_soft_reset = INREG(RBBM_SOFT_RESET);

OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset |
@@ -507,8 +524,7 @@
SOFT_RESET_RE |
SOFT_RESET_PP |
SOFT_RESET_E2 |
- SOFT_RESET_RB |
- SOFT_RESET_HDP);
+ SOFT_RESET_RB);
INREG(RBBM_SOFT_RESET);
OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32)
~(SOFT_RESET_CP |
@@ -517,13 +533,16 @@
SOFT_RESET_RE |
SOFT_RESET_PP |
SOFT_RESET_E2 |
- SOFT_RESET_RB |
- SOFT_RESET_HDP));
+ SOFT_RESET_RB));
INREG(RBBM_SOFT_RESET);

- OUTPLL(MCLK_CNTL, mclk_cntl);
- OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET);
+ INREG(HOST_PATH_CNTL);
+ OUTREG(HOST_PATH_CNTL, host_path_cntl);
+
OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
+ OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
+ OUTPLL(MCLK_CNTL, mclk_cntl);

return;
}
@@ -531,6 +550,7 @@
#define radeon_engine_reset() _radeon_engine_reset(rinfo)


+#if 0
static __inline__ u8 radeon_get_post_div_bitval(int post_div)
{
switch (post_div) {
@@ -552,6 +572,7 @@
return 0x02;
}
}
+#endif



@@ -592,16 +613,29 @@
* globals
*/

-static char fontname[40] __initdata;
static char *mode_option __initdata;
-static char noaccel __initdata = 0;
-static int panel_yres __initdata = 0;
-static char force_dfp __initdata = 0;
-static struct radeonfb_info *board_list = NULL;
+static struct radeonfb_info *board_list;
+
+char *font __initdata;
+int noaccel;
+int nofastsw;
+int fb16fix;
+int nostretch;
+int nomtrr __initdata;
+int panel_yres __initdata;
+int dfp __initdata;

#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_radeon8;
#endif
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_radeon16;
+static struct display_switch fbcon_radeon16_noaccel;
+#endif
+#ifdef FBCON_HAS_CFB32
+static struct display_switch fbcon_radeon32;
+static struct display_switch fbcon_radeon32_noaccel;
+#endif


/*
@@ -686,6 +720,59 @@
};


+int __init radeonfb_setup (char *options)
+{
+ static char *opts[] = {
+ "font:",
+ "noaccel",
+ "dfp",
+ "panel_yres:",
+ "nomtrr",
+ "fb16fix",
+ "nofastsw",
+ "nostretch",
+ NULL
+ };
+
+ char *this_opt, *value;
+ int idx;
+
+ if (!options || !*options)
+ return 0;
+
+ while ((this_opt = strsep (&options, ",")) != NULL) {
+
+ if (!*this_opt)
+ continue;
+
+ for (idx = 0; opts[idx] && strncmp(this_opt, opts[idx], strlen(opts[idx])); ++idx)
+ ;
+ if (!opts[idx]) {
+ mode_option = this_opt;
+ continue;
+ }
+ value = this_opt + strlen(opts[idx]);
+
+ switch(idx) {
+
+ case 0: font = value; break;
+ case 1: noaccel = 1; break;
+ case 2: dfp = 1; break;
+
+ case 3:
+ panel_yres = simple_strtoul(value, NULL, 0);
+ break;
+
+ case 4: nomtrr = 1; break;
+ case 5: fb16fix = 1; break;
+ case 6: nofastsw = 1; break;
+ case 7: nostretch = 1; break;
+ }
+ }
+
+ return 0;
+}
+
static struct pci_driver radeonfb_driver = {
name: "radeonfb",
id_table: radeonfb_pci_table,
@@ -696,6 +783,13 @@

int __init radeonfb_init (void)
{
+ /* XXX stop the module being unloaded. on my machine *
+ * it causes a crash, and looking at the code it *
+ * doesn't restore PLL settings so the chances of it *
+ * working are zero anyway :pdh */
+
+ MOD_DEC_USE_COUNT;
+
return pci_module_init (&radeonfb_driver);
}

@@ -706,47 +800,12 @@
}


-int __init radeonfb_setup (char *options)
-{
- char *this_opt;
-
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep (&options, ",")) != NULL) {
- if (!*this_opt)
- continue;
- if (!strncmp (this_opt, "font:", 5)) {
- char *p;
- int i;
-
- p = this_opt + 5;
- for (i=0; i<sizeof (fontname) - 1; i++)
- if (!*p || *p == ' ' || *p == ',')
- break;
- memcpy(fontname, this_opt + 5, i);
- } else if (!strncmp(this_opt, "noaccel", 7)) {
- noaccel = 1;
- } else if (!strncmp(this_opt, "dfp", 3)) {
- force_dfp = 1;
- } else if (!strncmp(this_opt, "panel_yres:", 11)) {
- panel_yres = simple_strtoul((this_opt+11), NULL, 0);
- } else
- mode_option = this_opt;
- }
-
- return 0;
-}
-
#ifdef MODULE
module_init(radeonfb_init);
module_exit(radeonfb_exit);
#endif


-MODULE_AUTHOR("Ani Joshi");
-MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
-MODULE_LICENSE("GPL");

static int radeonfb_pci_register (struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -755,7 +814,7 @@
u32 tmp;
int i, j;

- RTRACE("radeonfb_pci_register BEGIN\n");
+ RTRACE("radeonfb_pci_register BEGIN");

rinfo = kmalloc (sizeof (struct radeonfb_info), GFP_KERNEL);
if (!rinfo) {
@@ -915,7 +974,7 @@
rinfo->bios_seg = radeon_find_rom(rinfo);
radeon_get_pllinfo(rinfo, rinfo->bios_seg);

- RTRACE("radeonfb: probed %s %dk videoram\n", (rinfo->ram_type), (rinfo->video_ram/1024));
+ RTRACE("probed %s %dk videoram", (rinfo->ram_type), (rinfo->video_ram/1024));

#if !defined(__powerpc__)
radeon_get_moninfo(rinfo);
@@ -960,9 +1019,6 @@
return -ENODEV;
}

- /* XXX turn off accel for now, blts aren't working right */
- noaccel = 1;
-
/* currcon not yet configured, will be set by first switch */
rinfo->currcon = -1;

@@ -977,9 +1033,9 @@
/* init palette */
for (i=0; i<16; i++) {
j = color_table[i];
- rinfo->palette[i].red = default_red[j];
- rinfo->palette[i].green = default_grn[j];
- rinfo->palette[i].blue = default_blu[j];
+ rinfo->palette_red[i] = default_red[j];
+ rinfo->palette_grn[i] = default_grn[j];
+ rinfo->palette_blu[i] = default_blu[j];
}

pci_set_drvdata(pdev, rinfo);
@@ -998,10 +1054,16 @@
return -ENODEV;
}

+#ifdef CONFIG_MTRR
+ rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys, rinfo->video_ram, MTRR_TYPE_WRCOMB, 1);
+#endif
+
+#if 0
if (!noaccel) {
/* initialize the engine */
radeon_engine_init (rinfo);
}
+#endif

#ifdef CONFIG_PMAC_BACKLIGHT
if (rinfo->dviDisp_type == MT_LCD)
@@ -1029,7 +1091,7 @@
GET_MON_NAME(rinfo->crtDisp_type));
}

- RTRACE("radeonfb_pci_register END\n");
+ RTRACE("radeonfb_pci_register END");

return 0;
}
@@ -1044,8 +1106,16 @@
return;

/* restore original state */
+
+ /* XXX what about the PLL? :pdh */
+
radeon_write_mode (rinfo, &rinfo->init_state);

+#ifdef CONFIG_MTRR
+ if(rinfo->mtrr_hdl >= 0)
+ mtrr_del(rinfo->mtrr_hdl, 0, 0);
+#endif
+
unregister_framebuffer ((struct fb_info *) rinfo);

iounmap ((void*)rinfo->mmio_base);
@@ -1157,7 +1227,7 @@
rinfo->pll.ppll_min = pll.PCLK_min_freq;
rinfo->pll.ppll_max = pll.PCLK_max_freq;

- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from BIOS\n",
+ _RTRACE("ref_clk=%d, ref_div=%d, xclk=%d from BIOS",
rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
} else {
#ifdef CONFIG_ALL_PPC
@@ -1177,7 +1247,7 @@
rinfo->pll.ppll_min = 12000;
rinfo->pll.ppll_max = 35000;

- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d from OF\n",
+ _RTRACE("ref_clk=%d, ref_div=%d, xclk=%d from OF",
rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);

return;
@@ -1212,7 +1282,7 @@
break;
}

- printk("radeonfb: ref_clk=%d, ref_div=%d, xclk=%d defaults\n",
+ _RTRACE("ref_clk=%d, ref_div=%d, xclk=%d defaults",
rinfo->pll.ref_clk, rinfo->pll.ref_div, rinfo->pll.xclk);
}
}
@@ -1222,7 +1292,7 @@
{
unsigned int tmp;

- if (force_dfp) {
+ if (dfp) {
rinfo->dviDisp_type = MT_DFP;
return;
}
@@ -1271,7 +1341,7 @@
{
#ifdef CONFIG_ALL_PPC
if (!radeon_get_EDID_OF(rinfo))
- RTRACE("radeonfb: could not retrieve EDID from OF\n");
+ RTRACE("radeonfb: could not retrieve EDID from OF");
#else
/* XXX use other methods later */
#endif
@@ -1540,15 +1610,12 @@
radeon_engine_reset ();

radeon_fifo_wait (1);
- OUTREG(DSTCACHE_MODE, 0);
-
- /* XXX */
- rinfo->pitch = ((rinfo->xres * (rinfo->bpp / 8) + 0x3f)) >> 6;
+ OUTREG(RB2D_DSTCACHE_MODE, 0);

radeon_fifo_wait (1);
temp = INREG(DEFAULT_PITCH_OFFSET);
OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) |
- (rinfo->pitch << 0x16)));
+ (rinfo->pitch << 16)));

radeon_fifo_wait (1);
OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
@@ -1589,6 +1656,8 @@
static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo)
{
struct fb_info *info;
+ char *ptr;
+ int len;

info = &rinfo->info;

@@ -1597,13 +1666,21 @@
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &radeon_fb_ops;
info->display_fg = NULL;
- strncpy (info->fontname, fontname, sizeof (info->fontname));
- info->fontname[sizeof (info->fontname) - 1] = 0;
info->changevar = NULL;
info->switch_con = radeonfb_switch;
info->updatevar = radeonfb_updatevar;
info->blank = radeonfb_blank;

+ len = 0;
+ if(font) {
+ ptr = strchr(font, ',');
+ len = (ptr == NULL) ? strlen(font) : ptr - font;
+ if(len > sizeof(info->fontname) - 1)
+ len = sizeof(info->fontname) - 1;
+ memcpy(info->fontname, font, len);
+ }
+ info->fontname[len] = '\0';
+
if (radeon_init_disp (rinfo) < 0)
return -1;

@@ -1635,11 +1712,8 @@

radeon_set_dispsw (rinfo, disp);

- if (noaccel)
- disp->scrollmode = SCROLL_YREDRAW;
- else
- disp->scrollmode = 0;
-
+ disp->scrollmode = noaccel ? SCROLL_YREDRAW : 0;
+
rinfo->currcon_display = disp;

if ((radeon_init_disp_var (rinfo)) < 0)
@@ -1665,13 +1739,15 @@
}
else
#endif
- if (rinfo->use_default_var)
+#ifndef MODULE
+ if (rinfo->use_default_var == 0)
+ fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60",
+ NULL, 0, NULL, 0);
+ else
+#endif
/* We will use the modified default far */
rinfo->disp.var = radeonfb_default_var;
- else

- fb_find_mode (&rinfo->disp.var, &rinfo->info, "640x480-8@60",
- NULL, 0, NULL, 0);

if (noaccel)
rinfo->disp.var.accel_flags &= ~FB_ACCELF_TEXT;
@@ -1703,30 +1779,22 @@
switch (disp->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8:
- disp->dispsw = &fbcon_cfb8;
+ disp->dispsw = accel ? &fbcon_radeon8 : &fbcon_cfb8;
disp->visual = FB_VISUAL_PSEUDOCOLOR;
disp->line_length = disp->var.xres_virtual;
break;
#endif
#ifdef FBCON_HAS_CFB16
case 16:
- disp->dispsw = &fbcon_cfb16;
+ disp->dispsw = accel ? &fbcon_radeon16 : &fbcon_radeon16_noaccel;
disp->dispsw_data = &rinfo->con_cmap.cfb16;
disp->visual = FB_VISUAL_DIRECTCOLOR;
disp->line_length = disp->var.xres_virtual * 2;
break;
#endif
-#ifdef FBCON_HAS_CFB32
- case 24:
- disp->dispsw = &fbcon_cfb24;
- disp->dispsw_data = &rinfo->con_cmap.cfb24;
- disp->visual = FB_VISUAL_DIRECTCOLOR;
- disp->line_length = disp->var.xres_virtual * 4;
- break;
-#endif
#ifdef FBCON_HAS_CFB32
case 32:
- disp->dispsw = &fbcon_cfb32;
+ disp->dispsw = accel ? &fbcon_radeon32 : &fbcon_radeon32_noaccel;
disp->dispsw_data = &rinfo->con_cmap.cfb32;
disp->visual = FB_VISUAL_DIRECTCOLOR;
disp->line_length = disp->var.xres_virtual * 4;
@@ -1736,8 +1804,8 @@
printk ("radeonfb: setting fbcon_dummy renderer\n");
disp->dispsw = &fbcon_dummy;
}
-
- return;
+
+ disp->next_line = disp->line_length;
}


@@ -1759,6 +1827,7 @@



+#if 0
static int radeonfb_do_maximize(struct radeonfb_info *rinfo,
struct fb_var_screeninfo *var,
struct fb_var_screeninfo *v,
@@ -1819,9 +1888,18 @@

return 0;
}
+#endif



+static void set_palette_entry(struct radeonfb_info *rinfo, unsigned idx, unsigned red, unsigned grn, unsigned blu)
+{
+ OUTREG(PALETTE_INDEX, idx);
+ OUTREG(PALETTE_DATA, (red << 16) | (grn << 8) | blu);
+
+ udelay(1); /* is this necessary ? */
+}
+
/*
* fb ops
*/
@@ -1844,7 +1922,7 @@
fix->type_aux = disp->type_aux;
fix->visual = disp->visual;

- fix->xpanstep = 8;
+ fix->xpanstep = 0;
fix->ypanstep = 1;
fix->ywrapstep = 0;

@@ -1855,7 +1933,7 @@
if (noaccel)
fix->accel = FB_ACCEL_NONE;
else
- fix->accel = 40; /* XXX */
+ fix->accel = FB_ACCEL_ATI_RADEON;

return 0;
}
@@ -1878,134 +1956,119 @@
struct fb_info *info)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
- struct display *disp;
+ int accel, bytpp, pitch, mon, chgvar;
struct fb_var_screeninfo v;
- int nom, den, accel;
- unsigned chgvar = 0;
+ struct display *disp;

disp = (con < 0) ? rinfo->info.disp : &fb_display[con];

accel = var->accel_flags & FB_ACCELF_TEXT;

- if (con >= 0) {
- chgvar = ((disp->var.xres != var->xres) ||
- (disp->var.yres != var->yres) ||
- (disp->var.xres_virtual != var->xres_virtual) ||
- (disp->var.yres_virtual != var->yres_virtual) ||
- (disp->var.bits_per_pixel != var->bits_per_pixel) ||
- memcmp (&disp->var.red, &var->red, sizeof (var->red)) ||
- memcmp (&disp->var.green, &var->green, sizeof (var->green)) ||
- memcmp (&disp->var.blue, &var->blue, sizeof (var->blue)));
- }
+ /* XXX we should probably fixup 'var' in place rather than *
+ * fixing up a copy as FBIOPUT_VSCREENINFO goes to the *
+ * trouble of copying the structure back to user space :pdh */

memcpy (&v, var, sizeof (v));

- switch (v.bits_per_pixel) {
- case 0 ... 8:
- v.bits_per_pixel = 8;
- break;
- case 9 ... 16:
- v.bits_per_pixel = 16;
- break;
- case 17 ... 24:
- v.bits_per_pixel = 24;
- break;
- case 25 ... 32:
- v.bits_per_pixel = 32;
- break;
- default:
- return -EINVAL;
- }
-
- switch (var_to_depth(&v)) {
#ifdef FBCON_HAS_CFB8
- case 8:
- nom = den = 1;
- disp->line_length = v.xres_virtual;
- disp->visual = FB_VISUAL_PSEUDOCOLOR;
- v.red.offset = v.green.offset = v.blue.offset = 0;
- v.red.length = v.green.length = v.blue.length = 8;
- v.transp.offset = v.transp.length = 0;
- break;
+ if(v.bits_per_pixel <= 8) {
+ v.bits_per_pixel = 8;
+ v.red.offset = v.green.offset = v.blue.offset = 0;
+ v.red.length = v.green.length = v.blue.length = 8;
+ v.transp.offset = v.transp.length = 0;
+ } else
#endif
-
#ifdef FBCON_HAS_CFB16
- case 15:
- nom = 2;
- den = 1;
- disp->line_length = v.xres_virtual * 2;
- disp->visual = FB_VISUAL_DIRECTCOLOR;
- v.red.offset = 10;
- v.green.offset = 5;
- v.red.offset = 0;
- v.red.length = v.green.length = v.blue.length = 5;
- v.transp.offset = v.transp.length = 0;
- break;
- case 16:
- nom = 2;
- den = 1;
- disp->line_length = v.xres_virtual * 2;
- disp->visual = FB_VISUAL_DIRECTCOLOR;
- v.red.offset = 11;
- v.green.offset = 5;
- v.blue.offset = 0;
- v.red.length = 5;
- v.green.length = 6;
- v.blue.length = 5;
- v.transp.offset = v.transp.length = 0;
- break;
-#endif
-
-#ifdef FBCON_HAS_CFB24
- case 24:
- nom = 4;
- den = 1;
- disp->line_length = v.xres_virtual * 3;
- disp->visual = FB_VISUAL_DIRECTCOLOR;
- v.red.offset = 16;
- v.green.offset = 8;
- v.blue.offset = 0;
- v.red.length = v.blue.length = v.green.length = 8;
- v.transp.offset = v.transp.length = 0;
- break;
+ if(v.bits_per_pixel <= 16) {
+#if FIX_DEPTH_15
+ if(v.bits_per_pixel < 16)
+ v.green.length = 5;
+#endif
+ if(v.green.length < 6)
+ v.green.length = 5;
+ else if(v.green.length > 6)
+ v.green.length = 6;
+ v.bits_per_pixel = 16;
+ v.red.offset = v.green.length + 5;
+ v.green.offset = 5;
+ v.blue.offset = 0;
+ v.red.length = 5;
+ v.blue.length = 5;
+ v.transp.offset = v.transp.length = 0;
+ } else
#endif
#ifdef FBCON_HAS_CFB32
- case 32:
- nom = 4;
- den = 1;
- disp->line_length = v.xres_virtual * 4;
- disp->visual = FB_VISUAL_DIRECTCOLOR;
- v.red.offset = 16;
- v.green.offset = 8;
- v.blue.offset = 0;
- v.red.length = v.blue.length = v.green.length = 8;
- v.transp.offset = 24;
- v.transp.length = 8;
- break;
+ if(v.bits_per_pixel <= 32) {
+ v.bits_per_pixel = 32;
+ v.red.offset = 16;
+ v.green.offset = 8;
+ v.blue.offset = 0;
+ v.red.length = v.blue.length = v.green.length = 8;
+ /* v.transp.offset = 24; v.transp.length = 8; */
+ v.transp.offset = v.transp.length = 0;
+ } else
#endif
- default:
- printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n",
- var->xres, var->yres, var->bits_per_pixel);
- return -EINVAL;
- }
+ return -EINVAL;
+
+ v.red.msb_right = v.green.msb_right = v.blue.msb_right = v.transp.msb_right = 0;
+
+ mon = PRIMARY_MONITOR(rinfo);
+
+ if(mon == MT_LCD || mon == MT_DFP) {
+ if(v.xres > rinfo->panel_xres)
+ v.xres = rinfo->panel_xres;
+ if(v.yres > rinfo->panel_yres)
+ v.yres = rinfo->panel_yres;
+ }
+
+ if(v.xres > v.xres_virtual)
+ v.xres_virtual = v.xres;
+ if(v.yres > v.yres_virtual)
+ v.yres_virtual = v.yres;
+
+ /* XXX this is probably wrong for 24bpp, if we ever get it working :pdh */
+
+ bytpp = v.bits_per_pixel >> 3;
+
+ pitch = (v.xres_virtual * bytpp + 63) & ~63;
+
+ if(pitch >= 8192)
+ pitch = 8192 - 64;
+
+ v.xres_virtual = pitch / bytpp;
+
+ if(v.xres_virtual < v.xres)
+ v.xres = v.xres_virtual;
+
+ v.yres_virtual = rinfo->video_ram / pitch;
+
+ /* XXX there is some limit here, I chose 8192 :pdh */
+
+ if(v.yres_virtual >= 8192)
+ v.yres_virtual = 8191;
+
+ if(v.yres_virtual < v.yres)
+ v.yres = v.yres_virtual;

+#if 0
if (radeonfb_do_maximize(rinfo, var, &v, nom, den) < 0)
return -EINVAL;
+#endif

+ /* XXX we don't do X pan yet :pdh */
+
+ v.xoffset = 0;
+
if (v.xoffset < 0)
v.xoffset = 0;
if (v.yoffset < 0)
v.yoffset = 0;

if (v.xoffset > v.xres_virtual - v.xres)
- v.xoffset = v.xres_virtual - v.xres - 1;
+ v.xoffset = v.xres_virtual - v.xres;

if (v.yoffset > v.yres_virtual - v.yres)
- v.yoffset = v.yres_virtual - v.yres - 1;
-
- v.red.msb_right = v.green.msb_right = v.blue.msb_right =
- v.transp.offset = v.transp.length =
- v.transp.msb_right = 0;
+ v.yoffset = v.yres_virtual - v.yres;

switch (v.activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
@@ -2016,17 +2079,29 @@
default:
return -EINVAL;
}
-
- memcpy (&disp->var, &v, sizeof (v));
-
- if (chgvar) {
- radeon_set_dispsw(rinfo, disp);

- if (noaccel)
- disp->scrollmode = SCROLL_YREDRAW;
- else
- disp->scrollmode = 0;
-
+ chgvar = (con >= 0 &&
+ (disp->var.xres != v.xres ||
+ disp->var.yres != v.yres ||
+ disp->var.xres_virtual != v.xres_virtual ||
+ disp->var.yres_virtual != v.yres_virtual ||
+ disp->var.bits_per_pixel != v.bits_per_pixel ||
+ memcmp (&disp->var.red, &v.red, sizeof (v.red)) ||
+ memcmp (&disp->var.green, &v.green, sizeof (v.green)) ||
+ memcmp (&disp->var.blue, &v.blue, sizeof (v.blue))));
+
+ memcpy (&disp->var, &v, sizeof (v));
+
+ if(chgvar) {
+
+ radeon_set_dispsw(rinfo, disp);
+
+ disp->scrollmode = noaccel ? SCROLL_YREDRAW : 0;
+
+ /* XXX needed by radeon_setcolreg() called fron ->changevar() :pdh */
+
+ rinfo->depth = var_to_depth(&v);
+
if (info && info->changevar)
info->changevar(con);
}
@@ -2035,6 +2110,9 @@

do_install_cmap(con, info);

+ if(accel)
+ radeon_engine_init(rinfo);
+
return 0;
}

@@ -2093,6 +2171,8 @@
struct fb_info *info)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
+
+#if 0
u32 offset, xoffset, yoffset;

xoffset = (var->xoffset + 7) & ~7;
@@ -2105,7 +2185,18 @@
offset = ((yoffset * var->xres + xoffset) * var->bits_per_pixel) >> 6;

OUTREG(CRTC_OFFSET, offset);
+#endif
+
+ /* XXX no X pan for the moment, think about the accelerator :pdh */
+
+ if(var->xoffset)
+ return -EINVAL;

+ if(var->yoffset + var->yres > var->yres_virtual)
+ return -EINVAL;
+
+ OUTREG(CRTC_OFFSET, var->yoffset * rinfo->pitch);
+
return 0;
}

@@ -2144,12 +2235,14 @@
do_install_cmap(con, info);
}

+#if 0
/* XXX absurd hack for X to restore console */
{
OUTREGP(CRTC_EXT_CNTL, rinfo->hack_crtc_ext_cntl,
CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
OUTREG(CRTC_V_SYNC_STRT_WID, rinfo->hack_crtc_v_sync_strt_wid);
}
+#endif

return 0;
}
@@ -2214,18 +2307,7 @@

static int radeon_get_cmap_len (const struct fb_var_screeninfo *var)
{
- int rc = 256; /* reasonable default */
-
- switch (var_to_depth(var)) {
- case 15:
- rc = 32;
- break;
- case 16:
- rc = 64;
- break;
- }
-
- return rc;
+ return var->bits_per_pixel == 16 ? (var->green.length == 5 ? 32 : 64) : 256;
}


@@ -2239,10 +2321,9 @@
if (regno > 255)
return 1;

- *red = (rinfo->palette[regno].red<<8) | rinfo->palette[regno].red;
- *green = (rinfo->palette[regno].green<<8) | rinfo->palette[regno].green;
- *blue = (rinfo->palette[regno].blue<<8) | rinfo->palette[regno].blue;
- *transp = 0;
+ *red = (unsigned) rinfo->palette_red[regno] << 8;
+ *green = (unsigned) rinfo->palette_grn[regno] << 8;
+ *blue = (unsigned) rinfo->palette_blu[regno] << 8;

return 0;
}
@@ -2250,78 +2331,76 @@


static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green,
- unsigned blue, unsigned transp, struct fb_info *info)
+ unsigned blue, unsigned alpha, struct fb_info *info)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *) info;
- u32 pindex;

- if (regno > 255)
+ if(regno > 255)
return 1;

- red >>= 8;
- green >>= 8;
- blue >>= 8;
- rinfo->palette[regno].red = red;
- rinfo->palette[regno].green = green;
- rinfo->palette[regno].blue = blue;
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+ alpha >>= 8;
+
+ rinfo->palette_red[regno] = red;
+ rinfo->palette_grn[regno] = green;
+ rinfo->palette_blu[regno] = blue;

- /* default */
- pindex = regno;
-
- if (rinfo->bpp == 16) {
- pindex = regno * 8;
+#ifdef FBCON_HAS_CFB16
+ if(rinfo->depth == 15) {

- if (rinfo->depth == 16 && regno > 63)
- return 1;
- if (rinfo->depth == 15 && regno > 31)
+ if(regno > 31)
return 1;
+ if(regno < 16)
+ rinfo->con_cmap.cfb16[regno] = (regno << 10) | (regno << 5) | regno;
+ regno <<= 3;
+
+ } else if(rinfo->depth == 16) {
+
+ if(fb16fix) {
+
+ /* this is just another format of 15 bit mode, the LSB of the *
+ * green pixel data is ignored. this is required for "fbtv" and *
+ * other apps to work correctly at 16bpp, but it means you land *
+ * up with a sick looking boot logo. the real fix is to run at *
+ * 15bpp when you want to use those apps :pdh */
+
+ if(regno > 31)
+ return 1;
+ if(regno < 16)
+ rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 6) | regno;
+ regno <<= 3;
+ set_palette_entry(rinfo, regno | 4, red, green, blue);

- /* For 565, the green component is mixed one order below */
- if (rinfo->depth == 16) {
- OUTREG(PALETTE_INDEX, pindex>>1);
- OUTREG(PALETTE_DATA, (rinfo->palette[regno>>1].red << 16) |
- (green << 8) | (rinfo->palette[regno>>1].blue));
- green = rinfo->palette[regno<<1].green;
- }
- }
-
- if (rinfo->depth != 16 || regno < 32) {
- OUTREG(PALETTE_INDEX, pindex);
- OUTREG(PALETTE_DATA, (red << 16) | (green << 8) | blue);
- }
+ } else {

- if (regno < 16) {
- switch (rinfo->depth) {
-#ifdef FBCON_HAS_CFB16
- case 15:
- rinfo->con_cmap.cfb16[regno] = (regno << 10) | (regno << 5) |
- regno;
- break;
- case 16:
- rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 5) |
- regno;
- break;
-#endif
-#ifdef FBCON_HAS_CFB24
- case 24:
- rinfo->con_cmap.cfb24[regno] = (regno << 16) | (regno << 8) | regno;
- break;
+ if(regno > 63)
+ return 1;
+ if(regno < 16)
+ rinfo->con_cmap.cfb16[regno] = (regno << 11) | (regno << 5) | regno;
+ set_palette_entry(rinfo, regno << 2, rinfo->palette_red[regno >> 1],
+ green, rinfo->palette_blu[regno >> 1]);
+ if(regno > 31)
+ return 0;
+ regno <<= 1;
+ green = rinfo->palette_grn[regno];
+ regno <<= 2;
+ }
+ } else
#endif
#ifdef FBCON_HAS_CFB32
- case 32: {
- u32 i;
-
- i = (regno << 8) | regno;
- rinfo->con_cmap.cfb32[regno] = (i << 16) | i;
- break;
- }
+ if(rinfo->depth == 32) {
+
+ if(regno < 16)
+ rinfo->con_cmap.cfb32[regno] = (regno << 16) | (regno << 8) | regno;
+ }
#endif
- }
- }
- return 0;
-}

+ set_palette_entry(rinfo, regno, red, green, blue);

+ return 0;
+}

static void radeon_save_state (struct radeonfb_info *rinfo,
struct radeon_regs *save)
@@ -2354,42 +2433,198 @@
}


+static void calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *reg, u32 pixclock)
+{
+ static struct {
+ int divider;
+ int bitvalue;
+ } *post_div,
+ post_divs[] = {
+ { 1, 0 },
+ { 2, 1 },
+ { 4, 2 },
+ { 8, 3 },
+ { 3, 4 },
+ { 16, 5 },
+ { 6, 6 },
+ { 12, 7 },
+ { 0, 0 },
+ };
+ int freq;
+
+ freq = 100000000 / pixclock;
+
+ if (freq > rinfo->pll.ppll_max)
+ freq = rinfo->pll.ppll_max;
+ if (freq*12 < rinfo->pll.ppll_min)
+ freq = rinfo->pll.ppll_min / 12;
+
+ for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
+ rinfo->pll_output_freq = post_div->divider * freq;
+ if (rinfo->pll_output_freq >= rinfo->pll.ppll_min &&
+ rinfo->pll_output_freq <= rinfo->pll.ppll_max)
+ break;
+ }
+
+ rinfo->post_div = post_div->divider;
+ rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq,
+ rinfo->pll.ref_clk);
+ reg->ppll_ref_div = rinfo->pll.ref_div;
+ reg->ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16);
+
+ RTRACE("post div = 0x%x", rinfo->post_div);
+ RTRACE("fb_div = 0x%x", rinfo->fb_div);
+ RTRACE("ppll_div_3 = 0x%x", reg->ppll_div_3);
+}
+
+static void set_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs)
+{
+ if(!nofastsw && rinfo->pixclock == rinfo->ppixclock)
+ return;
+
+ while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) !=
+ PPLL_DIV_SEL_MASK) {
+ OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff);
+ }
+
+ OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff);
+
+ while ((INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) !=
+ (regs->ppll_ref_div & PPLL_REF_DIV_MASK)) {
+ OUTPLLP(PPLL_REF_DIV, regs->ppll_ref_div, ~PPLL_REF_DIV_MASK);
+ }
+
+ while ((INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) !=
+ (regs->ppll_div_3 & PPLL_FB3_DIV_MASK)) {
+ OUTPLLP(PPLL_DIV_3, regs->ppll_div_3, ~PPLL_FB3_DIV_MASK);
+ }
+
+ while ((INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) !=
+ (regs->ppll_div_3 & PPLL_POST3_DIV_MASK)) {
+ OUTPLLP(PPLL_DIV_3, regs->ppll_div_3, ~PPLL_POST3_DIV_MASK);
+ }
+
+ OUTPLL(HTOTAL_CNTL, 0);
+
+ OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET);
+}
+
+static void calc_dda_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs)
+{
+ int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise;
+ int useable_precision, roff, ron;
+ int min_bits;
+
+ vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div,
+ rinfo->pll.ref_div * rinfo->post_div);
+ xclk_freq = rinfo->pll.xclk;
+
+ xclk_per_trans = round_div(xclk_freq * 128, vclk_freq * rinfo->bpp);
+
+ min_bits = min_bits_req(xclk_per_trans);
+ useable_precision = min_bits + 1;
+
+ xclk_per_trans_precise = round_div((xclk_freq * 128) << (11 - useable_precision),
+ vclk_freq * rinfo->bpp);
+
+ ron = (4 * rinfo->ram.mb + 3 * _max(rinfo->ram.trcd - 2, 0) +
+ 2 * rinfo->ram.trp + rinfo->ram.twr + rinfo->ram.cl + rinfo->ram.tr2w +
+ xclk_per_trans) << (11 - useable_precision);
+ roff = xclk_per_trans_precise * (32 - 4);
+
+ RTRACE("ron = %d, roff = %d", ron, roff);
+ RTRACE("vclk_freq = %d, per = %d", vclk_freq, xclk_per_trans_precise);
+
+ if ((ron + rinfo->ram.rloop) >= roff) {
+ printk("radeonfb: error ron out of range\n");
+ return;
+ }
+
+ regs->dda_config = (xclk_per_trans_precise |
+ (useable_precision << 16) |
+ (rinfo->ram.rloop << 20));
+ regs->dda_on_off = (ron << 16) | roff;
+}
+
+static void set_dda_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs)
+{
+ OUTREG(DDA_CONFIG, regs->dda_config);
+ OUTREG(DDA_ON_OFF, regs->dda_on_off);
+}
+
+static void calc_stretch_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs)
+{
+ unsigned int hRatio, vRatio;
+
+ regs->fp_horz_stretch = rinfo->init_state.fp_horz_stretch &
+ ~(HORZ_STRETCH_BLEND | HORZ_STRETCH_ENABLE);
+
+ regs->fp_vert_stretch = rinfo->init_state.fp_vert_stretch &
+ ~(VERT_STRETCH_BLEND | VERT_STRETCH_ENABLE);
+
+ if(nostretch)
+ return;
+
+ if (rinfo->xres != rinfo->panel_xres) {
+
+ regs->fp_horz_stretch = (((rinfo->panel_xres / 8) - 1)
+ << HORZ_PANEL_SHIFT);
+
+ hRatio = round_div(rinfo->xres * HORZ_STRETCH_RATIO_MAX,
+ rinfo->panel_xres);
+ regs->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
+ (regs->fp_horz_stretch &
+ (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
+ HORZ_AUTO_RATIO_INC)));
+ regs->fp_horz_stretch |= (HORZ_STRETCH_BLEND |
+ HORZ_STRETCH_ENABLE);
+
+ regs->fp_horz_stretch &= ~HORZ_AUTO_RATIO;
+ }
+
+ if (rinfo->yres != rinfo->panel_yres) {
+
+ regs->fp_vert_stretch = ((rinfo->panel_yres - 1)
+ << VERT_PANEL_SHIFT);
+ vRatio = round_div(rinfo->yres * VERT_STRETCH_RATIO_MAX,
+ rinfo->panel_yres);
+ regs->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
+ (regs->fp_vert_stretch &
+ (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
+ regs->fp_vert_stretch |= (VERT_STRETCH_BLEND |
+ VERT_STRETCH_ENABLE);
+
+ regs->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
+ }
+}

static void radeon_load_video_mode (struct radeonfb_info *rinfo,
struct fb_var_screeninfo *mode)
{
struct radeon_regs newmode;
int hTotal, vTotal, hSyncStart, hSyncEnd,
- hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync;
+ vSyncStart, vSyncEnd;
u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5};
u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5};
- u32 dotClock = 1000000000 / mode->pixclock,
- sync, h_sync_pol, v_sync_pol;
- int freq = dotClock / 10; /* x 100 */
- int xclk_freq, vclk_freq, xclk_per_trans, xclk_per_trans_precise;
- int useable_precision, roff, ron;
- int min_bits, format = 0;
+ u32 h_sync_pol, v_sync_pol;
+ int format = 0;
int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid;
int primary_mon = PRIMARY_MONITOR(rinfo);
int depth = var_to_depth(mode);

+ bytpp = mode->bits_per_pixel >> 3;
rinfo->xres = mode->xres;
rinfo->yres = mode->yres;
+ rinfo->pitch = mode->xres_virtual * bytpp;
+ rinfo->ppixclock = rinfo->pixclock;
rinfo->pixclock = mode->pixclock;

- hSyncStart = mode->xres + mode->right_margin;
- hSyncEnd = hSyncStart + mode->hsync_len;
- hTotal = hSyncEnd + mode->left_margin;
-
- vSyncStart = mode->yres + mode->lower_margin;
- vSyncEnd = vSyncStart + mode->vsync_len;
- vTotal = vSyncEnd + mode->upper_margin;
+ format = radeon_get_dstbpp(depth);
+
+ newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
+ (format << 8);

if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- if (rinfo->panel_xres < mode->xres)
- rinfo->xres = mode->xres = rinfo->panel_xres;
- if (rinfo->panel_yres < mode->yres)
- rinfo->yres = mode->yres = rinfo->panel_yres;

hTotal = mode->xres + rinfo->hblank;
hSyncStart = mode->xres + rinfo->hOver_plus;
@@ -2398,15 +2633,34 @@
vTotal = mode->yres + rinfo->vblank;
vSyncStart = mode->yres + rinfo->vOver_plus;
vSyncEnd = vSyncStart + rinfo->vSync_width;
+
+ hsync_fudge = hsync_fudge_fp[format - 1];
+
+ newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
+ newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
+ CRTC_INTERLACE_EN);
+
+ } else {
+
+ hSyncStart = mode->xres + mode->right_margin;
+ hSyncEnd = hSyncStart + mode->hsync_len;
+ hTotal = hSyncEnd + mode->left_margin;
+
+ vSyncStart = mode->yres + mode->lower_margin;
+ vSyncEnd = vSyncStart + mode->vsync_len;
+ vTotal = vSyncEnd + mode->upper_margin;
+
+ hsync_fudge = hsync_adj_tab[format - 1];
+
+ newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
+ CRTC_CRT_ON;
}

- sync = mode->sync;
- h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
- v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ hsync_start = hSyncStart - 8 + hsync_fudge;

- RTRACE("hStart = %d, hEnd = %d, hTotal = %d\n",
+ RTRACE("hStart = %d, hEnd = %d, hTotal = %d",
hSyncStart, hSyncEnd, hTotal);
- RTRACE("vStart = %d, vEnd = %d, vTotal = %d\n",
+ RTRACE("vStart = %d, vEnd = %d, vTotal = %d",
vSyncStart, vSyncEnd, vTotal);

hsync_wid = (hSyncEnd - hSyncStart) / 8;
@@ -2421,32 +2675,10 @@
else if (vsync_wid > 0x1f) /* max */
vsync_wid = 0x1f;

- hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
- vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ h_sync_pol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+ v_sync_pol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;

- cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
-
- format = radeon_get_dstbpp(depth);
- bytpp = mode->bits_per_pixel >> 3;
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD))
- hsync_fudge = hsync_fudge_fp[format-1];
- else
- hsync_fudge = hsync_adj_tab[format-1];
-
- hsync_start = hSyncStart - 8 + hsync_fudge;
-
- newmode.crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN |
- (format << 8);
-
- if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN;
- newmode.crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN |
- CRTC_INTERLACE_EN);
- } else {
- newmode.crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN |
- CRTC_CRT_ON;
- }
+ /* cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; */

newmode.dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN |
DAC_8BIT_EN;
@@ -2463,7 +2695,7 @@
newmode.crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) |
(vsync_wid << 16) | (v_sync_pol << 23));

- newmode.crtc_pitch = (mode->xres >> 3);
+ newmode.crtc_pitch = mode->xres_virtual >> 3;
newmode.crtc_pitch |= (newmode.crtc_pitch << 16);

#if defined(__BIG_ENDIAN)
@@ -2479,12 +2711,9 @@
}
#endif

- rinfo->pitch = ((mode->xres * ((mode->bits_per_pixel + 1) / 8) + 0x3f)
- & ~(0x3f)) / 64;
-
- RTRACE("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n",
+ RTRACE("h_total_disp = 0x%x hsync_strt_wid = 0x%x",
newmode.crtc_h_total_disp, newmode.crtc_h_sync_strt_wid);
- RTRACE("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n",
+ RTRACE("v_total_disp = 0x%x vsync_strt_wid = 0x%x",
newmode.crtc_v_total_disp, newmode.crtc_v_sync_strt_wid);

newmode.xres = mode->xres;
@@ -2493,115 +2722,17 @@
rinfo->bpp = mode->bits_per_pixel;
rinfo->depth = depth;

+#if 0
rinfo->hack_crtc_ext_cntl = newmode.crtc_ext_cntl;
rinfo->hack_crtc_v_sync_strt_wid = newmode.crtc_v_sync_strt_wid;
+#endif

- if (freq > rinfo->pll.ppll_max)
- freq = rinfo->pll.ppll_max;
- if (freq*12 < rinfo->pll.ppll_min)
- freq = rinfo->pll.ppll_min / 12;
-
- {
- struct {
- int divider;
- int bitvalue;
- } *post_div,
- post_divs[] = {
- { 1, 0 },
- { 2, 1 },
- { 4, 2 },
- { 8, 3 },
- { 3, 4 },
- { 16, 5 },
- { 6, 6 },
- { 12, 7 },
- { 0, 0 },
- };
-
- for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
- rinfo->pll_output_freq = post_div->divider * freq;
- if (rinfo->pll_output_freq >= rinfo->pll.ppll_min &&
- rinfo->pll_output_freq <= rinfo->pll.ppll_max)
- break;
- }
-
- rinfo->post_div = post_div->divider;
- rinfo->fb_div = round_div(rinfo->pll.ref_div*rinfo->pll_output_freq,
- rinfo->pll.ref_clk);
- newmode.ppll_ref_div = rinfo->pll.ref_div;
- newmode.ppll_div_3 = rinfo->fb_div | (post_div->bitvalue << 16);
- }
-
- RTRACE("post div = 0x%x\n", rinfo->post_div);
- RTRACE("fb_div = 0x%x\n", rinfo->fb_div);
- RTRACE("ppll_div_3 = 0x%x\n", newmode.ppll_div_3);
-
- /* DDA */
- vclk_freq = round_div(rinfo->pll.ref_clk * rinfo->fb_div,
- rinfo->pll.ref_div * rinfo->post_div);
- xclk_freq = rinfo->pll.xclk;
-
- xclk_per_trans = round_div(xclk_freq * 128, vclk_freq * mode->bits_per_pixel);
-
- min_bits = min_bits_req(xclk_per_trans);
- useable_precision = min_bits + 1;
-
- xclk_per_trans_precise = round_div((xclk_freq * 128) << (11 - useable_precision),
- vclk_freq * mode->bits_per_pixel);
-
- ron = (4 * rinfo->ram.mb + 3 * _max(rinfo->ram.trcd - 2, 0) +
- 2 * rinfo->ram.trp + rinfo->ram.twr + rinfo->ram.cl + rinfo->ram.tr2w +
- xclk_per_trans) << (11 - useable_precision);
- roff = xclk_per_trans_precise * (32 - 4);
-
- RTRACE("ron = %d, roff = %d\n", ron, roff);
- RTRACE("vclk_freq = %d, per = %d\n", vclk_freq, xclk_per_trans_precise);
-
- if ((ron + rinfo->ram.rloop) >= roff) {
- printk("radeonfb: error ron out of range\n");
- return;
- }
-
- newmode.dda_config = (xclk_per_trans_precise |
- (useable_precision << 16) |
- (rinfo->ram.rloop << 20));
- newmode.dda_on_off = (ron << 16) | roff;
+ calc_pll_regs(rinfo, &newmode, rinfo->pixclock);
+ calc_dda_regs(rinfo, &newmode);

if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
- unsigned int hRatio, vRatio;
-
- if (mode->xres > rinfo->panel_xres)
- mode->xres = rinfo->panel_xres;
- if (mode->yres > rinfo->panel_yres)
- mode->yres = rinfo->panel_yres;
-
- newmode.fp_horz_stretch = (((rinfo->panel_xres / 8) - 1)
- << HORZ_PANEL_SHIFT);
- newmode.fp_vert_stretch = ((rinfo->panel_yres - 1)
- << VERT_PANEL_SHIFT);

- if (mode->xres != rinfo->panel_xres) {
- hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX,
- rinfo->panel_xres);
- newmode.fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) |
- (newmode.fp_horz_stretch &
- (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH |
- HORZ_AUTO_RATIO_INC)));
- newmode.fp_horz_stretch |= (HORZ_STRETCH_BLEND |
- HORZ_STRETCH_ENABLE);
- }
- newmode.fp_horz_stretch &= ~HORZ_AUTO_RATIO;
-
- if (mode->yres != rinfo->panel_yres) {
- vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX,
- rinfo->panel_yres);
- newmode.fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) |
- (newmode.fp_vert_stretch &
- (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED)));
- newmode.fp_vert_stretch |= (VERT_STRETCH_BLEND |
- VERT_STRETCH_ENABLE);
- }
- newmode.fp_vert_stretch &= ~VERT_AUTO_RATIO_EN;
+ calc_stretch_regs(rinfo, &newmode);

newmode.fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32)
~(FP_SEL_CRTC2 |
@@ -2622,14 +2753,21 @@
newmode.tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl;

if (primary_mon == MT_LCD) {
+
newmode.lvds_gen_cntl |= (LVDS_ON | LVDS_BLON);
newmode.fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN);
+
} else {
- /* DFP */
+
newmode.fp_gen_cntl |= (FP_FPON | FP_TMDS_EN);
+ newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
+
+ /* XXX one user's DFP won't work with this line in, and *
+ * I notice XFree doesn't touch this register ... :pdh */
+#if 0
newmode.tmds_transmitter_cntl = (TMDS_RAN_PAT_RST |
ICHCSEL) & ~(TMDS_PLLRST);
- newmode.crtc_ext_cntl &= ~CRTC_CRT_ON;
+#endif
}

newmode.fp_crtc_h_total_disp = newmode.crtc_h_total_disp;
@@ -2657,15 +2795,13 @@
int primary_mon = PRIMARY_MONITOR(rinfo);

/* blank screen */
- OUTREGP(CRTC_EXT_CNTL, CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS,
- ~(CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS | CRTC_HSYNC_DIS));
+ OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
+ ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));

for (i=0; i<9; i++)
OUTREG(common_regs[i].reg, common_regs[i].val);

OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
- OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
- CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
@@ -2679,34 +2815,8 @@
OUTREG(SURFACE_CNTL, mode->surface_cntl);
#endif

- while ((INREG(CLOCK_CNTL_INDEX) & PPLL_DIV_SEL_MASK) !=
- PPLL_DIV_SEL_MASK) {
- OUTREGP(CLOCK_CNTL_INDEX, PPLL_DIV_SEL_MASK, 0xffff);
- }
-
- OUTPLLP(PPLL_CNTL, PPLL_RESET, 0xffff);
-
- while ((INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK) !=
- (mode->ppll_ref_div & PPLL_REF_DIV_MASK)) {
- OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
- }
-
- while ((INPLL(PPLL_DIV_3) & PPLL_FB3_DIV_MASK) !=
- (mode->ppll_div_3 & PPLL_FB3_DIV_MASK)) {
- OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
- }
-
- while ((INPLL(PPLL_DIV_3) & PPLL_POST3_DIV_MASK) !=
- (mode->ppll_div_3 & PPLL_POST3_DIV_MASK)) {
- OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
- }
-
- OUTPLL(HTOTAL_CNTL, 0);
-
- OUTPLLP(PPLL_CNTL, 0, ~PPLL_RESET);
-
- OUTREG(DDA_CONFIG, mode->dda_config);
- OUTREG(DDA_ON_OFF, mode->dda_on_off);
+ set_pll_regs(rinfo, mode);
+ set_dda_regs(rinfo, mode);

if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) {
OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp);
@@ -2743,7 +2853,7 @@
}

/* unblank screen */
- OUTREG8(CRTC_EXT_CNTL + 1, 0);
+ OUTREG(CRTC_EXT_CNTL, mode->crtc_ext_cntl);

return;
}
@@ -2957,7 +3067,7 @@
int dsty, int dstx, int height, int width)
{
struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info);
- u32 dp_cntl = DST_LAST_PEL;
+ u32 dp_cntl;

srcx *= fontwidth(p);
srcy *= fontheight(p);
@@ -2966,6 +3076,8 @@
width *= fontwidth(p);
height *= fontheight(p);

+ dp_cntl = 0;
+
if (srcy < dsty) {
srcy += height - 1;
dsty += height - 1;
@@ -2989,25 +3101,14 @@
OUTREG(SRC_Y_X, (srcy << 16) | srcx);
OUTREG(DST_Y_X, (dsty << 16) | dstx);
OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width);
+
+ radeon_engine_idle();
}



-static void fbcon_radeon_clear(struct vc_data *conp, struct display *p,
- int srcy, int srcx, int height, int width)
+static void fbcon_radeon_clear(struct radeonfb_info *rinfo, int srcy, int srcx, int height, int width, u32 clr)
{
- struct radeonfb_info *rinfo = (struct radeonfb_info *)(p->fb_info);
- u32 clr;
-
- clr = attr_bgcol_ec(p, conp);
- clr |= (clr << 8);
- clr |= (clr << 16);
-
- srcx *= fontwidth(p);
- srcy *= fontheight(p);
- width *= fontwidth(p);
- height *= fontheight(p);
-
radeon_fifo_wait(6);
OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl |
GMC_BRUSH_SOLID_COLOR |
@@ -3018,15 +3119,27 @@
OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
OUTREG(DST_Y_X, (srcy << 16) | srcx);
OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height);
+
+ radeon_engine_idle();
}

+#ifdef FBCON_HAS_CFB8
+static void fbcon_radeon8_clear(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ u32 clr;

+ clr = attr_bgcol_ec(p, conp);
+ clr |= clr << 8;
+
+ fbcon_radeon_clear((struct radeonfb_info *) p->fb_info, srcy * fontheight(p), srcx * fontwidth(p),
+ height * fontheight(p), width * fontwidth(p), clr | (clr << 16));
+}

-#ifdef FBCON_HAS_CFB8
static struct display_switch fbcon_radeon8 = {
setup: fbcon_cfb8_setup,
bmove: fbcon_radeon_bmove,
- clear: fbcon_radeon_clear,
+ clear: fbcon_radeon8_clear,
putc: fbcon_cfb8_putc,
putcs: fbcon_cfb8_putcs,
revc: fbcon_cfb8_revc,
@@ -3034,3 +3147,156 @@
fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
};
#endif
+
+#ifdef FBCON_HAS_CFB16
+static void fbcon_radeon16_clear(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ u32 clr;
+
+ clr = ((u16 *) p->dispsw_data)[attr_bgcol_ec(p, conp)];
+
+ fbcon_radeon_clear((struct radeonfb_info *) p->fb_info, srcy * fontheight(p), srcx * fontwidth(p),
+ height * fontheight(p), width * fontwidth(p), clr | (clr << 16));
+}
+
+void fbcon_radeon16_revc(struct display *p, int xx, int yy)
+{
+ u8 *dest;
+ u32 xor;
+ int bytes = p->next_line, rows;
+
+ xor = (p->var.green.length == 5 ? 0x3def3def : 0x79ef79ef);
+
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p)*2;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
+ case 16:
+ fb_writel(fb_readl(dest+24) ^ xor, dest+24);
+ fb_writel(fb_readl(dest+28) ^ xor, dest+28);
+ /* FALL THROUGH */
+ case 12:
+ fb_writel(fb_readl(dest+16) ^ xor, dest+16);
+ fb_writel(fb_readl(dest+20) ^ xor, dest+20);
+ /* FALL THROUGH */
+ case 8:
+ fb_writel(fb_readl(dest+8) ^ xor, dest+8);
+ fb_writel(fb_readl(dest+12) ^ xor, dest+12);
+ /* FALL THROUGH */
+ case 4:
+ fb_writel(fb_readl(dest+0) ^ xor, dest+0);
+ fb_writel(fb_readl(dest+4) ^ xor, dest+4);
+ }
+ }
+}
+
+static struct display_switch fbcon_radeon16_noaccel = {
+ setup: fbcon_cfb16_setup,
+ bmove: fbcon_cfb16_bmove,
+ clear: fbcon_cfb16_clear,
+ putc: fbcon_cfb16_putc,
+ putcs: fbcon_cfb16_putcs,
+ revc: fbcon_radeon16_revc,
+ clear_margins: fbcon_cfb16_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch fbcon_radeon16 = {
+ setup: fbcon_cfb16_setup,
+ bmove: fbcon_radeon_bmove,
+ clear: fbcon_radeon16_clear,
+ putc: fbcon_cfb16_putc,
+ putcs: fbcon_cfb16_putcs,
+ revc: fbcon_radeon16_revc,
+ clear_margins: fbcon_cfb16_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+#ifdef FBCON_HAS_CFB32
+static void fbcon_radeon32_clear(struct vc_data *conp, struct display *p,
+ int srcy, int srcx, int height, int width)
+{
+ fbcon_radeon_clear((struct radeonfb_info *) p->fb_info, srcy * fontheight(p), srcx * fontwidth(p),
+ height * fontheight(p), width * fontwidth(p), ((u32 *) p->dispsw_data)[attr_bgcol_ec(p, conp)]);
+}
+
+void fbcon_radeon32_revc(struct display *p, int xx, int yy)
+{
+ u8 *dest;
+ int bytes = p->next_line, rows;
+
+ dest = p->screen_base + yy * fontheight(p) * bytes + xx * fontwidth(p) * 4;
+ for (rows = fontheight(p); rows--; dest += bytes) {
+ switch (fontwidth(p)) {
+ case 16:
+ fb_writel(fb_readl(dest+(4*12)) ^ 0x000f0f0f, dest+(4*12));
+ fb_writel(fb_readl(dest+(4*13)) ^ 0x000f0f0f, dest+(4*13));
+ fb_writel(fb_readl(dest+(4*14)) ^ 0x000f0f0f, dest+(4*14));
+ fb_writel(fb_readl(dest+(4*15)) ^ 0x000f0f0f, dest+(4*15));
+ /* FALL THROUGH */
+ case 12:
+ fb_writel(fb_readl(dest+(4*8)) ^ 0x000f0f0f, dest+(4*8));
+ fb_writel(fb_readl(dest+(4*9)) ^ 0x000f0f0f, dest+(4*9));
+ fb_writel(fb_readl(dest+(4*10)) ^ 0x000f0f0f, dest+(4*10));
+ fb_writel(fb_readl(dest+(4*11)) ^ 0x000f0f0f, dest+(4*11));
+ /* FALL THROUGH */
+ case 8:
+ fb_writel(fb_readl(dest+(4*4)) ^ 0x000f0f0f, dest+(4*4));
+ fb_writel(fb_readl(dest+(4*5)) ^ 0x000f0f0f, dest+(4*5));
+ fb_writel(fb_readl(dest+(4*6)) ^ 0x000f0f0f, dest+(4*6));
+ fb_writel(fb_readl(dest+(4*7)) ^ 0x000f0f0f, dest+(4*7));
+ /* FALL THROUGH */
+ case 4:
+ fb_writel(fb_readl(dest+(4*0)) ^ 0x000f0f0f, dest+(4*0));
+ fb_writel(fb_readl(dest+(4*1)) ^ 0x000f0f0f, dest+(4*1));
+ fb_writel(fb_readl(dest+(4*2)) ^ 0x000f0f0f, dest+(4*2));
+ fb_writel(fb_readl(dest+(4*3)) ^ 0x000f0f0f, dest+(4*3));
+ /* FALL THROUGH */
+ }
+ }
+}
+
+static struct display_switch fbcon_radeon32_noaccel = {
+ setup: fbcon_cfb32_setup,
+ bmove: fbcon_cfb32_bmove,
+ clear: fbcon_cfb32_clear,
+ putc: fbcon_cfb32_putc,
+ putcs: fbcon_cfb32_putcs,
+ revc: fbcon_radeon32_revc,
+ clear_margins: fbcon_cfb32_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+
+static struct display_switch fbcon_radeon32 = {
+ setup: fbcon_cfb32_setup,
+ bmove: fbcon_radeon_bmove,
+ clear: fbcon_radeon32_clear,
+ putc: fbcon_cfb32_putc,
+ putcs: fbcon_cfb32_putcs,
+ revc: fbcon_radeon32_revc,
+ clear_margins: fbcon_cfb32_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
+MODULE_AUTHOR("Ani Joshi");
+MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset");
+MODULE_LICENSE("GPL");
+MODULE_PARM(font, "s");
+MODULE_PARM_DESC(font, "Selects display font");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disables use of accelerator engine");
+MODULE_PARM(nofastsw, "i");
+MODULE_PARM_DESC(nofastsw, "Always reset PLL on mode change");
+MODULE_PARM(fb16fix, "i");
+MODULE_PARM_DESC(fb16fix, "Fix 16bpp palette for fbtv and others");
+MODULE_PARM(nostretch, "i");
+MODULE_PARM_DESC(nostretch, "Disable stretching of modes to panel size");
+MODULE_PARM(nomtrr, "i");
+MODULE_PARM_DESC(nomtrr, "Disable use of MTRR");
+MODULE_PARM(panel_yres, "i");
+MODULE_PARM_DESC(panel_yres, "Specifies panel Y resolution");
+MODULE_PARM(dfp, "i");
+MODULE_PARM_DESC(dfp, "Force selection of DFP");
+
diff -ur linux-2.4.19-pre2/include/linux/fb.h linux.pdh/include/linux/fb.h
--- linux-2.4.19-pre2/include/linux/fb.h Sat Apr 6 16:34:40 2002
+++ linux.pdh/include/linux/fb.h Sun Apr 14 16:10:30 2002
@@ -94,6 +94,7 @@
#define FB_ACCEL_IGS_CYBER5000 35 /* CyberPro 5000 */
#define FB_ACCEL_SIS_GLAMOUR 36 /* SiS 300/630/540 */
#define FB_ACCEL_3DLABS_PERMEDIA3 37 /* 3Dlabs Permedia 3 */
+#define FB_ACCEL_ATI_RADEON 38 /* ATI Radeon */

struct fb_fix_screeninfo {
char id[16]; /* identification string eg "TT Builtin" */
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/