summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Simmons <jsimmons@heisenberg.transvirtual.com>2002-07-07 23:12:00 -0700
committerJames Simmons <jsimmons@heisenberg.transvirtual.com>2002-07-07 23:12:00 -0700
commit2eaf7c63e1b100708abd60a6c1c2e2f133bd6704 (patch)
tree2980bb42ecd602628573285d2b3b5bf13d128aff
parent8ef1bf6df837a5f92e2d8d50ca26c77998602ff4 (diff)
Port step some changes at authors request.
-rw-r--r--drivers/video/aty128fb.c3117
-rw-r--r--drivers/video/riva/fbdev.c1529
-rw-r--r--drivers/video/riva/riva_hw.c38
-rw-r--r--drivers/video/riva/riva_hw.h2
-rw-r--r--drivers/video/riva/rivafb.h60
-rw-r--r--drivers/video/sa1100fb.c823
-rw-r--r--drivers/video/sa1100fb.h17
7 files changed, 3329 insertions, 2257 deletions
diff --git a/drivers/video/aty128fb.c b/drivers/video/aty128fb.c
index 2d8646e3d417..9d07d3d30e27 100644
--- a/drivers/video/aty128fb.c
+++ b/drivers/video/aty128fb.c
@@ -69,7 +69,7 @@
#ifdef CONFIG_BOOTX_TEXT
#include <asm/btext.h>
-#endif /* CONFIG_BOOTX_TEXT */
+#endif /* CONFIG_BOOTX_TEXT */
#include <video/aty128.h>
#include <video/fbcon.h>
@@ -94,58 +94,57 @@
#ifndef CONFIG_PPC
/* default mode */
static struct fb_var_screeninfo default_var __initdata = {
- /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
- 640, 480, 640, 480, 0, 0, 8, 0,
- {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
- 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
- 0, FB_VMODE_NONINTERLACED
+ /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */
+ 640, 480, 640, 480, 0, 0, 8, 0,
+ {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
+ 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2,
+ 0, FB_VMODE_NONINTERLACED
};
-#else /* CONFIG_PPC */
+#else /* CONFIG_PPC */
/* default to 1024x768 at 75Hz on PPC - this will work
* on the iMac, the usual 640x480 @ 60Hz doesn't. */
static struct fb_var_screeninfo default_var = {
- /* 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, 160, 32, 28, 1, 96, 3,
- FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
- FB_VMODE_NONINTERLACED
+ /* 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, 160, 32, 28, 1, 96, 3,
+ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED
};
-#endif /* CONFIG_PPC */
+#endif /* CONFIG_PPC */
/* default modedb mode */
/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
static struct fb_videomode defaultmode __initdata = {
- refresh:60,
- xres:640,
- yres:480,
- pixclock:39722,
- left_margin:48,
- right_margin:16,
- upper_margin:33,
- lower_margin:10,
- hsync_len:96,
- vsync_len:2,
- sync:0,
- vmode:FB_VMODE_NONINTERLACED
+ refresh: 60,
+ xres: 640,
+ yres: 480,
+ pixclock: 39722,
+ left_margin: 48,
+ right_margin: 16,
+ upper_margin: 33,
+ lower_margin: 10,
+ hsync_len: 96,
+ vsync_len: 2,
+ sync: 0,
+ vmode: FB_VMODE_NONINTERLACED
};
static struct fb_fix_screeninfo aty128fb_fix __initdata = {
- id:"ATY Rage128",
- type:FB_TYPE_PACKED_PIXELS,
- visual:FB_VISUAL_PSEUDOCOLOR,
- xpanstep:8,
- ypanstep:1,
- mmio_len:0x1fff,
- accel:FB_ACCEL_ATI_RAGE128
+ id: "ATY Rage128",
+ type: FB_TYPE_PACKED_PIXELS,
+ visual: FB_VISUAL_PSEUDOCOLOR,
+ xpanstep: 8,
+ ypanstep: 1,
+ mmio_len: 0x1fff,
+ accel: FB_ACCEL_ATI_RAGE128
};
/* struct to hold chip description information */
struct aty128_chip_info {
- const char *name;
- unsigned short device;
- int chip_gen;
+ const char *name;
+ unsigned short device;
+ int chip_gen;
};
/* Chip generations */
@@ -156,21 +155,19 @@ enum {
};
/* supported Rage128 chipsets */
-static struct aty128_chip_info aty128_pci_probe_list[] __initdata = {
- {"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128},
- {"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128},
- {"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128},
- {"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128},
- {"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF,
- rage_128_pro},
- {"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR,
- rage_128_pro},
- {"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3,
- rage_128_pro},
- {"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3},
- {"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3},
- {NULL, 0, rage_128}
-};
+static struct aty128_chip_info aty128_pci_probe_list[] __initdata =
+{
+ {"Rage128 RE (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RE, rage_128},
+ {"Rage128 RF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RF, rage_128},
+ {"Rage128 RK (PCI)", PCI_DEVICE_ID_ATI_RAGE128_RK, rage_128},
+ {"Rage128 RL (AGP)", PCI_DEVICE_ID_ATI_RAGE128_RL, rage_128},
+ {"Rage128 Pro PF (AGP)", PCI_DEVICE_ID_ATI_RAGE128_PF, rage_128_pro},
+ {"Rage128 Pro PR (PCI)", PCI_DEVICE_ID_ATI_RAGE128_PR, rage_128_pro},
+ {"Rage128 Pro TR (AGP)", PCI_DEVICE_ID_ATI_RAGE128_U3, rage_128_pro},
+ {"Rage Mobility M3 (PCI)", PCI_DEVICE_ID_ATI_RAGE128_LE, rage_M3},
+ {"Rage Mobility M3 (AGP)", PCI_DEVICE_ID_ATI_RAGE128_LF, rage_M3},
+ {NULL, 0, rage_128}
+ };
/* packed BIOS settings */
#ifndef CONFIG_PPC
@@ -198,27 +195,27 @@ typedef struct {
u32 XCLK_min_freq;
u32 XCLK_max_freq;
} __attribute__ ((packed)) PLL_BLOCK;
-#endif /* !CONFIG_PPC */
+#endif /* !CONFIG_PPC */
/* onboard memory information */
struct aty128_meminfo {
- u8 ML;
- u8 MB;
- u8 Trcd;
- u8 Trp;
- u8 Twr;
- u8 CL;
- u8 Tr2w;
- u8 LoopLatency;
- u8 DspOn;
- u8 Rloop;
- const char *name;
+ u8 ML;
+ u8 MB;
+ u8 Trcd;
+ u8 Trp;
+ u8 Twr;
+ u8 CL;
+ u8 Tr2w;
+ u8 LoopLatency;
+ u8 DspOn;
+ u8 Rloop;
+ const char *name;
};
/* various memory configurations */
-static const struct aty128_meminfo sdr_128 =
+static const struct aty128_meminfo sdr_128 =
{ 4, 4, 3, 3, 1, 3, 1, 16, 30, 16, "128-bit SDR SGRAM (1:1)" };
-static const struct aty128_meminfo sdr_64 =
+static const struct aty128_meminfo sdr_64 =
{ 4, 8, 3, 3, 1, 3, 1, 17, 46, 17, "64-bit SDR SGRAM (1:1)" };
static const struct aty128_meminfo sdr_sgram =
{ 4, 4, 1, 2, 1, 2, 1, 16, 24, 16, "64-bit SDR SGRAM (2:1)" };
@@ -227,13 +224,14 @@ static const struct aty128_meminfo ddr_sgram =
static char fontname[40] __initdata = { 0 };
+static int noaccel __initdata = 0;
#ifdef MODULE
static char *font __initdata = NULL;
static char *mode __initdata = NULL;
#ifdef CONFIG_MTRR
-static int nomtrr __initdata = 0;
+static int nomtrr __initdata = 0;
#endif
-#endif /* MODULE */
+#endif /* MODULE */
static char *mode_option __initdata = NULL;
@@ -248,415 +246,490 @@ static int mtrr = 1;
/* PLL constants */
struct aty128_constants {
- u32 dotclock;
- u32 ppll_min;
- u32 ppll_max;
- u32 ref_divider;
- u32 xclk;
- u32 fifo_width;
- u32 fifo_depth;
+ u32 dotclock;
+ u32 ppll_min;
+ u32 ppll_max;
+ u32 ref_divider;
+ u32 xclk;
+ u32 fifo_width;
+ u32 fifo_depth;
};
struct aty128_crtc {
- u32 gen_cntl;
- u32 ext_cntl;
- u32 h_total, h_sync_strt_wid;
- u32 v_total, v_sync_strt_wid;
- u32 pitch;
- u32 offset, offset_cntl;
- u32 xoffset, yoffset;
- u32 vyres;
- u32 bpp;
+ u32 gen_cntl;
+ u32 ext_cntl;
+ u32 h_total, h_sync_strt_wid;
+ u32 v_total, v_sync_strt_wid;
+ u32 pitch;
+ u32 offset, offset_cntl;
+ u32 xoffset, yoffset;
+ u32 vxres, vyres;
+ u32 bpp;
};
struct aty128_pll {
- u32 post_divider;
- u32 feedback_divider;
- u32 vclk;
+ u32 post_divider;
+ u32 feedback_divider;
+ u32 vclk;
};
struct aty128_ddafifo {
- u32 dda_config;
- u32 dda_on_off;
+ u32 dda_config;
+ u32 dda_on_off;
};
/* register values for a specific mode */
struct aty128fb_par {
- struct aty128_crtc crtc;
- struct aty128_pll pll;
- struct aty128_ddafifo fifo_reg;
- const struct aty128_meminfo *mem; /* onboard mem info */
- struct aty128_constants constants; /* PLL and others */
- void *regbase; /* remapped mmio */
- int blitter_may_be_busy;
- int fifo_slots; /* free slots in FIFO (64 max) */
- int chip_gen;
+ struct aty128_crtc crtc;
+ struct aty128_pll pll;
+ struct aty128_ddafifo fifo_reg;
+ u32 accel_flags;
#ifdef CONFIG_MTRR
- struct { int vram; int vram_valid; } mtrr;
+ struct { int vram; int vram_valid; } mtrr;
#endif
};
+struct fb_info_aty128 {
+ struct fb_info fb_info;
+ struct fb_info_aty128 *next;
+ struct aty128_constants constants; /* PLL and others */
+ void *regbase; /* remapped mmio */
+ int chip_gen;
+ const struct aty128_meminfo *mem; /* onboard mem info */
+ int blitter_may_be_busy;
+ int fifo_slots; /* free slots in FIFO (64 max) */
+};
+
+static struct fb_info_aty128 *board_list = NULL;
+
#define round_div(n, d) ((n+(d/2))/d)
/*
* Interface used by the world
*/
-int aty128fb_init(void);
+
int aty128fb_setup(char *options);
-static int aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
-static int aty128fb_set_par(struct fb_info *info);
-static int aty128fb_setcolreg(u_int regno, u_int red, u_int green,
- u_int blue, u_int transp,
- struct fb_info *info);
+static int aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info);
+static int aty128fb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int aty128fb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info);
+static int aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+ u_int transp, struct fb_info *info);
static int aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *fb);
-static int aty128fb_blank(int blank, struct fb_info *info);
+ struct fb_info *fb);
+static int aty128fb_blank(int blank, struct fb_info *fb);
static int aty128fb_rasterimg(struct fb_info *info, int start);
/*
+ * Interface to the low level console driver
+ */
+
+int aty128fb_init(void);
+static int aty128fbcon_switch(int con, struct fb_info *fb);
+
+ /*
* Internal routines
*/
+
+static void aty128_encode_fix(struct fb_fix_screeninfo *fix,
+ struct aty128fb_par *par,
+ const struct fb_info_aty128 *info);
+static void aty128_set_dispsw(struct display *disp,
+ struct fb_info_aty128 *info, int bpp, int accel);
+static int aty128_encode_var(struct fb_var_screeninfo *var,
+ const struct aty128fb_par *par,
+ const struct fb_info_aty128 *info);
static int aty128_decode_var(struct fb_var_screeninfo *var,
- struct aty128fb_par *par,
- const struct fb_info *info);
+ struct aty128fb_par *par,
+ const struct fb_info_aty128 *info);
static int aty128_pci_register(struct pci_dev *pdev,
- const struct aty128_chip_info *aci);
+ const struct aty128_chip_info *aci);
+static struct fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128
+ *board_list, struct fb_info_aty128 *new_node);
#if !defined(CONFIG_PPC) && !defined(__sparc__)
-static void __init aty128_get_pllinfo(struct aty128fb_par *par,
- char *bios_seg);
-static char __init *aty128find_ROM(struct fb_info *info);
+static void __init aty128_get_pllinfo(struct fb_info_aty128 *info,
+ char *bios_seg);
+static char __init *aty128find_ROM(struct fb_info_aty128 *info);
#endif
-static void aty128_timings(struct aty128fb_par *par);
-static void aty128_init_engine(struct aty128fb_par *par,
- struct fb_info *info);
-static void aty128_reset_engine(struct aty128fb_par *par);
-static void aty128_flush_pixel_cache(struct aty128fb_par *par);
-static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par);
-static void wait_for_fifo(u16 entries, struct aty128fb_par *par);
-static void wait_for_idle(struct aty128fb_par *par);
+static void aty128_timings(struct fb_info_aty128 *info);
+static void aty128_init_engine(const struct aty128fb_par *par,
+ struct fb_info_aty128 *info);
+static void aty128_reset_engine(const struct fb_info_aty128 *info);
+static void aty128_flush_pixel_cache(const struct fb_info_aty128 *info);
+static void do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
+static void wait_for_fifo(u16 entries, struct fb_info_aty128 *info);
+static void wait_for_idle(struct fb_info_aty128 *info);
static u32 bpp_to_depth(u32 bpp);
+#ifdef FBCON_HAS_CFB8
+static struct display_switch fbcon_aty128_8;
+static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx);
+static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx);
+#endif
+#ifdef FBCON_HAS_CFB16
+static struct display_switch fbcon_aty128_16;
+static void fbcon_aty16_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx);
+static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx);
+#endif
+#ifdef FBCON_HAS_CFB24
+static struct display_switch fbcon_aty128_24;
+static void fbcon_aty24_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx);
+static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx);
+#endif
+#ifdef FBCON_HAS_CFB32
+static struct display_switch fbcon_aty128_32;
+static void fbcon_aty32_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx);
+static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx);
+#endif
+
static struct fb_ops aty128fb_ops = {
owner: THIS_MODULE,
- fb_get_fix: gen_get_fix,
- fb_get_var: gen_get_var,
- fb_set_var: gen_set_var,
+ fb_get_fix: aty128fb_get_fix,
+ fb_get_var: aty128fb_get_var,
+ fb_set_var: aty128fb_set_var,
fb_get_cmap: gen_get_cmap,
fb_set_cmap: gen_set_cmap,
- fb_check_var: aty128fb_check_var,
- fb_set_par: aty128fb_set_par,
fb_setcolreg: aty128fb_setcolreg,
fb_pan_display: aty128fb_pan_display,
fb_blank: aty128fb_blank,
- fb_fillrect: cfb_fillrect,
- fb_copyarea: cfb_copyarea,
- fb_imageblit: cfb_imageblit,
fb_rasterimg: aty128fb_rasterimg,
};
#ifdef CONFIG_PMAC_BACKLIGHT
-static int aty128_set_backlight_enable(int on, int level, void *data);
-static int aty128_set_backlight_level(int level, void *data);
+static int aty128_set_backlight_enable(int on, int level, void* data);
+static int aty128_set_backlight_level(int level, void* data);
static struct backlight_controller aty128_backlight_controller = {
aty128_set_backlight_enable,
aty128_set_backlight_level
};
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_BACKLIGHT */
/*
* Functions to read from/write to the mmio registers
- * - endian conversions may possibly be avoided by
+ * - endian conversions may possibly be avoided by
* using the other register aperture. TODO.
*/
static inline u32
-_aty_ld_le32(volatile unsigned int regindex, const struct aty128fb_par *par)
+_aty_ld_le32(volatile unsigned int regindex,
+ const struct fb_info_aty128 *info)
{
- u32 val;
+ u32 val;
#if defined(__powerpc__)
- asm("lwbrx %0,%1,%2;eieio": "=r"(val):"b"(regindex),"r"(par->regbase));
+ asm("lwbrx %0,%1,%2;eieio" : "=r"(val) : "b"(regindex), "r"(info->regbase));
#else
- val = readl(par->regbase + regindex);
+ val = readl (info->regbase + regindex);
#endif
- return val;
+
+ return val;
}
static inline void
-_aty_st_le32(volatile unsigned int regindex, u32 val, const struct aty128fb_par *par)
+_aty_st_le32(volatile unsigned int regindex, u32 val,
+ const struct fb_info_aty128 *info)
{
#if defined(__powerpc__)
- asm("stwbrx %0,%1,%2;eieio": : "r"(val), "b"(regindex), "r"(par->regbase):"memory");
+ asm("stwbrx %0,%1,%2;eieio" : : "r"(val), "b"(regindex),
+ "r"(info->regbase) : "memory");
#else
- writel(val, par->regbase + regindex);
+ writel (val, info->regbase + regindex);
#endif
}
static inline u8
-_aty_ld_8(unsigned int regindex, const struct aty128fb_par *par)
+_aty_ld_8(unsigned int regindex, const struct fb_info_aty128 *info)
{
- return readb(par->regbase + regindex);
+ return readb (info->regbase + regindex);
}
static inline void
-_aty_st_8(unsigned int regindex, u8 val, const struct aty128fb_par *par)
+_aty_st_8(unsigned int regindex, u8 val, const struct fb_info_aty128 *info)
{
- writeb(val, par->regbase + regindex);
+ writeb (val, info->regbase + regindex);
}
-#define aty_ld_le32(regindex) _aty_ld_le32(regindex, par)
-#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, par)
-#define aty_ld_8(regindex) _aty_ld_8(regindex, par)
-#define aty_st_8(regindex, val) _aty_st_8(regindex, val, par)
+#define aty_ld_le32(regindex) _aty_ld_le32(regindex, info)
+#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val, info)
+#define aty_ld_8(regindex) _aty_ld_8(regindex, info)
+#define aty_st_8(regindex, val) _aty_st_8(regindex, val, info)
/*
* Functions to read from/write to the pll registers
*/
-#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, par)
-#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, par)
+#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index, info)
+#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val, info)
static u32
-_aty_ld_pll(unsigned int pll_index, const struct aty128fb_par *par)
-{
- aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
- return aty_ld_le32(CLOCK_CNTL_DATA);
+_aty_ld_pll(unsigned int pll_index,
+ const struct fb_info_aty128 *info)
+{
+ aty_st_8(CLOCK_CNTL_INDEX, pll_index & 0x1F);
+ return aty_ld_le32(CLOCK_CNTL_DATA);
}
-
+
static void
-_aty_st_pll(unsigned int pll_index, u32 val, const struct aty128fb_par *par)
+_aty_st_pll(unsigned int pll_index, u32 val,
+ const struct fb_info_aty128 *info)
{
- aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN);
- aty_st_le32(CLOCK_CNTL_DATA, val);
+ aty_st_8(CLOCK_CNTL_INDEX, (pll_index & 0x1F) | PLL_WR_EN);
+ aty_st_le32(CLOCK_CNTL_DATA, val);
}
/* return true when the PLL has completed an atomic update */
-static int aty_pll_readupdate(const struct aty128fb_par *par)
+static int
+aty_pll_readupdate(const struct fb_info_aty128 *info)
{
- return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
+ return !(aty_ld_pll(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R);
}
-static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
+static void
+aty_pll_wait_readupdate(const struct fb_info_aty128 *info)
{
- unsigned long timeout = jiffies + HZ / 100; // should be more than enough
- int reset = 1;
+ unsigned long timeout = jiffies + HZ/100; // should be more than enough
+ int reset = 1;
- while (time_before(jiffies, timeout))
- if (aty_pll_readupdate(par)) {
- reset = 0;
- break;
- }
+ while (time_before(jiffies, timeout))
+ if (aty_pll_readupdate(info)) {
+ reset = 0;
+ break;
+ }
- if (reset) /* reset engine?? */
- printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
+ if (reset) /* reset engine?? */
+ printk(KERN_DEBUG "aty128fb: PLL write timeout!\n");
}
/* tell PLL to update */
-static void aty_pll_writeupdate(const struct aty128fb_par *par)
+static void
+aty_pll_writeupdate(const struct fb_info_aty128 *info)
{
- aty_pll_wait_readupdate(par);
+ aty_pll_wait_readupdate(info);
- aty_st_pll(PPLL_REF_DIV,
- aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
+ aty_st_pll(PPLL_REF_DIV,
+ aty_ld_pll(PPLL_REF_DIV) | PPLL_ATOMIC_UPDATE_W);
}
/* write to the scratch register to test r/w functionality */
-static int __init register_test(const struct aty128fb_par *par)
+static int __init
+register_test(const struct fb_info_aty128 *info)
{
- u32 val;
- int flag = 0;
+ u32 val;
+ int flag = 0;
- val = aty_ld_le32(BIOS_0_SCRATCH);
+ val = aty_ld_le32(BIOS_0_SCRATCH);
- aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
- if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
- aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
+ aty_st_le32(BIOS_0_SCRATCH, 0x55555555);
+ if (aty_ld_le32(BIOS_0_SCRATCH) == 0x55555555) {
+ aty_st_le32(BIOS_0_SCRATCH, 0xAAAAAAAA);
- if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
- flag = 1;
- }
+ if (aty_ld_le32(BIOS_0_SCRATCH) == 0xAAAAAAAA)
+ flag = 1;
+ }
- aty_st_le32(BIOS_0_SCRATCH, val); // restore value
- return flag;
+ aty_st_le32(BIOS_0_SCRATCH, val); // restore value
+ return flag;
}
/*
* Accelerator engine functions
*/
-static void do_wait_for_fifo(u16 entries, struct aty128fb_par *par)
+static void
+do_wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
{
- int i;
-
- for (;;) {
- for (i = 0; i < 2000000; i++) {
- par->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
- if (par->fifo_slots >= entries)
- return;
- }
- aty128_reset_engine(par);
- }
+ int i;
+
+ for (;;) {
+ for (i = 0; i < 2000000; i++) {
+ info->fifo_slots = aty_ld_le32(GUI_STAT) & 0x0fff;
+ if (info->fifo_slots >= entries)
+ return;
+ }
+ aty128_reset_engine(info);
+ }
}
-static void wait_for_idle(struct aty128fb_par *par)
-{
- int i;
- do_wait_for_fifo(64, par);
-
- for (;;) {
- for (i = 0; i < 2000000; i++) {
- if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
- aty128_flush_pixel_cache(par);
- par->blitter_may_be_busy = 0;
- return;
- }
- }
- aty128_reset_engine(par);
- }
+static void
+wait_for_idle(struct fb_info_aty128 *info)
+{
+ int i;
+
+ do_wait_for_fifo(64, info);
+
+ for (;;) {
+ for (i = 0; i < 2000000; i++) {
+ if (!(aty_ld_le32(GUI_STAT) & (1 << 31))) {
+ aty128_flush_pixel_cache(info);
+ info->blitter_may_be_busy = 0;
+ return;
+ }
+ }
+ aty128_reset_engine(info);
+ }
}
-static void wait_for_fifo(u16 entries, struct aty128fb_par *par)
+static void
+wait_for_fifo(u16 entries, struct fb_info_aty128 *info)
{
- if (par->fifo_slots < entries)
- do_wait_for_fifo(64, par);
- par->fifo_slots -= entries;
+ if (info->fifo_slots < entries)
+ do_wait_for_fifo(64, info);
+ info->fifo_slots -= entries;
}
-static void aty128_flush_pixel_cache(struct aty128fb_par *par)
+static void
+aty128_flush_pixel_cache(const struct fb_info_aty128 *info)
{
- u32 tmp;
- int i;
+ int i;
+ u32 tmp;
- tmp = aty_ld_le32(PC_NGUI_CTLSTAT);
- tmp &= ~(0x00ff);
- tmp |= 0x00ff;
- aty_st_le32(PC_NGUI_CTLSTAT, tmp);
+ tmp = aty_ld_le32(PC_NGUI_CTLSTAT);
+ tmp &= ~(0x00ff);
+ tmp |= 0x00ff;
+ aty_st_le32(PC_NGUI_CTLSTAT, tmp);
- for (i = 0; i < 2000000; i++)
- if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
- break;
+ for (i = 0; i < 2000000; i++)
+ if (!(aty_ld_le32(PC_NGUI_CTLSTAT) & PC_BUSY))
+ break;
}
-static void aty128_reset_engine(struct aty128fb_par *par)
+static void
+aty128_reset_engine(const struct fb_info_aty128 *info)
{
- u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
+ u32 gen_reset_cntl, clock_cntl_index, mclk_cntl;
- aty128_flush_pixel_cache(par);
+ aty128_flush_pixel_cache(info);
- clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
- mclk_cntl = aty_ld_pll(MCLK_CNTL);
+ clock_cntl_index = aty_ld_le32(CLOCK_CNTL_INDEX);
+ mclk_cntl = aty_ld_pll(MCLK_CNTL);
- aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
+ aty_st_pll(MCLK_CNTL, mclk_cntl | 0x00030000);
- gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
- aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
- aty_ld_le32(GEN_RESET_CNTL);
- aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
- aty_ld_le32(GEN_RESET_CNTL);
+ gen_reset_cntl = aty_ld_le32(GEN_RESET_CNTL);
+ aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl | SOFT_RESET_GUI);
+ aty_ld_le32(GEN_RESET_CNTL);
+ aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl & ~(SOFT_RESET_GUI));
+ aty_ld_le32(GEN_RESET_CNTL);
- aty_st_pll(MCLK_CNTL, mclk_cntl);
- aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
- aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
+ aty_st_pll(MCLK_CNTL, mclk_cntl);
+ aty_st_le32(CLOCK_CNTL_INDEX, clock_cntl_index);
+ aty_st_le32(GEN_RESET_CNTL, gen_reset_cntl);
- /* use old pio mode */
- aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
+ /* use old pio mode */
+ aty_st_le32(PM4_BUFFER_CNTL, PM4_BUFFER_CNTL_NONPM4);
- DBG("engine reset");
+ DBG("engine reset");
}
static void
-aty128_init_engine(struct aty128fb_par *par,
- struct fb_info *info)
+aty128_init_engine(const struct aty128fb_par *par,
+ struct fb_info_aty128 *info)
{
- u32 pitch_value;
-
- wait_for_idle(par);
-
- /* 3D scaler not spoken here */
- wait_for_fifo(1, par);
- aty_st_le32(SCALE_3D_CNTL, 0x00000000);
-
- aty128_reset_engine(par);
-
- pitch_value = par->crtc.pitch;
- if (par->crtc.bpp == 24) {
- pitch_value = pitch_value * 3;
- }
-
- wait_for_fifo(4, par);
- /* setup engine offset registers */
- aty_st_le32(DEFAULT_OFFSET, 0x00000000);
-
- /* setup engine pitch registers */
- aty_st_le32(DEFAULT_PITCH, pitch_value);
-
- /* set the default scissor register to max dimensions */
- aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
-
- /* set the drawing controls registers */
- aty_st_le32(DP_GUI_MASTER_CNTL,
- GMC_SRC_PITCH_OFFSET_DEFAULT |
- GMC_DST_PITCH_OFFSET_DEFAULT |
- GMC_SRC_CLIP_DEFAULT |
- GMC_DST_CLIP_DEFAULT |
- GMC_BRUSH_SOLIDCOLOR |
- (bpp_to_depth(par->crtc.bpp) << 8) |
- GMC_SRC_DSTCOLOR |
- GMC_BYTE_ORDER_MSB_TO_LSB |
- GMC_DP_CONVERSION_TEMP_6500 |
- ROP3_PATCOPY |
- GMC_DP_SRC_RECT |
- GMC_3D_FCN_EN_CLR |
- GMC_DST_CLR_CMP_FCN_CLEAR |
- GMC_AUX_CLIP_CLEAR | GMC_WRITE_MASK_SET);
-
- wait_for_fifo(8, par);
- /* clear the line drawing registers */
- aty_st_le32(DST_BRES_ERR, 0);
- aty_st_le32(DST_BRES_INC, 0);
- aty_st_le32(DST_BRES_DEC, 0);
-
- /* set brush color registers */
- aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
- aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
-
- /* set source color registers */
- aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF); /* white */
- aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000); /* black */
-
- /* default write mask */
- aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
-
- /* Wait for all the writes to be completed before returning */
- wait_for_idle(par);
+ u32 pitch_value;
+
+ wait_for_idle(info);
+
+ /* 3D scaler not spoken here */
+ wait_for_fifo(1, info);
+ aty_st_le32(SCALE_3D_CNTL, 0x00000000);
+
+ aty128_reset_engine(info);
+
+ pitch_value = par->crtc.pitch;
+ if (par->crtc.bpp == 24) {
+ pitch_value = pitch_value * 3;
+ }
+
+ wait_for_fifo(4, info);
+ /* setup engine offset registers */
+ aty_st_le32(DEFAULT_OFFSET, 0x00000000);
+
+ /* setup engine pitch registers */
+ aty_st_le32(DEFAULT_PITCH, pitch_value);
+
+ /* set the default scissor register to max dimensions */
+ aty_st_le32(DEFAULT_SC_BOTTOM_RIGHT, (0x1FFF << 16) | 0x1FFF);
+
+ /* set the drawing controls registers */
+ aty_st_le32(DP_GUI_MASTER_CNTL,
+ GMC_SRC_PITCH_OFFSET_DEFAULT |
+ GMC_DST_PITCH_OFFSET_DEFAULT |
+ GMC_SRC_CLIP_DEFAULT |
+ GMC_DST_CLIP_DEFAULT |
+ GMC_BRUSH_SOLIDCOLOR |
+ (bpp_to_depth(par->crtc.bpp) << 8) |
+ GMC_SRC_DSTCOLOR |
+ GMC_BYTE_ORDER_MSB_TO_LSB |
+ GMC_DP_CONVERSION_TEMP_6500 |
+ ROP3_PATCOPY |
+ GMC_DP_SRC_RECT |
+ GMC_3D_FCN_EN_CLR |
+ GMC_DST_CLR_CMP_FCN_CLEAR |
+ GMC_AUX_CLIP_CLEAR |
+ GMC_WRITE_MASK_SET);
+
+ wait_for_fifo(8, info);
+ /* clear the line drawing registers */
+ aty_st_le32(DST_BRES_ERR, 0);
+ aty_st_le32(DST_BRES_INC, 0);
+ aty_st_le32(DST_BRES_DEC, 0);
+
+ /* set brush color registers */
+ aty_st_le32(DP_BRUSH_FRGD_CLR, 0xFFFFFFFF); /* white */
+ aty_st_le32(DP_BRUSH_BKGD_CLR, 0x00000000); /* black */
+
+ /* set source color registers */
+ aty_st_le32(DP_SRC_FRGD_CLR, 0xFFFFFFFF); /* white */
+ aty_st_le32(DP_SRC_BKGD_CLR, 0x00000000); /* black */
+
+ /* default write mask */
+ aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
+
+ /* Wait for all the writes to be completed before returning */
+ wait_for_idle(info);
}
/* convert bpp values to their register representation */
-static u32 bpp_to_depth(u32 bpp)
+static u32
+bpp_to_depth(u32 bpp)
{
- if (bpp <= 8)
- return DST_8BPP;
- else if (bpp <= 16)
- return DST_15BPP;
- else if (bpp <= 24)
- return DST_24BPP;
- else if (bpp <= 32)
- return DST_32BPP;
-
- return -EINVAL;
+ if (bpp <= 8)
+ return DST_8BPP;
+ else if (bpp <= 16)
+ return DST_15BPP;
+ else if (bpp <= 24)
+ return DST_24BPP;
+ else if (bpp <= 32)
+ return DST_32BPP;
+
+ return -EINVAL;
}
@@ -667,484 +740,484 @@ static u32 bpp_to_depth(u32 bpp)
/* Program the CRTC registers */
static void
aty128_set_crtc(const struct aty128_crtc *crtc,
- const struct aty128fb_par *par)
-{
- aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
- aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
- aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
- aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
- aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
- aty_st_le32(CRTC_PITCH, crtc->pitch);
- aty_st_le32(CRTC_OFFSET, crtc->offset);
- aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
- /* Disable ATOMIC updating. Is this the right place?
- * -- BenH: Breaks on my G4
- */
+ const struct fb_info_aty128 *info)
+{
+ aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl);
+ aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_total);
+ aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid);
+ aty_st_le32(CRTC_V_TOTAL_DISP, crtc->v_total);
+ aty_st_le32(CRTC_V_SYNC_STRT_WID, crtc->v_sync_strt_wid);
+ aty_st_le32(CRTC_PITCH, crtc->pitch);
+ aty_st_le32(CRTC_OFFSET, crtc->offset);
+ aty_st_le32(CRTC_OFFSET_CNTL, crtc->offset_cntl);
+ /* Disable ATOMIC updating. Is this the right place?
+ * -- BenH: Breaks on my G4
+ */
#if 0
- aty_st_le32(PPLL_CNTL, aty_ld_le32(PPLL_CNTL) & ~(0x00030000));
+ aty_st_le32(PPLL_CNTL, aty_ld_le32(PPLL_CNTL) & ~(0x00030000));
#endif
}
static int
-aty128_var_to_crtc(struct fb_var_screeninfo *var,
- struct aty128_crtc *crtc,
- const struct fb_info *info)
-{
- u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
- u32 left, right, upper, lower, hslen, vslen, sync, vmode;
- u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
- u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
- u32 depth, bytpp;
- u8 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 };
- u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
-
- /* input */
- xres = var->xres;
- yres = var->yres;
- vxres = var->xres_virtual;
- vyres = var->yres_virtual;
- xoffset = var->xoffset;
- yoffset = var->yoffset;
- bpp = var->bits_per_pixel;
- left = var->left_margin;
- right = var->right_margin;
- upper = var->upper_margin;
- lower = var->lower_margin;
- hslen = var->hsync_len;
- vslen = var->vsync_len;
- sync = var->sync;
- vmode = var->vmode;
-
- /* check for mode eligibility
- * accept only non interlaced modes */
- if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
- return -EINVAL;
-
- /* convert (and round up) and validate */
- xres = (xres + 7) & ~7;
- xoffset = (xoffset + 7) & ~7;
-
- if (vxres < xres + xoffset)
- vxres = xres + xoffset;
-
- if (vyres < yres + yoffset)
- vyres = yres + yoffset;
-
- /* convert bpp into ATI register depth */
- depth = bpp_to_depth(bpp);
-
- /* make sure we didn't get an invalid depth */
- if (depth == -EINVAL) {
- printk(KERN_ERR "aty128fb: Invalid depth\n");
- return -EINVAL;
- }
+aty128_var_to_crtc(const struct fb_var_screeninfo *var,
+ struct aty128_crtc *crtc,
+ const struct fb_info_aty128 *info)
+{
+ u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp;
+ u32 left, right, upper, lower, hslen, vslen, sync, vmode;
+ u32 h_total, h_disp, h_sync_strt, h_sync_wid, h_sync_pol;
+ u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync;
+ u32 depth, bytpp;
+ u8 hsync_strt_pix[5] = { 0, 0x12, 9, 6, 5 };
+ u8 mode_bytpp[7] = { 0, 0, 1, 2, 2, 3, 4 };
+
+ /* input */
+ xres = var->xres;
+ yres = var->yres;
+ vxres = var->xres_virtual;
+ vyres = var->yres_virtual;
+ xoffset = var->xoffset;
+ yoffset = var->yoffset;
+ bpp = var->bits_per_pixel;
+ left = var->left_margin;
+ right = var->right_margin;
+ upper = var->upper_margin;
+ lower = var->lower_margin;
+ hslen = var->hsync_len;
+ vslen = var->vsync_len;
+ sync = var->sync;
+ vmode = var->vmode;
+
+ /* check for mode eligibility
+ * accept only non interlaced modes */
+ if ((vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)
+ return -EINVAL;
- /* convert depth to bpp */
- bytpp = mode_bytpp[depth];
+ /* convert (and round up) and validate */
+ xres = (xres + 7) & ~7;
+ xoffset = (xoffset + 7) & ~7;
- /* make sure there is enough video ram for the mode */
- if ((u32) (vxres * vyres * bytpp) > info->fix.smem_len) {
- printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
- return -EINVAL;
- }
+ if (vxres < xres + xoffset)
+ vxres = xres + xoffset;
- h_disp = (xres >> 3) - 1;
- h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL;
+ if (vyres < yres + yoffset)
+ vyres = yres + yoffset;
- v_disp = yres - 1;
- v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
+ /* convert bpp into ATI register depth */
+ depth = bpp_to_depth(bpp);
- /* check to make sure h_total and v_total are in range */
- if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
- printk(KERN_ERR "aty128fb: invalid width ranges\n");
- return -EINVAL;
- }
+ /* make sure we didn't get an invalid depth */
+ if (depth == -EINVAL) {
+ printk(KERN_ERR "aty128fb: Invalid depth\n");
+ return -EINVAL;
+ }
- h_sync_wid = (hslen + 7) >> 3;
- if (h_sync_wid == 0)
- h_sync_wid = 1;
- else if (h_sync_wid > 0x3f) /* 0x3f = max hwidth */
- h_sync_wid = 0x3f;
+ /* convert depth to bpp */
+ bytpp = mode_bytpp[depth];
- h_sync_strt = h_disp + (right >> 3);
+ /* make sure there is enough video ram for the mode */
+ if ((u32)(vxres * vyres * bytpp) > info->fb_info.fix.smem_len) {
+ printk(KERN_ERR "aty128fb: Not enough memory for mode\n");
+ return -EINVAL;
+ }
- v_sync_wid = vslen;
- if (v_sync_wid == 0)
- v_sync_wid = 1;
- else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */
- v_sync_wid = 0x1f;
+ h_disp = (xres >> 3) - 1;
+ h_total = (((xres + right + hslen + left) >> 3) - 1) & 0xFFFFL;
- v_sync_strt = v_disp + lower;
+ v_disp = yres - 1;
+ v_total = (yres + upper + vslen + lower - 1) & 0xFFFFL;
- h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
- v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+ /* check to make sure h_total and v_total are in range */
+ if (((h_total >> 3) - 1) > 0x1ff || (v_total - 1) > 0x7FF) {
+ printk(KERN_ERR "aty128fb: invalid width ranges\n");
+ return -EINVAL;
+ }
- c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
+ h_sync_wid = (hslen + 7) >> 3;
+ if (h_sync_wid == 0)
+ h_sync_wid = 1;
+ else if (h_sync_wid > 0x3f) /* 0x3f = max hwidth */
+ h_sync_wid = 0x3f;
- crtc->gen_cntl = 0x3000000L | c_sync | (depth << 8);
+ h_sync_strt = h_disp + (right >> 3);
- crtc->h_total = h_total | (h_disp << 16);
- crtc->v_total = v_total | (v_disp << 16);
+ v_sync_wid = vslen;
+ if (v_sync_wid == 0)
+ v_sync_wid = 1;
+ else if (v_sync_wid > 0x1f) /* 0x1f = max vwidth */
+ v_sync_wid = 0x1f;
+
+ v_sync_strt = v_disp + lower;
- crtc->h_sync_strt_wid =
- hsync_strt_pix[bytpp] | (h_sync_strt << 3) | (h_sync_wid << 16)
- | (h_sync_pol << 23);
- crtc->v_sync_strt_wid =
- v_sync_strt | (v_sync_wid << 16) | (v_sync_pol << 23);
+ h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1;
+ v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1;
+
+ c_sync = sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0;
- crtc->pitch = vxres >> 3;
+ crtc->gen_cntl = 0x3000000L | c_sync | (depth << 8);
- crtc->offset = 0;
+ crtc->h_total = h_total | (h_disp << 16);
+ crtc->v_total = v_total | (v_disp << 16);
- if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
- crtc->offset_cntl = 0x00010000;
- else
- crtc->offset_cntl = 0;
+ crtc->h_sync_strt_wid = hsync_strt_pix[bytpp] | (h_sync_strt << 3) |
+ (h_sync_wid << 16) | (h_sync_pol << 23);
+ crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) |
+ (v_sync_pol << 23);
- var->xres_virtual = vxres;
- crtc->vyres = vyres;
- crtc->xoffset = xoffset;
- crtc->yoffset = yoffset;
- crtc->bpp = bpp;
+ crtc->pitch = vxres >> 3;
- return 0;
+ crtc->offset = 0;
+
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW)
+ crtc->offset_cntl = 0x00010000;
+ else
+ crtc->offset_cntl = 0;
+
+ crtc->vxres = vxres;
+ crtc->vyres = vyres;
+ crtc->xoffset = xoffset;
+ crtc->yoffset = yoffset;
+ crtc->bpp = bpp;
+
+ return 0;
}
-static int aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
+static int
+aty128_bpp_to_var(int pix_width, struct fb_var_screeninfo *var)
{
- /* fill in pixel info */
- switch (pix_width) {
- case CRTC_PIX_WIDTH_8BPP:
- var->bits_per_pixel = 8;
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case CRTC_PIX_WIDTH_15BPP:
- case CRTC_PIX_WIDTH_16BPP:
- var->bits_per_pixel = 16;
- var->red.offset = 10;
- var->red.length = 5;
- var->green.offset = 5;
- var->green.length = 5;
- var->blue.offset = 0;
- var->blue.length = 5;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case CRTC_PIX_WIDTH_24BPP:
- var->bits_per_pixel = 24;
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 0;
- var->transp.length = 0;
- break;
- case CRTC_PIX_WIDTH_32BPP:
- var->bits_per_pixel = 32;
- var->red.offset = 16;
- var->red.length = 8;
- var->green.offset = 8;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
- var->transp.offset = 24;
- var->transp.length = 8;
- break;
- default:
- printk(KERN_ERR "aty128fb: Invalid pixel width\n");
- return -EINVAL;
- }
-
- return 0;
+ /* fill in pixel info */
+ switch (pix_width) {
+ case CRTC_PIX_WIDTH_8BPP:
+ var->bits_per_pixel = 8;
+ var->red.offset = 0;
+ var->red.length = 8;
+ var->green.offset = 0;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case CRTC_PIX_WIDTH_15BPP:
+ case CRTC_PIX_WIDTH_16BPP:
+ var->bits_per_pixel = 16;
+ var->red.offset = 10;
+ var->red.length = 5;
+ var->green.offset = 5;
+ var->green.length = 5;
+ var->blue.offset = 0;
+ var->blue.length = 5;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case CRTC_PIX_WIDTH_24BPP:
+ var->bits_per_pixel = 24;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 0;
+ var->transp.length = 0;
+ break;
+ case CRTC_PIX_WIDTH_32BPP:
+ var->bits_per_pixel = 32;
+ var->red.offset = 16;
+ var->red.length = 8;
+ var->green.offset = 8;
+ var->green.length = 8;
+ var->blue.offset = 0;
+ var->blue.length = 8;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ break;
+ default:
+ printk(KERN_ERR "aty128fb: Invalid pixel width\n");
+ return -EINVAL;
+ }
+
+ return 0;
}
static int
aty128_crtc_to_var(const struct aty128_crtc *crtc,
- struct fb_var_screeninfo *var)
-{
- u32 xres, yres, 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, c_sync;
- u32 pix_width;
-
- /* fun with masking */
- h_total = crtc->h_total & 0x1ff;
- h_disp = (crtc->h_total >> 16) & 0xff;
- h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff;
- h_sync_dly = crtc->h_sync_strt_wid & 0x7;
- h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x3f;
- h_sync_pol = (crtc->h_sync_strt_wid >> 23) & 0x1;
- v_total = crtc->v_total & 0x7ff;
- v_disp = (crtc->v_total >> 16) & 0x7ff;
- 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 >> 23) & 0x1;
- c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
- pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
-
- /* do conversions */
- xres = (h_disp + 1) << 3;
- yres = v_disp + 1;
- left = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly;
- right = ((h_sync_strt - h_disp) << 3) + h_sync_dly;
- hslen = h_sync_wid << 3;
- 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) |
- (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
-
- aty128_bpp_to_var(pix_width, var);
-
- var->xres = xres;
- var->yres = yres;
- var->yres_virtual = crtc->vyres;
- var->xoffset = crtc->xoffset;
- var->yoffset = crtc->yoffset;
- var->left_margin = left;
- var->right_margin = right;
- var->upper_margin = upper;
- var->lower_margin = lower;
- var->hsync_len = hslen;
- var->vsync_len = vslen;
- var->sync = sync;
- var->vmode = FB_VMODE_NONINTERLACED;
-
- return 0;
+ struct fb_var_screeninfo *var)
+{
+ u32 xres, yres, 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, c_sync;
+ u32 pix_width;
+
+ /* fun with masking */
+ h_total = crtc->h_total & 0x1ff;
+ h_disp = (crtc->h_total >> 16) & 0xff;
+ h_sync_strt = (crtc->h_sync_strt_wid >> 3) & 0x1ff;
+ h_sync_dly = crtc->h_sync_strt_wid & 0x7;
+ h_sync_wid = (crtc->h_sync_strt_wid >> 16) & 0x3f;
+ h_sync_pol = (crtc->h_sync_strt_wid >> 23) & 0x1;
+ v_total = crtc->v_total & 0x7ff;
+ v_disp = (crtc->v_total >> 16) & 0x7ff;
+ 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 >> 23) & 0x1;
+ c_sync = crtc->gen_cntl & CRTC_CSYNC_EN ? 1 : 0;
+ pix_width = crtc->gen_cntl & CRTC_PIX_WIDTH_MASK;
+
+ /* do conversions */
+ xres = (h_disp + 1) << 3;
+ yres = v_disp + 1;
+ left = ((h_total - h_sync_strt - h_sync_wid) << 3) - h_sync_dly;
+ right = ((h_sync_strt - h_disp) << 3) + h_sync_dly;
+ hslen = h_sync_wid << 3;
+ 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) |
+ (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0);
+
+ aty128_bpp_to_var(pix_width, var);
+
+ var->xres = xres;
+ var->yres = yres;
+ var->xres_virtual = crtc->vxres;
+ var->yres_virtual = crtc->vyres;
+ var->xoffset = crtc->xoffset;
+ var->yoffset = crtc->yoffset;
+ var->left_margin = left;
+ var->right_margin = right;
+ var->upper_margin = upper;
+ var->lower_margin = lower;
+ var->hsync_len = hslen;
+ var->vsync_len = vslen;
+ var->sync = sync;
+ var->vmode = FB_VMODE_NONINTERLACED;
+
+ return 0;
}
static void
-aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
+aty128_set_pll(struct aty128_pll *pll, const struct fb_info_aty128 *info)
{
- u32 div3;
+ u32 div3;
- unsigned char post_conv[] = /* register values for post dividers */
- { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
+ unsigned char post_conv[] = /* register values for post dividers */
+ { 2, 0, 1, 4, 2, 2, 6, 2, 3, 2, 2, 2, 7 };
- /* select PPLL_DIV_3 */
- aty_st_le32(CLOCK_CNTL_INDEX,
- aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
+ /* select PPLL_DIV_3 */
+ aty_st_le32(CLOCK_CNTL_INDEX, aty_ld_le32(CLOCK_CNTL_INDEX) | (3 << 8));
- /* reset PLL */
- aty_st_pll(PPLL_CNTL,
- aty_ld_pll(PPLL_CNTL) | PPLL_RESET |
- PPLL_ATOMIC_UPDATE_EN);
+ /* reset PLL */
+ aty_st_pll(PPLL_CNTL,
+ aty_ld_pll(PPLL_CNTL) | PPLL_RESET | PPLL_ATOMIC_UPDATE_EN);
- /* write the reference divider */
- aty_pll_wait_readupdate(par);
- aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider & 0x3ff);
- aty_pll_writeupdate(par);
+ /* write the reference divider */
+ aty_pll_wait_readupdate(info);
+ aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider & 0x3ff);
+ aty_pll_writeupdate(info);
- div3 = aty_ld_pll(PPLL_DIV_3);
- div3 &= ~PPLL_FB3_DIV_MASK;
- div3 |= pll->feedback_divider;
- div3 &= ~PPLL_POST3_DIV_MASK;
- div3 |= post_conv[pll->post_divider] << 16;
+ div3 = aty_ld_pll(PPLL_DIV_3);
+ div3 &= ~PPLL_FB3_DIV_MASK;
+ div3 |= pll->feedback_divider;
+ div3 &= ~PPLL_POST3_DIV_MASK;
+ div3 |= post_conv[pll->post_divider] << 16;
- /* write feedback and post dividers */
- aty_pll_wait_readupdate(par);
- aty_st_pll(PPLL_DIV_3, div3);
- aty_pll_writeupdate(par);
+ /* write feedback and post dividers */
+ aty_pll_wait_readupdate(info);
+ aty_st_pll(PPLL_DIV_3, div3);
+ aty_pll_writeupdate(info);
- aty_pll_wait_readupdate(par);
- aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */
- aty_pll_writeupdate(par);
+ aty_pll_wait_readupdate(info);
+ aty_st_pll(HTOTAL_CNTL, 0); /* no horiz crtc adjustment */
+ aty_pll_writeupdate(info);
- /* clear the reset, just in case */
- aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
+ /* clear the reset, just in case */
+ aty_st_pll(PPLL_CNTL, aty_ld_pll(PPLL_CNTL) & ~PPLL_RESET);
}
static int
aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
- const struct aty128fb_par *par)
-{
- const struct aty128_constants c = par->constants;
- unsigned char post_dividers[] = { 1, 2, 4, 8, 3, 6, 12 };
- u32 output_freq;
- u32 vclk; /* in .01 MHz */
- int i;
- u32 n, d;
-
- vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */
-
- /* adjust pixel clock if necessary */
- if (vclk > c.ppll_max)
- vclk = c.ppll_max;
- if (vclk * 12 < c.ppll_min)
- vclk = c.ppll_min / 12;
-
- /* now, find an acceptable divider */
- for (i = 0; i < sizeof(post_dividers); i++) {
- output_freq = post_dividers[i] * vclk;
- if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
- break;
- }
-
- /* calculate feedback divider */
- n = c.ref_divider * output_freq;
- d = c.dotclock;
-
- pll->post_divider = post_dividers[i];
- pll->feedback_divider = round_div(n, d);
- pll->vclk = vclk;
-
- DBG("post %d feedback %d vlck %d output %d ref_divider %d "
- "vclk_per: %d\n", pll->post_divider,
- pll->feedback_divider, vclk, output_freq,
- c.ref_divider, period_in_ps);
-
- return 0;
+ const struct fb_info_aty128 *info)
+{
+ const struct aty128_constants c = info->constants;
+ unsigned char post_dividers[] = {1,2,4,8,3,6,12};
+ u32 output_freq;
+ u32 vclk; /* in .01 MHz */
+ int i;
+ u32 n, d;
+
+ vclk = 100000000 / period_in_ps; /* convert units to 10 kHz */
+
+ /* adjust pixel clock if necessary */
+ if (vclk > c.ppll_max)
+ vclk = c.ppll_max;
+ if (vclk * 12 < c.ppll_min)
+ vclk = c.ppll_min/12;
+
+ /* now, find an acceptable divider */
+ for (i = 0; i < sizeof(post_dividers); i++) {
+ output_freq = post_dividers[i] * vclk;
+ if (output_freq >= c.ppll_min && output_freq <= c.ppll_max)
+ break;
+ }
+
+ /* calculate feedback divider */
+ n = c.ref_divider * output_freq;
+ d = c.dotclock;
+
+ pll->post_divider = post_dividers[i];
+ pll->feedback_divider = round_div(n, d);
+ pll->vclk = vclk;
+
+ DBG("post %d feedback %d vlck %d output %d ref_divider %d "
+ "vclk_per: %d\n", pll->post_divider,
+ pll->feedback_divider, vclk, output_freq,
+ c.ref_divider, period_in_ps);
+
+ return 0;
}
static int
-aty128_pll_to_var(const struct aty128_pll *pll,
- struct fb_var_screeninfo *var,
- const struct fb_info *info)
+aty128_pll_to_var(const struct aty128_pll *pll, struct fb_var_screeninfo *var,
+ const struct fb_info_aty128 *info)
{
- var->pixclock = 100000000 / pll->vclk;
+ var->pixclock = 100000000 / pll->vclk;
- return 0;
+ return 0;
}
static void
aty128_set_fifo(const struct aty128_ddafifo *dsp,
- const struct aty128fb_par *par)
+ const struct fb_info_aty128 *info)
{
- aty_st_le32(DDA_CONFIG, dsp->dda_config);
- aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
+ aty_st_le32(DDA_CONFIG, dsp->dda_config);
+ aty_st_le32(DDA_ON_OFF, dsp->dda_on_off);
}
static int
aty128_ddafifo(struct aty128_ddafifo *dsp,
- const struct aty128_pll *pll,
- u32 bpp, const struct fb_info *info)
-{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- const struct aty128_meminfo *m = par->mem;
- u32 xclk = par->constants.xclk;
- u32 fifo_width = par->constants.fifo_width;
- u32 fifo_depth = par->constants.fifo_depth;
- s32 x, b, p, ron, roff;
- u32 n, d;
-
- /* 15bpp is really 16bpp */
- if (bpp == 15)
- bpp = 16;
-
- n = xclk * fifo_width;
- d = pll->vclk * bpp;
- x = round_div(n, d);
-
- ron = 4 * m->MB +
- 3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
- 2 * m->Trp + m->Twr + m->CL + m->Tr2w + x;
-
- DBG("x %x\n", x);
-
- b = 0;
- while (x) {
- x >>= 1;
- b++;
- }
- p = b + 1;
-
- ron <<= (11 - p);
-
- n <<= (11 - p);
- x = round_div(n, d);
- roff = x * (fifo_depth - 4);
-
- if ((ron + m->Rloop) >= roff) {
- printk(KERN_ERR "aty128fb: Mode out of range!\n");
- return -EINVAL;
- }
+ const struct aty128_pll *pll,
+ u32 bpp,
+ const struct fb_info_aty128 *info)
+{
+ const struct aty128_meminfo *m = info->mem;
+ u32 xclk = info->constants.xclk;
+ u32 fifo_width = info->constants.fifo_width;
+ u32 fifo_depth = info->constants.fifo_depth;
+ s32 x, b, p, ron, roff;
+ u32 n, d;
+
+ /* 15bpp is really 16bpp */
+ if (bpp == 15)
+ bpp = 16;
+
+ n = xclk * fifo_width;
+ d = pll->vclk * bpp;
+ x = round_div(n, d);
+
+ ron = 4 * m->MB +
+ 3 * ((m->Trcd - 2 > 0) ? m->Trcd - 2 : 0) +
+ 2 * m->Trp +
+ m->Twr +
+ m->CL +
+ m->Tr2w +
+ x;
+
+ DBG("x %x\n", x);
+
+ b = 0;
+ while (x) {
+ x >>= 1;
+ b++;
+ }
+ p = b + 1;
+
+ ron <<= (11 - p);
+
+ n <<= (11 - p);
+ x = round_div(n, d);
+ roff = x * (fifo_depth - 4);
+
+ if ((ron + m->Rloop) >= roff) {
+ printk(KERN_ERR "aty128fb: Mode out of range!\n");
+ return -EINVAL;
+ }
- DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
- p, m->Rloop, x, ron, roff);
+ DBG("p: %x rloop: %x x: %x ron: %x roff: %x\n",
+ p, m->Rloop, x, ron, roff);
- dsp->dda_config = p << 16 | m->Rloop << 20 | x;
- dsp->dda_on_off = ron << 16 | roff;
+ dsp->dda_config = p << 16 | m->Rloop << 20 | x;
+ dsp->dda_on_off = ron << 16 | roff;
- return 0;
+ return 0;
}
/*
* This actually sets the video mode.
*/
-static int
-aty128fb_set_par(struct fb_info *info)
+static void
+aty128_set_par(struct aty128fb_par *par,
+ struct fb_info_aty128 *info)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- u32 config;
-
- if (par->blitter_may_be_busy)
- wait_for_idle(par);
-
- /* clear all registers that may interfere with mode setting */
- aty_st_le32(OVR_CLR, 0);
- aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
- aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
- aty_st_le32(OV0_SCALE_CNTL, 0);
- aty_st_le32(MPP_TB_CONFIG, 0);
- aty_st_le32(MPP_GP_CONFIG, 0);
- aty_st_le32(SUBPIC_CNTL, 0);
- aty_st_le32(VIPH_CONTROL, 0);
- aty_st_le32(I2C_CNTL_1, 0); /* turn off i2c */
- aty_st_le32(GEN_INT_CNTL, 0); /* turn off interrupts */
- aty_st_le32(CAP0_TRIG_CNTL, 0);
- aty_st_le32(CAP1_TRIG_CNTL, 0);
-
- aty_st_8(CRTC_EXT_CNTL + 1, 4); /* turn video off */
-
- aty128_set_crtc(&par->crtc, par);
- aty128_set_pll(&par->pll, par);
- aty128_set_fifo(&par->fifo_reg, par);
-
- config = aty_ld_le32(CONFIG_CNTL) & ~3;
+ u32 config;
+
+ info->fb_info.par = par;
+
+ if (info->blitter_may_be_busy)
+ wait_for_idle(info);
+
+ /* clear all registers that may interfere with mode setting */
+ aty_st_le32(OVR_CLR, 0);
+ aty_st_le32(OVR_WID_LEFT_RIGHT, 0);
+ aty_st_le32(OVR_WID_TOP_BOTTOM, 0);
+ aty_st_le32(OV0_SCALE_CNTL, 0);
+ aty_st_le32(MPP_TB_CONFIG, 0);
+ aty_st_le32(MPP_GP_CONFIG, 0);
+ aty_st_le32(SUBPIC_CNTL, 0);
+ aty_st_le32(VIPH_CONTROL, 0);
+ aty_st_le32(I2C_CNTL_1, 0); /* turn off i2c */
+ aty_st_le32(GEN_INT_CNTL, 0); /* turn off interrupts */
+ aty_st_le32(CAP0_TRIG_CNTL, 0);
+ aty_st_le32(CAP1_TRIG_CNTL, 0);
+
+ aty_st_8(CRTC_EXT_CNTL + 1, 4); /* turn video off */
+
+ aty128_set_crtc(&par->crtc, info);
+ aty128_set_pll(&par->pll, info);
+ aty128_set_fifo(&par->fifo_reg, info);
+
+ config = aty_ld_le32(CONFIG_CNTL) & ~3;
#if defined(__BIG_ENDIAN)
- if (par->crtc.bpp >= 24)
- config |= 2; /* make aperture do 32 byte swapping */
- else if (par->crtc.bpp > 8)
- config |= 1; /* make aperture do 16 byte swapping */
+ if (par->crtc.bpp >= 24)
+ config |= 2; /* make aperture do 32 byte swapping */
+ else if (par->crtc.bpp > 8)
+ config |= 1; /* make aperture do 16 byte swapping */
#endif
- aty_st_le32(CONFIG_CNTL, config);
- aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
+ aty_st_le32(CONFIG_CNTL, config);
+ aty_st_8(CRTC_EXT_CNTL + 1, 0); /* turn the video back on */
- if (info->var.accel_flags & FB_ACCELF_TEXT)
- aty128_init_engine(par, info);
+ if (par->accel_flags & FB_ACCELF_TEXT)
+ aty128_init_engine(par, info);
#if defined(CONFIG_BOOTX_TEXT)
- btext_update_display(info->fix.smem_start,
- (((par->crtc.h_total >> 16) & 0xff) + 1) * 8,
- ((par->crtc.v_total >> 16) & 0x7ff) + 1,
- par->crtc.bpp,
- par->crtc.vxres * par->crtc.bpp / 8);
-#endif /* CONFIG_BOOTX_TEXT */
- info->fix.line_length = (info->var.xres_virtual * info->var.bits_per_pixel) >> 3;
- info->fix.visual = info->var.bits_per_pixel <= 8 ? FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
- return 0;
+ btext_update_display(info->fb_info.fix.smem_start,
+ (((par->crtc.h_total>>16) & 0xff)+1)*8,
+ ((par->crtc.v_total>>16) & 0x7ff)+1,
+ par->crtc.bpp,
+ par->crtc.vxres*par->crtc.bpp/8);
+#endif /* CONFIG_BOOTX_TEXT */
}
/*
@@ -1153,221 +1226,353 @@ aty128fb_set_par(struct fb_info *info)
static int
aty128_decode_var(struct fb_var_screeninfo *var, struct aty128fb_par *par,
- const struct fb_info *info)
+ const struct fb_info_aty128 *info)
{
- int err;
+ int err;
- if ((err = aty128_var_to_crtc(var, &par->crtc, info)))
- return err;
+ if ((err = aty128_var_to_crtc(var, &par->crtc, info)))
+ return err;
- if ((err = aty128_var_to_pll(var->pixclock, &par->pll, par)))
- return err;
+ if ((err = aty128_var_to_pll(var->pixclock, &par->pll, info)))
+ return err;
- if ((err =
- aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp,
- info)))
- return err;
- return 0;
+ if ((err = aty128_ddafifo(&par->fifo_reg, &par->pll, par->crtc.bpp, info)))
+ return err;
+
+ if (var->accel_flags & FB_ACCELF_TEXT)
+ par->accel_flags = FB_ACCELF_TEXT;
+ else
+ par->accel_flags = 0;
+
+ return 0;
}
+
static int
-aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+aty128_encode_var(struct fb_var_screeninfo *var,
+ const struct aty128fb_par *par,
+ const struct fb_info_aty128 *info)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- int err;
+ int err;
- /* basic (in)sanity checks */
- if (!var->xres)
- var->xres = 1;
- if (!var->yres)
- var->yres = 1;
- if (var->xres > var->xres_virtual)
- var->xres_virtual = var->xres;
- if (var->yres > var->yres_virtual)
- var->yres_virtual = var->yres;
-
- switch (var->bits_per_pixel) {
- case 0 ... 8:
- var->bits_per_pixel = 8;
- break;
- case 9 ... 16:
- var->bits_per_pixel = 16;
- break;
- case 17 ... 24:
- var->bits_per_pixel = 24;
- break;
- case 25 ... 32:
- var->bits_per_pixel = 32;
- break;
- default:
- return -EINVAL;
- }
+ if ((err = aty128_crtc_to_var(&par->crtc, var)))
+ return err;
- var->red.msb_right = 0;
- var->green.msb_right = 0;
- var->blue.msb_right = 0;
- var->transp.msb_right = 0;
+ if ((err = aty128_pll_to_var(&par->pll, var, info)))
+ return err;
- var->nonstd = 0;
- var->activate = 0;
+ var->red.msb_right = 0;
+ var->green.msb_right = 0;
+ var->blue.msb_right = 0;
+ var->transp.msb_right = 0;
- var->height = -1;
- var->width = -1;
+ var->nonstd = 0;
+ var->activate = 0;
- if ((err = aty128_decode_var(var, par, info)))
- return err;
-
- if ((err = aty128_crtc_to_var(&par->crtc, var)))
- return err;
+ var->height = -1;
+ var->width = -1;
+ var->accel_flags = par->accel_flags;
- if ((err = aty128_pll_to_var(&par->pll, var, info)))
- return err;
- return 0;
+ return 0;
+}
+
+
+ /*
+ * Get the User Defined Part of the Display
+ */
+
+static int
+aty128fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
+{
+ const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
+
+ if (con == -1)
+ aty128_encode_var(var, par, info);
+ else
+ *var = fb_display[con].var;
+ return 0;
}
+
/*
- * Pan or Wrap the Display
- *
- * Not supported (yet!)
+ * Set the User Defined Part of the Display
*/
+
static int
-aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
- struct fb_info *info)
+aty128fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- u32 xoffset, yoffset;
- u32 offset;
- u32 xres, yres;
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct aty128fb_par par;
+ struct display *display;
+ int oldxres, oldyres, oldvxres, oldvyres, oldbpp, oldaccel;
+ int accel, err;
+
+ display = (con >= 0) ? &fb_display[con] : fb->disp;
+
+ /* basic (in)sanity checks */
+ if (!var->xres)
+ var->xres = 1;
+ if (!var->yres)
+ var->yres = 1;
+ if (var->xres > var->xres_virtual)
+ var->xres_virtual = var->xres;
+ if (var->yres > var->yres_virtual)
+ var->yres_virtual = var->yres;
+
+ switch (var->bits_per_pixel) {
+ case 0 ... 8:
+ var->bits_per_pixel = 8;
+ break;
+ case 9 ... 16:
+ var->bits_per_pixel = 16;
+ break;
+ case 17 ... 24:
+ var->bits_per_pixel = 24;
+ break;
+ case 25 ... 32:
+ var->bits_per_pixel = 32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((err = aty128_decode_var(var, &par, info)))
+ return err;
+
+ aty128_encode_var(var, &par, info);
+
+ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
+ return 0;
+
+ oldxres = display->var.xres;
+ oldyres = display->var.yres;
+ oldvxres = display->var.xres_virtual;
+ oldvyres = display->var.yres_virtual;
+ oldbpp = display->var.bits_per_pixel;
+ oldaccel = display->var.accel_flags;
+ display->var = *var;
+ if (oldxres != var->xres || oldyres != var->yres ||
+ oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
+ oldbpp != var->bits_per_pixel || oldaccel != var->accel_flags) {
+
+ struct fb_fix_screeninfo fix;
+
+ aty128_encode_fix(&fix, &par, info);
+ display->visual = fix.visual;
+ display->type = fix.type;
+ display->type_aux = fix.type_aux;
+ display->ypanstep = fix.ypanstep;
+ display->ywrapstep = fix.ywrapstep;
+ display->line_length = fix.line_length;
+ display->can_soft_blank = 1;
+ display->inverse = 0;
+
+ accel = var->accel_flags & FB_ACCELF_TEXT;
+ aty128_set_dispsw(display, info, par.crtc.bpp, accel);
+
+ if (accel)
+ display->scrollmode = SCROLL_YNOMOVE;
+ else
+ display->scrollmode = SCROLL_YREDRAW;
- xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
- yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
+ if (info->fb_info.changevar)
+ (*info->fb_info.changevar)(con);
+ }
- xoffset = (var->xoffset + 7) & ~7;
- yoffset = var->yoffset;
+ if (!info->fb_info.display_fg || info->fb_info.display_fg->vc_num == con)
+ aty128_set_par(&par, info);
- if (xoffset + xres > info->var.xres_virtual
- || yoffset + yres > par->crtc.vyres)
- return -EINVAL;
+ if (oldbpp != var->bits_per_pixel) {
+ if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
+ return err;
+ do_install_cmap(con, &info->fb_info);
+ }
- par->crtc.xoffset = xoffset;
- par->crtc.yoffset = yoffset;
+ return 0;
+}
- offset =
- ((yoffset * info->var.xres_virtual + xoffset) * par->crtc.bpp) >> 6;
- aty_st_le32(CRTC_OFFSET, offset);
+static void
+aty128_set_dispsw(struct display *disp,
+ struct fb_info_aty128 *info, int bpp, int accel)
+{
+ switch (bpp) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ disp->dispsw = accel ? &fbcon_aty128_8 : &fbcon_cfb8;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 15:
+ case 16:
+ disp->dispsw = accel ? &fbcon_aty128_16 : &fbcon_cfb16;
+ disp->dispsw_data = info->fb_info.pseudo_palette;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 24:
+ disp->dispsw = accel ? &fbcon_aty128_24 : &fbcon_cfb24;
+ disp->dispsw_data = info->fb_info.pseudo_palette;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ disp->dispsw = accel ? &fbcon_aty128_32 : &fbcon_cfb32;
+ disp->dispsw_data = info->fb_info.pseudo_palette;
+ break;
+#endif
+ default:
+ disp->dispsw = &fbcon_dummy;
+ }
+}
- return 0;
+
+static void
+aty128_encode_fix(struct fb_fix_screeninfo *fix,
+ struct aty128fb_par *par,
+ const struct fb_info_aty128 *info)
+{
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+
+ strcpy(fix->id, info->fb_info.fix.id);
+
+ fix->smem_start = info->fb_info.fix.smem_start;
+ fix->mmio_start = info->fb_info.fix.mmio_start;
+
+ fix->smem_len = info->fb_info.fix.smem_len;
+ fix->mmio_len = info->fb_info.fix.mmio_len;
+
+ fix->type = info->fb_info.fix.type;
+ fix->type_aux = info->fb_info.fix.type_aux;
+ fix->line_length = (par->crtc.vxres * par->crtc.bpp) >> 3;
+ fix->visual = par->crtc.bpp <= 8 ? FB_VISUAL_PSEUDOCOLOR
+ : FB_VISUAL_DIRECTCOLOR;
+ fix->ywrapstep = info->fb_info.fix.ywrapstep;
+ fix->xpanstep = info->fb_info.fix.xpanstep;
+ fix->ypanstep = info->fb_info.fix.ypanstep;
+
+ fix->accel = info->fb_info.fix.accel;
+ return;
}
+
/*
- * Accelerated functions
+ * Get the Fixed Part of the Display
*/
+static int
+aty128fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb)
+{
+ const struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
+
+ aty128_decode_var(&fb_display[con].var, par, info);
+ aty128_encode_fix(fix, par, info);
+ return 0;
+}
-static void
-aty128fb_rectcopy(int srcx, int srcy, int dstx, int dsty,
- u_int width, u_int height, struct fb_info *info)
-{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- u32 save_dp_datatype, save_dp_cntl, bppval;
-
- if (!width || !height)
- return;
-
- bppval = bpp_to_depth(par->crtc.bpp);
- if (bppval == DST_24BPP) {
- srcx *= 3;
- dstx *= 3;
- width *= 3;
- } else if (bppval == -EINVAL) {
- printk("aty128fb: invalid depth\n");
- return;
- }
- wait_for_fifo(2, par);
- save_dp_datatype = aty_ld_le32(DP_DATATYPE);
- save_dp_cntl = aty_ld_le32(DP_CNTL);
+ /*
+ * Pan or Wrap the Display
+ *
+ * Not supported (yet!)
+ */
+static int
+aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
+ struct fb_info *fb)
+{
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
+ u32 xoffset, yoffset;
+ u32 offset;
+ u32 xres, yres;
+
+ xres = (((par->crtc.h_total >> 16) & 0xff) + 1) << 3;
+ yres = ((par->crtc.v_total >> 16) & 0x7ff) + 1;
+
+ xoffset = (var->xoffset +7) & ~7;
+ yoffset = var->yoffset;
+
+ if (xoffset+xres > par->crtc.vxres || yoffset+yres > par->crtc.vyres)
+ return -EINVAL;
- wait_for_fifo(6, par);
- aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
- aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
- aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
- aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);
+ par->crtc.xoffset = xoffset;
+ par->crtc.yoffset = yoffset;
- aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
- aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+ offset = ((yoffset * par->crtc.vxres + xoffset) * par->crtc.bpp) >> 6;
- par->blitter_may_be_busy = 1;
+ aty_st_le32(CRTC_OFFSET, offset);
- wait_for_fifo(2, par);
- aty_st_le32(DP_DATATYPE, save_dp_datatype);
- aty_st_le32(DP_CNTL, save_dp_cntl);
+ return 0;
}
-static int aty128fb_rasterimg(struct fb_info *info, int start)
+static int
+aty128fb_rasterimg(struct fb_info *info, int start)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)info;
- if (par->blitter_may_be_busy)
- wait_for_idle(par);
- return 0;
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ return 0;
}
-int __init aty128fb_setup(char *options)
+int __init
+aty128fb_setup(char *options)
{
- char *this_opt;
+ char *this_opt;
- if (!options || !*options)
- return 0;
-
- while ((this_opt = strsep(&options, ",")) != NULL) {
- if (!strncmp(this_opt, "font:", 5)) {
- char *p;
- int i;
+ if (!options || !*options)
+ return 0;
- p = this_opt + 5;
- for (i = 0; i < sizeof(fontname) - 1; i++)
- if (!*p || *p == ' ' || *p == ',')
- break;
- memcpy(fontname, this_opt + 5, i);
- fontname[i] = 0;
- }
+ while ((this_opt = strsep(&options, ",")) != NULL) {
+ 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);
+ fontname[i] = 0;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ }
#ifdef CONFIG_MTRR
- else if (!strncmp(this_opt, "nomtrr", 6)) {
- mtrr = 0;
- }
+ else if(!strncmp(this_opt, "nomtrr", 6)) {
+ mtrr = 0;
+ }
#endif
#ifdef CONFIG_PPC
- /* vmode and cmode depreciated */
- 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)) {
- unsigned int cmode =
- simple_strtoul(this_opt + 6, NULL, 0);
- switch (cmode) {
- case 0:
- case 8:
- default_cmode = CMODE_8;
- break;
- case 15:
- case 16:
- default_cmode = CMODE_16;
- break;
- case 24:
- case 32:
- default_cmode = CMODE_32;
- break;
- }
- }
-#endif /* CONFIG_PPC */
- else
- mode_option = this_opt;
- }
- return 0;
+ /* vmode and cmode depreciated */
+ 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)) {
+ unsigned int cmode = simple_strtoul(this_opt+6, NULL, 0);
+ switch (cmode) {
+ case 0:
+ case 8:
+ default_cmode = CMODE_8;
+ break;
+ case 15:
+ case 16:
+ default_cmode = CMODE_16;
+ break;
+ case 24:
+ case 32:
+ default_cmode = CMODE_32;
+ break;
+ }
+ }
+#endif /* CONFIG_PPC */
+ else
+ mode_option = this_opt;
+ }
+ return 0;
}
@@ -1376,175 +1581,180 @@ int __init aty128fb_setup(char *options)
*/
static int __init
-aty128_init(struct fb_info *info, struct aty128fb_par *par,
- struct pci_dev *pdev, const char *name)
+aty128_init(struct fb_info_aty128 *info, struct aty128fb_par *par, struct pci_dev *pdev, const char *name)
{
- struct fb_var_screeninfo var;
- u32 dac;
- int size;
- u8 chip_rev;
- const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
- char *video_card = "Rage128";
+ struct fb_var_screeninfo var;
+ u32 dac;
+ int size;
+ u8 chip_rev;
+ const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
+ char *video_card = "Rage128";
- if (!info->fix.smem_len) /* may have already been probed */
- info->fix.smem_len =
- aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+ if (!info->fb_info.fix.smem_len) /* may have already been probed */
+ info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
#ifdef CONFIG_MTRR
if (mtrr) {
- par->mtrr.vram = mtrr_add(info->fix.smem_start,
- info->fix.smem_len,
- MTRR_TYPE_WRCOMB, 1);
+ par->mtrr.vram = mtrr_add(info->fb_info.fix.smem_start,
+ info->fb_info.fix.smem_len, MTRR_TYPE_WRCOMB, 1);
par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO "aty128fb: Rage128 MTRR set to ON\n");
}
-#endif /* CONFIG_MTRR */
+#endif /* CONFIG_MTRR */
+
+ /* Get the chip revision */
+ chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
+
+ /* put a name with the face */
+ while (aci->name && pdev->device != aci->device) { aci++; }
+ video_card = (char *)aci->name;
+ info->chip_gen = aci->chip_gen;
+
+ printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card, chip_rev);
+
+ if (info->fb_info.fix.smem_len % (1024 * 1024) == 0)
+ printk("%dM %s\n", info->fb_info.fix.smem_len / (1024*1024), info->mem->name);
+ else
+ printk("%dk %s\n", info->fb_info.fix.smem_len / 1024, info->mem->name);
+
+ /* fill in info */
+ strcpy(info->fb_info.modename, info->fb_info.fix.id);
+ info->fb_info.node = NODEV;
+ info->fb_info.fbops = &aty128fb_ops;
+ strcpy(info->fb_info.fontname, fontname);
+ info->fb_info.changevar = NULL;
+ info->fb_info.switch_con = &aty128fbcon_switch;
+ info->fb_info.updatevar = NULL;
+ info->fb_info.flags = FBINFO_FLAG_DEFAULT;
+
+ var = default_var;
+#ifdef CONFIG_PPC
+ if (_machine == _MACH_Pmac) {
+ if (mode_option) {
+ if (!mac_find_mode(&var, &info->fb_info, mode_option, 8))
+ var = default_var;
+ } else {
+ if (default_vmode <= 0 || default_vmode > VMODE_MAX)
+ default_vmode = VMODE_1024_768_60;
+
+ /* iMacs need that resolution
+ * PowerMac2,1 first r128 iMacs
+ * PowerMac2,2 summer 2000 iMacs
+ * PowerMac4,1 january 2001 iMacs "flower power"
+ */
+ if (machine_is_compatible("PowerMac2,1") ||
+ machine_is_compatible("PowerMac2,2") ||
+ machine_is_compatible("PowerMac4,1"))
+ default_vmode = VMODE_1024_768_75;
+
+ /* iBook SE */
+ if (machine_is_compatible("PowerBook2,2"))
+ default_vmode = VMODE_800_600_60;
+
+ /* PowerBook Firewire (Pismo), iBook Dual USB */
+ if (machine_is_compatible("PowerBook3,1") ||
+ machine_is_compatible("PowerBook4,1"))
+ default_vmode = VMODE_1024_768_60;
+
+ /* PowerBook Titanium */
+ if (machine_is_compatible("PowerBook3,2"))
+ default_vmode = VMODE_1152_768_60;
+
+ if (default_cmode < CMODE_8 || default_cmode > CMODE_32)
+ default_cmode = CMODE_8;
+
+ if (mac_vmode_to_var(default_vmode, default_cmode, &var))
+ var = default_var;
+ }
+ } else
+#endif /* CONFIG_PPC */
+ {
+ if (fb_find_mode(&var, &info->fb_info, mode_option, NULL, 0,
+ &defaultmode, 8) == 0)
+ var = default_var;
+ }
+
+ if (noaccel)
+ var.accel_flags &= ~FB_ACCELF_TEXT;
+ else
+ var.accel_flags |= FB_ACCELF_TEXT;
+
+ if (aty128_decode_var(&var, par, info)) {
+ printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
+ return 0;
+ }
- /* Get the chip revision */
- chip_rev = (aty_ld_le32(CONFIG_CNTL) >> 16) & 0x1F;
+ /* setup the DAC the way we like it */
+ dac = aty_ld_le32(DAC_CNTL);
+ dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
+ dac |= DAC_MASK;
+ aty_st_le32(DAC_CNTL, dac);
- /* put a name with the face */
- while (aci->name && pdev->device != aci->device) {
- aci++;
- }
- video_card = (char *) aci->name;
- par->chip_gen = aci->chip_gen;
+ /* turn off bus mastering, just in case */
+ aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
- printk(KERN_INFO "aty128fb: %s [chip rev 0x%x] ", video_card,
- chip_rev);
+ aty128fb_set_var(&var, -1, &info->fb_info);
+ aty128_init_engine(par, info);
- if (info->fix.smem_len % (1024 * 1024) == 0)
- printk("%dM %s\n",
- info->fix.smem_len / (1024 * 1024),
- par->mem->name);
- else
- printk("%dk %s\n", info->fix.smem_len / 1024,
- par->mem->name);
-
- /* fill in info */
- strcpy(info->modename, info->fix.id);
- info->node = NODEV;
- info->fbops = &aty128fb_ops;
- strcpy(info->fontname, fontname);
- info->changevar = NULL;
- info->switch_con = gen_switch;
- info->updatevar = NULL;
- info->flags = FBINFO_FLAG_DEFAULT;
-
- var = default_var;
-#ifdef CONFIG_PPC
- if (_machine == _MACH_Pmac) {
- if (mode_option) {
- if (!mac_find_mode
- (&var, info, mode_option, 8))
- var = default_var;
- } else {
- if (default_vmode <= 0
- || default_vmode > VMODE_MAX)
- default_vmode = VMODE_1024_768_60;
-
- /* iMacs need that resolution
- * PowerMac2,1 first r128 iMacs
- * PowerMac2,2 summer 2000 iMacs
- * PowerMac4,1 january 2001 iMacs "flower power"
- */
- if (machine_is_compatible("PowerMac2,1") ||
- machine_is_compatible("PowerMac2,2") ||
- machine_is_compatible("PowerMac4,1"))
- default_vmode = VMODE_1024_768_75;
-
- /* iBook SE */
- if (machine_is_compatible("PowerBook2,2"))
- default_vmode = VMODE_800_600_60;
-
- /* PowerBook Firewire (Pismo), iBook Dual USB */
- if (machine_is_compatible("PowerBook3,1") ||
- machine_is_compatible("PowerBook4,1"))
- default_vmode = VMODE_1024_768_60;
-
- /* PowerBook Titanium */
- if (machine_is_compatible("PowerBook3,2"))
- default_vmode = VMODE_1152_768_60;
-
- if (default_cmode < CMODE_8
- || default_cmode > CMODE_32)
- default_cmode = CMODE_8;
-
- if (mac_vmode_to_var
- (default_vmode, default_cmode, &var))
- var = default_var;
- }
- } else
-#endif /* CONFIG_PPC */
- {
- if (fb_find_mode
- (&var, info, mode_option, NULL, 0,
- &defaultmode, 8) == 0)
- var = default_var;
- }
-
- var.accel_flags |= FB_ACCELF_TEXT;
+ board_list = aty128_board_list_add(board_list, info);
- info->var = var;
+ size = (var.bits_per_pixel <= 8) ? 256 : 32;
+ fb_alloc_cmap(&info->fb_info.cmap, size, 0);
- if (aty128_decode_var(&var, par, info)) {
- printk(KERN_ERR "aty128fb: Cannot set default mode.\n");
- return 0;
- }
-
- /* setup the DAC the way we like it */
- dac = aty_ld_le32(DAC_CNTL);
- dac |= (DAC_8BIT_EN | DAC_RANGE_CNTL);
- dac |= DAC_MASK;
- aty_st_le32(DAC_CNTL, dac);
+ if (register_framebuffer(&info->fb_info) < 0)
+ return 0;
- /* turn off bus mastering, just in case */
- aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_MASTER_DIS);
+#ifdef CONFIG_PMAC_BACKLIGHT
+ /* Could be extended to Rage128Pro LVDS output too */
+ if (info->chip_gen == rage_M3)
+ register_backlight_controller(&aty128_backlight_controller, info, "ati");
+#endif /* CONFIG_PMAC_BACKLIGHT */
- gen_set_var(&var, -1, info);
- aty128_init_engine(par, info);
+ printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
+ GET_FB_IDX(info->fb_info.node), info->fb_info.fix.id, name);
- size = (var.bits_per_pixel <= 8) ? 256 : 32;
- fb_alloc_cmap(&info->cmap, size, 0);
+ return 1; /* success! */
+}
- if (register_framebuffer(info) < 0)
- return 0;
-#ifdef CONFIG_PMAC_BACKLIGHT
- /* Could be extended to Rage128Pro LVDS output too */
- if (info->chip_gen == rage_M3)
- register_backlight_controller(&aty128_backlight_controller,
- par, "ati");
-#endif /* CONFIG_PMAC_BACKLIGHT */
+/* add a new card to the list ++ajoshi */
+static struct
+fb_info_aty128 *aty128_board_list_add(struct fb_info_aty128 *board_list,
+ struct fb_info_aty128 *new_node)
+{
+ struct fb_info_aty128 *i_p = board_list;
- printk(KERN_INFO "fb%d: %s frame buffer device on %s\n",
- GET_FB_IDX(info->node), info->fix.id, name);
+ new_node->next = NULL;
+ if(board_list == NULL)
+ return new_node;
+ while(i_p->next != NULL)
+ i_p = i_p->next;
+ i_p->next = new_node;
- return 1; /* success! */
+ return board_list;
}
-int __init aty128fb_init(void)
+
+int __init
+aty128fb_init(void)
{
#ifdef CONFIG_PCI
- struct pci_dev *pdev = NULL;
- const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
-
- while (aci->name != NULL) {
- pdev =
- pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
- while (pdev != NULL) {
- if (aty128_pci_register(pdev, aci) == 0)
- return 0;
- pdev =
- pci_find_device(PCI_VENDOR_ID_ATI, aci->device,
- pdev);
- }
- aci++;
- }
+ struct pci_dev *pdev = NULL;
+ const struct aty128_chip_info *aci = &aty128_pci_probe_list[0];
+
+ while (aci->name != NULL) {
+ pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
+ while (pdev != NULL) {
+ if (aty128_pci_register(pdev, aci) == 0)
+ return 0;
+ pdev = pci_find_device(PCI_VENDOR_ID_ATI, aci->device, pdev);
+ }
+ aci++;
+ }
#endif
- return 0;
+ return 0;
}
@@ -1552,143 +1762,134 @@ int __init aty128fb_init(void)
/* register a card ++ajoshi */
static int __init
aty128_pci_register(struct pci_dev *pdev,
- const struct aty128_chip_info *aci)
+ const struct aty128_chip_info *aci)
{
- struct aty128fb_par *par = NULL;
- struct fb_info *info = NULL;
+ struct fb_info_aty128 *info = NULL;
+ struct aty128fb_par *par;
+ int err;
#if !defined(CONFIG_PPC) && !defined(__sparc__)
char *bios_seg = NULL;
#endif
- int err;
/* Enable device in PCI config */
if ((err = pci_enable_device(pdev))) {
printk(KERN_ERR "aty128fb: Cannot enable PCI device: %d\n",
- err);
+ err);
goto err_out;
}
aty128fb_fix.smem_start = pci_resource_start(pdev, 0);
- if (!request_mem_region
- (aty128fb_fix.smem_start, pci_resource_len(pdev, 0),
- "aty128fb FB")) {
+ if (!request_mem_region(aty128fb_fix.smem_start, pci_resource_len(pdev, 0),
+ "aty128fb FB")) {
printk(KERN_ERR "aty128fb: cannot reserve frame "
- "buffer memory\n");
+ "buffer memory\n");
goto err_free_fb;
}
aty128fb_fix.mmio_start = pci_resource_start(pdev, 2);
- if (!request_mem_region
- (aty128fb_fix.mmio_start, pci_resource_len(pdev, 2),
- "aty128fb MMIO")) {
+ if (!request_mem_region(aty128fb_fix.mmio_start, pci_resource_len(pdev, 2),
+ "aty128fb MMIO")) {
printk(KERN_ERR "aty128fb: cannot reserve MMIO region\n");
goto err_free_mmio;
}
/* We have the resources. Now virtualize them */
- if (!
- (info =
- kmalloc(sizeof(struct fb_info) +
- sizeof(struct display) + sizeof(u32) * 17,
- GFP_ATOMIC))) {
- printk(KERN_ERR "aty128fb: can't alloc fb_info\n");
+ if (!(info = kmalloc(sizeof(struct fb_info_aty128) + sizeof(struct display) + sizeof(u32) * 17, GFP_ATOMIC))) {
+ printk(KERN_ERR "aty128fb: can't alloc fb_info_aty128\n");
goto err_unmap_out;
}
- if (!(par = kmalloc(sizeof(struct aty128fb_par), GFP_ATOMIC))) {
+ if (!(par = kmalloc(sizeof(struct aty128fb_par), GFP_ATOMIC))) {
printk(KERN_ERR "aty128fb: can't alloc aty128fb_par\n");
goto err_unmap_out;
- }
+ }
- memset(info, 0, sizeof(struct fb_info));
+ memset(info, 0, sizeof(struct fb_info_aty128));
memset(par, 0, sizeof(struct aty128fb_par));
- info->disp = (struct display *) (info + 1);
- info->pseudo_palette = (void *) (info->disp + 1);
- info->par = par;
+ info->fb_info.disp = (struct display *)(info + 1);
+ info->fb_info.pseudo_palette = (void *)(info->fb_info.disp + 1);
+ info->fb_info.par = par;
- info->currcon = -1;
- info->fix = aty128fb_fix;
+ info->fb_info.currcon = -1;
+ info->fb_info.fix = aty128fb_fix;
/* Virtualize mmio region */
- par->regbase = ioremap(aty128fb_fix.mmio_start, 0x1FFF);
+ info->regbase = ioremap(aty128fb_fix.mmio_start, 0x1FFF);
- if (!par->regbase)
+ if (!info->regbase)
goto err_free_info;
/* Grab memory size from the card */
- info->fix.smem_len =
- aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
+ info->fb_info.fix.smem_len = aty_ld_le32(CONFIG_MEMSIZE) & 0x03FFFFFF;
/* Virtualize the framebuffer */
- info->screen_base =
- ioremap(aty128fb_fix.smem_start, info->fix.smem_len);
+ info->fb_info.screen_base = ioremap(aty128fb_fix.smem_start, info->fb_info.fix.smem_len);
- if (!info->screen_base) {
- iounmap((void *) par->regbase);
+ if (!info->fb_info.screen_base) {
+ iounmap((void *)info->regbase);
goto err_free_info;
}
/* If we can't test scratch registers, something is seriously wrong */
- if (!register_test(par)) {
- printk(KERN_ERR
- "aty128fb: Can't write to video register!\n");
+ if (!register_test(info)) {
+ printk(KERN_ERR "aty128fb: Can't write to video register!\n");
goto err_out;
}
+
#if !defined(CONFIG_PPC) && !defined(__sparc__)
if (!(bios_seg = aty128find_ROM(info)))
printk(KERN_INFO "aty128fb: Rage128 BIOS not located. "
- "Guessing...\n");
+ "Guessing...\n");
else {
printk(KERN_INFO "aty128fb: Rage128 BIOS located at "
- "segment %4.4X\n", (unsigned int) bios_seg);
- aty128_get_pllinfo(par, bios_seg);
+ "segment %4.4X\n", (unsigned int)bios_seg);
+ aty128_get_pllinfo(info, bios_seg);
}
#endif
- aty128_timings(par);
+ aty128_timings(info);
if (!aty128_init(info, par, pdev, "PCI"))
goto err_out;
return 0;
- err_out:
- iounmap(info->screen_base);
- iounmap(par->regbase);
- err_free_info:
+err_out:
+ iounmap(info->fb_info.screen_base);
+ iounmap(info->regbase);
+err_free_info:
kfree(info);
- err_unmap_out:
+err_unmap_out:
release_mem_region(pci_resource_start(pdev, 2),
- pci_resource_len(pdev, 2));
- err_free_mmio:
+ pci_resource_len(pdev, 2));
+err_free_mmio:
release_mem_region(pci_resource_start(pdev, 0),
- pci_resource_len(pdev, 0));
- err_free_fb:
+ pci_resource_len(pdev, 0));
+err_free_fb:
release_mem_region(pci_resource_start(pdev, 1),
- pci_resource_len(pdev, 1));
+ pci_resource_len(pdev, 1));
return -ENODEV;
}
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI */
/* PPC and Sparc cannot read video ROM */
#if !defined(CONFIG_PPC) && !defined(__sparc__)
-static char __init * aty128find_ROM(struct fb_info *info)
+static char __init
+*aty128find_ROM(struct fb_info_aty128 *info)
{
- u32 segstart;
+ u32 segstart;
char *rom_base;
char *rom;
- int stage;
- int i;
- char aty_rom_sig[] = "761295520"; /* ATI ROM Signature */
- char R128_sig[] = "R128"; /* Rage128 ROM identifier */
+ int stage;
+ int i;
+ char aty_rom_sig[] = "761295520"; /* ATI ROM Signature */
+ char R128_sig[] = "R128"; /* Rage128 ROM identifier */
- for (segstart = 0x000c0000; segstart < 0x000f0000;
- segstart += 0x00001000) {
- stage = 1;
+ for (segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) {
+ stage = 1;
- rom_base = (char *) ioremap(segstart, 0x1000);
+ rom_base = (char *)ioremap(segstart, 0x1000);
- if ((*rom_base == 0x55)
- && (((*(rom_base + 1)) & 0xff) == 0xaa))
+ if ((*rom_base == 0x55) && (((*(rom_base + 1)) & 0xff) == 0xaa))
stage = 2;
if (stage != 2) {
@@ -1697,12 +1898,10 @@ static char __init * aty128find_ROM(struct fb_info *info)
}
rom = rom_base;
- for (i = 0;
- (i < 128 - strlen(aty_rom_sig)) && (stage != 3);
- i++) {
+ for (i = 0; (i < 128 - strlen(aty_rom_sig)) && (stage != 3); i++) {
if (aty_rom_sig[0] == *rom)
if (strncmp(aty_rom_sig, rom,
- strlen(aty_rom_sig)) == 0)
+ strlen(aty_rom_sig)) == 0)
stage = 3;
rom++;
}
@@ -1715,8 +1914,8 @@ static char __init * aty128find_ROM(struct fb_info *info)
/* ATI signature found. Let's see if it's a Rage128 */
for (i = 0; (i < 512) && (stage != 4); i++) {
if (R128_sig[0] == *rom)
- if (strncmp(R128_sig, rom,
- strlen(R128_sig)) == 0)
+ if (strncmp(R128_sig, rom,
+ strlen(R128_sig)) == 0)
stage = 4;
rom++;
}
@@ -1733,7 +1932,7 @@ static char __init * aty128find_ROM(struct fb_info *info)
static void __init
-aty128_get_pllinfo(struct aty128fb_par *par, char *bios_seg)
+aty128_get_pllinfo(struct fb_info_aty128 *info, char *bios_seg)
{
void *bios_header;
void *header_ptr;
@@ -1741,7 +1940,7 @@ aty128_get_pllinfo(struct aty128fb_par *par, char *bios_seg)
PLL_BLOCK pll;
bios_header = bios_seg + 0x48L;
- header_ptr = bios_header;
+ header_ptr = bios_header;
bios_header_offset = readw(header_ptr);
bios_header = bios_seg + bios_header_offset;
@@ -1753,114 +1952,145 @@ aty128_get_pllinfo(struct aty128fb_par *par, char *bios_seg)
memcpy_fromio(&pll, header_ptr, 50);
- par->constants.ppll_max = pll.PCLK_max_freq;
- par->constants.ppll_min = pll.PCLK_min_freq;
- par->constants.xclk = (u32) pll.XCLK;
- par->constants.ref_divider = (u32) pll.PCLK_ref_divider;
- par->constants.dotclock = (u32) pll.PCLK_ref_freq;
+ info->constants.ppll_max = pll.PCLK_max_freq;
+ info->constants.ppll_min = pll.PCLK_min_freq;
+ info->constants.xclk = (u32)pll.XCLK;
+ info->constants.ref_divider = (u32)pll.PCLK_ref_divider;
+ info->constants.dotclock = (u32)pll.PCLK_ref_freq;
DBG("ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d\n",
- par->constants.ppll_max, par->constants.ppll_min,
- par->constants.xclk, par->constants.ref_divider,
- par->constants.dotclock);
+ info->constants.ppll_max, info->constants.ppll_min,
+ info->constants.xclk, info->constants.ref_divider,
+ info->constants.dotclock);
-}
-#endif /* !CONFIG_PPC */
+}
+#endif /* !CONFIG_PPC */
/* fill in known card constants if pll_block is not available */
-static void __init aty128_timings(struct aty128fb_par *par)
+static void __init
+aty128_timings(struct fb_info_aty128 *info)
{
#ifdef CONFIG_PPC
- /* instead of a table lookup, assume OF has properly
- * setup the PLL registers and use their values
- * to set the XCLK values and reference divider values */
-
- u32 x_mpll_ref_fb_div;
- u32 xclk_cntl;
- u32 Nx, M;
- unsigned PostDivSet[] = { 0, 1, 2, 4, 8, 3, 6, 12 };
+ /* instead of a table lookup, assume OF has properly
+ * setup the PLL registers and use their values
+ * to set the XCLK values and reference divider values */
+
+ u32 x_mpll_ref_fb_div;
+ u32 xclk_cntl;
+ u32 Nx, M;
+ unsigned PostDivSet[] =
+ { 0, 1, 2, 4, 8, 3, 6, 12 };
#endif
- if (!par->constants.dotclock)
- par->constants.dotclock = 2950;
+ if (!info->constants.dotclock)
+ info->constants.dotclock = 2950;
#ifdef CONFIG_PPC
- x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
- xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
- Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
- M = x_mpll_ref_fb_div & 0x0000ff;
+ x_mpll_ref_fb_div = aty_ld_pll(X_MPLL_REF_FB_DIV);
+ xclk_cntl = aty_ld_pll(XCLK_CNTL) & 0x7;
+ Nx = (x_mpll_ref_fb_div & 0x00ff00) >> 8;
+ M = x_mpll_ref_fb_div & 0x0000ff;
- par->constants.xclk = round_div((2 * Nx *
- par->constants.dotclock),
- (M * PostDivSet[xclk_cntl]));
+ info->constants.xclk = round_div((2 * Nx *
+ info->constants.dotclock), (M * PostDivSet[xclk_cntl]));
- par->constants.ref_divider =
- aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
+ info->constants.ref_divider =
+ aty_ld_pll(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
#endif
- if (!par->constants.ref_divider) {
- par->constants.ref_divider = 0x3b;
+ if (!info->constants.ref_divider) {
+ info->constants.ref_divider = 0x3b;
+
+ aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
+ aty_pll_writeupdate(info);
+ }
+ aty_st_pll(PPLL_REF_DIV, info->constants.ref_divider);
+ aty_pll_writeupdate(info);
+
+ /* from documentation */
+ if (!info->constants.ppll_min)
+ info->constants.ppll_min = 12500;
+ if (!info->constants.ppll_max)
+ info->constants.ppll_max = 25000; /* 23000 on some cards? */
+ if (!info->constants.xclk)
+ info->constants.xclk = 0x1d4d; /* same as mclk */
+
+ info->constants.fifo_width = 128;
+ info->constants.fifo_depth = 32;
+
+ switch (aty_ld_le32(MEM_CNTL) & 0x3) {
+ case 0:
+ info->mem = &sdr_128;
+ break;
+ case 1:
+ info->mem = &sdr_sgram;
+ break;
+ case 2:
+ info->mem = &ddr_sgram;
+ break;
+ default:
+ info->mem = &sdr_sgram;
+ }
+}
- aty_st_pll(X_MPLL_REF_FB_DIV, 0x004c4c1e);
- aty_pll_writeupdate(par);
- }
- aty_st_pll(PPLL_REF_DIV, par->constants.ref_divider);
- aty_pll_writeupdate(par);
-
- /* from documentation */
- if (!par->constants.ppll_min)
- par->constants.ppll_min = 12500;
- if (!par->constants.ppll_max)
- par->constants.ppll_max = 25000; /* 23000 on some cards? */
- if (!par->constants.xclk)
- par->constants.xclk = 0x1d4d; /* same as mclk */
-
- par->constants.fifo_width = 128;
- par->constants.fifo_depth = 32;
-
- switch (aty_ld_le32(MEM_CNTL) & 0x3) {
- case 0:
- par->mem = &sdr_128;
- break;
- case 1:
- par->mem = &sdr_sgram;
- break;
- case 2:
- par->mem = &ddr_sgram;
- break;
- default:
- par->mem = &sdr_sgram;
- }
+
+static int
+aty128fbcon_switch(int con, struct fb_info *fb)
+{
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct display *disp;
+ struct aty128fb_par par;
+
+ if (info->fb_info.currcon >= 0) {
+ disp = fb_display + info->fb_info.currcon;
+ if (disp->cmap.len)
+ fb_copy_cmap(&info->fb_info.cmap, &disp->cmap, 0);
+ }
+
+ /* set the current console */
+ fb->currcon = con;
+
+ aty128_decode_var(&fb_display[con].var, &par, info);
+ aty128_set_par(&par, info);
+
+ aty128_set_dispsw(&fb_display[con], info, par.crtc.bpp,
+ par.accel_flags & FB_ACCELF_TEXT);
+
+ do_install_cmap(con, fb);
+
+ return 1;
}
+
/*
* Blank the display.
*/
-static int aty128fb_blank(int blank, struct fb_info *info)
+static int
+aty128fb_blank(int blank, struct fb_info *fb)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- u8 state = 0;
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ u8 state = 0;
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && blank)
- set_backlight_enable(0);
-#endif /* CONFIG_PMAC_BACKLIGHT */
+ if ((_machine == _MACH_Pmac) && blank)
+ set_backlight_enable(0);
+#endif /* CONFIG_PMAC_BACKLIGHT */
- if (blank & VESA_VSYNC_SUSPEND)
- state |= 2;
- if (blank & VESA_HSYNC_SUSPEND)
- state |= 1;
- if (blank & VESA_POWERDOWN)
- state |= 4;
+ if (blank & VESA_VSYNC_SUSPEND)
+ state |= 2;
+ if (blank & VESA_HSYNC_SUSPEND)
+ state |= 1;
+ if (blank & VESA_POWERDOWN)
+ state |= 4;
- aty_st_8(CRTC_EXT_CNTL + 1, state);
+ aty_st_8(CRTC_EXT_CNTL+1, state);
#ifdef CONFIG_PMAC_BACKLIGHT
- if ((_machine == _MACH_Pmac) && !blank)
- set_backlight_enable(1);
-#endif /* CONFIG_PMAC_BACKLIGHT */
- return 0;
+ if ((_machine == _MACH_Pmac) && !blank)
+ set_backlight_enable(1);
+#endif /* CONFIG_PMAC_BACKLIGHT */
+ return 0;
}
/*
@@ -1870,94 +2100,90 @@ static int aty128fb_blank(int blank, struct fb_info *info)
*/
static int
aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
- u_int transp, struct fb_info *info)
+ u_int transp, struct fb_info *fb)
{
- struct aty128fb_par *par = (struct aty128fb_par *) info->par;
- u32 col;
-
- if (regno > 255)
- return 1;
-
- red >>= 8;
- green >>= 8;
- blue >>= 8;
-
- /* Note: For now, on M3, we set palette on both heads, which may
- * be useless. Can someone with a M3 check this ? */
-
- /* initialize gamma ramp for hi-color+ */
-
- if ((par->crtc.bpp > 8) && (regno == 0)) {
- int i;
-
- if (par->chip_gen == rage_M3)
- aty_st_le32(DAC_CNTL,
- aty_ld_le32(DAC_CNTL) &
- ~DAC_PALETTE_ACCESS_CNTL);
-
- for (i = 16; i < 256; i++) {
- aty_st_8(PALETTE_INDEX, i);
- col = (i << 16) | (i << 8) | i;
- aty_st_le32(PALETTE_DATA, col);
- }
-
- if (par->chip_gen == rage_M3) {
- aty_st_le32(DAC_CNTL,
- aty_ld_le32(DAC_CNTL) |
- DAC_PALETTE_ACCESS_CNTL);
-
- for (i = 16; i < 256; i++) {
- aty_st_8(PALETTE_INDEX, i);
- col = (i << 16) | (i << 8) | i;
- aty_st_le32(PALETTE_DATA, col);
- }
- }
- }
-
- /* initialize palette */
-
- if (par->chip_gen == rage_M3)
- aty_st_le32(DAC_CNTL,
- aty_ld_le32(DAC_CNTL) &
- ~DAC_PALETTE_ACCESS_CNTL);
-
- if (par->crtc.bpp == 16)
- aty_st_8(PALETTE_INDEX, (regno << 3));
- else
- aty_st_8(PALETTE_INDEX, regno);
- col = (red << 16) | (green << 8) | blue;
- aty_st_le32(PALETTE_DATA, col);
- if (par->chip_gen == rage_M3) {
- aty_st_le32(DAC_CNTL,
- aty_ld_le32(DAC_CNTL) |
- DAC_PALETTE_ACCESS_CNTL);
- if (par->crtc.bpp == 16)
- aty_st_8(PALETTE_INDEX, (regno << 3));
- else
- aty_st_8(PALETTE_INDEX, regno);
- aty_st_le32(PALETTE_DATA, col);
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)fb;
+ struct aty128fb_par *par = (struct aty128fb_par *) fb->par;
+ u32 col;
+
+ if (regno > 255)
+ return 1;
+
+ red >>= 8;
+ green >>= 8;
+ blue >>= 8;
+
+ /* Note: For now, on M3, we set palette on both heads, which may
+ * be useless. Can someone with a M3 check this ? */
+
+ /* initialize gamma ramp for hi-color+ */
+
+ if ((par->crtc.bpp > 8) && (regno == 0)) {
+ int i;
+
+ if (info->chip_gen == rage_M3)
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
+
+ for (i=16; i<256; i++) {
+ aty_st_8(PALETTE_INDEX, i);
+ col = (i << 16) | (i << 8) | i;
+ aty_st_le32(PALETTE_DATA, col);
+ }
+
+ if (info->chip_gen == rage_M3) {
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
+
+ for (i=16; i<256; i++) {
+ aty_st_8(PALETTE_INDEX, i);
+ col = (i << 16) | (i << 8) | i;
+ aty_st_le32(PALETTE_DATA, col);
+ }
+ }
+ }
+
+ /* initialize palette */
+
+ if (info->chip_gen == rage_M3)
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) & ~DAC_PALETTE_ACCESS_CNTL);
+
+ if (par->crtc.bpp == 16)
+ aty_st_8(PALETTE_INDEX, (regno << 3));
+ else
+ aty_st_8(PALETTE_INDEX, regno);
+ col = (red << 16) | (green << 8) | blue;
+ aty_st_le32(PALETTE_DATA, col);
+ if (info->chip_gen == rage_M3) {
+ aty_st_le32(DAC_CNTL, aty_ld_le32(DAC_CNTL) | DAC_PALETTE_ACCESS_CNTL);
+ if (par->crtc.bpp == 16)
+ aty_st_8(PALETTE_INDEX, (regno << 3));
+ else
+ aty_st_8(PALETTE_INDEX, regno);
+ aty_st_le32(PALETTE_DATA, col);
+ }
+
+ if (regno < 16)
+ switch (par->crtc.bpp) {
+#ifdef FBCON_HAS_CFB16
+ case 9 ... 16:
+ ((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 10) | (regno << 5) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB24
+ case 17 ... 24:
+ ((u32*) (info->fb_info.pseudo_palette))[regno] = (regno << 16) | (regno << 8) | regno;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 25 ... 32: {
+ u32 i;
+
+ i = (regno << 8) | regno;
+ ((u32*) (info->fb_info.pseudo_palette))[regno] = (i << 16) | i;
+ break;
+ }
+#endif
}
-
- if (regno < 16)
- switch (par->crtc.bpp) {
- case 9 ... 16:
- ((u32 *) (info->pseudo_palette))[regno] =
- (regno << 10) | (regno << 5) | regno;
- break;
- case 17 ... 24:
- ((u32 *) (info->pseudo_palette))[regno] =
- (regno << 16) | (regno << 8) | regno;
- break;
- case 25 ... 32:{
- u32 i;
-
- i = (regno << 8) | regno;
- ((u32 *) (info->pseudo_palette))[regno] =
- (i << 16) | i;
- break;
- }
- }
- return 0;
+ return 0;
}
#ifdef CONFIG_PMAC_BACKLIGHT
@@ -1966,11 +2192,12 @@ static int backlight_conv[] = {
0x73, 0x68, 0x5d, 0x52, 0x47, 0x3c, 0x31, 0x24
};
-static int aty128_set_backlight_enable(int on, int level, void *data)
+static int
+aty128_set_backlight_enable(int on, int level, void* data)
{
- struct aty128fb_par *par = (struct aty128fb_par *) data;
+ struct fb_info_aty128 *info = (struct fb_info_aty128 *)data;
unsigned int reg = aty_ld_le32(LVDS_GEN_CNTL);
-
+
reg |= LVDS_BL_MOD_EN | LVDS_BLON;
if (on && level > BACKLIGHT_OFF) {
reg &= ~LVDS_BL_MOD_LEVEL_MASK;
@@ -1984,11 +2211,12 @@ static int aty128_set_backlight_enable(int on, int level, void *data)
return 0;
}
-static int aty128_set_backlight_level(int level, void *data)
+static int
+aty128_set_backlight_level(int level, void* data)
{
return aty128_set_backlight_enable(1, level, data);
}
-#endif /* CONFIG_PMAC_BACKLIGHT */
+#endif /* CONFIG_PMAC_BACKLIGHT */
/*
* Accelerated functions
@@ -1996,107 +2224,328 @@ static int aty128_set_backlight_level(int level, void *data)
static inline void
aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
- u_int width, u_int height, struct fb_info *info)
-{
- struct aty128fb_par *par =
- (struct aty128fb_par *) info->par;
- u32 save_dp_datatype, save_dp_cntl, bppval;
-
- if (!width || !height)
- return;
-
- bppval = bpp_to_depth(par->crtc.bpp);
- if (bppval == DST_24BPP) {
- srcx *= 3;
- dstx *= 3;
- width *= 3;
- } else if (bppval == -EINVAL) {
- printk("aty128fb: invalid depth\n");
- return;
- }
+ u_int width, u_int height,
+ struct fb_info_aty128 *info)
+{
+ struct aty128fb_par *par = (struct aty128fb_par *) info->fb_info.par;
+ u32 save_dp_datatype, save_dp_cntl, bppval;
+
+ if (!width || !height)
+ return;
+
+ bppval = bpp_to_depth(par->crtc.bpp);
+ if (bppval == DST_24BPP) {
+ srcx *= 3;
+ dstx *= 3;
+ width *= 3;
+ } else if (bppval == -EINVAL) {
+ printk("aty128fb: invalid depth\n");
+ return;
+ }
+
+ wait_for_fifo(2, info);
+ save_dp_datatype = aty_ld_le32(DP_DATATYPE);
+ save_dp_cntl = aty_ld_le32(DP_CNTL);
+
+ wait_for_fifo(6, info);
+ aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
+ aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
+ aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
+ aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);
+
+ aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
+ aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+
+ info->blitter_may_be_busy = 1;
+
+ wait_for_fifo(2, info);
+ aty_st_le32(DP_DATATYPE, save_dp_datatype);
+ aty_st_le32(DP_CNTL, save_dp_cntl);
+}
+
+
+ /*
+ * Text mode accelerated functions
+ */
+
+static void
+fbcon_aty128_bmove(struct display *p, int sy, int sx, int dy, int dx,
+ int height, int width)
+{
+ sx *= fontwidth(p);
+ sy *= fontheight(p);
+ dx *= fontwidth(p);
+ dy *= fontheight(p);
+ width *= fontwidth(p);
+ height *= fontheight(p);
+
+ aty128_rectcopy(sx, sy, dx, dy, width, height,
+ (struct fb_info_aty128 *)p->fb_info);
+}
+
+
+#ifdef FBCON_HAS_CFB8
+static void fbcon_aty8_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb8_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty8_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb8_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty8_clear_margins(struct vc_data *conp,
+ struct display *p, int bottom_only)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb8_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_8 = {
+ setup: fbcon_cfb8_setup,
+ bmove: fbcon_aty128_bmove,
+ clear: fbcon_cfb8_clear,
+ putc: fbcon_aty8_putc,
+ putcs: fbcon_aty8_putcs,
+ revc: fbcon_cfb8_revc,
+ clear_margins: fbcon_aty8_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB16
+static void fbcon_aty16_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb16_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty16_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb16_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty16_clear_margins(struct vc_data *conp,
+ struct display *p, int bottom_only)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb16_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_16 = {
+ setup: fbcon_cfb16_setup,
+ bmove: fbcon_aty128_bmove,
+ clear: fbcon_cfb16_clear,
+ putc: fbcon_aty16_putc,
+ putcs: fbcon_aty16_putcs,
+ revc: fbcon_cfb16_revc,
+ clear_margins: fbcon_aty16_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB24
+static void fbcon_aty24_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb24_putc(conp, p, c, yy, xx);
+}
+
+
+static void fbcon_aty24_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb24_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty24_clear_margins(struct vc_data *conp,
+ struct display *p, int bottom_only)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb24_clear_margins(conp, p, bottom_only);
+}
+
+static struct display_switch fbcon_aty128_24 = {
+ setup: fbcon_cfb24_setup,
+ bmove: fbcon_aty128_bmove,
+ clear: fbcon_cfb24_clear,
+ putc: fbcon_aty24_putc,
+ putcs: fbcon_aty24_putcs,
+ revc: fbcon_cfb24_revc,
+ clear_margins: fbcon_aty24_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+#ifdef FBCON_HAS_CFB32
+static void fbcon_aty32_putc(struct vc_data *conp, struct display *p,
+ int c, int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
+
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb32_putc(conp, p, c, yy, xx);
+}
- wait_for_fifo(2, par);
- save_dp_datatype = aty_ld_le32(DP_DATATYPE);
- save_dp_cntl = aty_ld_le32(DP_CNTL);
- wait_for_fifo(6, par);
- aty_st_le32(SRC_Y_X, (srcy << 16) | srcx);
- aty_st_le32(DP_MIX, ROP3_SRCCOPY | DP_SRC_RECT);
- aty_st_le32(DP_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
- aty_st_le32(DP_DATATYPE, save_dp_datatype | bppval | SRC_DSTCOLOR);
+static void fbcon_aty32_putcs(struct vc_data *conp, struct display *p,
+ const unsigned short *s, int count,
+ int yy, int xx)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
- aty_st_le32(DST_Y_X, (dsty << 16) | dstx);
- aty_st_le32(DST_HEIGHT_WIDTH, (height << 16) | width);
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
+
+ fbcon_cfb32_putcs(conp, p, s, count, yy, xx);
+}
+
+
+static void fbcon_aty32_clear_margins(struct vc_data *conp,
+ struct display *p, int bottom_only)
+{
+ struct fb_info_aty128 *fb = (struct fb_info_aty128 *)(p->fb_info);
- par->blitter_may_be_busy = 1;
+ if (fb->blitter_may_be_busy)
+ wait_for_idle(fb);
- wait_for_fifo(2, par);
- aty_st_le32(DP_DATATYPE, save_dp_datatype);
- aty_st_le32(DP_CNTL, save_dp_cntl);
+ fbcon_cfb32_clear_margins(conp, p, bottom_only);
}
+static struct display_switch fbcon_aty128_32 = {
+ setup: fbcon_cfb32_setup,
+ bmove: fbcon_aty128_bmove,
+ clear: fbcon_cfb32_clear,
+ putc: fbcon_aty32_putc,
+ putcs: fbcon_aty32_putcs,
+ revc: fbcon_cfb32_revc,
+ clear_margins: fbcon_aty32_clear_margins,
+ fontwidthmask: FONTWIDTH(4)|FONTWIDTH(8)|FONTWIDTH(12)|FONTWIDTH(16)
+};
+#endif
+
#ifdef MODULE
MODULE_AUTHOR("(c)1999-2000 Brad Douglas <brad@neruo.com>");
MODULE_DESCRIPTION("FBDev driver for ATI Rage128 / Pro cards");
MODULE_LICENSE("GPL");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disable hardware acceleration (0 or 1=disabled) (default=0)");
MODULE_PARM(font, "s");
-MODULE_PARM_DESC(font,
- "Specify one of the compiled-in fonts (default=none)");
+MODULE_PARM_DESC(font, "Specify one of the compiled-in fonts (default=none)");
MODULE_PARM(mode, "s");
-MODULE_PARM_DESC(mode,
- "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+MODULE_PARM_DESC(mode, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
#ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i");
-MODULE_PARM_DESC(nomtrr,
- "Disable MTRR support (0 or 1=disabled) (default=0)");
+MODULE_PARM_DESC(nomtrr, "Disable MTRR support (0 or 1=disabled) (default=0)");
#endif
-int __init init_module(void)
+int __init
+init_module(void)
{
- if (font) {
- strncpy(fontname, font, sizeof(fontname) - 1);
- printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n",
- font);
- }
- if (mode) {
- mode_option = mode;
- printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n",
- mode);
- }
+ if (noaccel) {
+ noaccel = 1;
+ printk(KERN_INFO "aty128fb: Parameter NOACCEL set\n");
+ }
+ if (font) {
+ strncpy(fontname, font, sizeof(fontname)-1);
+ printk(KERN_INFO "aty128fb: Parameter FONT set to %s\n", font);
+ }
+ if (mode) {
+ mode_option = mode;
+ printk(KERN_INFO "aty128fb: Parameter MODE set to %s\n", mode);
+ }
#ifdef CONFIG_MTRR
- if (nomtrr) {
- mtrr = 0;
- printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n");
- }
+ if (nomtrr) {
+ mtrr = 0;
+ printk(KERN_INFO "aty128fb: Parameter NOMTRR set\n");
+ }
#endif
-
- aty128fb_init();
- return 0;
+
+ aty128fb_init();
+ return 0;
}
-void __exit cleanup_module(void)
+void __exit
+cleanup_module(void)
{
- struct fb_info *info = board_list;
- struct aty128fb_par *par;
+ struct fb_info_aty128 *info = board_list;
+ struct aty128fb_par *par;
- par = info->par;
+ while (board_list) {
+ info = board_list;
+ board_list = board_list->next;
+ par = info->fb_info.par;
- unregister_framebuffer(info);
+ unregister_framebuffer(&info->fb_info);
#ifdef CONFIG_MTRR
- if (par->mtrr.vram_valid)
- mtrr_del(par->mtrr.vram,
- info->fix.smem_start,
- info->fix.smem_len);
-#endif /* CONFIG_MTRR */
- iounmap(par->regbase);
- iounmap(info->screen_base);
-
- release_mem_region(pci_resource_start(info->pdev, 0),
- pci_resource_len(info->pdev, 0));
- release_mem_region(pci_resource_start(info->pdev, 1),
- pci_resource_len(info->pdev, 1));
- release_mem_region(pci_resource_start(info->pdev, 2),
- pci_resource_len(info->pdev, 2));
- kfree(info);
+ if (par->mtrr.vram_valid)
+ mtrr_del(par->mtrr.vram, info->fb_info.fix.smem_start,
+ info->fb_info.fix.smem_len);
+#endif /* CONFIG_MTRR */
+ iounmap(info->regbase);
+ iounmap(info->fb_info.screen_base);
+
+ release_mem_region(pci_resource_start(info->pdev, 0),
+ pci_resource_len(info->pdev, 0));
+ release_mem_region(pci_resource_start(info->pdev, 1),
+ pci_resource_len(info->pdev, 1));
+ release_mem_region(pci_resource_start(info->pdev, 2),
+ pci_resource_len(info->pdev, 2));
+
+ kfree(info);
+ }
}
-#endif /* MODULE */
+#endif /* MODULE */
diff --git a/drivers/video/riva/fbdev.c b/drivers/video/riva/fbdev.c
index 8e348621a263..77edfb918c9a 100644
--- a/drivers/video/riva/fbdev.c
+++ b/drivers/video/riva/fbdev.c
@@ -1,5 +1,5 @@
/*
- * linux/drivers/video/riva/fbdevar->c - nVidia RIVA 128/TNT/TNT2 fb driver
+ * linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
*
@@ -25,6 +25,7 @@
* Known bugs and issues:
* restoring text mode fails
* doublescan modes are broken
+ * option 'noaccel' has no effect
*/
#include <linux/config.h>
@@ -51,10 +52,12 @@
#error This driver requires PCI support.
#endif
-#include "../fbcon-accel.h"
+
/* version number of this driver */
-#define RIVAFB_VERSION "0.9.3"
+#define RIVAFB_VERSION "0.9.2a"
+
+
/* ------------------------------------------------------------------------- *
*
@@ -88,8 +91,8 @@
#define Set8Bits(value) ((value)&0xff)
/* HW cursor parameters */
-#define DEFAULT_CURSOR_BLINK_RATE (20)
-#define CURSOR_HIDE_DELAY (10)
+#define DEFAULT_CURSOR_BLINK_RATE (40)
+#define CURSOR_HIDE_DELAY (20)
#define CURSOR_SHOW_DELAY (3)
#define CURSOR_COLOR 0x7fff
@@ -97,6 +100,7 @@
#define MAX_CURS 32
+
/* ------------------------------------------------------------------------- *
*
* prototypes
@@ -105,6 +109,11 @@
static int rivafb_blank(int blank, struct fb_info *info);
+extern void riva_setup_accel(struct rivafb_info *rinfo);
+extern inline void wait_for_idle(struct rivafb_info *rinfo);
+
+
+
/* ------------------------------------------------------------------------- *
*
* card identification
@@ -127,11 +136,6 @@ enum riva_chips {
CH_GEFORCE2_GTS,
CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO,
- CH_GEFORCE2_GO,
- CH_GEFORCE3,
- CH_GEFORCE3_1,
- CH_GEFORCE3_2,
- CH_QUADRO_DDC
};
/* directly indexed by riva_chips enum, above */
@@ -154,11 +158,6 @@ static struct riva_chip_info {
{ "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", NV_ARCH_10},
{ "Quadro2-PRO", NV_ARCH_10},
- { "GeForce2-Go", NV_ARCH_10},
- { "GeForce3", NV_ARCH_20},
- { "GeForce3 Ti 200", NV_ARCH_20},
- { "GeForce3 Ti 500", NV_ARCH_20},
- { "Quadro DDC", NV_ARCH_20}
};
static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
@@ -196,30 +195,64 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
- { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
+
+
+/* ------------------------------------------------------------------------- *
+ *
+ * framebuffer related structures
+ *
+ * ------------------------------------------------------------------------- */
+
+#ifdef FBCON_HAS_CFB8
+extern struct display_switch fbcon_riva8;
+#endif
+#ifdef FBCON_HAS_CFB16
+extern struct display_switch fbcon_riva16;
+#endif
+#ifdef FBCON_HAS_CFB32
+extern struct display_switch fbcon_riva32;
+#endif
+
+#if 0
+/* describes the state of a Riva board */
+struct rivafb_par {
+ struct riva_regs state; /* state of hw board */
+ __u32 visual; /* FB_VISUAL_xxx */
+ unsigned depth; /* bpp of current mode */
+};
+#endif
+
+struct riva_cursor {
+ int enable;
+ int on;
+ int vbl_cnt;
+ int last_move_delay;
+ int blink_rate;
+ struct {
+ u16 x, y;
+ } pos, size;
+ unsigned short image[MAX_CURS*MAX_CURS];
+ struct timer_list *timer;
+};
+
+
+
/* ------------------------------------------------------------------------- *
*
* global variables
*
* ------------------------------------------------------------------------- */
-struct fb_info *riva_boards = NULL;
+struct rivafb_info *riva_boards = NULL;
/* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 };
+static char noaccel __initdata = 0;
+static char nomove = 0;
static char nohwcursor __initdata = 0;
static char noblink = 0;
#ifdef CONFIG_MTRR
@@ -232,26 +265,24 @@ static char *mode_option __initdata = NULL;
static char *font = NULL;
#endif
-static struct fb_fix_screeninfo rivafb_fix = {
- id: "nVidia",
- type: FB_TYPE_PACKED_PIXELS,
- xpanstep: 1,
- ypanstep: 1,
-};
-
static struct fb_var_screeninfo rivafb_default_var = {
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
+ xoffset: 0,
+ yoffset: 0,
bits_per_pixel: 8,
+ grayscale: 0,
red: {0, 6, 0},
green: {0, 6, 0},
blue: {0, 6, 0},
- activate: FB_ACTIVATE_NOW,
+ transp: {0, 0, 0},
+ nonstd: 0,
+ activate: 0,
height: -1,
width: -1,
- accel_flags: FB_ACCELF_TEXT,
+ accel_flags: 0,
pixclock: 39721,
left_margin: 40,
right_margin: 24,
@@ -259,28 +290,10 @@ static struct fb_var_screeninfo rivafb_default_var = {
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
+ sync: 0,
vmode: FB_VMODE_NONINTERLACED
};
-static u8 byte_rev[256] = {
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
-};
-
/* from GGI */
static const struct riva_regs reg_template = {
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
@@ -302,76 +315,78 @@ static const struct riva_regs reg_template = {
0xEB /* MISC */
};
+
+
/* ------------------------------------------------------------------------- *
*
* MMIO access macros
*
* ------------------------------------------------------------------------- */
-static inline void CRTCout(struct riva_par *par, unsigned char index,
+static inline void CRTCout(struct rivafb_info *rinfo, unsigned char index,
unsigned char val)
{
- VGA_WR08(par->riva.PCIO, 0x3d4, index);
- VGA_WR08(par->riva.PCIO, 0x3d5, val);
+ VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+ VGA_WR08(rinfo->riva.PCIO, 0x3d5, val);
}
-static inline unsigned char CRTCin(struct riva_par *par,
+static inline unsigned char CRTCin(struct rivafb_info *rinfo,
unsigned char index)
{
- VGA_WR08(par->riva.PCIO, 0x3d4, index);
- return (VGA_RD08(par->riva.PCIO, 0x3d5));
+ VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
+ return (VGA_RD08(rinfo->riva.PCIO, 0x3d5));
}
-static inline void GRAout(struct riva_par *par, unsigned char index,
+static inline void GRAout(struct rivafb_info *rinfo, unsigned char index,
unsigned char val)
{
- VGA_WR08(par->riva.PVIO, 0x3ce, index);
- VGA_WR08(par->riva.PVIO, 0x3cf, val);
+ VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+ VGA_WR08(rinfo->riva.PVIO, 0x3cf, val);
}
-static inline unsigned char GRAin(struct riva_par *par,
+static inline unsigned char GRAin(struct rivafb_info *rinfo,
unsigned char index)
{
- VGA_WR08(par->riva.PVIO, 0x3ce, index);
- return (VGA_RD08(par->riva.PVIO, 0x3cf));
+ VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
+ return (VGA_RD08(rinfo->riva.PVIO, 0x3cf));
}
-static inline void SEQout(struct riva_par *par, unsigned char index,
+static inline void SEQout(struct rivafb_info *rinfo, unsigned char index,
unsigned char val)
{
- VGA_WR08(par->riva.PVIO, 0x3c4, index);
- VGA_WR08(par->riva.PVIO, 0x3c5, val);
+ VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+ VGA_WR08(rinfo->riva.PVIO, 0x3c5, val);
}
-static inline unsigned char SEQin(struct riva_par *par,
+static inline unsigned char SEQin(struct rivafb_info *rinfo,
unsigned char index)
{
- VGA_WR08(par->riva.PVIO, 0x3c4, index);
- return (VGA_RD08(par->riva.PVIO, 0x3c5));
+ VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
+ return (VGA_RD08(rinfo->riva.PVIO, 0x3c5));
}
-static inline void ATTRout(struct riva_par *par, unsigned char index,
+static inline void ATTRout(struct rivafb_info *rinfo, unsigned char index,
unsigned char val)
{
- VGA_WR08(par->riva.PCIO, 0x3c0, index);
- VGA_WR08(par->riva.PCIO, 0x3c0, val);
+ VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+ VGA_WR08(rinfo->riva.PCIO, 0x3c0, val);
}
-static inline unsigned char ATTRin(struct riva_par *par,
+static inline unsigned char ATTRin(struct rivafb_info *rinfo,
unsigned char index)
{
- VGA_WR08(par->riva.PCIO, 0x3c0, index);
- return (VGA_RD08(par->riva.PCIO, 0x3c1));
+ VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
+ return (VGA_RD08(rinfo->riva.PCIO, 0x3c1));
}
-static inline void MISCout(struct riva_par *par, unsigned char val)
+static inline void MISCout(struct rivafb_info *rinfo, unsigned char val)
{
- VGA_WR08(par->riva.PVIO, 0x3c2, val);
+ VGA_WR08(rinfo->riva.PVIO, 0x3c2, val);
}
-static inline unsigned char MISCin(struct riva_par *par)
+static inline unsigned char MISCin(struct rivafb_info *rinfo)
{
- return (VGA_RD08(par->riva.PVIO, 0x3cc));
+ return (VGA_RD08(rinfo->riva.PVIO, 0x3cc));
}
@@ -384,40 +399,39 @@ static inline unsigned char MISCin(struct riva_par *par)
/**
* riva_cursor_timer_handler - blink timer
- * @dev_addr: pointer to fb_info object containing info for current riva board
+ * @dev_addr: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Cursor blink timer.
*/
static void riva_cursor_timer_handler(unsigned long dev_addr)
{
- struct fb_info *info = (struct fb_info *)dev_addr;
- struct riva_par *par = (struct riva_par *) info->par;
+ struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr;
- if (!par->cursor) return;
+ if (!rinfo->cursor) return;
- if (!par->cursor->enable) goto out;
+ if (!rinfo->cursor->enable) goto out;
- par->cursor->prev_slice_moves = par->cursor->last_slice_moves;
- par->cursor->last_slice_moves = 0;
+ if (rinfo->cursor->last_move_delay < 1000)
+ rinfo->cursor->last_move_delay++;
- if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) {
- par->cursor->on ^= 1;
- if (par->cursor->on)
- *(par->riva.CURSORPOS) = (par->cursor->pos.x & 0xFFFF)
- | (par->cursor->pos.y << 16);
- par->riva.ShowHideCursor(&par->riva, par->cursor->on);
+ if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
+ rinfo->cursor->on ^= 1;
+ if (rinfo->cursor->on)
+ *(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
+ | (rinfo->cursor->pos.y << 16);
+ rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
if (!noblink)
- par->cursor->vbl_cnt = par->cursor->blink_rate;
+ rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
}
out:
- par->cursor->timer->expires = jiffies + (HZ / 50);
- add_timer(par->cursor->timer);
+ rinfo->cursor->timer->expires = jiffies + (HZ / 100);
+ add_timer(rinfo->cursor->timer);
}
/**
* rivafb_init_cursor - allocates cursor structure and starts blink timer
- * @info: pointer to fb_info object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Allocates cursor structure and starts blink timer.
@@ -428,7 +442,7 @@ out:
* CALLED FROM:
* rivafb_init_one()
*/
-static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
+static struct riva_cursor * __init rivafb_init_cursor(struct rivafb_info *rinfo)
{
struct riva_cursor *cursor;
@@ -446,8 +460,8 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
init_timer(cursor->timer);
- cursor->timer->expires = jiffies + (HZ / 50);
- cursor->timer->data = (unsigned long)info;
+ cursor->timer->expires = jiffies + (HZ / 100);
+ cursor->timer->data = (unsigned long)rinfo;
cursor->timer->function = riva_cursor_timer_handler;
add_timer(cursor->timer);
@@ -456,7 +470,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
/**
* rivafb_exit_cursor - stops blink timer and releases cursor structure
- * @par: pointer to riva_par object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Stops blink timer and releases cursor structure.
@@ -465,9 +479,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
* rivafb_init_one()
* rivafb_remove_one()
*/
-static void rivafb_exit_cursor(struct riva_par *par)
+static void rivafb_exit_cursor(struct rivafb_info *rinfo)
{
- struct riva_cursor *cursor = par->cursor;
+ struct riva_cursor *cursor = rinfo->cursor;
if (cursor) {
if (cursor->timer) {
@@ -475,13 +489,13 @@ static void rivafb_exit_cursor(struct riva_par *par)
kfree(cursor->timer);
}
kfree(cursor);
- par->cursor = NULL;
+ rinfo->cursor = 0;
}
}
/**
* rivafb_download_cursor - writes cursor shape into card registers
- * @par: pointer to riva_par object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Writes cursor shape into card registers.
@@ -489,24 +503,24 @@ static void rivafb_exit_cursor(struct riva_par *par)
* CALLED FROM:
* riva_load_video_mode()
*/
-static void rivafb_download_cursor(struct riva_par *par)
+static void rivafb_download_cursor(struct rivafb_info *rinfo)
{
int i, save;
int *image;
- if (!par->cursor) return;
+ if (!rinfo->cursor) return;
- image = (int *)par->cursor->image;
- save = par->riva.ShowHideCursor(&par->riva, 0);
+ image = (int *)rinfo->cursor->image;
+ save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
- writel(image[i], par->riva.CURSOR + i);
+ writel(image[i], rinfo->riva.CURSOR + i);
- par->riva.ShowHideCursor(&par->riva, save);
+ rinfo->riva.ShowHideCursor(&rinfo->riva, save);
}
/**
* rivafb_create_cursor - sets rectangular cursor
- * @par: pointer to riva_par object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
* @width: cursor width in pixels
* @height: cursor height in pixels
*
@@ -515,11 +529,11 @@ static void rivafb_download_cursor(struct riva_par *par)
*
* CALLED FROM:
* rivafb_set_font()
- * rivafb_set_par()
+ * rivafb_set_var()
*/
-static void rivafb_create_cursor(struct riva_par *par, int width, int height)
+static void rivafb_create_cursor(struct rivafb_info *rinfo, int width, int height)
{
- struct riva_cursor *c = par->cursor;
+ struct riva_cursor *c = rinfo->cursor;
int i, j, idx;
if (c) {
@@ -561,10 +575,9 @@ static void rivafb_create_cursor(struct riva_par *par, int width, int height)
*/
static int rivafb_set_font(struct display *p, int width, int height)
{
- struct fb_info *fb = p->fb_info;
- struct riva_par *par = (struct riva_par *) fb->par;
+ struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
- rivafb_create_cursor(par, width, height);
+ rivafb_create_cursor(fb, width, height);
return 1;
}
@@ -580,9 +593,8 @@ static int rivafb_set_font(struct display *p, int width, int height)
*/
static void rivafb_cursor(struct display *p, int mode, int x, int y)
{
- struct fb_info *info = p->fb_info;
- struct riva_par *par = (struct riva_par *) info->par;
- struct riva_cursor *c = par->cursor;
+ struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
+ struct riva_cursor *c = rinfo->cursor;
if (!c) return;
@@ -593,7 +605,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return;
c->enable = 0;
- if (c->on) par->riva.ShowHideCursor(&par->riva, 0);
+ if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
c->pos.x = x;
c->pos.y = y;
@@ -604,15 +616,15 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
break;
case CM_DRAW:
case CM_MOVE:
- if (c->last_slice_moves > 2 || c->prev_slice_moves > 2) {
+ if (c->last_move_delay <= 1) { /* rapid cursor movement */
c->vbl_cnt = CURSOR_SHOW_DELAY;
} else {
- *(par->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
- par->riva.ShowHideCursor(&par->riva, 1);
+ *(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
+ rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1;
}
- c->last_slice_moves++;
+ c->last_move_delay = 0;
c->enable = 1;
break;
}
@@ -627,6 +639,80 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
* ------------------------------------------------------------------------- */
/**
+ * riva_set_dispsw - sets dispsw
+ * @rinfo: pointer to internal driver struct for a given Riva card
+ * @disp: pointer to display object
+ *
+ * DESCRIPTION:
+ * Sets up console low level operations depending on the current? color depth
+ * of the display.
+ *
+ * CALLED FROM:
+ * rivafb_set_var()
+ * rivafb_switch()
+ * riva_init_disp()
+ */
+static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp)
+{
+ int accel = disp->var.accel_flags & FB_ACCELF_TEXT;
+
+ DPRINTK("ENTER\n");
+
+ assert(rinfo != NULL);
+
+ disp->dispsw_data = NULL;
+
+ disp->type = FB_TYPE_PACKED_PIXELS;
+ disp->type_aux = 0;
+ disp->ypanstep = 1;
+ disp->ywrapstep = 0;
+ disp->can_soft_blank = 1;
+ disp->inverse = 0;
+
+ switch (disp->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
+ case 8:
+ rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8;
+ disp->dispsw = &rinfo->dispsw;
+ disp->line_length = disp->var.xres_virtual;
+ disp->visual = FB_VISUAL_PSEUDOCOLOR;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16:
+ rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16;
+ disp->dispsw_data = &rinfo->con_cmap.cfb16;
+ disp->dispsw = &rinfo->dispsw;
+ disp->line_length = disp->var.xres_virtual * 2;
+ disp->visual = FB_VISUAL_DIRECTCOLOR;
+ break;
+#endif
+#ifdef FBCON_HAS_CFB32
+ case 32:
+ rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32;
+ disp->dispsw_data = rinfo->con_cmap.cfb32;
+ disp->dispsw = &rinfo->dispsw;
+ disp->line_length = disp->var.xres_virtual * 4;
+ disp->visual = FB_VISUAL_DIRECTCOLOR;
+ break;
+#endif
+ default:
+ DPRINTK("Setting fbcon_dummy renderer\n");
+ rinfo->dispsw = fbcon_dummy;
+ disp->dispsw = &rinfo->dispsw;
+ }
+
+ /* FIXME: verify that the above code sets dsp->* fields correctly */
+
+ if (rinfo->cursor) {
+ rinfo->dispsw.cursor = rivafb_cursor;
+ rinfo->dispsw.set_font = rivafb_set_font;
+ }
+
+ DPRINTK("EXIT\n");
+}
+
+/**
* riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object
* @regnum: register number
@@ -652,7 +738,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/**
* riva_save_state - saves current chip state
- * @par: pointer to riva_par object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
@@ -662,36 +748,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one()
*/
/* from GGI */
-static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
+static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs)
{
int i;
- par->riva.LockUnlock(&par->riva, 0);
+ rinfo->riva.LockUnlock(&rinfo->riva, 0);
- par->riva.UnloadStateExt(&par->riva, &regs->ext);
+ rinfo->riva.UnloadStateExt(&rinfo->riva, &regs->ext);
- regs->misc_output = MISCin(par);
+ regs->misc_output = MISCin(rinfo);
for (i = 0; i < NUM_CRT_REGS; i++) {
- regs->crtc[i] = CRTCin(par, i);
+ regs->crtc[i] = CRTCin(rinfo, i);
}
for (i = 0; i < NUM_ATC_REGS; i++) {
- regs->attr[i] = ATTRin(par, i);
+ regs->attr[i] = ATTRin(rinfo, i);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
- regs->gra[i] = GRAin(par, i);
+ regs->gra[i] = GRAin(rinfo, i);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
- regs->seq[i] = SEQin(par, i);
+ regs->seq[i] = SEQin(rinfo, i);
}
}
/**
* riva_load_state - loads current chip state
- * @par: pointer to riva_par object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
@@ -703,18 +789,18 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
* rivafb_remove_one()
*/
/* from GGI */
-static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
+static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs)
{
- RIVA_HW_STATE *state = &regs->ext;
int i;
-
- CRTCout(par, 0x11, 0x00);
+ RIVA_HW_STATE *state = &regs->ext;
+
+ CRTCout(rinfo, 0x11, 0x00);
- par->riva.LockUnlock(&par->riva, 0);
+ rinfo->riva.LockUnlock(&rinfo->riva, 0);
- par->riva.LoadStateExt(&par->riva, state);
+ rinfo->riva.LoadStateExt(&rinfo->riva, state);
- MISCout(par, regs->misc_output);
+ MISCout(rinfo, regs->misc_output);
for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) {
@@ -722,44 +808,44 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
case 0x20 ... 0x40:
break;
default:
- CRTCout(par, i, regs->crtc[i]);
+ CRTCout(rinfo, i, regs->crtc[i]);
}
}
for (i = 0; i < NUM_ATC_REGS; i++) {
- ATTRout(par, i, regs->attr[i]);
+ ATTRout(rinfo, i, regs->attr[i]);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
- GRAout(par, i, regs->gra[i]);
+ GRAout(rinfo, i, regs->gra[i]);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
- SEQout(par, i, regs->seq[i]);
+ SEQout(rinfo, i, regs->seq[i]);
}
}
/**
* riva_load_video_mode - calculate timings
- * @info: pointer to fb_info object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
* @video_mode: video mode to set
*
* DESCRIPTION:
* Calculate some timings and then send em off to riva_load_state().
*
* CALLED FROM:
- * rivafb_set_par()
+ * rivafb_set_var()
*/
-static void riva_load_video_mode(struct fb_info *info,
+static void riva_load_video_mode(struct rivafb_info *rinfo,
struct fb_var_screeninfo *video_mode)
{
- struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
/* time to calculate */
- rivafb_blank(1, info);
+
+ rivafb_blank(1, (struct fb_info *)rinfo);
bpp = video_mode->bits_per_pixel;
if (bpp == 16 && video_mode->green.length == 5)
@@ -813,27 +899,83 @@ static void riva_load_video_mode(struct fb_info *info,
newmode.ext.width = width;
newmode.ext.height = height;
- par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
+ rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width,
hDisplaySize, hDisplay, hStart, hEnd,
hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock);
- if (video_mode->sync & FB_SYNC_HOR_HIGH_ACT)
- newmode.misc_output &= ~0x40;
- if (video_mode->sync & FB_SYNC_VERT_HIGH_ACT)
- newmode.misc_output &= ~0x80;
+ rinfo->current_state = newmode;
+ riva_load_state(rinfo, &rinfo->current_state);
+
+ rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */
+ rivafb_download_cursor(rinfo);
+}
+
+/**
+ * riva_board_list_add - maintains board list
+ * @board_list: root node of list of boards
+ * @new_node: new node to be added
+ *
+ * DESCRIPTION:
+ * Adds @new_node to the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_init_one()
+ */
+static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list,
+ struct rivafb_info *new_node)
+{
+ struct rivafb_info *i_p = board_list;
+
+ new_node->next = NULL;
+
+ if (board_list == NULL)
+ return new_node;
- par->current_state = newmode;
- riva_load_state(par, &par->current_state);
+ while (i_p->next != NULL)
+ i_p = i_p->next;
+ i_p->next = new_node;
- par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
- rivafb_download_cursor(par);
+ return board_list;
+}
+
+/**
+ * riva_board_list_del - maintains board list
+ * @board_list: root node of list of boards
+ * @del_node: node to be removed
+ *
+ * DESCRIPTION:
+ * Removes @del_node from the list referenced by @board_list.
+ *
+ * RETURNS:
+ * New root node
+ *
+ * CALLED FROM:
+ * rivafb_remove_one()
+ */
+static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list,
+ struct rivafb_info *del_node)
+{
+ struct rivafb_info *i_p = board_list;
+
+ if (board_list == del_node)
+ return del_node->next;
+
+ while (i_p->next != del_node)
+ i_p = i_p->next;
+ i_p->next = del_node->next;
+
+ return board_list;
}
/**
* rivafb_do_maximize -
- * @info: pointer to fb_info object containing info for current riva board
+ * @rinfo: pointer to rivafb_info object containing info for current riva board
* @var:
+ * @v:
* @nom:
* @den:
*
@@ -845,13 +987,13 @@ static void riva_load_video_mode(struct fb_info *info,
*
*
* CALLED FROM:
- * rivafb_check_var()
+ * rivafb_set_var()
*/
-static int rivafb_do_maximize(struct fb_info *info,
+static int rivafb_do_maximize(struct rivafb_info *rinfo,
struct fb_var_screeninfo *var,
+ struct fb_var_screeninfo *v,
int nom, int den)
{
- struct riva_par *par = (struct riva_par *) info->par;
static struct {
int xres, yres;
} modes[] = {
@@ -865,12 +1007,12 @@ static int rivafb_do_maximize(struct fb_info *info,
int i;
/* use highest possible virtual resolution */
- if (var->xres_virtual == -1 && var->yres_virtual == -1) {
+ if (v->xres_virtual == -1 && v->yres_virtual == -1) {
printk(KERN_WARNING PFX
"using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres <
- par->ram_amount / 2)
+ rinfo->ram_amount / 2)
break;
}
if (modes[i].xres == -1) {
@@ -879,26 +1021,26 @@ static int rivafb_do_maximize(struct fb_info *info,
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
- var->xres_virtual = modes[i].xres;
- var->yres_virtual = modes[i].yres;
+ v->xres_virtual = modes[i].xres;
+ v->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n",
- var->xres_virtual, var->yres_virtual);
- } else if (var->xres_virtual == -1) {
- var->xres_virtual = (par->ram_amount * den /
- (nom * var->yres_virtual * 2)) & ~15;
+ v->xres_virtual, v->yres_virtual);
+ } else if (v->xres_virtual == -1) {
+ v->xres_virtual = (rinfo->ram_amount * den /
+ (nom * v->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX
- "setting virtual X resolution to %d\n", var->xres_virtual);
- } else if (var->yres_virtual == -1) {
- var->xres_virtual = (var->xres_virtual + 15) & ~15;
- var->yres_virtual = par->ram_amount * den /
- (nom * var->xres_virtual * 2);
+ "setting virtual X resolution to %d\n", v->xres_virtual);
+ } else if (v->yres_virtual == -1) {
+ v->xres_virtual = (v->xres_virtual + 15) & ~15;
+ v->yres_virtual = rinfo->ram_amount * den /
+ (nom * v->xres_virtual * 2);
printk(KERN_WARNING PFX
- "setting virtual Y resolution to %d\n", var->yres_virtual);
+ "setting virtual Y resolution to %d\n", v->yres_virtual);
} else {
- var->xres_virtual = (var->xres_virtual + 15) & ~15;
- if (var->xres_virtual * nom / den * var->yres_virtual > par->ram_amount) {
+ v->xres_virtual = (v->xres_virtual + 15) & ~15;
+ if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
@@ -907,146 +1049,29 @@ static int rivafb_do_maximize(struct fb_info *info,
}
}
- if (var->xres_virtual * nom / den >= 8192) {
+ if (v->xres_virtual * nom / den >= 8192) {
printk(KERN_WARNING PFX
"virtual X resolution (%d) is too high, lowering to %d\n",
- var->xres_virtual, 8192 * den / nom - 16);
- var->xres_virtual = 8192 * den / nom - 16;
+ v->xres_virtual, 8192 * den / nom - 16);
+ v->xres_virtual = 8192 * den / nom - 16;
}
- if (var->xres_virtual < var->xres) {
+ if (v->xres_virtual < v->xres) {
printk(KERN_ERR PFX
- "virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
+ "virtual X resolution (%d) is smaller than real\n", v->xres_virtual);
return -EINVAL;
}
- if (var->yres_virtual < var->yres) {
+ if (v->yres_virtual < v->yres) {
printk(KERN_ERR PFX
- "virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
+ "virtual Y resolution (%d) is smaller than real\n", v->yres_virtual);
return -EINVAL;
}
+
return 0;
}
-/* acceleration routines */
-
-static inline void convert_bgcolor_16(u32 *col)
-{
- *col = ((*col & 0x00007C00) << 9)
- | ((*col & 0x000003E0) << 6)
- | ((*col & 0x0000001F) << 3)
- | 0xFF000000;
-}
-
-inline void wait_for_idle(struct riva_par *par)
-{
- while (par->riva.Busy(&par->riva));
-}
-
-/* set copy ROP, no mask */
-static void riva_setup_ROP(struct riva_par *par)
-{
- RIVA_FIFO_FREE(par->riva, Patt, 5);
- par->riva.Patt->Shape = 0;
- par->riva.Patt->Color0 = 0xffffffff;
- par->riva.Patt->Color1 = 0xffffffff;
- par->riva.Patt->Monochrome[0] = 0xffffffff;
- par->riva.Patt->Monochrome[1] = 0xffffffff;
-
- RIVA_FIFO_FREE(par->riva, Rop, 1);
- par->riva.Rop->Rop3 = 0xCC;
-}
-
-void riva_setup_accel(struct riva_par *par)
-{
- RIVA_FIFO_FREE(par->riva, Clip, 2);
- par->riva.Clip->TopLeft = 0x0;
- par->riva.Clip->WidthHeight = 0x80008000;
- riva_setup_ROP(par);
- wait_for_idle(par);
-}
-
-static inline void reverse_order(u32 *l)
-{
- u8 *a = (u8 *)l;
- *a++ = byte_rev[*a];
-/* *a++ = byte_rev[*a];
- *a++ = byte_rev[*a];*/
- *a = byte_rev[*a];
-}
-
-static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
-{
- struct riva_par *par = (struct riva_par *) info->par;
-
- RIVA_FIFO_FREE(par->riva, Rop, 1);
- par->riva.Rop->Rop3 = rect->rop ? 0x66 : 0xCC;
-
- RIVA_FIFO_FREE(par->riva, Bitmap, 1);
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR)
- par->riva.Bitmap->Color1A = ((u32 *) (info->pseudo_palette))[rect->color];
- else
- par->riva.Bitmap->Color1A = rect->color;
-
- RIVA_FIFO_FREE(par->riva, Bitmap, 2);
- par->riva.Bitmap->UnclippedRectangle[0].TopLeft = (rect->dx << 16) | rect->dy;
- par->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (rect->width << 16) | rect->height;
- RIVA_FIFO_FREE(par->riva, Rop, 1);
- par->riva.Rop->Rop3 = 0xCC; // back to COPY
-}
-
-static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *area)
-{
- struct riva_par *par = (struct riva_par *) info->par;
-
- RIVA_FIFO_FREE(par->riva, Blt, 3);
- par->riva.Blt->TopLeftSrc = (area->sy << 16) | area->sx;
- par->riva.Blt->TopLeftDst = (area->dy << 16) | area->dx;
- par->riva.Blt->WidthHeight = (area->height << 16) | area->width;
-}
-static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
-{
- struct riva_par *par = (struct riva_par *) info->par;
- volatile u32 *d;
- int i, j, cnt;
- u32 cdat2;
-
- RIVA_FIFO_FREE(par->riva, Bitmap, 7);
- par->riva.Bitmap->ClipE.TopLeft = (image->dy << 16) | (image->dx & 0xFFFF);
- par->riva.Bitmap->ClipE.BottomRight = ((image->dy + image->height) << 16) | ((image->dx + image->width) & 0xffff);
- if (info->var.green.length == 6)
- convert_bgcolor_16(&image->bg_color);
-
- if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
- par->riva.Bitmap->Color0E = ((u32 *) (info->pseudo_palette))[image->bg_color];
- par->riva.Bitmap->Color1E = ((u32 *) (info->pseudo_palette))[image->fg_color];
- } else {
- par->riva.Bitmap->Color0E = image->bg_color;
- par->riva.Bitmap->Color1E = image->fg_color;
- }
-
- par->riva.Bitmap->WidthHeightInE = (image->height << 16) | 32;
- par->riva.Bitmap->WidthHeightOutE = (image->height << 16) | 32;
- par->riva.Bitmap->PointE = (image->dy << 16) | (image->dx & 0xFFFF);
- d = &par->riva.Bitmap->MonochromeData01E;
- for (i = image->height; i > 0; i -= 16) {
- if (i >= 16)
- cnt = 16;
- else
- cnt = i;
- RIVA_FIFO_FREE(par->riva, Bitmap, cnt);
- for (j = 0; j < cnt; j++) {
- if (image->width <= 8)
- cdat2 = *image->data++;
- else
- cdat2 = *((u16*)image->data)++;
- reverse_order(&cdat2);
- d[j] = cdat2;
- }
- }
-}
/* ------------------------------------------------------------------------- *
*
@@ -1065,7 +1090,10 @@ static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
* Length of color map
*
* CALLED FROM:
+ * riva_getcolreg()
* rivafb_setcolreg()
+ * rivafb_get_cmap()
+ * rivafb_set_cmap()
*/
static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
{
@@ -1074,18 +1102,24 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert(var != NULL);
switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */
break;
+#endif
+#ifdef FBCON_HAS_CFB16
case 15:
rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */
break;
case 16:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
+#ifdef FBCON_HAS_CFB32
case 32:
rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
+#endif
default:
/* should not occur */
break;
@@ -1095,13 +1129,53 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
}
/**
+ * riva_getcolreg
+ * @regno: register index
+ * @red: red component
+ * @green: green component
+ * @blue: blue component
+ * @transp: transparency
+ * @info: pointer to rivafb_info object containing info for current riva board
+ *
+ * DESCRIPTION:
+ * Read a single color register and split it into colors/transparent.
+ * The return values must have a 16 bit magnitude.
+ *
+ * RETURNS:
+ * Return != 0 for invalid regno.
+ *
+ * CALLED FROM:
+ * rivafb_get_cmap()
+ * rivafb_switch()
+ * fbcmap.c:fb_get_cmap()
+ * fbgen.c:fbgen_get_cmap()
+ * fbgen.c:fbgen_switch()
+ */
+static int riva_getcolreg(unsigned regno, unsigned *red, unsigned *green,
+ unsigned *blue, unsigned *transp,
+ struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+
+ if (regno >= riva_get_cmap_len(&rivainfo->currcon_display->var))
+ return 1;
+
+ *red = rivainfo->palette[regno].red;
+ *green = rivainfo->palette[regno].green;
+ *blue = rivainfo->palette[regno].blue;
+ *transp = 0;
+
+ return 0;
+}
+
+/**
* rivafb_setcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
- * @info: pointer to fb_info object containing info for current riva board
+ * @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
@@ -1111,54 +1185,79 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
* Return != 0 for invalid regno.
*
* CALLED FROM:
+ * rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
- * fbgen.c:gen_get_cmap()
+ * fbgen.c:fbgen_get_cmap()
+ * fbgen.c:do_install_cmap()
+ * fbgen.c:fbgen_set_var()
+ * fbgen.c:fbgen_switch()
+ * fbgen.c:fbgen_blank()
+ * fbgen.c:fbgen_blank()
*/
static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
- RIVA_HW_INST *chip = &par->riva;
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ RIVA_HW_INST *chip = &rivainfo->riva;
+ struct display *p;
+
+ DPRINTK("ENTER\n");
- if (regno >= riva_get_cmap_len(&info->var))
+ assert(rivainfo != NULL);
+ assert(rivainfo->currcon_display != NULL);
+
+ p = rivainfo->currcon_display;
+
+ if (regno >= riva_get_cmap_len(&p->var))
return -EINVAL;
- if (info->var.grayscale) {
+ rivainfo->palette[regno].red = red;
+ rivainfo->palette[regno].green = green;
+ rivainfo->palette[regno].blue = blue;
+
+ if (p->var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
- switch (info->var.bits_per_pixel) {
+ switch (p->var.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
case 8:
/* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
+#endif /* FBCON_HAS_CFB8 */
+#ifdef FBCON_HAS_CFB16
case 16:
assert(regno < 16);
- if (info->var.green.length == 5) {
+ if (p->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
- ((u16 *)(info->pseudo_palette))[regno] =
+ rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
- ((u16 *)(info->pseudo_palette))[regno] =
+ rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
+#endif /* FBCON_HAS_CFB16 */
+#ifdef FBCON_HAS_CFB32
case 32:
assert(regno < 16);
- ((u32 *)(info->pseudo_palette))[regno] =
+ rivainfo->con_cmap.cfb32[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
+#endif /* FBCON_HAS_CFB32 */
default:
/* do nothing */
break;
}
+
return 0;
}
@@ -1170,58 +1269,177 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
*
* ------------------------------------------------------------------------- */
-static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+static int rivafb_get_fix(struct fb_fix_screeninfo *fix, int con,
+ struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ struct display *p;
+
+ DPRINTK("ENTER\n");
+
+ assert(fix != NULL);
+ assert(info != NULL);
+ assert(rivainfo->drvr_name && rivainfo->drvr_name[0]);
+ assert(rivainfo->fb_base_phys > 0);
+ assert(rivainfo->ram_amount > 0);
+
+ p = (con < 0) ? rivainfo->info.disp : &fb_display[con];
+
+ memset(fix, 0, sizeof(struct fb_fix_screeninfo));
+ sprintf(fix->id, "nVidia %s", rivainfo->drvr_name);
+
+ fix->smem_start = rivainfo->fb_base_phys;
+ fix->smem_len = rivainfo->ram_amount;
+
+ fix->type = p->type;
+ fix->type_aux = p->type_aux;
+ fix->visual = p->visual;
+
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ fix->ywrapstep = 0; /* FIXME: no ywrap for now */
+
+ fix->line_length = p->line_length;
+
+ fix->mmio_start = rivainfo->ctrl_base_phys;
+ fix->mmio_len = rivainfo->base0_region_size;
+ fix->smem_start = rivainfo->fb_base_phys;
+ fix->smem_len = rivainfo->base1_region_size;
+
+ switch (rivainfo->riva.Architecture) {
+ case NV_ARCH_03:
+ fix->accel = FB_ACCEL_NV3;
+ break;
+ case NV_ARCH_04: /* riva_hw.c now doesn't distinguish between TNT & TNT2 */
+ fix->accel = FB_ACCEL_NV4;
+ break;
+ case NV_ARCH_10: /* FIXME: ID for GeForce */
+ fix->accel = FB_ACCEL_NV4;
+ break;
+
+ }
+
+ DPRINTK("EXIT, returning 0\n");
+
+ return 0;
+}
+
+static int rivafb_get_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+
+ DPRINTK("ENTER\n");
+
+ assert(info != NULL);
+ assert(var != NULL);
+
+ *var = (con < 0) ? rivainfo->disp.var : fb_display[con].var;
+
+ DPRINTK("EXIT, returning 0\n");
+
+ return 0;
+}
+
+static int rivafb_set_var(struct fb_var_screeninfo *var, int con,
+ struct fb_info *info)
{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ struct display *dsp;
+ struct fb_var_screeninfo v;
int nom, den; /* translating from pixels->bytes */
+ int accel;
+ unsigned chgvar = 0;
- switch (var->bits_per_pixel) {
+ DPRINTK("ENTER\n");
+
+ assert(info != NULL);
+ assert(var != NULL);
+
+ DPRINTK("Requested: %dx%dx%d\n", var->xres, var->yres,
+ var->bits_per_pixel);
+ DPRINTK(" virtual: %dx%d\n", var->xres_virtual,
+ var->yres_virtual);
+ DPRINTK(" offset: (%d,%d)\n", var->xoffset, var->yoffset);
+ DPRINTK("grayscale: %d\n", var->grayscale);
+
+ dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
+ assert(dsp != NULL);
+
+ /* if var has changed, we should call changevar() later */
+ if (con >= 0) {
+ chgvar = ((dsp->var.xres != var->xres) ||
+ (dsp->var.yres != var->yres) ||
+ (dsp->var.xres_virtual != var->xres_virtual) ||
+ (dsp->var.yres_virtual != var->yres_virtual) ||
+ (dsp->var.accel_flags != var->accel_flags) ||
+ (dsp->var.bits_per_pixel != var->bits_per_pixel)
+ || memcmp(&dsp->var.red, &var->red,
+ sizeof(var->red))
+ || memcmp(&dsp->var.green, &var->green,
+ sizeof(var->green))
+ || memcmp(&dsp->var.blue, &var->blue,
+ sizeof(var->blue)));
+ }
+
+ memcpy(&v, var, sizeof(v));
+
+ accel = v.accel_flags & FB_ACCELF_TEXT;
+
+ switch (v.bits_per_pixel) {
+#ifdef FBCON_HAS_CFB8
case 1 ... 8:
- var->bits_per_pixel = 8;
+ v.bits_per_pixel = 8;
nom = 1;
den = 1;
- var->red.offset = 0;
- var->red.length = 8;
- var->green.offset = 0;
- var->green.length = 8;
- var->blue.offset = 0;
- var->blue.length = 8;
+ v.red.offset = 0;
+ v.red.length = 8;
+ v.green.offset = 0;
+ v.green.length = 8;
+ v.blue.offset = 0;
+ v.blue.length = 8;
break;
+#endif
+#ifdef FBCON_HAS_CFB16
case 9 ... 15:
- var->green.length = 5;
+ v.green.length = 5;
/* fall through */
case 16:
- var->bits_per_pixel = 16;
+ v.bits_per_pixel = 16;
nom = 2;
den = 1;
- if (var->green.length == 5) {
+ if (v.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
- var->red.offset = 10;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 5;
- var->blue.length = 5;
+ v.red.offset = 10;
+ v.green.offset = 5;
+ v.blue.offset = 0;
+ v.red.length = 5;
+ v.green.length = 5;
+ v.blue.length = 5;
} else {
/* rrrrrggg gggbbbbb */
- var->red.offset = 11;
- var->green.offset = 5;
- var->blue.offset = 0;
- var->red.length = 5;
- var->green.length = 6;
- var->blue.length = 5;
+ v.red.offset = 11;
+ v.green.offset = 5;
+ v.blue.offset = 0;
+ v.red.length = 5;
+ v.green.length = 6;
+ v.blue.length = 5;
}
break;
+#endif
+#ifdef FBCON_HAS_CFB32
case 17 ... 32:
- var->bits_per_pixel = 32;
+ v.bits_per_pixel = 32;
nom = 4;
den = 1;
- var->red.offset = 16;
- var->green.offset = 8;
- var->blue.offset = 0;
- var->red.length = 8;
- var->green.length = 8;
- var->blue.length = 8;
+ v.red.offset = 16;
+ v.green.offset = 8;
+ v.blue.offset = 0;
+ v.red.length = 8;
+ v.green.length = 8;
+ v.blue.length = 8;
break;
+#endif
default:
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
@@ -1230,57 +1448,122 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return -EINVAL;
}
- if (rivafb_do_maximize(info, var, nom, den) < 0)
+ if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
return -EINVAL;
- if (var->xoffset < 0)
- var->xoffset = 0;
- if (var->yoffset < 0)
- var->yoffset = 0;
+ if (v.xoffset < 0)
+ v.xoffset = 0;
+ if (v.yoffset < 0)
+ v.yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */
- if (var->xoffset > var->xres_virtual - var->xres)
- var->xoffset = var->xres_virtual - var->xres - 1;
+ if (v.xoffset > v.xres_virtual - v.xres)
+ v.xoffset = v.xres_virtual - v.xres - 1;
- if (var->yoffset > var->yres_virtual - var->yres)
- var->yoffset = var->yres_virtual - var->yres - 1;
+ if (v.yoffset > v.yres_virtual - v.yres)
+ v.yoffset = v.yres_virtual - v.yres - 1;
- var->red.msb_right =
- var->green.msb_right =
- var->blue.msb_right =
- var->transp.offset = var->transp.length = var->transp.msb_right = 0;
- var->accel_flags |= FB_ACCELF_TEXT;
+ v.red.msb_right =
+ v.green.msb_right =
+ v.blue.msb_right =
+ v.transp.offset = v.transp.length = v.transp.msb_right = 0;
+
+ switch (v.activate & FB_ACTIVATE_MASK) {
+ case FB_ACTIVATE_TEST:
+ DPRINTK("EXIT - FB_ACTIVATE_TEST\n");
+ return 0;
+ case FB_ACTIVATE_NXTOPEN: /* ?? */
+ case FB_ACTIVATE_NOW:
+ break; /* continue */
+ default:
+ DPRINTK("EXIT - unknown activation type\n");
+ return -EINVAL; /* unknown */
+ }
+
+ memcpy(&dsp->var, &v, sizeof(v));
+ if (chgvar) {
+ riva_set_dispsw(rivainfo, dsp);
+
+ if (accel) {
+ if (nomove)
+ dsp->scrollmode = SCROLL_YNOMOVE;
+ else
+ dsp->scrollmode = 0;
+ } else
+ dsp->scrollmode = SCROLL_YREDRAW;
+
+ if (info && info->changevar)
+ info->changevar(con);
+ }
+
+ rivafb_create_cursor(rivainfo, fontwidth(dsp), fontheight(dsp));
+ riva_load_video_mode(rivainfo, &v);
+ if (accel) riva_setup_accel(rivainfo);
+
+ DPRINTK("EXIT, returning 0\n");
return 0;
}
-static int rivafb_set_par(struct fb_info *info)
+static int rivafb_get_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ struct display *dsp;
- switch (info->var.bits_per_pixel) {
- case 8:
- info->fix.line_length = info->var.xres_virtual;
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- break;
- case 16:
- info->fix.line_length = info->var.xres_virtual * 2;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
- break;
- case 32:
- info->fix.line_length = info->var.xres_virtual * 4;
- info->fix.visual = FB_VISUAL_DIRECTCOLOR;
- break;
- }
-/*
- if (par->cursor) {
- disp->dispsw.cursor = rivafb_cursor;
- disp->dispsw.set_font = rivafb_set_font;
+ DPRINTK("ENTER\n");
+
+ assert(rivainfo != NULL);
+ assert(cmap != NULL);
+
+ dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
+
+ if (con == info->currcon) { /* current console? */
+ int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
+ DPRINTK("EXIT - returning %d\n", rc);
+ return rc;
+ } else if (dsp->cmap.len) /* non default colormap? */
+ fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
+ else
+ fb_copy_cmap(fb_default_cmap
+ (riva_get_cmap_len(&dsp->var)), cmap,
+ kspc ? 0 : 2);
+
+ DPRINTK("EXIT, returning 0\n");
+
+ return 0;
+}
+
+static int rivafb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ struct display *dsp;
+ unsigned int cmap_len;
+
+ DPRINTK("ENTER\n");
+
+ assert(rivainfo != NULL);
+ assert(cmap != NULL);
+
+ dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
+
+ cmap_len = riva_get_cmap_len(&dsp->var);
+ if (dsp->cmap.len != cmap_len) {
+ int err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0);
+ if (err) {
+ DPRINTK("EXIT - returning %d\n", err);
+ return err;
+ }
}
- rivafb_create_cursor(par, fontwidth(dsp), fontheight(dsp));
-*/
+ if (con == info->currcon) { /* current console? */
+ int rc = fb_set_cmap(cmap, kspc, info);
+ DPRINTK("EXIT - returning %d\n", rc);
+ return rc;
+ } else
+ fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1);
+
+ DPRINTK("EXIT, returning 0\n");
- riva_load_video_mode(info, &info->var);
- riva_setup_accel(par);
return 0;
}
@@ -1288,7 +1571,7 @@ static int rivafb_set_par(struct fb_info *info)
* rivafb_pan_display
* @var: standard kernel fb changeable data
* @con: TODO
- * @info: pointer to fb_info object containing info for current riva board
+ * @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the
@@ -1300,58 +1583,132 @@ static int rivafb_set_par(struct fb_info *info)
static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *) info->par;
- struct display *dsp;
unsigned int base;
-
+ struct display *dsp;
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+
+ DPRINTK("ENTER\n");
+
+ assert(rivainfo != NULL);
+
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
- dsp = (con < 0) ? info->disp : &fb_display[con];
+ dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0
- || var->yoffset >= info->var.yres_virtual
+ || var->yoffset >= dsp->var.yres_virtual
|| var->xoffset) return -EINVAL;
} else {
- if (var->xoffset + info->var.xres > info->var.xres_virtual ||
- var->yoffset + info->var.yres > info->var.yres_virtual)
+ if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
+ var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
return -EINVAL;
}
base = var->yoffset * dsp->line_length + var->xoffset;
- if (con == info->currcon)
- par->riva.SetStartAddress(&par->riva, base);
+ if (con == info->currcon) {
+ rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
+ }
- info->var.xoffset = var->xoffset;
- info->var.yoffset = var->yoffset;
+ dsp->var.xoffset = var->xoffset;
+ dsp->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
- info->var.vmode |= FB_VMODE_YWRAP;
+ dsp->var.vmode |= FB_VMODE_YWRAP;
else
- info->var.vmode &= ~FB_VMODE_YWRAP;
+ dsp->var.vmode &= ~FB_VMODE_YWRAP;
+
+ DPRINTK("EXIT, returning 0\n");
+
return 0;
}
+static int rivafb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+ unsigned long arg, int con, struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+
+ DPRINTK("ENTER\n");
+
+ assert(rivainfo != NULL);
+
+ /* no rivafb-specific ioctls */
+
+ DPRINTK("EXIT, returning -EINVAL\n");
+
+ return -EINVAL;
+}
+
static int rivafb_rasterimg(struct fb_info *info, int start)
{
- struct riva_par *par = (struct riva_par *) info->par;
+ struct rivafb_info *rinfo = (struct rivafb_info *)info;
- wait_for_idle(par);
+ wait_for_idle(rinfo);
return 0;
}
+static int rivafb_switch(int con, struct fb_info *info)
+{
+ struct rivafb_info *rivainfo = (struct rivafb_info *)info;
+ struct fb_cmap *cmap;
+ struct display *dsp;
+
+ DPRINTK("ENTER\n");
+
+ assert(rivainfo != NULL);
+
+ dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
+
+ if (info->currcon >= 0) {
+ /* Do we have to save the colormap? */
+ cmap = &(rivainfo->currcon_display->cmap);
+ DPRINTK("switch1: con = %d, cmap.len = %d\n",
+ info->currcon, cmap->len);
+
+ if (cmap->len) {
+ DPRINTK("switch1a: %p %p %p %p\n", cmap->red,
+ cmap->green, cmap->blue, cmap->transp);
+ fb_get_cmap(cmap, 1, riva_getcolreg, info);
+ }
+ }
+ info->currcon = con;
+ rivainfo->currcon_display = dsp;
+
+ rivafb_set_var(&dsp->var, con, info);
+ riva_set_dispsw(rivainfo, dsp);
+
+ DPRINTK("EXIT, returning 0\n");
+ return 0;
+}
+
+static int rivafb_updatevar(int con, struct fb_info *info)
+{
+ int rc;
+
+ DPRINTK("ENTER\n");
+
+ rc = (con < 0) ? -EINVAL : rivafb_pan_display(&fb_display[con].var,
+ con, info);
+ DPRINTK("EXIT, returning %d\n", rc);
+ return rc;
+}
+
static int rivafb_blank(int blank, struct fb_info *info)
{
- struct riva_par *par = (struct riva_par *)info->par;
unsigned char tmp, vesa;
+ struct rivafb_info *rinfo = (struct rivafb_info *)info;
+
+ DPRINTK("ENTER\n");
+
+ assert(rinfo != NULL);
- tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
- vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
+ tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */
+ vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */
if (blank) {
tmp |= 0x20;
@@ -1370,11 +1727,15 @@ static int rivafb_blank(int blank, struct fb_info *info)
}
}
- SEQout(par, 0x01, tmp);
- CRTCout(par, 0x1a, vesa);
+ SEQout(rinfo, 0x01, tmp);
+ CRTCout(rinfo, 0x1a, vesa);
+
+ DPRINTK("EXIT\n");
return 0;
}
+
+
/* ------------------------------------------------------------------------- *
*
* initialization helper functions
@@ -1384,29 +1745,78 @@ static int rivafb_blank(int blank, struct fb_info *info)
/* kernel interface */
static struct fb_ops riva_fb_ops = {
owner: THIS_MODULE,
- fb_get_fix: gen_get_fix,
- fb_get_var: gen_get_var,
- fb_set_var: gen_set_var,
- fb_get_cmap: gen_get_cmap,
- fb_set_cmap: gen_set_cmap,
- fb_check_var: rivafb_check_var,
- fb_set_par: rivafb_set_par,
+ fb_get_fix: rivafb_get_fix,
+ fb_get_var: rivafb_get_var,
+ fb_set_var: rivafb_set_var,
+ fb_get_cmap: rivafb_get_cmap,
+ fb_set_cmap: rivafb_set_cmap,
fb_setcolreg: rivafb_setcolreg,
fb_pan_display: rivafb_pan_display,
fb_blank: rivafb_blank,
- fb_fillrect: rivafb_fillrect,
- fb_copyarea: rivafb_copyarea,
- fb_imageblit: rivafb_imageblit,
+ fb_ioctl: rivafb_ioctl,
fb_rasterimg: rivafb_rasterimg,
};
-static int __devinit riva_set_fbinfo(struct fb_info *info)
+static int __devinit riva_init_disp_var(struct rivafb_info *rinfo)
+{
+#ifndef MODULE
+ if (mode_option)
+ fb_find_mode(&rinfo->disp.var, &rinfo->info, mode_option,
+ NULL, 0, NULL, 8);
+#endif
+ return 0;
+}
+
+static int __devinit riva_init_disp(struct rivafb_info *rinfo)
+{
+ struct fb_info *info;
+ struct display *disp;
+
+ DPRINTK("ENTER\n");
+
+ assert(rinfo != NULL);
+
+ info = &rinfo->info;
+ disp = &rinfo->disp;
+
+ disp->var = rivafb_default_var;
+
+ if (noaccel)
+ disp->var.accel_flags &= ~FB_ACCELF_TEXT;
+ else
+ disp->var.accel_flags |= FB_ACCELF_TEXT;
+
+ info->disp = disp;
+
+ /* FIXME: assure that disp->cmap is completely filled out */
+
+ rinfo->currcon_display = disp;
+
+ if ((riva_init_disp_var(rinfo)) < 0) {
+ DPRINTK("EXIT, returning -1\n");
+ return -1;
+ }
+
+ riva_set_dispsw(rinfo, disp);
+
+ DPRINTK("EXIT, returning 0\n");
+ return 0;
+
+}
+
+static int __devinit riva_set_fbinfo(struct rivafb_info *rinfo)
{
- strcpy(info->modename, rivafb_fix.id);
+ struct fb_info *info;
+
+ assert(rinfo != NULL);
+
+ info = &rinfo->info;
+
+ strcpy(info->modename, rinfo->drvr_name);
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
- info->fix = rivafb_fix;
+ info->screen_base = rinfo->fb_base;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
@@ -1415,21 +1825,12 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL;
- info->switch_con = gen_switch;
- info->updatevar = gen_update_var;
+ info->switch_con = rivafb_switch;
+ info->updatevar = rivafb_updatevar;
-#ifndef MODULE
- if (mode_option) {
- int err = fb_find_mode(&info->var, info, mode_option,
- NULL, 0, NULL, 8);
- if (!err || err == 4)
- info->var = rivafb_default_var;
- } else
-#endif
- info->var = rivafb_default_var;
- fb_alloc_cmap(&info->cmap, riva_get_cmap_len(&info->var), 0);
+ if (riva_init_disp(rinfo) < 0) /* must be done last */
+ return -1;
- gen_set_var(&info->var, -1, info);
return 0;
}
@@ -1444,230 +1845,194 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent)
{
+ struct rivafb_info *rinfo;
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
- struct riva_par *default_par;
- struct fb_info *info;
- int size;
assert(pd != NULL);
assert(rci != NULL);
- size = sizeof(struct fb_info) + sizeof(struct display) + sizeof(u32) * 16;
-
- info = kmalloc(size, GFP_KERNEL);
- if (!info)
+ rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
+ if (!rinfo)
goto err_out;
- memset(info, 0, size);
-
- default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);
- if (!default_par)
- goto err_out;
+ memset(rinfo, 0, sizeof(struct rivafb_info));
- memset(default_par, 0, sizeof(struct riva_par));
+ rinfo->drvr_name = rci->name;
+ rinfo->riva.Architecture = rci->arch_rev;
- info->disp = (struct display *)(info + 1);
- info->pseudo_palette = (void *)(info->disp + 1);
+ rinfo->pd = pd;
+ rinfo->base0_region_size = pci_resource_len(pd, 0);
+ rinfo->base1_region_size = pci_resource_len(pd, 1);
- strcat(rivafb_fix.id, rci->name);
- default_par->riva.Architecture = rci->arch_rev;
+ assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */
+ assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */
- rivafb_fix.mmio_len = pci_resource_len(pd, 0);
- rivafb_fix.smem_len = pci_resource_len(pd, 1);
+ rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
+ rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
- assert(rivafb_fix.mmio_len >= 0x00800000); /* from GGI */
- assert(rivafb_fix.smem_len >= 0x01000000); /* from GGI */
-
- rivafb_fix.mmio_start = pci_resource_start(pd, 0);
- rivafb_fix.smem_start = pci_resource_start(pd, 1);
-
- if (!request_mem_region(rivafb_fix.mmio_start,
- rivafb_fix.mmio_len, "rivafb")) {
+ if (!request_mem_region(rinfo->ctrl_base_phys,
+ rinfo->base0_region_size, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree;
}
- default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
- rivafb_fix.mmio_len);
- if (!default_par->ctrl_base) {
+ if (!request_mem_region(rinfo->fb_base_phys,
+ rinfo->base1_region_size, "rivafb")) {
+ printk(KERN_ERR PFX "cannot reserve FB region\n");
+ goto err_out_free_base0;
+ }
+
+ rinfo->ctrl_base = ioremap(rinfo->ctrl_base_phys,
+ rinfo->base0_region_size);
+ if (!rinfo->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1;
}
- default_par->riva.EnableIRQ = 0;
- default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + 0x00680000);
- default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + 0x00100000);
- default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + 0x00002000);
- default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + 0x00400000);
- default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base + 0x00101000);
- default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base + 0x00009000);
- default_par->riva.PMC = (unsigned *)(default_par->ctrl_base + 0x00000000);
- default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + 0x00800000);
-
- default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
- default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
- default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
- default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
-
- switch (default_par->riva.Architecture) {
- case NV_ARCH_03:
- /*
- * We have to map the full BASE_1 aperture for Riva128's
- * because they use the PRAMIN set in "framebuffer" space
- */
- if (!request_mem_region(rivafb_fix.smem_start,
- rivafb_fix.smem_len, "rivafb")) {
- printk(KERN_ERR PFX "cannot reserve FB region\n");
- goto err_out_free_base0;
+ rinfo->fb_base = ioremap(rinfo->fb_base_phys,
+ rinfo->base1_region_size);
+ if (!rinfo->fb_base) {
+ printk(KERN_ERR PFX "cannot ioremap FB base\n");
+ goto err_out_iounmap_ctrl;
+ }
+
+#ifdef CONFIG_MTRR
+ if (!nomtrr) {
+ rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
+ rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
+ if (rinfo->mtrr.vram < 0) {
+ printk(KERN_ERR PFX "unable to setup MTRR\n");
+ } else {
+ rinfo->mtrr.vram_valid = 1;
+ /* let there be speed */
+ printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
}
+ }
+#endif /* CONFIG_MTRR */
- info->screen_base = ioremap(rivafb_fix.smem_start,
- rivafb_fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR PFX "cannot ioremap FB base\n");
- goto err_out_iounmap_ctrl;
- }
+ rinfo->riva.EnableIRQ = 0;
+ rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
+ rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
+ rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
+ rinfo->riva.PGRAPH = (unsigned *)(rinfo->ctrl_base + 0x00400000);
+ rinfo->riva.PEXTDEV = (unsigned *)(rinfo->ctrl_base + 0x00101000);
+ rinfo->riva.PTIMER = (unsigned *)(rinfo->ctrl_base + 0x00009000);
+ rinfo->riva.PMC = (unsigned *)(rinfo->ctrl_base + 0x00000000);
+ rinfo->riva.FIFO = (unsigned *)(rinfo->ctrl_base + 0x00800000);
+
+ rinfo->riva.PCIO = (U008 *)(rinfo->ctrl_base + 0x00601000);
+ rinfo->riva.PDIO = (U008 *)(rinfo->ctrl_base + 0x00681000);
+ rinfo->riva.PVIO = (U008 *)(rinfo->ctrl_base + 0x000C0000);
- default_par->riva.PRAMIN = (unsigned *)(info->screen_base + 0x00C00000);
- rivafb_fix.accel = FB_ACCEL_NV3;
+ rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
+
+ switch (rinfo->riva.Architecture) {
+ case NV_ARCH_03:
+ rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000);
break;
case NV_ARCH_04:
case NV_ARCH_10:
- case NV_ARCH_20:
- /* riva_hw.c now doesn't distinguish between TNT & TNT2 */
- default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base + 0x00600000);
- default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base + 0x00710000);
-
- rivafb_fix.accel = FB_ACCEL_NV4;
+ rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
+ rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
break;
}
- RivaGetConfig(&default_par->riva);
-
- /* unlock io */
- CRTCout(default_par, 0x11, 0xFF);/* vgaHWunlock()+riva unlock (0x7F) */
- default_par->riva.LockUnlock(&default_par->riva, 0);
-
- riva_save_state(default_par, &default_par->initial_state);
-
- default_par->ram_amount = default_par->riva.RamAmountKBytes * 1024;
- default_par->dclk_max = default_par->riva.MaxVClockFreqKHz * 1000;
+ RivaGetConfig(&rinfo->riva);
- if (default_par->riva.Architecture != NV_ARCH_03) {
- /*
- * Now the _normal_ chipsets can just map the amount of real
- * physical ram instead of the whole aperture
- */
- rivafb_fix.smem_len = default_par->ram_amount;
+ /* back to normal */
- if (!request_mem_region(rivafb_fix.smem_start,
- rivafb_fix.smem_len, "rivafb")) {
- printk(KERN_ERR PFX "cannot reserve FB region\n");
- goto err_out_free_base0;
- }
+ assert(rinfo->pd != NULL);
- info->screen_base = ioremap(rivafb_fix.smem_start,
- rivafb_fix.smem_len);
- if (!info->screen_base) {
- printk(KERN_ERR PFX "cannot ioremap FB base\n");
- goto err_out_iounmap_ctrl;
- }
- }
+ /* unlock io */
+ CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
+ rinfo->riva.LockUnlock(&rinfo->riva, 0);
-#ifdef CONFIG_MTRR
- if (!nomtrr) {
- default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
- rivafb_fix.smem_len, MTRR_TYPE_WRCOMB, 1);
- if (default_par->mtrr.vram < 0) {
- printk(KERN_ERR PFX "unable to setup MTRR\n");
- } else {
- default_par->mtrr.vram_valid = 1;
- /* let there be speed */
- printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
- }
- }
-#endif /* CONFIG_MTRR */
+ riva_save_state(rinfo, &rinfo->initial_state);
- if (!nohwcursor) default_par->cursor = rivafb_init_cursor(info);
+ rinfo->ram_amount = rinfo->riva.RamAmountKBytes * 1024;
+ rinfo->dclk_max = rinfo->riva.MaxVClockFreqKHz * 1000;
- info->par = default_par;
+ if (!nohwcursor) rinfo->cursor = rivafb_init_cursor(rinfo);
- if (riva_set_fbinfo(info) < 0) {
+ if (riva_set_fbinfo(rinfo) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor;
}
- if (register_framebuffer(info) < 0) {
+ if (register_framebuffer((struct fb_info *)rinfo) < 0) {
printk(KERN_ERR PFX
"error registering riva framebuffer\n");
goto err_out_load_state;
}
- pci_set_drvdata(pd, info);
+ riva_boards = riva_board_list_add(riva_boards, rinfo);
+
+ pci_set_drvdata(pd, rinfo);
printk(KERN_INFO PFX
- "PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
- default_par->riva.Architecture,
+ "PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
+ rinfo->riva.Architecture,
RIVAFB_VERSION,
- info->fix.id,
- default_par->ram_amount / (1024 * 1024),
- info->fix.smem_start);
+ rinfo->drvr_name,
+ rinfo->ram_amount / (1024 * 1024),
+ rinfo->fb_base_phys);
return 0;
err_out_load_state:
- riva_load_state(default_par, &default_par->initial_state);
+ riva_load_state(rinfo, &rinfo->initial_state);
err_out_cursor:
- rivafb_exit_cursor(default_par);
+ rivafb_exit_cursor(rinfo);
/* err_out_iounmap_fb: */
- iounmap(info->screen_base);
+ iounmap(rinfo->fb_base);
err_out_iounmap_ctrl:
- iounmap(default_par->ctrl_base);
+ iounmap(rinfo->ctrl_base);
err_out_free_base1:
- release_mem_region(info->fix.smem_start, info->fix.smem_len);
+ release_mem_region(rinfo->fb_base_phys, rinfo->base1_region_size);
err_out_free_base0:
- release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+ release_mem_region(rinfo->ctrl_base_phys, rinfo->base0_region_size);
err_out_kfree:
- kfree(default_par);
- kfree(info);
+ kfree(rinfo);
err_out:
return -ENODEV;
}
static void __devexit rivafb_remove_one(struct pci_dev *pd)
{
- struct fb_info *board = pci_get_drvdata(pd);
- struct riva_par *par = (struct riva_par *) board->par;
+ struct rivafb_info *board = pci_get_drvdata(pd);
if (!board)
return;
- riva_load_state(par, &par->initial_state);
+ riva_boards = riva_board_list_del(riva_boards, board);
+
+ riva_load_state(board, &board->initial_state);
- unregister_framebuffer(board);
+ unregister_framebuffer((struct fb_info *)board);
- rivafb_exit_cursor(par);
+ rivafb_exit_cursor(board);
#ifdef CONFIG_MTRR
- if (par->mtrr.vram_valid)
- mtrr_del(par->mtrr.vram, board->fix.smem_start,
- board->fix.smem_len);
+ if (board->mtrr.vram_valid)
+ mtrr_del(board->mtrr.vram, board->fb_base_phys,
+ board->base1_region_size);
#endif /* CONFIG_MTRR */
- iounmap(par->ctrl_base);
- iounmap(board->screen_base);
+ iounmap(board->ctrl_base);
+ iounmap(board->fb_base);
- release_mem_region(board->fix.mmio_start,
- board->fix.mmio_len);
- release_mem_region(board->fix.smem_start,
- board->fix.smem_len);
+ release_mem_region(board->ctrl_base_phys,
+ board->base0_region_size);
+ release_mem_region(board->fb_base_phys,
+ board->base1_region_size);
- kfree(par);
kfree(board);
pci_set_drvdata(pd, NULL);
}
+
+
/* ------------------------------------------------------------------------- *
*
* initialization
@@ -1698,6 +2063,10 @@ int __init rivafb_setup(char *options)
} else if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1;
+ } else if (!strncmp(this_opt, "noaccel", 7)) {
+ noaccel = 1;
+ } else if (!strncmp(this_opt, "nomove", 6)) {
+ nomove = 1;
#ifdef CONFIG_MTRR
} else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1;
@@ -1750,6 +2119,10 @@ module_exit(rivafb_exit);
MODULE_PARM(font, "s");
MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)");
+MODULE_PARM(noaccel, "i");
+MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");
+MODULE_PARM(nomove, "i");
+MODULE_PARM_DESC(nomove, "Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)");
MODULE_PARM(nohwcursor, "i");
MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");
MODULE_PARM(noblink, "i");
diff --git a/drivers/video/riva/riva_hw.c b/drivers/video/riva/riva_hw.c
index b412f99424c9..f6f0f785bf61 100644
--- a/drivers/video/riva/riva_hw.c
+++ b/drivers/video/riva/riva_hw.c
@@ -1220,7 +1220,6 @@ static void CalcStateExt
state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
break;
case NV_ARCH_10:
- case NV_ARCH_20:
nv10UpdateArbitrationSettings(VClk,
pixelDepth * 8,
&(state->arbitration0),
@@ -1286,7 +1285,6 @@ static void UpdateFifoState
chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
break;
case NV_ARCH_10:
- case NV_ARCH_20:
/*
* Initialize state for the RivaTriangle3D05 routines.
*/
@@ -1395,7 +1393,6 @@ static void LoadStateExt
chip->PGRAPH[0x0000067C/4] = state->pitch3;
break;
case NV_ARCH_10:
- case NV_ARCH_20:
LOAD_FIXED_STATE(nv10,PFIFO);
LOAD_FIXED_STATE(nv10,PRAMIN);
LOAD_FIXED_STATE(nv10,PGRAPH);
@@ -1424,31 +1421,15 @@ static void LoadStateExt
chip->Tri03 = 0L;
break;
}
-
- if (chip->Architecture == NV_ARCH_10) {
- chip->PGRAPH[0x00000640/4] = state->offset0;
- chip->PGRAPH[0x00000644/4] = state->offset1;
- chip->PGRAPH[0x00000648/4] = state->offset2;
- chip->PGRAPH[0x0000064C/4] = state->offset3;
- chip->PGRAPH[0x00000670/4] = state->pitch0;
- chip->PGRAPH[0x00000674/4] = state->pitch1;
- chip->PGRAPH[0x00000678/4] = state->pitch2;
- chip->PGRAPH[0x0000067C/4] = state->pitch3;
- chip->PGRAPH[0x00000680/4] = state->pitch3;
- } else {
- chip->PGRAPH[0x00000820/4] = state->offset0;
- chip->PGRAPH[0x00000824/4] = state->offset1;
- chip->PGRAPH[0x00000828/4] = state->offset2;
- chip->PGRAPH[0x0000082C/4] = state->offset3;
- chip->PGRAPH[0x00000850/4] = state->pitch0;
- chip->PGRAPH[0x00000854/4] = state->pitch1;
- chip->PGRAPH[0x00000858/4] = state->pitch2;
- chip->PGRAPH[0x0000085C/4] = state->pitch3;
- chip->PGRAPH[0x00000860/4] = state->pitch3;
- chip->PGRAPH[0x00000864/4] = state->pitch3;
- chip->PGRAPH[0x000009A4/4] = chip->PFB[0x00000200/4];
- chip->PGRAPH[0x000009A8/4] = chip->PFB[0x00000204/4];
- }
+ chip->PGRAPH[0x00000640/4] = state->offset0;
+ chip->PGRAPH[0x00000644/4] = state->offset1;
+ chip->PGRAPH[0x00000648/4] = state->offset2;
+ chip->PGRAPH[0x0000064C/4] = state->offset3;
+ chip->PGRAPH[0x00000670/4] = state->pitch0;
+ chip->PGRAPH[0x00000674/4] = state->pitch1;
+ chip->PGRAPH[0x00000678/4] = state->pitch2;
+ chip->PGRAPH[0x0000067C/4] = state->pitch3;
+ chip->PGRAPH[0x00000680/4] = state->pitch3;
chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
@@ -1626,7 +1607,6 @@ static void UnloadStateExt
state->pitch3 = chip->PGRAPH[0x0000067C/4];
break;
case NV_ARCH_10:
- case NV_ARCH_20:
state->offset0 = chip->PGRAPH[0x00000640/4];
state->offset1 = chip->PGRAPH[0x00000644/4];
state->offset2 = chip->PGRAPH[0x00000648/4];
diff --git a/drivers/video/riva/riva_hw.h b/drivers/video/riva/riva_hw.h
index a51e773a6ced..da27e20a3d2e 100644
--- a/drivers/video/riva/riva_hw.h
+++ b/drivers/video/riva/riva_hw.h
@@ -74,8 +74,6 @@ typedef unsigned int U032;
#define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
-#define NV_ARCH_20 0x20
-
/***************************************************************************\
* *
* FIFO registers. *
diff --git a/drivers/video/riva/rivafb.h b/drivers/video/riva/rivafb.h
index c5be7ce12051..d0e64d2b0211 100644
--- a/drivers/video/riva/rivafb.h
+++ b/drivers/video/riva/rivafb.h
@@ -3,7 +3,6 @@
#include <linux/config.h>
#include <linux/fb.h>
-#include <linux/timer.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
@@ -28,35 +27,58 @@ struct riva_regs {
RIVA_HW_STATE ext;
};
-#define MAX_CURS 32
-
-struct riva_cursor {
- int enable;
- int on;
- int vbl_cnt;
- int last_slice_moves, prev_slice_moves;
- int blink_rate;
- struct {
- u16 x, y;
- } pos, size;
- unsigned short image[MAX_CURS*MAX_CURS];
- struct timer_list *timer;
-};
+typedef struct {
+ unsigned char red, green, blue, transp;
+} riva_cfb8_cmap_t;
+
+struct rivafb_info;
+struct rivafb_info {
+ struct fb_info info; /* kernel framebuffer info */
-/* describes the state of a Riva board */
-struct riva_par {
RIVA_HW_INST riva; /* interface to riva_hw.c */
+ const char *drvr_name; /* Riva hardware board type */
+
+ unsigned long ctrl_base_phys; /* physical control register base addr */
+ unsigned long fb_base_phys; /* physical framebuffer base addr */
+
+ caddr_t ctrl_base; /* virtual control register base addr */
+ caddr_t fb_base; /* virtual framebuffer base addr */
+
unsigned ram_amount; /* amount of RAM on card, in bytes */
unsigned dclk_max; /* max DCLK */
struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state;
+ struct display disp;
+ int currcon;
+ struct display *currcon_display;
+
+ struct rivafb_info *next;
+
+ struct pci_dev *pd; /* pointer to board's pci info */
+ unsigned base0_region_size; /* size of control register region */
+ unsigned base1_region_size; /* size of framebuffer region */
+
struct riva_cursor *cursor;
- caddr_t ctrl_base; /* Virtual control register base addr */
+
+ struct display_switch dispsw;
+
+ riva_cfb8_cmap_t palette[256]; /* VGA DAC palette cache */
+
+#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
+ union {
+#ifdef FBCON_HAS_CFB16
+ u_int16_t cfb16[16];
+#endif
+#ifdef FBCON_HAS_CFB32
+ u_int32_t cfb32[16];
+#endif
+ } con_cmap;
+#endif /* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
#ifdef CONFIG_MTRR
- struct { int vram; int vram_valid; } mtrr;
+ struct { int vram; int vram_valid; } mtrr;
#endif
};
diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c
index ba1fb26f26f1..29f2386eceb6 100644
--- a/drivers/video/sa1100fb.c
+++ b/drivers/video/sa1100fb.c
@@ -661,7 +661,7 @@ static struct sa1100fb_mach_info xp860_info __initdata = {
static struct sa1100fb_mach_info * __init
-sa1100fb_get_machine_info(struct sa1100_par *par)
+sa1100fb_get_machine_info(struct sa1100fb_info *fbi)
{
struct sa1100fb_mach_info *inf = NULL;
@@ -683,7 +683,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_H3XXX
if (machine_is_h3600()) {
inf = &h3600_info;
- par->rgb[RGB_16] = &h3600_rgb_16;
+ fbi->rgb[RGB_16] = &h3600_rgb_16;
}
if (machine_is_h3100()) {
inf = &h3100_info;
@@ -705,7 +705,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_FREEBIRD
if (machine_is_freebird()) {
inf = &freebird_info;
- par->rgb[RGB_16] = &freebird_rgb16;
+ fbi->rgb[RGB_16] = &freebird_rgb16;
}
#endif
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
@@ -758,10 +758,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
if (machine_is_stork()) {
#if STORK_TFT
inf = &stork_tft_info;
- par->rgb[RGB_16] = &stork_tft_rgb_16;
+ fbi->rgb[RGB_16] = &stork_tft_rgb_16;
#else
inf = &stork_dstn_info;
- par->rgb[RGB_16] = &stork_dstn_rgb_16;
+ fbi->rgb[RGB_16] = &stork_dstn_rgb_16;
#endif
}
#endif
@@ -773,10 +773,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
return inf;
}
-static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *);
-static void set_ctrlr_state(struct sa1100_par *par, u_int state);
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);
-static inline void sa1100fb_schedule_task(struct sa1100_par *par, u_int state)
+static inline void sa1100fb_schedule_task(struct sa1100fb_info *fbi, u_int state)
{
unsigned long flags;
@@ -789,18 +789,43 @@ static inline void sa1100fb_schedule_task(struct sa1100_par *par, u_int state)
* 2. When we are blanking, but immediately unblank before we have
* blanked. We do the "REENABLE" thing here as well, just to be sure.
*/
- if (par->task_state == C_ENABLE && state == C_REENABLE)
+ if (fbi->task_state == C_ENABLE && state == C_REENABLE)
state = (u_int) -1;
- if (par->task_state == C_DISABLE && state == C_ENABLE)
+ if (fbi->task_state == C_DISABLE && state == C_ENABLE)
state = C_REENABLE;
if (state != (u_int)-1) {
- par->task_state = state;
- schedule_task(&par->task);
+ fbi->task_state = state;
+ schedule_task(&fbi->task);
}
local_irq_restore(flags);
}
+/*
+ * Get the VAR structure pointer for the specified console
+ */
+static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con)
+{
+ return (con == info->currcon || con == -1) ? &info->var : &fb_display[con].var;
+}
+
+/*
+ * Get the DISPLAY structure pointer for the specified console
+ */
+static inline struct display *get_con_display(struct fb_info *info, int con)
+{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ return (con < 0) ? fbi->fb.disp : &fb_display[con];
+}
+
+/*
+ * Get the CMAP pointer for the specified console
+ */
+static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con)
+{
+ return (con == info->currcon || con == -1) ? &info->cmap : &fb_display[con].cmap;
+}
+
static inline u_int
chan_to_field(u_int chan, struct fb_bitfield *bf)
{
@@ -813,13 +838,19 @@ chan_to_field(u_int chan, struct fb_bitfield *bf)
* Convert bits-per-pixel to a hardware palette PBS value.
*/
static inline u_int
-palette_pbs(int bpp)
+palette_pbs(struct fb_var_screeninfo *var)
{
int ret = 0;
- switch (bpp) {
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
case 4: ret = 0 << 12; break;
+#endif
+#ifdef FBCON_HAS_CFB8
case 8: ret = 1 << 12; break;
+#endif
+#ifdef FBCON_HAS_CFB16
case 16: ret = 2 << 12; break;
+#endif
}
return ret;
}
@@ -828,18 +859,18 @@ static int
sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
- struct sa1100_par *par = (struct sa1100_par *) info->par;
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
u_int val, ret = 1;
- if (regno < par->palette_size) {
+ if (regno < fbi->palette_size) {
val = ((red >> 4) & 0xf00);
val |= ((green >> 8) & 0x0f0);
val |= ((blue >> 12) & 0x00f);
if (regno == 0)
- val |= palette_pbs(info->var.bits_per_pixel);
+ val |= palette_pbs(&fbi->fb.var);
- par->palette_cpu[regno] = val;
+ fbi->palette_cpu[regno] = val;
ret = 0;
}
return ret;
@@ -849,6 +880,8 @@ static int
sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info)
{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct display *disp = get_con_display(info, info->currcon);
u_int val;
int ret = 1;
@@ -857,34 +890,33 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* rather than the register number. The register number
* is what you poke into the framebuffer to produce the
* colour you requested.
- *
- if (inverse) {
+ */
+ if (disp->inverse) {
red = 0xffff - red;
green = 0xffff - green;
blue = 0xffff - blue;
}
- */
/*
* If greyscale is true, then we convert the RGB value
* to greyscale no mater what visual we are using.
*/
- if (info->var.grayscale)
+ if (fbi->fb.var.grayscale)
red = green = blue = (19595 * red + 38470 * green +
7471 * blue) >> 16;
- switch (info->fix.visual) {
+ switch (fbi->fb.disp->visual) {
case FB_VISUAL_TRUECOLOR:
/*
* 12 or 16-bit True Colour. We encode the RGB value
* according to the RGB bitfield information.
*/
if (regno < 16) {
- u16 *pal = info->pseudo_palette;
+ u16 *pal = fbi->fb.pseudo_palette;
- val = chan_to_field(red, &info->var.red);
- val |= chan_to_field(green, &info->var.green);
- val |= chan_to_field(blue, &info->var.blue);
+ val = chan_to_field(red, &fbi->fb.var.red);
+ val |= chan_to_field(green, &fbi->fb.var.green);
+ val |= chan_to_field(blue, &fbi->fb.var.blue);
pal[regno] = val;
ret = 0;
@@ -931,20 +963,19 @@ sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
* bitfields, horizontal timing, vertical timing.
*/
static int
-sa1100fb_check_var(struct fb_var_screeninfo *var,
- struct fb_info *info)
+sa1100fb_validate_var(struct fb_var_screeninfo *var,
+ struct sa1100fb_info *fbi)
{
- struct sa1100_par *par = (struct sa1100_par *) info->par;
- int rgbidx = RGB_16, ret = -EINVAL;
+ int ret = -EINVAL;
if (var->xres < MIN_XRES)
var->xres = MIN_XRES;
if (var->yres < MIN_YRES)
var->yres = MIN_YRES;
- if (var->xres > par->max_xres)
- var->xres = par->max_xres;
- if (var->yres > par->max_yres)
- var->yres = par->max_yres;
+ if (var->xres > fbi->max_xres)
+ var->xres = fbi->max_xres;
+ if (var->yres > fbi->max_yres)
+ var->yres = fbi->max_yres;
var->xres_virtual =
var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
var->yres_virtual =
@@ -952,22 +983,23 @@ sa1100fb_check_var(struct fb_var_screeninfo *var,
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) {
- case 4: rgbidx = RGB_8; ret = 0; break;
- case 8: rgbidx = RGB_8; ret = 0; break;
- case 16: rgbidx = RGB_16; ret = 0; break;
+#ifdef FBCON_HAS_CFB4
+ case 4: ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB8
+ case 8: ret = 0; break;
+#endif
+#ifdef FBCON_HAS_CFB16
+ case 16: ret = 0; break;
+#endif
default:
break;
}
- var->red = par->rgb[rgbidx]->red;
- var->green = par->rgb[rgbidx]->green;
- var->blue = par->rgb[rgbidx]->blue;
- var->transp = par->rgb[rgbidx]->transp;
-
#ifdef CONFIG_CPU_FREQ
printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
sa1100fb_display_dma_period(var),
- cpufreq_get());
+ cpufreq_get(smp_processor_id()));
#endif
return ret;
@@ -994,26 +1026,24 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color)
}
}
-static int
-sa1100fb_set_par(struct fb_info *info)
+static void
+sa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
{
- struct sa1100_par *par = (struct sa1100_par *) info->par;
u_long palette_mem_size;
- par->bpp = info->var.bits_per_pixel;
- par->palette_size = par->bpp == 8 ? 256 : 16;
+ fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
- palette_mem_size = par->palette_size * sizeof(u16);
+ palette_mem_size = fbi->palette_size * sizeof(u16);
DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
- par->palette_cpu = (u16 *)(par->map_cpu + PAGE_SIZE - palette_mem_size);
- par->palette_dma = par->map_dma + PAGE_SIZE - palette_mem_size;
+ fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
+ fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
- fb_set_cmap(&info->cmap, 1, info);
+ fb_set_cmap(&fbi->fb.cmap, 1, &fbi->fb);
/* Set board control register to handle new color depth */
- sa1100fb_set_truecolor(info->var.bits_per_pixel >= 16);
+ sa1100fb_set_truecolor(var->bits_per_pixel >= 16);
#ifdef CONFIG_SA1100_OMNIMETER
#error Do we have to do this here? We already do it at init time.
@@ -1021,31 +1051,210 @@ sa1100fb_set_par(struct fb_info *info)
SetLCDContrast(DefaultLCDContrast);
#endif
- sa1100fb_activate_var(&info->var, info);
+ sa1100fb_activate_var(var, fbi);
+
+ fbi->palette_cpu[0] = (fbi->palette_cpu[0] &
+ 0xcfff) | palette_pbs(var);
+
+}
+
+/*
+ * sa1100fb_set_var():
+ * Set the user defined part of the display for the specified console
+ */
+static int
+sa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con);
+ struct display *display = get_con_display(&fbi->fb, con);
+ int err, chgvar = 0, rgbidx;
+
+ DPRINTK("set_var\n");
+
+ /*
+ * Decode var contents into a par structure, adjusting any
+ * out of range values.
+ */
+ err = sa1100fb_validate_var(var, fbi);
+ if (err)
+ return err;
+
+ if (var->activate & FB_ACTIVATE_TEST)
+ return 0;
+
+ if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)
+ return -EINVAL;
+
+ if (dvar->xres != var->xres)
+ chgvar = 1;
+ if (dvar->yres != var->yres)
+ chgvar = 1;
+ if (dvar->xres_virtual != var->xres_virtual)
+ chgvar = 1;
+ if (dvar->yres_virtual != var->yres_virtual)
+ chgvar = 1;
+ if (dvar->bits_per_pixel != var->bits_per_pixel)
+ chgvar = 1;
+ if (con < 0)
+ chgvar = 0;
- par->palette_cpu[0] = (par->palette_cpu[0] &
- 0xcfff) | palette_pbs(info->var.bits_per_pixel);
-
- switch (info->var.bits_per_pixel) {
+ switch (var->bits_per_pixel) {
+#ifdef FBCON_HAS_CFB4
case 4:
- if (par->cmap_static)
- info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ if (fbi->cmap_static)
+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
else
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- info->fix.line_length = info->var.xres / 2;
+ display->visual = FB_VISUAL_PSEUDOCOLOR;
+ display->line_length = var->xres / 2;
+ display->dispsw = &fbcon_cfb4;
+ rgbidx = RGB_8;
break;
+#endif
+#ifdef FBCON_HAS_CFB8
case 8:
- if (par->cmap_static)
- info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
+ if (fbi->cmap_static)
+ display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
else
- info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
- info->fix.line_length = info->var.xres;
+ display->visual = FB_VISUAL_PSEUDOCOLOR;
+ display->line_length = var->xres;
+ display->dispsw = &fbcon_cfb8;
+ rgbidx = RGB_8;
break;
+#endif
+#ifdef FBCON_HAS_CFB16
case 16:
- info->fix.visual = FB_VISUAL_TRUECOLOR;
- info->fix.line_length = info->var.xres * 2;
+ display->visual = FB_VISUAL_TRUECOLOR;
+ display->line_length = var->xres * 2;
+ display->dispsw = &fbcon_cfb16;
+ display->dispsw_data = fbi->fb.pseudo_palette;
+ rgbidx = RGB_16;
+ break;
+#endif
+ default:
+ rgbidx = 0;
+ display->dispsw = &fbcon_dummy;
break;
}
+
+ display->next_line = display->line_length;
+ display->type = fbi->fb.fix.type;
+ display->type_aux = fbi->fb.fix.type_aux;
+ display->ypanstep = fbi->fb.fix.ypanstep;
+ display->ywrapstep = fbi->fb.fix.ywrapstep;
+ display->can_soft_blank = 1;
+ display->inverse = fbi->cmap_inverse;
+
+ *dvar = *var;
+ dvar->activate &= ~FB_ACTIVATE_ALL;
+
+ /*
+ * Copy the RGB parameters for this display
+ * from the machine specific parameters.
+ */
+ dvar->red = fbi->rgb[rgbidx]->red;
+ dvar->green = fbi->rgb[rgbidx]->green;
+ dvar->blue = fbi->rgb[rgbidx]->blue;
+ dvar->transp = fbi->rgb[rgbidx]->transp;
+
+ DPRINTK("RGBT length = %d:%d:%d:%d\n",
+ dvar->red.length, dvar->green.length, dvar->blue.length,
+ dvar->transp.length);
+
+ DPRINTK("RGBT offset = %d:%d:%d:%d\n",
+ dvar->red.offset, dvar->green.offset, dvar->blue.offset,
+ dvar->transp.offset);
+
+ /*
+ * Update the old var. The fbcon drivers still use this.
+ * Once they are using fbi->fb.var, this can be dropped.
+ */
+ display->var = *dvar;
+
+ /*
+ * If we are setting all the virtual consoles, also set the
+ * defaults used to create new consoles.
+ */
+ if (var->activate & FB_ACTIVATE_ALL)
+ fbi->fb.disp->var = *dvar;
+
+ /*
+ * If the console has changed and the console has defined
+ * a changevar function, call that function.
+ */
+ if (chgvar && info && fbi->fb.changevar)
+ fbi->fb.changevar(con);
+
+ /* If the current console is selected, activate the new var. */
+ if (con != fbi->fb.currcon)
+ return 0;
+
+ sa1100fb_hw_set_var(dvar, fbi);
+
+ return 0;
+}
+
+static int
+__do_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct fb_cmap *dcmap = get_con_cmap(info, con);
+ int err = 0;
+
+ if (con == -1)
+ con = info->currcon;
+
+ /* no colormap allocated? (we always have "this" colour map allocated) */
+ if (con >= 0)
+ err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0);
+
+ if (!err && con == info->currcon)
+ err = fb_set_cmap(cmap, kspc, info);
+
+ if (!err)
+ fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1);
+
+ return err;
+}
+
+static int
+sa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,
+ struct fb_info *info)
+{
+ struct display *disp = get_con_display(info, con);
+
+ if (disp->visual == FB_VISUAL_TRUECOLOR ||
+ disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ return -EINVAL;
+
+ return __do_set_cmap(cmap, kspc, con, info);
+}
+
+static int
+sa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info)
+{
+ struct display *display = get_con_display(info, con);
+
+ *fix = info->fix;
+
+ fix->line_length = display->line_length;
+ fix->visual = display->visual;
+ return 0;
+}
+
+static int
+sa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
+{
+ *var = *get_con_var(info, con);
+ return 0;
+}
+
+static int
+sa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info)
+{
+ struct fb_cmap *dcmap = get_con_cmap(info, con);
+ fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2);
return 0;
}
@@ -1086,21 +1295,21 @@ sa1100fb_set_par(struct fb_info *info)
*/
static int sa1100fb_blank(int blank, struct fb_info *info)
{
- struct sa1100_par *par = (struct sa1100_par *) info->par;
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
int i;
- DPRINTK("sa1100fb_blank: blank=%d fix.id=%s\n", blank,
- info->fix.id);
+ DPRINTK("sa1100fb_blank: blank=%d info->modename=%s\n", blank,
+ fbi->fb.modename);
switch (blank) {
case VESA_POWERDOWN:
case VESA_VSYNC_SUSPEND:
case VESA_HSYNC_SUSPEND:
- if (info->disp->visual == FB_VISUAL_PSEUDOCOLOR ||
- info->disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- for (i = 0; i < par->palette_size; i++)
+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ for (i = 0; i < fbi->palette_size; i++)
sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
- sa1100fb_schedule_task(par, C_DISABLE);
+ sa1100fb_schedule_task(fbi, C_DISABLE);
if (sa1100fb_blank_helper)
sa1100fb_blank_helper(blank);
break;
@@ -1108,31 +1317,84 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
case VESA_NO_BLANKING:
if (sa1100fb_blank_helper)
sa1100fb_blank_helper(blank);
- if (info->disp->visual == FB_VISUAL_PSEUDOCOLOR ||
- info->disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
- fb_set_cmap(&info->cmap, 1, info);
- sa1100fb_schedule_task(par, C_ENABLE);
+ if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
+ fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
+ fb_set_cmap(&fbi->fb.cmap, 1, info);
+ sa1100fb_schedule_task(fbi, C_ENABLE);
}
return 0;
}
static struct fb_ops sa1100fb_ops = {
owner: THIS_MODULE,
- fb_get_fix: gen_get_fix,
- fb_get_var: gen_get_var,
- fb_set_var: gen_set_var,
- fb_get_cmap: gen_get_cmap,
- fb_set_cmap: gen_set_cmap,
- fb_check_var: sa1100fb_check_var,
- fb_set_par: sa1100fb_set_par,
+ fb_get_fix: sa1100fb_get_fix,
+ fb_get_var: sa1100fb_get_var,
+ fb_set_var: sa1100fb_set_var,
+ fb_get_cmap: sa1100fb_get_cmap,
+ fb_set_cmap: sa1100fb_set_cmap,
fb_setcolreg: sa1100fb_setcolreg,
fb_blank: sa1100fb_blank,
- fb_fillrect: cfb_fillrect,
- fb_copyarea: cfb_copyarea,
- fb_imageblit: cfb_imageblit,
};
/*
+ * sa1100fb_switch():
+ * Change to the specified console. Palette and video mode
+ * are changed to the console's stored parameters.
+ *
+ * Uh oh, this can be called from a tasklet (IRQ)
+ */
+static int sa1100fb_switch(int con, struct fb_info *info)
+{
+ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info;
+ struct display *disp;
+ struct fb_cmap *cmap;
+
+ DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename);
+
+ if (con == info->currcon)
+ return 0;
+
+ if (info->currcon >= 0) {
+ disp = fb_display + info->currcon;
+
+ /*
+ * Save the old colormap and video mode.
+ */
+ disp->var = fbi->fb.var;
+
+ if (disp->cmap.len)
+ fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0);
+ }
+
+ info->currcon = con;
+ disp = fb_display + con;
+
+ /*
+ * Make sure that our colourmap contains 256 entries.
+ */
+ fb_alloc_cmap(&fbi->fb.cmap, 256, 0);
+
+ if (disp->cmap.len)
+ cmap = &disp->cmap;
+ else
+ cmap = fb_default_cmap(1 << disp->var.bits_per_pixel);
+
+ fb_copy_cmap(cmap, &fbi->fb.cmap, 0);
+
+ fbi->fb.var = disp->var;
+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
+
+ sa1100fb_set_var(&fbi->fb.var, con, info);
+ return 0;
+}
+
+static int sa1100fb_updatevar(int con, struct fb_info *info)
+{
+ DPRINTK("entered\n");
+ return 0;
+}
+
+/*
* Calculate the PCD value from the clock rate (in picoseconds).
* We take account of the PPCR clock setting.
*/
@@ -1141,7 +1403,7 @@ static inline int get_pcd(unsigned int pixclock)
unsigned int pcd;
if (pixclock) {
- pcd = cpufreq_get() / 100;
+ pcd = cpufreq_get(0) / 100;
pcd *= pixclock;
pcd /= 10000000;
pcd += 1; /* make up for integer math truncations */
@@ -1171,9 +1433,8 @@ static inline int get_pcd(unsigned int pixclock)
* Configures LCD Controller based on entries in var parameter. Settings are
* only written to the controller if changes were made.
*/
-static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
+static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi)
{
- struct sa1100_par *par = (struct sa1100_par *) info->par;
struct sa1100fb_lcd_reg new_regs;
u_int half_screen_size, yres, pcd = get_pcd(var->pixclock);
u_long flags;
@@ -1190,31 +1451,31 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
#if DEBUG_VAR
if (var->xres < 16 || var->xres > 1024)
printk(KERN_ERR "%s: invalid xres %d\n",
- info->fix.id, var->xres);
+ fbi->fb.fix.id, var->xres);
if (var->hsync_len < 1 || var->hsync_len > 64)
printk(KERN_ERR "%s: invalid hsync_len %d\n",
- info->fix.id, var->hsync_len);
+ fbi->fb.fix.id, var->hsync_len);
if (var->left_margin < 1 || var->left_margin > 255)
printk(KERN_ERR "%s: invalid left_margin %d\n",
- info->fix.id, var->left_margin);
+ fbi->fb.fix.id, var->left_margin);
if (var->right_margin < 1 || var->right_margin > 255)
printk(KERN_ERR "%s: invalid right_margin %d\n",
- info->fix.id, var->right_margin);
+ fbi->fb.fix.id, var->right_margin);
if (var->yres < 1 || var->yres > 1024)
printk(KERN_ERR "%s: invalid yres %d\n",
- info->fix.id, var->yres);
+ fbi->fb.fix.id, var->yres);
if (var->vsync_len < 1 || var->vsync_len > 64)
printk(KERN_ERR "%s: invalid vsync_len %d\n",
- info->fix.id, var->vsync_len);
+ fbi->fb.fix.id, var->vsync_len);
if (var->upper_margin < 0 || var->upper_margin > 255)
printk(KERN_ERR "%s: invalid upper_margin %d\n",
- info->fix.id, var->upper_margin);
+ fbi->fb.fix.id, var->upper_margin);
if (var->lower_margin < 0 || var->lower_margin > 255)
printk(KERN_ERR "%s: invalid lower_margin %d\n",
- info->fix.id, var->lower_margin);
+ fbi->fb.fix.id, var->lower_margin);
#endif
- new_regs.lccr0 = par->lccr0 |
+ new_regs.lccr0 = fbi->lccr0 |
LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
@@ -1229,7 +1490,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
* the YRES parameter.
*/
yres = var->yres;
- if (par->lccr0 & LCCR0_Dual)
+ if (fbi->lccr0 & LCCR0_Dual)
yres /= 2;
new_regs.lccr2 =
@@ -1238,7 +1499,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
LCCR2_BegFrmDel(var->upper_margin) +
LCCR2_EndFrmDel(var->lower_margin);
- new_regs.lccr3 = par->lccr3 |
+ new_regs.lccr3 = fbi->lccr3 |
(var->sync & FB_SYNC_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
LCCR3_ACBsCntOff;
@@ -1256,23 +1517,23 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
/* Update shadow copy atomically */
local_irq_save(flags);
- par->dbar1 = par->palette_dma;
- par->dbar2 = par->screen_dma + half_screen_size;
+ fbi->dbar1 = fbi->palette_dma;
+ fbi->dbar2 = fbi->screen_dma + half_screen_size;
- par->reg_lccr0 = new_regs.lccr0;
- par->reg_lccr1 = new_regs.lccr1;
- par->reg_lccr2 = new_regs.lccr2;
- par->reg_lccr3 = new_regs.lccr3;
+ fbi->reg_lccr0 = new_regs.lccr0;
+ fbi->reg_lccr1 = new_regs.lccr1;
+ fbi->reg_lccr2 = new_regs.lccr2;
+ fbi->reg_lccr3 = new_regs.lccr3;
local_irq_restore(flags);
/*
* Only update the registers if the controller is enabled
* and something has changed.
*/
- if ((LCCR0 != par->reg_lccr0) || (LCCR1 != par->reg_lccr1) ||
- (LCCR2 != par->reg_lccr2) || (LCCR3 != par->reg_lccr3) ||
- (DBAR1 != par->dbar1) || (DBAR2 != par->dbar2))
- sa1100fb_schedule_task(par, C_REENABLE);
+ if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
+ (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
+ (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
+ sa1100fb_schedule_task(fbi, C_REENABLE);
return 0;
}
@@ -1289,7 +1550,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
-static inline void sa1100fb_backlight_on(struct sa1100_par *par)
+static inline void sa1100fb_backlight_on(struct sa1100fb_info *fbi)
{
DPRINTK("backlight on\n");
@@ -1302,7 +1563,7 @@ static inline void sa1100fb_backlight_on(struct sa1100_par *par)
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
-static inline void sa1100fb_backlight_off(struct sa1100_par *par)
+static inline void sa1100fb_backlight_off(struct sa1100fb_info *fbi)
{
DPRINTK("backlight off\n");
@@ -1310,7 +1571,7 @@ static inline void sa1100fb_backlight_off(struct sa1100_par *par)
sa1100fb_backlight_power(0);
}
-static inline void sa1100fb_power_up_lcd(struct sa1100_par *par)
+static inline void sa1100fb_power_up_lcd(struct sa1100fb_info *fbi)
{
DPRINTK("LCD power on\n");
@@ -1325,7 +1586,7 @@ static inline void sa1100fb_power_up_lcd(struct sa1100_par *par)
#endif
}
-static inline void sa1100fb_power_down_lcd(struct sa1100_par *par)
+static inline void sa1100fb_power_down_lcd(struct sa1100fb_info *fbi)
{
DPRINTK("LCD power off\n");
@@ -1340,7 +1601,7 @@ static inline void sa1100fb_power_down_lcd(struct sa1100_par *par)
#endif
}
-static void sa1100fb_setup_gpio(struct sa1100_par *par)
+static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
{
u_int mask = 0;
@@ -1356,12 +1617,12 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par)
* clear LDD15 to 12 for 4 or 8bpp modes with active
* panels.
*/
- if ((par->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
- (par->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
+ if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
+ (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
- if (par->bpp > 8 ||
- (par->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
+ if (fbi->fb.var.bits_per_pixel > 8 ||
+ (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
}
@@ -1405,23 +1666,23 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par)
}
}
-static void sa1100fb_enable_controller(struct sa1100_par *par)
+static void sa1100fb_enable_controller(struct sa1100fb_info *fbi)
{
DPRINTK("Enabling LCD controller\n");
/*
* Make sure the mode bits are present in the first palette entry
*/
- par->palette_cpu[0] &= 0xcfff;
- par->palette_cpu[0] |= palette_pbs(par->bpp);
+ fbi->palette_cpu[0] &= 0xcfff;
+ fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
/* Sequence from 11.7.10 */
- LCCR3 = par->reg_lccr3;
- LCCR2 = par->reg_lccr2;
- LCCR1 = par->reg_lccr1;
- LCCR0 = par->reg_lccr0 & ~LCCR0_LEN;
- DBAR1 = par->dbar1;
- DBAR2 = par->dbar2;
+ LCCR3 = fbi->reg_lccr3;
+ LCCR2 = fbi->reg_lccr2;
+ LCCR1 = fbi->reg_lccr1;
+ LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
+ DBAR1 = fbi->dbar1;
+ DBAR2 = fbi->dbar2;
LCCR0 |= LCCR0_LEN;
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
@@ -1447,7 +1708,7 @@ static void sa1100fb_enable_controller(struct sa1100_par *par)
DPRINTK("LCCR3 = 0x%08x\n", LCCR3);
}
-static void sa1100fb_disable_controller(struct sa1100_par *par)
+static void sa1100fb_disable_controller(struct sa1100fb_info *fbi)
{
DECLARE_WAITQUEUE(wait, current);
@@ -1481,7 +1742,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
GPCR |= SHANNON_GPIO_DISP_EN;
}
- add_wait_queue(&par->ctrlr_wait, &wait);
+ add_wait_queue(&fbi->ctrlr_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE);
LCSR = 0xffffffff; /* Clear LCD Status Register */
@@ -1490,7 +1751,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
schedule_timeout(20 * HZ / 1000);
current->state = TASK_RUNNING;
- remove_wait_queue(&par->ctrlr_wait, &wait);
+ remove_wait_queue(&fbi->ctrlr_wait, &wait);
}
/*
@@ -1498,12 +1759,12 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
*/
static void sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
{
- struct sa1100_par *par = dev_id;
+ struct sa1100fb_info *fbi = dev_id;
unsigned int lcsr = LCSR;
if (lcsr & LCSR_LDD) {
LCCR0 |= LCCR0_LDM;
- wake_up(&par->ctrlr_wait);
+ wake_up(&fbi->ctrlr_wait);
}
LCSR = lcsr;
@@ -1514,13 +1775,13 @@ static void sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
* sleep when disabling the LCD controller, or if we get two contending
* processes trying to alter state.
*/
-static void set_ctrlr_state(struct sa1100_par *par, u_int state)
+static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state)
{
u_int old_state;
- down(&par->ctrlr_sem);
+ down(&fbi->ctrlr_sem);
- old_state = par->state;
+ old_state = fbi->state;
switch (state) {
case C_DISABLE_CLKCHANGE:
@@ -1529,8 +1790,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* controller is already disabled, then do nothing.
*/
if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
- par->state = state;
- sa1100fb_disable_controller(par);
+ fbi->state = state;
+ sa1100fb_disable_controller(fbi);
}
break;
@@ -1540,12 +1801,12 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* Disable controller
*/
if (old_state != C_DISABLE) {
- par->state = state;
+ fbi->state = state;
- sa1100fb_backlight_off(par);
+ sa1100fb_backlight_off(fbi);
if (old_state != C_DISABLE_CLKCHANGE)
- sa1100fb_disable_controller(par);
- sa1100fb_power_down_lcd(par);
+ sa1100fb_disable_controller(fbi);
+ sa1100fb_power_down_lcd(fbi);
}
break;
@@ -1555,8 +1816,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* do this if we were disabled for the clock change.
*/
if (old_state == C_DISABLE_CLKCHANGE) {
- par->state = C_ENABLE;
- sa1100fb_enable_controller(par);
+ fbi->state = C_ENABLE;
+ sa1100fb_enable_controller(fbi);
}
break;
@@ -1567,9 +1828,9 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* registers.
*/
if (old_state == C_ENABLE) {
- sa1100fb_disable_controller(par);
- sa1100fb_setup_gpio(par);
- sa1100fb_enable_controller(par);
+ sa1100fb_disable_controller(fbi);
+ sa1100fb_setup_gpio(fbi);
+ sa1100fb_enable_controller(fbi);
}
break;
@@ -1589,15 +1850,15 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* turn on the backlight.
*/
if (old_state != C_ENABLE) {
- par->state = C_ENABLE;
- sa1100fb_setup_gpio(par);
- sa1100fb_power_up_lcd(par);
- sa1100fb_enable_controller(par);
- sa1100fb_backlight_on(par);
+ fbi->state = C_ENABLE;
+ sa1100fb_setup_gpio(fbi);
+ sa1100fb_power_up_lcd(fbi);
+ sa1100fb_enable_controller(fbi);
+ sa1100fb_backlight_on(fbi);
}
break;
}
- up(&par->ctrlr_sem);
+ up(&fbi->ctrlr_sem);
}
/*
@@ -1606,12 +1867,10 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
*/
static void sa1100fb_task(void *dummy)
{
- struct fb_info *info = dummy;
- struct sa1100_par *par = (struct sa1100_par *) info->par;
+ struct sa1100fb_info *fbi = dummy;
+ u_int state = xchg(&fbi->task_state, -1);
- u_int state = xchg(&par->task_state, -1);
-
- set_ctrlr_state(par, state);
+ set_ctrlr_state(fbi, state);
}
#ifdef CONFIG_CPU_FREQ
@@ -1620,7 +1879,7 @@ static void sa1100fb_task(void *dummy)
* This, together with the SDRAM bandwidth defines the slowest CPU
* frequency that can be selected.
*/
-static unsigned int sa1100fb_min_dma_period(struct fb_info *info)
+static unsigned int sa1100fb_min_dma_period(struct sa1100fb_info *fbi)
{
unsigned int min_period = (unsigned int)-1;
int i;
@@ -1631,13 +1890,13 @@ static unsigned int sa1100fb_min_dma_period(struct fb_info *info)
/*
* Do we own this display?
*/
- if (fb_display[i].fb_info != info)
+ if (fb_display[i].fb_info != &fbi->fb)
continue;
/*
* Ok, calculate its DMA period
*/
- period = sa1100fb_display_dma_period(&info->var);
+ period = sa1100fb_display_dma_period(get_con_var(&fbi->fb, i));
if (period < min_period)
min_period = period;
}
@@ -1654,27 +1913,26 @@ static int
sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
void *data)
{
- struct fb_info *info = TO_INF(nb, clockchg);
- struct sa1100_par *par = (struct sa1100_par *) info->par;
- struct cpufreq_freqs *mm = data;
+ struct sa1100fb_info *fbi = TO_INF(nb, clockchg);
+ struct cpufreq_minmax *mm = data;
u_int pcd;
switch (val) {
case CPUFREQ_MINMAX:
printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, "
- "new clock %d kHz\n", sa1100fb_min_dma_period(info),
- mm->cur, mm->new);
+ "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
+ mm->cur_freq, mm->new_freq);
/* todo: fill in min/max values */
break;
case CPUFREQ_PRECHANGE:
- set_ctrlr_state(par, C_DISABLE_CLKCHANGE);
+ set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
break;
case CPUFREQ_POSTCHANGE:
- pcd = get_pcd(info->var.pixclock);
- par->reg_lccr3 = (par->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
- set_ctrlr_state(par, C_ENABLE_CLKCHANGE);
+ pcd = get_pcd(fbi->fb.var.pixclock);
+ fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
+ set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
break;
}
return 0;
@@ -1689,7 +1947,7 @@ sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
static int
sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
{
- struct sa1100_par *par = pm_dev->data;
+ struct sa1100fb_info *fbi = pm_dev->data;
DPRINTK("pm_callback: %d\n", req);
@@ -1698,10 +1956,10 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
if (state == 0) {
/* Enter D0. */
- set_ctrlr_state(par, C_ENABLE_PM);
+ set_ctrlr_state(fbi, C_ENABLE_PM);
} else {
/* Enter D1-D3. Disable the LCD controller. */
- set_ctrlr_state(par, C_DISABLE_PM);
+ set_ctrlr_state(fbi, C_DISABLE_PM);
}
}
DPRINTK("done\n");
@@ -1717,142 +1975,133 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
-static int __init sa1100fb_map_video_memory(struct fb_info *info)
+static int __init sa1100fb_map_video_memory(struct sa1100fb_info *fbi)
{
- struct sa1100_par *par= (struct sa1100_par *) info->par;
/*
* We reserve one page for the palette, plus the size
* of the framebuffer.
*/
- par->map_size = PAGE_ALIGN(info->fix.smem_len + PAGE_SIZE);
- par->map_cpu = consistent_alloc(GFP_KERNEL, par->map_size,
- &par->map_dma);
-
- if (par->map_cpu) {
- info->screen_base = par->map_cpu + PAGE_SIZE;
- par->screen_dma = par->map_dma + PAGE_SIZE;
- info->fix.smem_start = par->screen_dma;
+ fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
+ fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
+ &fbi->map_dma);
+
+ if (fbi->map_cpu) {
+ fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
+ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
+ fbi->fb.fix.smem_start = fbi->screen_dma;
}
- return par->map_cpu ? 0 : -ENOMEM;
+ return fbi->map_cpu ? 0 : -ENOMEM;
}
-/* Fake monspecs to fill in infonfo structure */
+/* Fake monspecs to fill in fbinfo structure */
static struct fb_monspecs monspecs __initdata = {
30000, 70000, 50, 65, 0 /* Generic */
};
-static struct fb_info * __init sa1100fb_init_fbinfo(void)
+static struct sa1100fb_info * __init sa1100fb_init_fbinfo(void)
{
struct sa1100fb_mach_info *inf;
- struct fb_info *info;
- struct sa1100_par *par;
+ struct sa1100fb_info *fbi;
- info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) +
+ fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(struct display) +
sizeof(u16) * 16, GFP_KERNEL);
- if (!info)
+ if (!fbi)
return NULL;
- memset(info, 0, sizeof(struct fb_info) + sizeof(struct display));
-
- par = kmalloc(sizeof(struct sa1100_par), GFP_KERNEL);
- memset(par, 0, sizeof(struct sa1100_par));
-
- info->currcon = -1;
-
- strcpy(info->fix.id, SA1100_NAME);
-
- info->fix.type = FB_TYPE_PACKED_PIXELS;
- info->fix.type_aux = 0;
- info->fix.xpanstep = 0;
- info->fix.ypanstep = 0;
- info->fix.ywrapstep = 0;
- info->fix.accel = FB_ACCEL_NONE;
-
- info->var.nonstd = 0;
- info->var.activate = FB_ACTIVATE_NOW;
- info->var.height = -1;
- info->var.width = -1;
- info->var.accel_flags = 0;
- info->var.vmode = FB_VMODE_NONINTERLACED;
-
- strcpy(info->modename, info->fix.id);
- strcpy(info->fontname, "Acorn8x8");
-
- info->fbops = &sa1100fb_ops;
- info->changevar = NULL;
- info->switch_con = gen_switch;
- info->updatevar = gen_update_var;
- info->flags = FBINFO_FLAG_DEFAULT;
- info->node = NODEV;
- info->monspecs = monspecs;
- info->currcon = -1;
- info->disp = (struct display *)(info + 1);
- info->pseudo_palette = (void *)(info->disp + 1);
- info->par = par;
-
- par->rgb[RGB_8] = &rgb_8;
- par->rgb[RGB_16] = &def_rgb_16;
-
- inf = sa1100fb_get_machine_info(par);
-
- par->max_xres = inf->xres;
- info->var.xres = inf->xres;
- info->var.xres_virtual = inf->xres;
- par->max_yres = inf->yres;
- info->var.yres = inf->yres;
- info->var.yres_virtual = inf->yres;
- par->max_bpp = inf->bpp;
- info->var.bits_per_pixel = inf->bpp;
- info->var.pixclock = inf->pixclock;
- info->var.hsync_len = inf->hsync_len;
- info->var.left_margin = inf->left_margin;
- info->var.right_margin = inf->right_margin;
- info->var.vsync_len = inf->vsync_len;
- info->var.upper_margin = inf->upper_margin;
- info->var.lower_margin = inf->lower_margin;
- info->var.sync = inf->sync;
- info->var.grayscale = inf->cmap_greyscale;
- par->cmap_inverse = inf->cmap_inverse;
- par->cmap_static = inf->cmap_static;
- par->lccr0 = inf->lccr0;
- par->lccr3 = inf->lccr3;
- par->state = C_DISABLE;
- par->task_state = (u_char)-1;
- info->fix.smem_len = par->max_xres * par->max_yres *
- par->max_bpp / 8;
-
- init_waitqueue_head(&par->ctrlr_wait);
- INIT_TQUEUE(&par->task, sa1100fb_task, info);
- init_MUTEX(&par->ctrlr_sem);
-
- fb_alloc_cmap(&info->cmap, 256, 0);
-
- return info;
+ memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display));
+
+ fbi->fb.currcon = -1;
+
+ strcpy(fbi->fb.fix.id, SA1100_NAME);
+
+ fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
+ fbi->fb.fix.type_aux = 0;
+ fbi->fb.fix.xpanstep = 0;
+ fbi->fb.fix.ypanstep = 0;
+ fbi->fb.fix.ywrapstep = 0;
+ fbi->fb.fix.accel = FB_ACCEL_NONE;
+
+ fbi->fb.var.nonstd = 0;
+ fbi->fb.var.activate = FB_ACTIVATE_NOW;
+ fbi->fb.var.height = -1;
+ fbi->fb.var.width = -1;
+ fbi->fb.var.accel_flags = 0;
+ fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
+
+ strcpy(fbi->fb.modename, SA1100_NAME);
+ strcpy(fbi->fb.fontname, "Acorn8x8");
+
+ fbi->fb.fbops = &sa1100fb_ops;
+ fbi->fb.changevar = NULL;
+ fbi->fb.switch_con = sa1100fb_switch;
+ fbi->fb.updatevar = sa1100fb_updatevar;
+ fbi->fb.flags = FBINFO_FLAG_DEFAULT;
+ fbi->fb.node = NODEV;
+ fbi->fb.monspecs = monspecs;
+ fbi->fb.currcon = -1;
+ fbi->fb.disp = (struct display *)(fbi + 1);
+ fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
+
+ fbi->rgb[RGB_8] = &rgb_8;
+ fbi->rgb[RGB_16] = &def_rgb_16;
+
+ inf = sa1100fb_get_machine_info(fbi);
+
+ fbi->max_xres = inf->xres;
+ fbi->fb.var.xres = inf->xres;
+ fbi->fb.var.xres_virtual = inf->xres;
+ fbi->max_yres = inf->yres;
+ fbi->fb.var.yres = inf->yres;
+ fbi->fb.var.yres_virtual = inf->yres;
+ fbi->max_bpp = inf->bpp;
+ fbi->fb.var.bits_per_pixel = inf->bpp;
+ fbi->fb.var.pixclock = inf->pixclock;
+ fbi->fb.var.hsync_len = inf->hsync_len;
+ fbi->fb.var.left_margin = inf->left_margin;
+ fbi->fb.var.right_margin = inf->right_margin;
+ fbi->fb.var.vsync_len = inf->vsync_len;
+ fbi->fb.var.upper_margin = inf->upper_margin;
+ fbi->fb.var.lower_margin = inf->lower_margin;
+ fbi->fb.var.sync = inf->sync;
+ fbi->fb.var.grayscale = inf->cmap_greyscale;
+ fbi->cmap_inverse = inf->cmap_inverse;
+ fbi->cmap_static = inf->cmap_static;
+ fbi->lccr0 = inf->lccr0;
+ fbi->lccr3 = inf->lccr3;
+ fbi->state = C_DISABLE;
+ fbi->task_state = (u_char)-1;
+ fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
+ fbi->max_bpp / 8;
+
+ init_waitqueue_head(&fbi->ctrlr_wait);
+ INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi);
+ init_MUTEX(&fbi->ctrlr_sem);
+
+ return fbi;
}
int __init sa1100fb_init(void)
{
- struct fb_info *info;
- struct sa1100_par *par;
+ struct sa1100fb_info *fbi;
int ret;
if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY;
- info = sa1100fb_init_fbinfo();
+ fbi = sa1100fb_init_fbinfo();
ret = -ENOMEM;
- if (!info)
+ if (!fbi)
goto failed;
/* Initialize video memory */
- ret = sa1100fb_map_video_memory(info);
+ ret = sa1100fb_map_video_memory(fbi);
if (ret)
goto failed;
ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
- "LCD", info->par);
+ "LCD", fbi);
if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
goto failed;
@@ -1873,32 +2122,30 @@ int __init sa1100fb_init(void)
}
#endif
- gen_set_var(&info->var, -1, info);
+ sa1100fb_set_var(&fbi->fb.var, -1, &fbi->fb);
- ret = register_framebuffer(info);
+ ret = register_framebuffer(&fbi->fb);
if (ret < 0)
goto failed;
- par = info->par;
-
#ifdef CONFIG_PM
/*
* Note that the console registers this as well, but we want to
* power down the display prior to sleeping.
*/
- par->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
- if (par->pm)
- par->pm->data = par;
+ fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
+ if (fbi->pm)
+ fbi->pm->data = fbi;
#endif
#ifdef CONFIG_CPU_FREQ
- info->clockchg.notifier_call = sa1100fb_clkchg_notifier;
- cpufreq_register_notifier(&info->clockchg);
+ fbi->clockchg.notifier_call = sa1100fb_clkchg_notifier;
+ cpufreq_register_notifier(&fbi->clockchg);
#endif
/*
* Ok, now enable the LCD controller
*/
- set_ctrlr_state(par, C_ENABLE);
+ set_ctrlr_state(fbi, C_ENABLE);
/* This driver cannot be unloaded at the moment */
MOD_INC_USE_COUNT;
@@ -1906,8 +2153,8 @@ int __init sa1100fb_init(void)
return 0;
failed:
- if (info)
- kfree(info);
+ if (fbi)
+ kfree(fbi);
release_mem_region(0xb0100000, 0x10000);
return ret;
}
diff --git a/drivers/video/sa1100fb.h b/drivers/video/sa1100fb.h
index 8b04a889ba64..96e79705be5c 100644
--- a/drivers/video/sa1100fb.h
+++ b/drivers/video/sa1100fb.h
@@ -61,13 +61,13 @@ struct sa1100fb_lcd_reg {
#define RGB_16 (1)
#define NR_RGB 2
-struct sa1100_par {
+struct sa1100fb_info {
+ struct fb_info fb;
struct sa1100fb_rgb *rgb[NR_RGB];
+ u_int max_bpp;
u_int max_xres;
u_int max_yres;
- u_int max_bpp;
- u_int bpp;
/*
* These are the addresses we mapped
@@ -86,13 +86,12 @@ struct sa1100_par {
dma_addr_t dbar1;
dma_addr_t dbar2;
+ u_int lccr0;
+ u_int lccr3;
u_int cmap_inverse:1,
cmap_static:1,
unused:30;
- u_int lccr0;
- u_int lccr3;
-
u_int reg_lccr0;
u_int reg_lccr1;
u_int reg_lccr2;
@@ -103,14 +102,18 @@ struct sa1100_par {
struct semaphore ctrlr_sem;
wait_queue_head_t ctrlr_wait;
struct tq_struct task;
+
#ifdef CONFIG_PM
struct pm_dev *pm;
#endif
+#ifdef CONFIG_CPU_FREQ
+ struct notifier_block clockchg;
+#endif
};
#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
-#define TO_INF(ptr,member) __type_entry(ptr, struct fb_info, member)
+#define TO_INF(ptr,member) __type_entry(ptr,struct sa1100fb_info,member)
#define SA1100_PALETTE_MODE_VAL(bpp) (((bpp) & 0x018) << 9)