Commit 2eaf7c63 authored by James Simmons's avatar James Simmons

Port step some changes at authors request.

parent 8ef1bf6d
This source diff could not be displayed because it is too large. You can view the blob instead.
/* /*
* 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> * Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
* *
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
* Known bugs and issues: * Known bugs and issues:
* restoring text mode fails * restoring text mode fails
* doublescan modes are broken * doublescan modes are broken
* option 'noaccel' has no effect
*/ */
#include <linux/config.h> #include <linux/config.h>
...@@ -51,10 +52,12 @@ ...@@ -51,10 +52,12 @@
#error This driver requires PCI support. #error This driver requires PCI support.
#endif #endif
#include "../fbcon-accel.h"
/* version number of this driver */ /* version number of this driver */
#define RIVAFB_VERSION "0.9.3" #define RIVAFB_VERSION "0.9.2a"
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
...@@ -88,8 +91,8 @@ ...@@ -88,8 +91,8 @@
#define Set8Bits(value) ((value)&0xff) #define Set8Bits(value) ((value)&0xff)
/* HW cursor parameters */ /* HW cursor parameters */
#define DEFAULT_CURSOR_BLINK_RATE (20) #define DEFAULT_CURSOR_BLINK_RATE (40)
#define CURSOR_HIDE_DELAY (10) #define CURSOR_HIDE_DELAY (20)
#define CURSOR_SHOW_DELAY (3) #define CURSOR_SHOW_DELAY (3)
#define CURSOR_COLOR 0x7fff #define CURSOR_COLOR 0x7fff
...@@ -97,6 +100,7 @@ ...@@ -97,6 +100,7 @@
#define MAX_CURS 32 #define MAX_CURS 32
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* prototypes * prototypes
...@@ -105,6 +109,11 @@ ...@@ -105,6 +109,11 @@
static int rivafb_blank(int blank, struct fb_info *info); 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 * card identification
...@@ -127,11 +136,6 @@ enum riva_chips { ...@@ -127,11 +136,6 @@ enum riva_chips {
CH_GEFORCE2_GTS, CH_GEFORCE2_GTS,
CH_GEFORCE2_ULTRA, CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO, CH_QUADRO2_PRO,
CH_GEFORCE2_GO,
CH_GEFORCE3,
CH_GEFORCE3_1,
CH_GEFORCE3_2,
CH_QUADRO_DDC
}; };
/* directly indexed by riva_chips enum, above */ /* directly indexed by riva_chips enum, above */
...@@ -154,11 +158,6 @@ static struct riva_chip_info { ...@@ -154,11 +158,6 @@ static struct riva_chip_info {
{ "GeForce2-GTS", NV_ARCH_10}, { "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", NV_ARCH_10}, { "GeForce2-ULTRA", NV_ARCH_10},
{ "Quadro2-PRO", 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 = { static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
...@@ -196,30 +195,64 @@ 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_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_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 */ { 0, } /* terminate list */
}; };
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl); 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 * global variables
* *
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
struct fb_info *riva_boards = NULL; struct rivafb_info *riva_boards = NULL;
/* command line data, set in rivafb_setup() */ /* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 }; static char fontname[40] __initdata = { 0 };
static char noaccel __initdata = 0;
static char nomove = 0;
static char nohwcursor __initdata = 0; static char nohwcursor __initdata = 0;
static char noblink = 0; static char noblink = 0;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
...@@ -232,26 +265,24 @@ static char *mode_option __initdata = NULL; ...@@ -232,26 +265,24 @@ static char *mode_option __initdata = NULL;
static char *font = NULL; static char *font = NULL;
#endif #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 = { static struct fb_var_screeninfo rivafb_default_var = {
xres: 640, xres: 640,
yres: 480, yres: 480,
xres_virtual: 640, xres_virtual: 640,
yres_virtual: 480, yres_virtual: 480,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 8, bits_per_pixel: 8,
grayscale: 0,
red: {0, 6, 0}, red: {0, 6, 0},
green: {0, 6, 0}, green: {0, 6, 0},
blue: {0, 6, 0}, blue: {0, 6, 0},
activate: FB_ACTIVATE_NOW, transp: {0, 0, 0},
nonstd: 0,
activate: 0,
height: -1, height: -1,
width: -1, width: -1,
accel_flags: FB_ACCELF_TEXT, accel_flags: 0,
pixclock: 39721, pixclock: 39721,
left_margin: 40, left_margin: 40,
right_margin: 24, right_margin: 24,
...@@ -259,28 +290,10 @@ static struct fb_var_screeninfo rivafb_default_var = { ...@@ -259,28 +290,10 @@ static struct fb_var_screeninfo rivafb_default_var = {
lower_margin: 11, lower_margin: 11,
hsync_len: 96, hsync_len: 96,
vsync_len: 2, vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED 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 */ /* from GGI */
static const struct riva_regs reg_template = { static const struct riva_regs reg_template = {
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */ {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
...@@ -302,76 +315,78 @@ static const struct riva_regs reg_template = { ...@@ -302,76 +315,78 @@ static const struct riva_regs reg_template = {
0xEB /* MISC */ 0xEB /* MISC */
}; };
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* MMIO access macros * 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) unsigned char val)
{ {
VGA_WR08(par->riva.PCIO, 0x3d4, index); VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
VGA_WR08(par->riva.PCIO, 0x3d5, val); 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) unsigned char index)
{ {
VGA_WR08(par->riva.PCIO, 0x3d4, index); VGA_WR08(rinfo->riva.PCIO, 0x3d4, index);
return (VGA_RD08(par->riva.PCIO, 0x3d5)); 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) unsigned char val)
{ {
VGA_WR08(par->riva.PVIO, 0x3ce, index); VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
VGA_WR08(par->riva.PVIO, 0x3cf, val); 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) unsigned char index)
{ {
VGA_WR08(par->riva.PVIO, 0x3ce, index); VGA_WR08(rinfo->riva.PVIO, 0x3ce, index);
return (VGA_RD08(par->riva.PVIO, 0x3cf)); 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) unsigned char val)
{ {
VGA_WR08(par->riva.PVIO, 0x3c4, index); VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
VGA_WR08(par->riva.PVIO, 0x3c5, val); 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) unsigned char index)
{ {
VGA_WR08(par->riva.PVIO, 0x3c4, index); VGA_WR08(rinfo->riva.PVIO, 0x3c4, index);
return (VGA_RD08(par->riva.PVIO, 0x3c5)); 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) unsigned char val)
{ {
VGA_WR08(par->riva.PCIO, 0x3c0, index); VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
VGA_WR08(par->riva.PCIO, 0x3c0, val); 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) unsigned char index)
{ {
VGA_WR08(par->riva.PCIO, 0x3c0, index); VGA_WR08(rinfo->riva.PCIO, 0x3c0, index);
return (VGA_RD08(par->riva.PCIO, 0x3c1)); 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) ...@@ -384,40 +399,39 @@ static inline unsigned char MISCin(struct riva_par *par)
/** /**
* riva_cursor_timer_handler - blink timer * 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: * DESCRIPTION:
* Cursor blink timer. * Cursor blink timer.
*/ */
static void riva_cursor_timer_handler(unsigned long dev_addr) static void riva_cursor_timer_handler(unsigned long dev_addr)
{ {
struct fb_info *info = (struct fb_info *)dev_addr; struct rivafb_info *rinfo = (struct rivafb_info *)dev_addr;
struct riva_par *par = (struct riva_par *) info->par;
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; if (rinfo->cursor->last_move_delay < 1000)
par->cursor->last_slice_moves = 0; rinfo->cursor->last_move_delay++;
if (par->cursor->vbl_cnt && --par->cursor->vbl_cnt == 0) { if (rinfo->cursor->vbl_cnt && --rinfo->cursor->vbl_cnt == 0) {
par->cursor->on ^= 1; rinfo->cursor->on ^= 1;
if (par->cursor->on) if (rinfo->cursor->on)
*(par->riva.CURSORPOS) = (par->cursor->pos.x & 0xFFFF) *(rinfo->riva.CURSORPOS) = (rinfo->cursor->pos.x & 0xFFFF)
| (par->cursor->pos.y << 16); | (rinfo->cursor->pos.y << 16);
par->riva.ShowHideCursor(&par->riva, par->cursor->on); rinfo->riva.ShowHideCursor(&rinfo->riva, rinfo->cursor->on);
if (!noblink) if (!noblink)
par->cursor->vbl_cnt = par->cursor->blink_rate; rinfo->cursor->vbl_cnt = rinfo->cursor->blink_rate;
} }
out: out:
par->cursor->timer->expires = jiffies + (HZ / 50); rinfo->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(par->cursor->timer); add_timer(rinfo->cursor->timer);
} }
/** /**
* rivafb_init_cursor - allocates cursor structure and starts blink 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: * DESCRIPTION:
* Allocates cursor structure and starts blink timer. * Allocates cursor structure and starts blink timer.
...@@ -428,7 +442,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr) ...@@ -428,7 +442,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr)
* CALLED FROM: * CALLED FROM:
* rivafb_init_one() * 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; struct riva_cursor *cursor;
...@@ -446,8 +460,8 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info) ...@@ -446,8 +460,8 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE; cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
init_timer(cursor->timer); init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 50); cursor->timer->expires = jiffies + (HZ / 100);
cursor->timer->data = (unsigned long)info; cursor->timer->data = (unsigned long)rinfo;
cursor->timer->function = riva_cursor_timer_handler; cursor->timer->function = riva_cursor_timer_handler;
add_timer(cursor->timer); add_timer(cursor->timer);
...@@ -456,7 +470,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info) ...@@ -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 * 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: * DESCRIPTION:
* Stops blink timer and releases cursor structure. * Stops blink timer and releases cursor structure.
...@@ -465,9 +479,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info) ...@@ -465,9 +479,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
* rivafb_init_one() * rivafb_init_one()
* rivafb_remove_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) {
if (cursor->timer) { if (cursor->timer) {
...@@ -475,13 +489,13 @@ static void rivafb_exit_cursor(struct riva_par *par) ...@@ -475,13 +489,13 @@ static void rivafb_exit_cursor(struct riva_par *par)
kfree(cursor->timer); kfree(cursor->timer);
} }
kfree(cursor); kfree(cursor);
par->cursor = NULL; rinfo->cursor = 0;
} }
} }
/** /**
* rivafb_download_cursor - writes cursor shape into card registers * 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: * DESCRIPTION:
* Writes cursor shape into card registers. * Writes cursor shape into card registers.
...@@ -489,24 +503,24 @@ static void rivafb_exit_cursor(struct riva_par *par) ...@@ -489,24 +503,24 @@ static void rivafb_exit_cursor(struct riva_par *par)
* CALLED FROM: * CALLED FROM:
* riva_load_video_mode() * 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 i, save;
int *image; int *image;
if (!par->cursor) return; if (!rinfo->cursor) return;
image = (int *)par->cursor->image; image = (int *)rinfo->cursor->image;
save = par->riva.ShowHideCursor(&par->riva, 0); save = rinfo->riva.ShowHideCursor(&rinfo->riva, 0);
for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++) 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 * 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 * @width: cursor width in pixels
* @height: cursor height in pixels * @height: cursor height in pixels
* *
...@@ -515,11 +529,11 @@ static void rivafb_download_cursor(struct riva_par *par) ...@@ -515,11 +529,11 @@ static void rivafb_download_cursor(struct riva_par *par)
* *
* CALLED FROM: * CALLED FROM:
* rivafb_set_font() * 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; int i, j, idx;
if (c) { if (c) {
...@@ -561,10 +575,9 @@ static void rivafb_create_cursor(struct riva_par *par, int width, int height) ...@@ -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) static int rivafb_set_font(struct display *p, int width, int height)
{ {
struct fb_info *fb = p->fb_info; struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info);
struct riva_par *par = (struct riva_par *) fb->par;
rivafb_create_cursor(par, width, height); rivafb_create_cursor(fb, width, height);
return 1; return 1;
} }
...@@ -580,9 +593,8 @@ static int rivafb_set_font(struct display *p, int width, int height) ...@@ -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) static void rivafb_cursor(struct display *p, int mode, int x, int y)
{ {
struct fb_info *info = p->fb_info; struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
struct riva_par *par = (struct riva_par *) info->par; struct riva_cursor *c = rinfo->cursor;
struct riva_cursor *c = par->cursor;
if (!c) return; if (!c) return;
...@@ -593,7 +605,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -593,7 +605,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return; return;
c->enable = 0; 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.x = x;
c->pos.y = y; c->pos.y = y;
...@@ -604,15 +616,15 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -604,15 +616,15 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
break; break;
case CM_DRAW: case CM_DRAW:
case CM_MOVE: 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; c->vbl_cnt = CURSOR_SHOW_DELAY;
} else { } else {
*(par->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16); *(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16);
par->riva.ShowHideCursor(&par->riva, 1); rinfo->riva.ShowHideCursor(&rinfo->riva, 1);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY; if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1; c->on = 1;
} }
c->last_slice_moves++; c->last_move_delay = 0;
c->enable = 1; c->enable = 1;
break; break;
} }
...@@ -626,6 +638,80 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y) ...@@ -626,6 +638,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 * riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object * @chip: pointer to RIVA_HW_INST object
...@@ -652,7 +738,7 @@ static void riva_wclut(RIVA_HW_INST *chip, ...@@ -652,7 +738,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/** /**
* riva_save_state - saves current chip state * 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 * @regs: pointer to riva_regs object
* *
* DESCRIPTION: * DESCRIPTION:
...@@ -662,36 +748,36 @@ static void riva_wclut(RIVA_HW_INST *chip, ...@@ -662,36 +748,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one() * rivafb_init_one()
*/ */
/* from GGI */ /* 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; 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++) { 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++) { 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++) { 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++) { 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 * 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 * @regs: pointer to riva_regs object
* *
* DESCRIPTION: * DESCRIPTION:
...@@ -703,18 +789,18 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs) ...@@ -703,18 +789,18 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
* rivafb_remove_one() * rivafb_remove_one()
*/ */
/* from GGI */ /* 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; int i;
RIVA_HW_STATE *state = &regs->ext;
CRTCout(par, 0x11, 0x00);
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++) { for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) { switch (i) {
...@@ -722,44 +808,44 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs) ...@@ -722,44 +808,44 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
case 0x20 ... 0x40: case 0x20 ... 0x40:
break; break;
default: default:
CRTCout(par, i, regs->crtc[i]); CRTCout(rinfo, i, regs->crtc[i]);
} }
} }
for (i = 0; i < NUM_ATC_REGS; 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++) { 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++) { 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 * 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 * @video_mode: video mode to set
* *
* DESCRIPTION: * DESCRIPTION:
* Calculate some timings and then send em off to riva_load_state(). * Calculate some timings and then send em off to riva_load_state().
* *
* CALLED FROM: * 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 fb_var_screeninfo *video_mode)
{ {
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode; struct riva_regs newmode;
int bpp, width, hDisplaySize, hDisplay, hStart, int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
/* time to calculate */ /* time to calculate */
rivafb_blank(1, info);
rivafb_blank(1, (struct fb_info *)rinfo);
bpp = video_mode->bits_per_pixel; bpp = video_mode->bits_per_pixel;
if (bpp == 16 && video_mode->green.length == 5) if (bpp == 16 && video_mode->green.length == 5)
...@@ -813,27 +899,83 @@ static void riva_load_video_mode(struct fb_info *info, ...@@ -813,27 +899,83 @@ static void riva_load_video_mode(struct fb_info *info,
newmode.ext.width = width; newmode.ext.width = width;
newmode.ext.height = height; 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, hDisplaySize, hDisplay, hStart, hEnd,
hTotal, height, vDisplay, vStart, vEnd, hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock); vTotal, dotClock);
if (video_mode->sync & FB_SYNC_HOR_HIGH_ACT) rinfo->current_state = newmode;
newmode.misc_output &= ~0x40; riva_load_state(rinfo, &rinfo->current_state);
if (video_mode->sync & FB_SYNC_VERT_HIGH_ACT)
newmode.misc_output &= ~0x80; 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; while (i_p->next != NULL)
riva_load_state(par, &par->current_state); i_p = i_p->next;
i_p->next = new_node;
par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */ return board_list;
rivafb_download_cursor(par); }
/**
* 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 - * 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: * @var:
* @v:
* @nom: * @nom:
* @den: * @den:
* *
...@@ -845,13 +987,13 @@ static void riva_load_video_mode(struct fb_info *info, ...@@ -845,13 +987,13 @@ static void riva_load_video_mode(struct fb_info *info,
* *
* *
* CALLED FROM: * 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 *var,
struct fb_var_screeninfo *v,
int nom, int den) int nom, int den)
{ {
struct riva_par *par = (struct riva_par *) info->par;
static struct { static struct {
int xres, yres; int xres, yres;
} modes[] = { } modes[] = {
...@@ -865,12 +1007,12 @@ static int rivafb_do_maximize(struct fb_info *info, ...@@ -865,12 +1007,12 @@ static int rivafb_do_maximize(struct fb_info *info,
int i; int i;
/* use highest possible virtual resolution */ /* 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 printk(KERN_WARNING PFX
"using maximum available virtual resolution\n"); "using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) { for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres < if (modes[i].xres * nom / den * modes[i].yres <
par->ram_amount / 2) rinfo->ram_amount / 2)
break; break;
} }
if (modes[i].xres == -1) { if (modes[i].xres == -1) {
...@@ -879,26 +1021,26 @@ static int rivafb_do_maximize(struct fb_info *info, ...@@ -879,26 +1021,26 @@ static int rivafb_do_maximize(struct fb_info *info,
DPRINTK("EXIT - EINVAL error\n"); DPRINTK("EXIT - EINVAL error\n");
return -EINVAL; return -EINVAL;
} }
var->xres_virtual = modes[i].xres; v->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres; v->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n", "virtual resolution set to maximum of %dx%d\n",
var->xres_virtual, var->yres_virtual); v->xres_virtual, v->yres_virtual);
} else if (var->xres_virtual == -1) { } else if (v->xres_virtual == -1) {
var->xres_virtual = (par->ram_amount * den / v->xres_virtual = (rinfo->ram_amount * den /
(nom * var->yres_virtual * 2)) & ~15; (nom * v->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX printk(KERN_WARNING PFX
"setting virtual X resolution to %d\n", var->xres_virtual); "setting virtual X resolution to %d\n", v->xres_virtual);
} else if (var->yres_virtual == -1) { } else if (v->yres_virtual == -1) {
var->xres_virtual = (var->xres_virtual + 15) & ~15; v->xres_virtual = (v->xres_virtual + 15) & ~15;
var->yres_virtual = par->ram_amount * den / v->yres_virtual = rinfo->ram_amount * den /
(nom * var->xres_virtual * 2); (nom * v->xres_virtual * 2);
printk(KERN_WARNING PFX 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 { } else {
var->xres_virtual = (var->xres_virtual + 15) & ~15; v->xres_virtual = (v->xres_virtual + 15) & ~15;
if (var->xres_virtual * nom / den * var->yres_virtual > par->ram_amount) { if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel); var->xres, var->yres, var->bits_per_pixel);
...@@ -907,146 +1049,29 @@ static int rivafb_do_maximize(struct fb_info *info, ...@@ -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 printk(KERN_WARNING PFX
"virtual X resolution (%d) is too high, lowering to %d\n", "virtual X resolution (%d) is too high, lowering to %d\n",
var->xres_virtual, 8192 * den / nom - 16); v->xres_virtual, 8192 * den / nom - 16);
var->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 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; return -EINVAL;
} }
if (var->yres_virtual < var->yres) { if (v->yres_virtual < v->yres) {
printk(KERN_ERR PFX 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 -EINVAL;
} }
return 0; 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) ...@@ -1065,7 +1090,10 @@ static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
* Length of color map * Length of color map
* *
* CALLED FROM: * CALLED FROM:
* riva_getcolreg()
* rivafb_setcolreg() * rivafb_setcolreg()
* rivafb_get_cmap()
* rivafb_set_cmap()
*/ */
static int riva_get_cmap_len(const struct fb_var_screeninfo *var) 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) ...@@ -1074,18 +1102,24 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert(var != NULL); assert(var != NULL);
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB8
case 8: case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */ rc = 256; /* pseudocolor... 256 entries HW palette */
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 15: case 15:
rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */ rc = 15; /* fix for 15 bpp depths on Riva 128 based cards */
break; break;
case 16: case 16:
rc = 16; /* directcolor... 16 entries SW palette */ rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
#ifdef FBCON_HAS_CFB32
case 32: case 32:
rc = 16; /* directcolor... 16 entries SW palette */ rc = 16; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */ break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
default: default:
/* should not occur */ /* should not occur */
break; break;
...@@ -1094,6 +1128,46 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) ...@@ -1094,6 +1128,46 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
return rc; return rc;
} }
/**
* 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 * rivafb_setcolreg
* @regno: register index * @regno: register index
...@@ -1101,7 +1175,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var) ...@@ -1101,7 +1175,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
* @green: green component * @green: green component
* @blue: blue component * @blue: blue component
* @transp: transparency * @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: * DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit * 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) ...@@ -1111,54 +1185,79 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
* Return != 0 for invalid regno. * Return != 0 for invalid regno.
* *
* CALLED FROM: * CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_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, static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp, unsigned blue, unsigned transp,
struct fb_info *info) struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par; struct rivafb_info *rivainfo = (struct rivafb_info *)info;
RIVA_HW_INST *chip = &par->riva; 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; 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 */ /* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue = red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8; (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: case 8:
/* "transparent" stuff is completely ignored. */ /* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8); riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break; break;
#endif /* FBCON_HAS_CFB8 */
#ifdef FBCON_HAS_CFB16
case 16: case 16:
assert(regno < 16); assert(regno < 16);
if (info->var.green.length == 5) { if (p->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */ /* 0rrrrrgg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] = rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 1) | ((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else { } else {
/* rrrrrggg gggbbbbb */ /* rrrrrggg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] = rivainfo->con_cmap.cfb16[regno] =
((red & 0xf800) >> 0) | ((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11); ((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
} }
break; break;
#endif /* FBCON_HAS_CFB16 */
#ifdef FBCON_HAS_CFB32
case 32: case 32:
assert(regno < 16); assert(regno < 16);
((u32 *)(info->pseudo_palette))[regno] = rivainfo->con_cmap.cfb32[regno] =
((red & 0xff00) << 8) | ((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8); ((green & 0xff00)) | ((blue & 0xff00) >> 8);
break; break;
#endif /* FBCON_HAS_CFB32 */
default: default:
/* do nothing */ /* do nothing */
break; break;
} }
return 0; return 0;
} }
...@@ -1170,58 +1269,177 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green, ...@@ -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 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: case 1 ... 8:
var->bits_per_pixel = 8; v.bits_per_pixel = 8;
nom = 1; nom = 1;
den = 1; den = 1;
var->red.offset = 0; v.red.offset = 0;
var->red.length = 8; v.red.length = 8;
var->green.offset = 0; v.green.offset = 0;
var->green.length = 8; v.green.length = 8;
var->blue.offset = 0; v.blue.offset = 0;
var->blue.length = 8; v.blue.length = 8;
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 9 ... 15: case 9 ... 15:
var->green.length = 5; v.green.length = 5;
/* fall through */ /* fall through */
case 16: case 16:
var->bits_per_pixel = 16; v.bits_per_pixel = 16;
nom = 2; nom = 2;
den = 1; den = 1;
if (var->green.length == 5) { if (v.green.length == 5) {
/* 0rrrrrgg gggbbbbb */ /* 0rrrrrgg gggbbbbb */
var->red.offset = 10; v.red.offset = 10;
var->green.offset = 5; v.green.offset = 5;
var->blue.offset = 0; v.blue.offset = 0;
var->red.length = 5; v.red.length = 5;
var->green.length = 5; v.green.length = 5;
var->blue.length = 5; v.blue.length = 5;
} else { } else {
/* rrrrrggg gggbbbbb */ /* rrrrrggg gggbbbbb */
var->red.offset = 11; v.red.offset = 11;
var->green.offset = 5; v.green.offset = 5;
var->blue.offset = 0; v.blue.offset = 0;
var->red.length = 5; v.red.length = 5;
var->green.length = 6; v.green.length = 6;
var->blue.length = 5; v.blue.length = 5;
} }
break; break;
#endif
#ifdef FBCON_HAS_CFB32
case 17 ... 32: case 17 ... 32:
var->bits_per_pixel = 32; v.bits_per_pixel = 32;
nom = 4; nom = 4;
den = 1; den = 1;
var->red.offset = 16; v.red.offset = 16;
var->green.offset = 8; v.green.offset = 8;
var->blue.offset = 0; v.blue.offset = 0;
var->red.length = 8; v.red.length = 8;
var->green.length = 8; v.green.length = 8;
var->blue.length = 8; v.blue.length = 8;
break; break;
#endif
default: default:
printk(KERN_ERR PFX printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n", "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) ...@@ -1230,57 +1448,122 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return -EINVAL; return -EINVAL;
} }
if (rivafb_do_maximize(info, var, nom, den) < 0) if (rivafb_do_maximize(rivainfo, var, &v, nom, den) < 0)
return -EINVAL; return -EINVAL;
if (var->xoffset < 0) if (v.xoffset < 0)
var->xoffset = 0; v.xoffset = 0;
if (var->yoffset < 0) if (v.yoffset < 0)
var->yoffset = 0; v.yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */ /* truncate xoffset and yoffset to maximum if too high */
if (var->xoffset > var->xres_virtual - var->xres) if (v.xoffset > v.xres_virtual - v.xres)
var->xoffset = var->xres_virtual - var->xres - 1; v.xoffset = v.xres_virtual - v.xres - 1;
if (var->yoffset > var->yres_virtual - var->yres) if (v.yoffset > v.yres_virtual - v.yres)
var->yoffset = var->yres_virtual - var->yres - 1; v.yoffset = v.yres_virtual - v.yres - 1;
var->red.msb_right = v.red.msb_right =
var->green.msb_right = v.green.msb_right =
var->blue.msb_right = v.blue.msb_right =
var->transp.offset = var->transp.length = var->transp.msb_right = 0; v.transp.offset = v.transp.length = v.transp.msb_right = 0;
var->accel_flags |= FB_ACCELF_TEXT;
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; 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) { DPRINTK("ENTER\n");
case 8:
info->fix.line_length = info->var.xres_virtual; assert(rivainfo != NULL);
info->fix.visual = FB_VISUAL_PSEUDOCOLOR; assert(cmap != NULL);
break;
case 16: dsp = (con < 0) ? rivainfo->info.disp : &fb_display[con];
info->fix.line_length = info->var.xres_virtual * 2;
info->fix.visual = FB_VISUAL_DIRECTCOLOR; if (con == info->currcon) { /* current console? */
break; int rc = fb_get_cmap(cmap, kspc, riva_getcolreg, info);
case 32: DPRINTK("EXIT - returning %d\n", rc);
info->fix.line_length = info->var.xres_virtual * 4; return rc;
info->fix.visual = FB_VISUAL_DIRECTCOLOR; } else if (dsp->cmap.len) /* non default colormap? */
break; fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2);
} else
/* fb_copy_cmap(fb_default_cmap
if (par->cursor) { (riva_get_cmap_len(&dsp->var)), cmap,
disp->dispsw.cursor = rivafb_cursor; kspc ? 0 : 2);
disp->dispsw.set_font = rivafb_set_font;
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; return 0;
} }
...@@ -1288,7 +1571,7 @@ static int rivafb_set_par(struct fb_info *info) ...@@ -1288,7 +1571,7 @@ static int rivafb_set_par(struct fb_info *info)
* rivafb_pan_display * rivafb_pan_display
* @var: standard kernel fb changeable data * @var: standard kernel fb changeable data
* @con: TODO * @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: * DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the * 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) ...@@ -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, static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
struct fb_info *info) struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *) info->par;
struct display *dsp;
unsigned int base; 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)) if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL; return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres)) if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL; 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->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0 if (var->yoffset < 0
|| var->yoffset >= info->var.yres_virtual || var->yoffset >= dsp->var.yres_virtual
|| var->xoffset) return -EINVAL; || var->xoffset) return -EINVAL;
} else { } else {
if (var->xoffset + info->var.xres > info->var.xres_virtual || if (var->xoffset + dsp->var.xres > dsp->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual) var->yoffset + dsp->var.yres > dsp->var.yres_virtual)
return -EINVAL; return -EINVAL;
} }
base = var->yoffset * dsp->line_length + var->xoffset; base = var->yoffset * dsp->line_length + var->xoffset;
if (con == info->currcon) if (con == info->currcon) {
par->riva.SetStartAddress(&par->riva, base); rivainfo->riva.SetStartAddress(&rivainfo->riva, base);
}
info->var.xoffset = var->xoffset; dsp->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset; dsp->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP) if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP; dsp->var.vmode |= FB_VMODE_YWRAP;
else else
info->var.vmode &= ~FB_VMODE_YWRAP; dsp->var.vmode &= ~FB_VMODE_YWRAP;
DPRINTK("EXIT, returning 0\n");
return 0; 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) 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; 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) static int rivafb_blank(int blank, struct fb_info *info)
{ {
struct riva_par *par = (struct riva_par *)info->par;
unsigned char tmp, vesa; 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 */ tmp = SEQin(rinfo, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */ vesa = CRTCin(rinfo, 0x1a) & ~0xc0; /* sync on/off */
if (blank) { if (blank) {
tmp |= 0x20; tmp |= 0x20;
...@@ -1370,11 +1727,15 @@ static int rivafb_blank(int blank, struct fb_info *info) ...@@ -1370,11 +1727,15 @@ static int rivafb_blank(int blank, struct fb_info *info)
} }
} }
SEQout(par, 0x01, tmp); SEQout(rinfo, 0x01, tmp);
CRTCout(par, 0x1a, vesa); CRTCout(rinfo, 0x1a, vesa);
DPRINTK("EXIT\n");
return 0; return 0;
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* initialization helper functions * initialization helper functions
...@@ -1384,29 +1745,78 @@ static int rivafb_blank(int blank, struct fb_info *info) ...@@ -1384,29 +1745,78 @@ static int rivafb_blank(int blank, struct fb_info *info)
/* kernel interface */ /* kernel interface */
static struct fb_ops riva_fb_ops = { static struct fb_ops riva_fb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: gen_get_fix, fb_get_fix: rivafb_get_fix,
fb_get_var: gen_get_var, fb_get_var: rivafb_get_var,
fb_set_var: gen_set_var, fb_set_var: rivafb_set_var,
fb_get_cmap: gen_get_cmap, fb_get_cmap: rivafb_get_cmap,
fb_set_cmap: gen_set_cmap, fb_set_cmap: rivafb_set_cmap,
fb_check_var: rivafb_check_var,
fb_set_par: rivafb_set_par,
fb_setcolreg: rivafb_setcolreg, fb_setcolreg: rivafb_setcolreg,
fb_pan_display: rivafb_pan_display, fb_pan_display: rivafb_pan_display,
fb_blank: rivafb_blank, fb_blank: rivafb_blank,
fb_fillrect: rivafb_fillrect, fb_ioctl: rivafb_ioctl,
fb_copyarea: rivafb_copyarea,
fb_imageblit: rivafb_imageblit,
fb_rasterimg: rivafb_rasterimg, 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->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops; info->fbops = &riva_fb_ops;
info->fix = rivafb_fix; info->screen_base = rinfo->fb_base;
/* FIXME: set monspecs to what??? */ /* FIXME: set monspecs to what??? */
info->display_fg = NULL; info->display_fg = NULL;
...@@ -1415,21 +1825,12 @@ static int __devinit riva_set_fbinfo(struct fb_info *info) ...@@ -1415,21 +1825,12 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info->fontname[sizeof(info->fontname) - 1] = 0; info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL; info->changevar = NULL;
info->switch_con = gen_switch; info->switch_con = rivafb_switch;
info->updatevar = gen_update_var; info->updatevar = rivafb_updatevar;
#ifndef MODULE if (riva_init_disp(rinfo) < 0) /* must be done last */
if (mode_option) { return -1;
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);
gen_set_var(&info->var, -1, info);
return 0; return 0;
} }
...@@ -1444,230 +1845,194 @@ static int __devinit riva_set_fbinfo(struct fb_info *info) ...@@ -1444,230 +1845,194 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
static int __devinit rivafb_init_one(struct pci_dev *pd, static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent) const struct pci_device_id *ent)
{ {
struct rivafb_info *rinfo;
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data]; 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(pd != NULL);
assert(rci != NULL); assert(rci != NULL);
size = sizeof(struct fb_info) + sizeof(struct display) + sizeof(u32) * 16; rinfo = kmalloc(sizeof(struct rivafb_info), GFP_KERNEL);
if (!rinfo)
info = kmalloc(size, GFP_KERNEL);
if (!info)
goto err_out; goto err_out;
memset(info, 0, size); memset(rinfo, 0, sizeof(struct rivafb_info));
default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);
if (!default_par)
goto err_out;
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); rinfo->pd = pd;
info->pseudo_palette = (void *)(info->disp + 1); rinfo->base0_region_size = pci_resource_len(pd, 0);
rinfo->base1_region_size = pci_resource_len(pd, 1);
strcat(rivafb_fix.id, rci->name); assert(rinfo->base0_region_size >= 0x00800000); /* from GGI */
default_par->riva.Architecture = rci->arch_rev; assert(rinfo->base1_region_size >= 0x01000000); /* from GGI */
rivafb_fix.mmio_len = pci_resource_len(pd, 0); rinfo->ctrl_base_phys = pci_resource_start(rinfo->pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1); rinfo->fb_base_phys = pci_resource_start(rinfo->pd, 1);
assert(rivafb_fix.mmio_len >= 0x00800000); /* from GGI */ if (!request_mem_region(rinfo->ctrl_base_phys,
assert(rivafb_fix.smem_len >= 0x01000000); /* from GGI */ rinfo->base0_region_size, "rivafb")) {
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")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n"); printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree; goto err_out_kfree;
} }
default_par->ctrl_base = ioremap(rivafb_fix.mmio_start, if (!request_mem_region(rinfo->fb_base_phys,
rivafb_fix.mmio_len); rinfo->base1_region_size, "rivafb")) {
if (!default_par->ctrl_base) { 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"); printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base1; goto err_out_free_base1;
} }
default_par->riva.EnableIRQ = 0; rinfo->fb_base = ioremap(rinfo->fb_base_phys,
default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base + 0x00680000); rinfo->base1_region_size);
default_par->riva.PFB = (unsigned *)(default_par->ctrl_base + 0x00100000); if (!rinfo->fb_base) {
default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base + 0x00002000); printk(KERN_ERR PFX "cannot ioremap FB base\n");
default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base + 0x00400000); goto err_out_iounmap_ctrl;
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); #ifdef CONFIG_MTRR
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + 0x00800000); if (!nomtrr) {
rinfo->mtrr.vram = mtrr_add(rinfo->fb_base_phys,
default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000); rinfo->base1_region_size, MTRR_TYPE_WRCOMB, 1);
default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000); if (rinfo->mtrr.vram < 0) {
default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000); printk(KERN_ERR PFX "unable to setup MTRR\n");
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0; } else {
rinfo->mtrr.vram_valid = 1;
switch (default_par->riva.Architecture) { /* let there be speed */
case NV_ARCH_03: printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
/*
* 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;
} }
}
#endif /* CONFIG_MTRR */
info->screen_base = ioremap(rivafb_fix.smem_start, rinfo->riva.EnableIRQ = 0;
rivafb_fix.smem_len); rinfo->riva.PRAMDAC = (unsigned *)(rinfo->ctrl_base + 0x00680000);
if (!info->screen_base) { rinfo->riva.PFB = (unsigned *)(rinfo->ctrl_base + 0x00100000);
printk(KERN_ERR PFX "cannot ioremap FB base\n"); rinfo->riva.PFIFO = (unsigned *)(rinfo->ctrl_base + 0x00002000);
goto err_out_iounmap_ctrl; 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); rinfo->riva.IO = (MISCin(rinfo) & 0x01) ? 0x3D0 : 0x3B0;
rivafb_fix.accel = FB_ACCEL_NV3;
switch (rinfo->riva.Architecture) {
case NV_ARCH_03:
rinfo->riva.PRAMIN = (unsigned *)(rinfo->fb_base + 0x00C00000);
break; break;
case NV_ARCH_04: case NV_ARCH_04:
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20: rinfo->riva.PCRTC = (unsigned *)(rinfo->ctrl_base + 0x00600000);
/* riva_hw.c now doesn't distinguish between TNT & TNT2 */ rinfo->riva.PRAMIN = (unsigned *)(rinfo->ctrl_base + 0x00710000);
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;
break; break;
} }
RivaGetConfig(&default_par->riva); RivaGetConfig(&rinfo->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;
if (default_par->riva.Architecture != NV_ARCH_03) { /* back to normal */
/*
* 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;
if (!request_mem_region(rivafb_fix.smem_start, assert(rinfo->pd != NULL);
rivafb_fix.smem_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve FB region\n");
goto err_out_free_base0;
}
info->screen_base = ioremap(rivafb_fix.smem_start, /* unlock io */
rivafb_fix.smem_len); CRTCout(rinfo, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
if (!info->screen_base) { rinfo->riva.LockUnlock(&rinfo->riva, 0);
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
}
#ifdef CONFIG_MTRR riva_save_state(rinfo, &rinfo->initial_state);
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 */
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"); printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor; goto err_out_cursor;
} }
if (register_framebuffer(info) < 0) { if (register_framebuffer((struct fb_info *)rinfo) < 0) {
printk(KERN_ERR PFX printk(KERN_ERR PFX
"error registering riva framebuffer\n"); "error registering riva framebuffer\n");
goto err_out_load_state; 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 printk(KERN_INFO PFX
"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n", "PCI nVidia NV%d framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
default_par->riva.Architecture, rinfo->riva.Architecture,
RIVAFB_VERSION, RIVAFB_VERSION,
info->fix.id, rinfo->drvr_name,
default_par->ram_amount / (1024 * 1024), rinfo->ram_amount / (1024 * 1024),
info->fix.smem_start); rinfo->fb_base_phys);
return 0; return 0;
err_out_load_state: err_out_load_state:
riva_load_state(default_par, &default_par->initial_state); riva_load_state(rinfo, &rinfo->initial_state);
err_out_cursor: err_out_cursor:
rivafb_exit_cursor(default_par); rivafb_exit_cursor(rinfo);
/* err_out_iounmap_fb: */ /* err_out_iounmap_fb: */
iounmap(info->screen_base); iounmap(rinfo->fb_base);
err_out_iounmap_ctrl: err_out_iounmap_ctrl:
iounmap(default_par->ctrl_base); iounmap(rinfo->ctrl_base);
err_out_free_base1: 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: 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: err_out_kfree:
kfree(default_par); kfree(rinfo);
kfree(info);
err_out: err_out:
return -ENODEV; return -ENODEV;
} }
static void __devexit rivafb_remove_one(struct pci_dev *pd) static void __devexit rivafb_remove_one(struct pci_dev *pd)
{ {
struct fb_info *board = pci_get_drvdata(pd); struct rivafb_info *board = pci_get_drvdata(pd);
struct riva_par *par = (struct riva_par *) board->par;
if (!board) if (!board)
return; 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 #ifdef CONFIG_MTRR
if (par->mtrr.vram_valid) if (board->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, board->fix.smem_start, mtrr_del(board->mtrr.vram, board->fb_base_phys,
board->fix.smem_len); board->base1_region_size);
#endif /* CONFIG_MTRR */ #endif /* CONFIG_MTRR */
iounmap(par->ctrl_base); iounmap(board->ctrl_base);
iounmap(board->screen_base); iounmap(board->fb_base);
release_mem_region(board->fix.mmio_start, release_mem_region(board->ctrl_base_phys,
board->fix.mmio_len); board->base0_region_size);
release_mem_region(board->fix.smem_start, release_mem_region(board->fb_base_phys,
board->fix.smem_len); board->base1_region_size);
kfree(par);
kfree(board); kfree(board);
pci_set_drvdata(pd, NULL); pci_set_drvdata(pd, NULL);
} }
/* ------------------------------------------------------------------------- * /* ------------------------------------------------------------------------- *
* *
* initialization * initialization
...@@ -1698,6 +2063,10 @@ int __init rivafb_setup(char *options) ...@@ -1698,6 +2063,10 @@ int __init rivafb_setup(char *options)
} else if (!strncmp(this_opt, "noblink", 7)) { } else if (!strncmp(this_opt, "noblink", 7)) {
noblink = 1; noblink = 1;
} else if (!strncmp(this_opt, "noaccel", 7)) {
noaccel = 1;
} else if (!strncmp(this_opt, "nomove", 6)) {
nomove = 1;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
} else if (!strncmp(this_opt, "nomtrr", 6)) { } else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1; nomtrr = 1;
...@@ -1750,6 +2119,10 @@ module_exit(rivafb_exit); ...@@ -1750,6 +2119,10 @@ module_exit(rivafb_exit);
MODULE_PARM(font, "s"); MODULE_PARM(font, "s");
MODULE_PARM_DESC(font, "Specifies one of the compiled-in fonts (default=none)"); 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(nohwcursor, "i");
MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)"); MODULE_PARM_DESC(nohwcursor, "Disables hardware cursor (0 or 1=disabled) (default=0)");
MODULE_PARM(noblink, "i"); MODULE_PARM(noblink, "i");
......
...@@ -1220,7 +1220,6 @@ static void CalcStateExt ...@@ -1220,7 +1220,6 @@ static void CalcStateExt
state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00; state->repaint1 = hDisplaySize < 1280 ? 0x04 : 0x00;
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
nv10UpdateArbitrationSettings(VClk, nv10UpdateArbitrationSettings(VClk,
pixelDepth * 8, pixelDepth * 8,
&(state->arbitration0), &(state->arbitration0),
...@@ -1286,7 +1285,6 @@ static void UpdateFifoState ...@@ -1286,7 +1285,6 @@ static void UpdateFifoState
chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]); chip->Tri05 = (RivaTexturedTriangle05 *)&(chip->FIFO[0x0000E000/4]);
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
/* /*
* Initialize state for the RivaTriangle3D05 routines. * Initialize state for the RivaTriangle3D05 routines.
*/ */
...@@ -1395,7 +1393,6 @@ static void LoadStateExt ...@@ -1395,7 +1393,6 @@ static void LoadStateExt
chip->PGRAPH[0x0000067C/4] = state->pitch3; chip->PGRAPH[0x0000067C/4] = state->pitch3;
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
LOAD_FIXED_STATE(nv10,PFIFO); LOAD_FIXED_STATE(nv10,PFIFO);
LOAD_FIXED_STATE(nv10,PRAMIN); LOAD_FIXED_STATE(nv10,PRAMIN);
LOAD_FIXED_STATE(nv10,PGRAPH); LOAD_FIXED_STATE(nv10,PGRAPH);
...@@ -1424,31 +1421,15 @@ static void LoadStateExt ...@@ -1424,31 +1421,15 @@ static void LoadStateExt
chip->Tri03 = 0L; chip->Tri03 = 0L;
break; break;
} }
chip->PGRAPH[0x00000640/4] = state->offset0;
if (chip->Architecture == NV_ARCH_10) { chip->PGRAPH[0x00000644/4] = state->offset1;
chip->PGRAPH[0x00000640/4] = state->offset0; chip->PGRAPH[0x00000648/4] = state->offset2;
chip->PGRAPH[0x00000644/4] = state->offset1; chip->PGRAPH[0x0000064C/4] = state->offset3;
chip->PGRAPH[0x00000648/4] = state->offset2; chip->PGRAPH[0x00000670/4] = state->pitch0;
chip->PGRAPH[0x0000064C/4] = state->offset3; chip->PGRAPH[0x00000674/4] = state->pitch1;
chip->PGRAPH[0x00000670/4] = state->pitch0; chip->PGRAPH[0x00000678/4] = state->pitch2;
chip->PGRAPH[0x00000674/4] = state->pitch1; chip->PGRAPH[0x0000067C/4] = state->pitch3;
chip->PGRAPH[0x00000678/4] = state->pitch2; chip->PGRAPH[0x00000680/4] = state->pitch3;
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[0x00000B00/4] = chip->PFB[0x00000240/4]; chip->PGRAPH[0x00000B00/4] = chip->PFB[0x00000240/4];
chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4]; chip->PGRAPH[0x00000B04/4] = chip->PFB[0x00000244/4];
chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4]; chip->PGRAPH[0x00000B08/4] = chip->PFB[0x00000248/4];
...@@ -1626,7 +1607,6 @@ static void UnloadStateExt ...@@ -1626,7 +1607,6 @@ static void UnloadStateExt
state->pitch3 = chip->PGRAPH[0x0000067C/4]; state->pitch3 = chip->PGRAPH[0x0000067C/4];
break; break;
case NV_ARCH_10: case NV_ARCH_10:
case NV_ARCH_20:
state->offset0 = chip->PGRAPH[0x00000640/4]; state->offset0 = chip->PGRAPH[0x00000640/4];
state->offset1 = chip->PGRAPH[0x00000644/4]; state->offset1 = chip->PGRAPH[0x00000644/4];
state->offset2 = chip->PGRAPH[0x00000648/4]; state->offset2 = chip->PGRAPH[0x00000648/4];
......
...@@ -74,8 +74,6 @@ typedef unsigned int U032; ...@@ -74,8 +74,6 @@ typedef unsigned int U032;
#define NV_ARCH_03 0x03 #define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04 #define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10 #define NV_ARCH_10 0x10
#define NV_ARCH_20 0x20
/***************************************************************************\ /***************************************************************************\
* * * *
* FIFO registers. * * FIFO registers. *
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
#include <linux/config.h> #include <linux/config.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/timer.h>
#include <video/fbcon.h> #include <video/fbcon.h>
#include <video/fbcon-cfb4.h> #include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h> #include <video/fbcon-cfb8.h>
...@@ -28,35 +27,58 @@ struct riva_regs { ...@@ -28,35 +27,58 @@ struct riva_regs {
RIVA_HW_STATE ext; RIVA_HW_STATE ext;
}; };
#define MAX_CURS 32 typedef struct {
unsigned char red, green, blue, transp;
struct riva_cursor { } riva_cfb8_cmap_t;
int enable;
int on; struct rivafb_info;
int vbl_cnt; struct rivafb_info {
int last_slice_moves, prev_slice_moves; struct fb_info info; /* kernel framebuffer info */
int blink_rate;
struct {
u16 x, y;
} pos, size;
unsigned short image[MAX_CURS*MAX_CURS];
struct timer_list *timer;
};
/* describes the state of a Riva board */
struct riva_par {
RIVA_HW_INST riva; /* interface to riva_hw.c */ 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 ram_amount; /* amount of RAM on card, in bytes */
unsigned dclk_max; /* max DCLK */ unsigned dclk_max; /* max DCLK */
struct riva_regs initial_state; /* initial startup video mode */ struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state; 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; 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 #ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr; struct { int vram; int vram_valid; } mtrr;
#endif #endif
}; };
......
...@@ -661,7 +661,7 @@ static struct sa1100fb_mach_info xp860_info __initdata = { ...@@ -661,7 +661,7 @@ static struct sa1100fb_mach_info xp860_info __initdata = {
static struct sa1100fb_mach_info * __init 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; struct sa1100fb_mach_info *inf = NULL;
...@@ -683,7 +683,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par) ...@@ -683,7 +683,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_H3XXX #ifdef CONFIG_SA1100_H3XXX
if (machine_is_h3600()) { if (machine_is_h3600()) {
inf = &h3600_info; inf = &h3600_info;
par->rgb[RGB_16] = &h3600_rgb_16; fbi->rgb[RGB_16] = &h3600_rgb_16;
} }
if (machine_is_h3100()) { if (machine_is_h3100()) {
inf = &h3100_info; inf = &h3100_info;
...@@ -705,7 +705,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par) ...@@ -705,7 +705,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_FREEBIRD #ifdef CONFIG_SA1100_FREEBIRD
if (machine_is_freebird()) { if (machine_is_freebird()) {
inf = &freebird_info; inf = &freebird_info;
par->rgb[RGB_16] = &freebird_rgb16; fbi->rgb[RGB_16] = &freebird_rgb16;
} }
#endif #endif
#ifdef CONFIG_SA1100_GRAPHICSCLIENT #ifdef CONFIG_SA1100_GRAPHICSCLIENT
...@@ -758,10 +758,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par) ...@@ -758,10 +758,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
if (machine_is_stork()) { if (machine_is_stork()) {
#if STORK_TFT #if STORK_TFT
inf = &stork_tft_info; inf = &stork_tft_info;
par->rgb[RGB_16] = &stork_tft_rgb_16; fbi->rgb[RGB_16] = &stork_tft_rgb_16;
#else #else
inf = &stork_dstn_info; inf = &stork_dstn_info;
par->rgb[RGB_16] = &stork_dstn_rgb_16; fbi->rgb[RGB_16] = &stork_dstn_rgb_16;
#endif #endif
} }
#endif #endif
...@@ -773,10 +773,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par) ...@@ -773,10 +773,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
return inf; return inf;
} }
static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *); static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);
static void set_ctrlr_state(struct sa1100_par *par, u_int state); 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; unsigned long flags;
...@@ -789,18 +789,43 @@ static inline void sa1100fb_schedule_task(struct sa1100_par *par, u_int state) ...@@ -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 * 2. When we are blanking, but immediately unblank before we have
* blanked. We do the "REENABLE" thing here as well, just to be sure. * 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; 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; state = C_REENABLE;
if (state != (u_int)-1) { if (state != (u_int)-1) {
par->task_state = state; fbi->task_state = state;
schedule_task(&par->task); schedule_task(&fbi->task);
} }
local_irq_restore(flags); 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 static inline u_int
chan_to_field(u_int chan, struct fb_bitfield *bf) chan_to_field(u_int chan, struct fb_bitfield *bf)
{ {
...@@ -813,13 +838,19 @@ 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. * Convert bits-per-pixel to a hardware palette PBS value.
*/ */
static inline u_int static inline u_int
palette_pbs(int bpp) palette_pbs(struct fb_var_screeninfo *var)
{ {
int ret = 0; int ret = 0;
switch (bpp) { switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB4
case 4: ret = 0 << 12; break; case 4: ret = 0 << 12; break;
#endif
#ifdef FBCON_HAS_CFB8
case 8: ret = 1 << 12; break; case 8: ret = 1 << 12; break;
#endif
#ifdef FBCON_HAS_CFB16
case 16: ret = 2 << 12; break; case 16: ret = 2 << 12; break;
#endif
} }
return ret; return ret;
} }
...@@ -828,18 +859,18 @@ static int ...@@ -828,18 +859,18 @@ static int
sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, sa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info) 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; u_int val, ret = 1;
if (regno < par->palette_size) { if (regno < fbi->palette_size) {
val = ((red >> 4) & 0xf00); val = ((red >> 4) & 0xf00);
val |= ((green >> 8) & 0x0f0); val |= ((green >> 8) & 0x0f0);
val |= ((blue >> 12) & 0x00f); val |= ((blue >> 12) & 0x00f);
if (regno == 0) 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; ret = 0;
} }
return ret; return ret;
...@@ -849,6 +880,8 @@ static int ...@@ -849,6 +880,8 @@ static int
sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int trans, struct fb_info *info) 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; u_int val;
int ret = 1; int ret = 1;
...@@ -857,34 +890,33 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, ...@@ -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 * rather than the register number. The register number
* is what you poke into the framebuffer to produce the * is what you poke into the framebuffer to produce the
* colour you requested. * colour you requested.
* */
if (inverse) { if (disp->inverse) {
red = 0xffff - red; red = 0xffff - red;
green = 0xffff - green; green = 0xffff - green;
blue = 0xffff - blue; blue = 0xffff - blue;
} }
*/
/* /*
* If greyscale is true, then we convert the RGB value * If greyscale is true, then we convert the RGB value
* to greyscale no mater what visual we are using. * 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 + red = green = blue = (19595 * red + 38470 * green +
7471 * blue) >> 16; 7471 * blue) >> 16;
switch (info->fix.visual) { switch (fbi->fb.disp->visual) {
case FB_VISUAL_TRUECOLOR: case FB_VISUAL_TRUECOLOR:
/* /*
* 12 or 16-bit True Colour. We encode the RGB value * 12 or 16-bit True Colour. We encode the RGB value
* according to the RGB bitfield information. * according to the RGB bitfield information.
*/ */
if (regno < 16) { 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(red, &fbi->fb.var.red);
val |= chan_to_field(green, &info->var.green); val |= chan_to_field(green, &fbi->fb.var.green);
val |= chan_to_field(blue, &info->var.blue); val |= chan_to_field(blue, &fbi->fb.var.blue);
pal[regno] = val; pal[regno] = val;
ret = 0; ret = 0;
...@@ -931,20 +963,19 @@ sa1100fb_display_dma_period(struct fb_var_screeninfo *var) ...@@ -931,20 +963,19 @@ sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
* bitfields, horizontal timing, vertical timing. * bitfields, horizontal timing, vertical timing.
*/ */
static int static int
sa1100fb_check_var(struct fb_var_screeninfo *var, sa1100fb_validate_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct sa1100fb_info *fbi)
{ {
struct sa1100_par *par = (struct sa1100_par *) info->par; int ret = -EINVAL;
int rgbidx = RGB_16, ret = -EINVAL;
if (var->xres < MIN_XRES) if (var->xres < MIN_XRES)
var->xres = MIN_XRES; var->xres = MIN_XRES;
if (var->yres < MIN_YRES) if (var->yres < MIN_YRES)
var->yres = MIN_YRES; var->yres = MIN_YRES;
if (var->xres > par->max_xres) if (var->xres > fbi->max_xres)
var->xres = par->max_xres; var->xres = fbi->max_xres;
if (var->yres > par->max_yres) if (var->yres > fbi->max_yres)
var->yres = par->max_yres; var->yres = fbi->max_yres;
var->xres_virtual = var->xres_virtual =
var->xres_virtual < var->xres ? var->xres : var->xres_virtual; var->xres_virtual < var->xres ? var->xres : var->xres_virtual;
var->yres_virtual = var->yres_virtual =
...@@ -952,22 +983,23 @@ sa1100fb_check_var(struct fb_var_screeninfo *var, ...@@ -952,22 +983,23 @@ sa1100fb_check_var(struct fb_var_screeninfo *var,
DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel);
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
case 4: rgbidx = RGB_8; ret = 0; break; #ifdef FBCON_HAS_CFB4
case 8: rgbidx = RGB_8; ret = 0; break; case 4: ret = 0; break;
case 16: rgbidx = RGB_16; 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: default:
break; 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 #ifdef CONFIG_CPU_FREQ
printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n",
sa1100fb_display_dma_period(var), sa1100fb_display_dma_period(var),
cpufreq_get()); cpufreq_get(smp_processor_id()));
#endif #endif
return ret; return ret;
...@@ -994,26 +1026,24 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color) ...@@ -994,26 +1026,24 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color)
} }
} }
static int static void
sa1100fb_set_par(struct fb_info *info) 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; u_long palette_mem_size;
par->bpp = info->var.bits_per_pixel; fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
par->palette_size = par->bpp == 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); DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size);
par->palette_cpu = (u16 *)(par->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
par->palette_dma = par->map_dma + 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 */ /* 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 #ifdef CONFIG_SA1100_OMNIMETER
#error Do we have to do this here? We already do it at init time. #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) ...@@ -1021,31 +1051,210 @@ sa1100fb_set_par(struct fb_info *info)
SetLCDContrast(DefaultLCDContrast); SetLCDContrast(DefaultLCDContrast);
#endif #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] & switch (var->bits_per_pixel) {
0xcfff) | palette_pbs(info->var.bits_per_pixel); #ifdef FBCON_HAS_CFB4
switch (info->var.bits_per_pixel) {
case 4: case 4:
if (par->cmap_static) if (fbi->cmap_static)
info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
else else
info->fix.visual = FB_VISUAL_PSEUDOCOLOR; display->visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.line_length = info->var.xres / 2; display->line_length = var->xres / 2;
display->dispsw = &fbcon_cfb4;
rgbidx = RGB_8;
break; break;
#endif
#ifdef FBCON_HAS_CFB8
case 8: case 8:
if (par->cmap_static) if (fbi->cmap_static)
info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR; display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
else else
info->fix.visual = FB_VISUAL_PSEUDOCOLOR; display->visual = FB_VISUAL_PSEUDOCOLOR;
info->fix.line_length = info->var.xres; display->line_length = var->xres;
display->dispsw = &fbcon_cfb8;
rgbidx = RGB_8;
break; break;
#endif
#ifdef FBCON_HAS_CFB16
case 16: case 16:
info->fix.visual = FB_VISUAL_TRUECOLOR; display->visual = FB_VISUAL_TRUECOLOR;
info->fix.line_length = info->var.xres * 2; 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; 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; return 0;
} }
...@@ -1086,21 +1295,21 @@ sa1100fb_set_par(struct fb_info *info) ...@@ -1086,21 +1295,21 @@ sa1100fb_set_par(struct fb_info *info)
*/ */
static int sa1100fb_blank(int blank, 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; int i;
DPRINTK("sa1100fb_blank: blank=%d fix.id=%s\n", blank, DPRINTK("sa1100fb_blank: blank=%d info->modename=%s\n", blank,
info->fix.id); fbi->fb.modename);
switch (blank) { switch (blank) {
case VESA_POWERDOWN: case VESA_POWERDOWN:
case VESA_VSYNC_SUSPEND: case VESA_VSYNC_SUSPEND:
case VESA_HSYNC_SUSPEND: case VESA_HSYNC_SUSPEND:
if (info->disp->visual == FB_VISUAL_PSEUDOCOLOR || if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
info->disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
for (i = 0; i < par->palette_size; i++) for (i = 0; i < fbi->palette_size; i++)
sa1100fb_setpalettereg(i, 0, 0, 0, 0, info); sa1100fb_setpalettereg(i, 0, 0, 0, 0, info);
sa1100fb_schedule_task(par, C_DISABLE); sa1100fb_schedule_task(fbi, C_DISABLE);
if (sa1100fb_blank_helper) if (sa1100fb_blank_helper)
sa1100fb_blank_helper(blank); sa1100fb_blank_helper(blank);
break; break;
...@@ -1108,30 +1317,83 @@ static int sa1100fb_blank(int blank, struct fb_info *info) ...@@ -1108,30 +1317,83 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
case VESA_NO_BLANKING: case VESA_NO_BLANKING:
if (sa1100fb_blank_helper) if (sa1100fb_blank_helper)
sa1100fb_blank_helper(blank); sa1100fb_blank_helper(blank);
if (info->disp->visual == FB_VISUAL_PSEUDOCOLOR || if (fbi->fb.disp->visual == FB_VISUAL_PSEUDOCOLOR ||
info->disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) fbi->fb.disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
fb_set_cmap(&info->cmap, 1, info); fb_set_cmap(&fbi->fb.cmap, 1, info);
sa1100fb_schedule_task(par, C_ENABLE); sa1100fb_schedule_task(fbi, C_ENABLE);
} }
return 0; return 0;
} }
static struct fb_ops sa1100fb_ops = { static struct fb_ops sa1100fb_ops = {
owner: THIS_MODULE, owner: THIS_MODULE,
fb_get_fix: gen_get_fix, fb_get_fix: sa1100fb_get_fix,
fb_get_var: gen_get_var, fb_get_var: sa1100fb_get_var,
fb_set_var: gen_set_var, fb_set_var: sa1100fb_set_var,
fb_get_cmap: gen_get_cmap, fb_get_cmap: sa1100fb_get_cmap,
fb_set_cmap: gen_set_cmap, fb_set_cmap: sa1100fb_set_cmap,
fb_check_var: sa1100fb_check_var,
fb_set_par: sa1100fb_set_par,
fb_setcolreg: sa1100fb_setcolreg, fb_setcolreg: sa1100fb_setcolreg,
fb_blank: sa1100fb_blank, 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). * Calculate the PCD value from the clock rate (in picoseconds).
* We take account of the PPCR clock setting. * We take account of the PPCR clock setting.
...@@ -1141,7 +1403,7 @@ static inline int get_pcd(unsigned int pixclock) ...@@ -1141,7 +1403,7 @@ static inline int get_pcd(unsigned int pixclock)
unsigned int pcd; unsigned int pcd;
if (pixclock) { if (pixclock) {
pcd = cpufreq_get() / 100; pcd = cpufreq_get(0) / 100;
pcd *= pixclock; pcd *= pixclock;
pcd /= 10000000; pcd /= 10000000;
pcd += 1; /* make up for integer math truncations */ pcd += 1; /* make up for integer math truncations */
...@@ -1171,9 +1433,8 @@ static inline int get_pcd(unsigned int pixclock) ...@@ -1171,9 +1433,8 @@ static inline int get_pcd(unsigned int pixclock)
* Configures LCD Controller based on entries in var parameter. Settings are * Configures LCD Controller based on entries in var parameter. Settings are
* only written to the controller if changes were made. * 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; struct sa1100fb_lcd_reg new_regs;
u_int half_screen_size, yres, pcd = get_pcd(var->pixclock); u_int half_screen_size, yres, pcd = get_pcd(var->pixclock);
u_long flags; u_long flags;
...@@ -1190,31 +1451,31 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info * ...@@ -1190,31 +1451,31 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
#if DEBUG_VAR #if DEBUG_VAR
if (var->xres < 16 || var->xres > 1024) if (var->xres < 16 || var->xres > 1024)
printk(KERN_ERR "%s: invalid xres %d\n", 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) if (var->hsync_len < 1 || var->hsync_len > 64)
printk(KERN_ERR "%s: invalid hsync_len %d\n", 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) if (var->left_margin < 1 || var->left_margin > 255)
printk(KERN_ERR "%s: invalid left_margin %d\n", 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) if (var->right_margin < 1 || var->right_margin > 255)
printk(KERN_ERR "%s: invalid right_margin %d\n", 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) if (var->yres < 1 || var->yres > 1024)
printk(KERN_ERR "%s: invalid yres %d\n", 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) if (var->vsync_len < 1 || var->vsync_len > 64)
printk(KERN_ERR "%s: invalid vsync_len %d\n", 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) if (var->upper_margin < 0 || var->upper_margin > 255)
printk(KERN_ERR "%s: invalid upper_margin %d\n", 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) if (var->lower_margin < 0 || var->lower_margin > 255)
printk(KERN_ERR "%s: invalid lower_margin %d\n", printk(KERN_ERR "%s: invalid lower_margin %d\n",
info->fix.id, var->lower_margin); fbi->fb.fix.id, var->lower_margin);
#endif #endif
new_regs.lccr0 = par->lccr0 | new_regs.lccr0 = fbi->lccr0 |
LCCR0_LEN | LCCR0_LDM | LCCR0_BAM | LCCR0_LEN | LCCR0_LDM | LCCR0_BAM |
LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0); LCCR0_ERM | LCCR0_LtlEnd | LCCR0_DMADel(0);
...@@ -1229,7 +1490,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info * ...@@ -1229,7 +1490,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
* the YRES parameter. * the YRES parameter.
*/ */
yres = var->yres; yres = var->yres;
if (par->lccr0 & LCCR0_Dual) if (fbi->lccr0 & LCCR0_Dual)
yres /= 2; yres /= 2;
new_regs.lccr2 = new_regs.lccr2 =
...@@ -1238,7 +1499,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info * ...@@ -1238,7 +1499,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
LCCR2_BegFrmDel(var->upper_margin) + LCCR2_BegFrmDel(var->upper_margin) +
LCCR2_EndFrmDel(var->lower_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_HOR_HIGH_ACT ? LCCR3_HorSnchH : LCCR3_HorSnchL) |
(var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) | (var->sync & FB_SYNC_VERT_HIGH_ACT ? LCCR3_VrtSnchH : LCCR3_VrtSnchL) |
LCCR3_ACBsCntOff; LCCR3_ACBsCntOff;
...@@ -1256,23 +1517,23 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info * ...@@ -1256,23 +1517,23 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
/* Update shadow copy atomically */ /* Update shadow copy atomically */
local_irq_save(flags); local_irq_save(flags);
par->dbar1 = par->palette_dma; fbi->dbar1 = fbi->palette_dma;
par->dbar2 = par->screen_dma + half_screen_size; fbi->dbar2 = fbi->screen_dma + half_screen_size;
par->reg_lccr0 = new_regs.lccr0; fbi->reg_lccr0 = new_regs.lccr0;
par->reg_lccr1 = new_regs.lccr1; fbi->reg_lccr1 = new_regs.lccr1;
par->reg_lccr2 = new_regs.lccr2; fbi->reg_lccr2 = new_regs.lccr2;
par->reg_lccr3 = new_regs.lccr3; fbi->reg_lccr3 = new_regs.lccr3;
local_irq_restore(flags); local_irq_restore(flags);
/* /*
* Only update the registers if the controller is enabled * Only update the registers if the controller is enabled
* and something has changed. * and something has changed.
*/ */
if ((LCCR0 != par->reg_lccr0) || (LCCR1 != par->reg_lccr1) || if ((LCCR0 != fbi->reg_lccr0) || (LCCR1 != fbi->reg_lccr1) ||
(LCCR2 != par->reg_lccr2) || (LCCR3 != par->reg_lccr3) || (LCCR2 != fbi->reg_lccr2) || (LCCR3 != fbi->reg_lccr3) ||
(DBAR1 != par->dbar1) || (DBAR2 != par->dbar2)) (DBAR1 != fbi->dbar1) || (DBAR2 != fbi->dbar2))
sa1100fb_schedule_task(par, C_REENABLE); sa1100fb_schedule_task(fbi, C_REENABLE);
return 0; return 0;
} }
...@@ -1289,7 +1550,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info * ...@@ -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 * Also, I'm expecting that the backlight stuff should
* be handled differently. * 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"); DPRINTK("backlight on\n");
...@@ -1302,7 +1563,7 @@ static inline void sa1100fb_backlight_on(struct sa1100_par *par) ...@@ -1302,7 +1563,7 @@ static inline void sa1100fb_backlight_on(struct sa1100_par *par)
* Also, I'm expecting that the backlight stuff should * Also, I'm expecting that the backlight stuff should
* be handled differently. * 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"); DPRINTK("backlight off\n");
...@@ -1310,7 +1571,7 @@ static inline void sa1100fb_backlight_off(struct sa1100_par *par) ...@@ -1310,7 +1571,7 @@ static inline void sa1100fb_backlight_off(struct sa1100_par *par)
sa1100fb_backlight_power(0); 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"); DPRINTK("LCD power on\n");
...@@ -1325,7 +1586,7 @@ static inline void sa1100fb_power_up_lcd(struct sa1100_par *par) ...@@ -1325,7 +1586,7 @@ static inline void sa1100fb_power_up_lcd(struct sa1100_par *par)
#endif #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"); DPRINTK("LCD power off\n");
...@@ -1340,7 +1601,7 @@ static inline void sa1100fb_power_down_lcd(struct sa1100_par *par) ...@@ -1340,7 +1601,7 @@ static inline void sa1100fb_power_down_lcd(struct sa1100_par *par)
#endif #endif
} }
static void sa1100fb_setup_gpio(struct sa1100_par *par) static void sa1100fb_setup_gpio(struct sa1100fb_info *fbi)
{ {
u_int mask = 0; u_int mask = 0;
...@@ -1356,12 +1617,12 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par) ...@@ -1356,12 +1617,12 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par)
* clear LDD15 to 12 for 4 or 8bpp modes with active * clear LDD15 to 12 for 4 or 8bpp modes with active
* panels. * panels.
*/ */
if ((par->reg_lccr0 & LCCR0_CMS) == LCCR0_Color && if ((fbi->reg_lccr0 & LCCR0_CMS) == LCCR0_Color &&
(par->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) { (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) != 0) {
mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8; mask = GPIO_LDD11 | GPIO_LDD10 | GPIO_LDD9 | GPIO_LDD8;
if (par->bpp > 8 || if (fbi->fb.var.bits_per_pixel > 8 ||
(par->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual) (fbi->reg_lccr0 & (LCCR0_Dual|LCCR0_Act)) == LCCR0_Dual)
mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12; mask |= GPIO_LDD15 | GPIO_LDD14 | GPIO_LDD13 | GPIO_LDD12;
} }
...@@ -1405,23 +1666,23 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par) ...@@ -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"); DPRINTK("Enabling LCD controller\n");
/* /*
* Make sure the mode bits are present in the first palette entry * Make sure the mode bits are present in the first palette entry
*/ */
par->palette_cpu[0] &= 0xcfff; fbi->palette_cpu[0] &= 0xcfff;
par->palette_cpu[0] |= palette_pbs(par->bpp); fbi->palette_cpu[0] |= palette_pbs(&fbi->fb.var);
/* Sequence from 11.7.10 */ /* Sequence from 11.7.10 */
LCCR3 = par->reg_lccr3; LCCR3 = fbi->reg_lccr3;
LCCR2 = par->reg_lccr2; LCCR2 = fbi->reg_lccr2;
LCCR1 = par->reg_lccr1; LCCR1 = fbi->reg_lccr1;
LCCR0 = par->reg_lccr0 & ~LCCR0_LEN; LCCR0 = fbi->reg_lccr0 & ~LCCR0_LEN;
DBAR1 = par->dbar1; DBAR1 = fbi->dbar1;
DBAR2 = par->dbar2; DBAR2 = fbi->dbar2;
LCCR0 |= LCCR0_LEN; LCCR0 |= LCCR0_LEN;
#ifdef CONFIG_SA1100_GRAPHICSCLIENT #ifdef CONFIG_SA1100_GRAPHICSCLIENT
...@@ -1447,7 +1708,7 @@ static void sa1100fb_enable_controller(struct sa1100_par *par) ...@@ -1447,7 +1708,7 @@ static void sa1100fb_enable_controller(struct sa1100_par *par)
DPRINTK("LCCR3 = 0x%08x\n", LCCR3); 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); DECLARE_WAITQUEUE(wait, current);
...@@ -1481,7 +1742,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par) ...@@ -1481,7 +1742,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
GPCR |= SHANNON_GPIO_DISP_EN; GPCR |= SHANNON_GPIO_DISP_EN;
} }
add_wait_queue(&par->ctrlr_wait, &wait); add_wait_queue(&fbi->ctrlr_wait, &wait);
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
LCSR = 0xffffffff; /* Clear LCD Status Register */ LCSR = 0xffffffff; /* Clear LCD Status Register */
...@@ -1490,7 +1751,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par) ...@@ -1490,7 +1751,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
schedule_timeout(20 * HZ / 1000); schedule_timeout(20 * HZ / 1000);
current->state = TASK_RUNNING; 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) ...@@ -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) 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; unsigned int lcsr = LCSR;
if (lcsr & LCSR_LDD) { if (lcsr & LCSR_LDD) {
LCCR0 |= LCCR0_LDM; LCCR0 |= LCCR0_LDM;
wake_up(&par->ctrlr_wait); wake_up(&fbi->ctrlr_wait);
} }
LCSR = lcsr; LCSR = lcsr;
...@@ -1514,13 +1775,13 @@ static void sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs) ...@@ -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 * sleep when disabling the LCD controller, or if we get two contending
* processes trying to alter state. * 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; u_int old_state;
down(&par->ctrlr_sem); down(&fbi->ctrlr_sem);
old_state = par->state; old_state = fbi->state;
switch (state) { switch (state) {
case C_DISABLE_CLKCHANGE: case C_DISABLE_CLKCHANGE:
...@@ -1529,8 +1790,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state) ...@@ -1529,8 +1790,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* controller is already disabled, then do nothing. * controller is already disabled, then do nothing.
*/ */
if (old_state != C_DISABLE && old_state != C_DISABLE_PM) { if (old_state != C_DISABLE && old_state != C_DISABLE_PM) {
par->state = state; fbi->state = state;
sa1100fb_disable_controller(par); sa1100fb_disable_controller(fbi);
} }
break; break;
...@@ -1540,12 +1801,12 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state) ...@@ -1540,12 +1801,12 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* Disable controller * Disable controller
*/ */
if (old_state != C_DISABLE) { 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) if (old_state != C_DISABLE_CLKCHANGE)
sa1100fb_disable_controller(par); sa1100fb_disable_controller(fbi);
sa1100fb_power_down_lcd(par); sa1100fb_power_down_lcd(fbi);
} }
break; break;
...@@ -1555,8 +1816,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state) ...@@ -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. * do this if we were disabled for the clock change.
*/ */
if (old_state == C_DISABLE_CLKCHANGE) { if (old_state == C_DISABLE_CLKCHANGE) {
par->state = C_ENABLE; fbi->state = C_ENABLE;
sa1100fb_enable_controller(par); sa1100fb_enable_controller(fbi);
} }
break; break;
...@@ -1567,9 +1828,9 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state) ...@@ -1567,9 +1828,9 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* registers. * registers.
*/ */
if (old_state == C_ENABLE) { if (old_state == C_ENABLE) {
sa1100fb_disable_controller(par); sa1100fb_disable_controller(fbi);
sa1100fb_setup_gpio(par); sa1100fb_setup_gpio(fbi);
sa1100fb_enable_controller(par); sa1100fb_enable_controller(fbi);
} }
break; break;
...@@ -1589,15 +1850,15 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state) ...@@ -1589,15 +1850,15 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* turn on the backlight. * turn on the backlight.
*/ */
if (old_state != C_ENABLE) { if (old_state != C_ENABLE) {
par->state = C_ENABLE; fbi->state = C_ENABLE;
sa1100fb_setup_gpio(par); sa1100fb_setup_gpio(fbi);
sa1100fb_power_up_lcd(par); sa1100fb_power_up_lcd(fbi);
sa1100fb_enable_controller(par); sa1100fb_enable_controller(fbi);
sa1100fb_backlight_on(par); sa1100fb_backlight_on(fbi);
} }
break; 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) ...@@ -1606,12 +1867,10 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
*/ */
static void sa1100fb_task(void *dummy) static void sa1100fb_task(void *dummy)
{ {
struct fb_info *info = dummy; struct sa1100fb_info *fbi = dummy;
struct sa1100_par *par = (struct sa1100_par *) info->par; u_int state = xchg(&fbi->task_state, -1);
u_int state = xchg(&par->task_state, -1); set_ctrlr_state(fbi, state);
set_ctrlr_state(par, state);
} }
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
...@@ -1620,7 +1879,7 @@ static void sa1100fb_task(void *dummy) ...@@ -1620,7 +1879,7 @@ static void sa1100fb_task(void *dummy)
* This, together with the SDRAM bandwidth defines the slowest CPU * This, together with the SDRAM bandwidth defines the slowest CPU
* frequency that can be selected. * 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; unsigned int min_period = (unsigned int)-1;
int i; int i;
...@@ -1631,13 +1890,13 @@ static unsigned int sa1100fb_min_dma_period(struct fb_info *info) ...@@ -1631,13 +1890,13 @@ static unsigned int sa1100fb_min_dma_period(struct fb_info *info)
/* /*
* Do we own this display? * Do we own this display?
*/ */
if (fb_display[i].fb_info != info) if (fb_display[i].fb_info != &fbi->fb)
continue; continue;
/* /*
* Ok, calculate its DMA period * 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) if (period < min_period)
min_period = period; min_period = period;
} }
...@@ -1654,27 +1913,26 @@ static int ...@@ -1654,27 +1913,26 @@ static int
sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val, sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
void *data) void *data)
{ {
struct fb_info *info = TO_INF(nb, clockchg); struct sa1100fb_info *fbi = TO_INF(nb, clockchg);
struct sa1100_par *par = (struct sa1100_par *) info->par; struct cpufreq_minmax *mm = data;
struct cpufreq_freqs *mm = data;
u_int pcd; u_int pcd;
switch (val) { switch (val) {
case CPUFREQ_MINMAX: case CPUFREQ_MINMAX:
printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, " printk(KERN_DEBUG "min dma period: %d ps, old clock %d kHz, "
"new clock %d kHz\n", sa1100fb_min_dma_period(info), "new clock %d kHz\n", sa1100fb_min_dma_period(fbi),
mm->cur, mm->new); mm->cur_freq, mm->new_freq);
/* todo: fill in min/max values */ /* todo: fill in min/max values */
break; break;
case CPUFREQ_PRECHANGE: case CPUFREQ_PRECHANGE:
set_ctrlr_state(par, C_DISABLE_CLKCHANGE); set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE);
break; break;
case CPUFREQ_POSTCHANGE: case CPUFREQ_POSTCHANGE:
pcd = get_pcd(info->var.pixclock); pcd = get_pcd(fbi->fb.var.pixclock);
par->reg_lccr3 = (par->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd); fbi->reg_lccr3 = (fbi->reg_lccr3 & ~0xff) | LCCR3_PixClkDiv(pcd);
set_ctrlr_state(par, C_ENABLE_CLKCHANGE); set_ctrlr_state(fbi, C_ENABLE_CLKCHANGE);
break; break;
} }
return 0; return 0;
...@@ -1689,7 +1947,7 @@ sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val, ...@@ -1689,7 +1947,7 @@ sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
static int static int
sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) 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); DPRINTK("pm_callback: %d\n", req);
...@@ -1698,10 +1956,10 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ...@@ -1698,10 +1956,10 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
if (state == 0) { if (state == 0) {
/* Enter D0. */ /* Enter D0. */
set_ctrlr_state(par, C_ENABLE_PM); set_ctrlr_state(fbi, C_ENABLE_PM);
} else { } else {
/* Enter D1-D3. Disable the LCD controller. */ /* Enter D1-D3. Disable the LCD controller. */
set_ctrlr_state(par, C_DISABLE_PM); set_ctrlr_state(fbi, C_DISABLE_PM);
} }
} }
DPRINTK("done\n"); DPRINTK("done\n");
...@@ -1717,142 +1975,133 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data) ...@@ -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 * cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region. * 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 * We reserve one page for the palette, plus the size
* of the framebuffer. * of the framebuffer.
*/ */
par->map_size = PAGE_ALIGN(info->fix.smem_len + PAGE_SIZE); fbi->map_size = PAGE_ALIGN(fbi->fb.fix.smem_len + PAGE_SIZE);
par->map_cpu = consistent_alloc(GFP_KERNEL, par->map_size, fbi->map_cpu = consistent_alloc(GFP_KERNEL, fbi->map_size,
&par->map_dma); &fbi->map_dma);
if (par->map_cpu) { if (fbi->map_cpu) {
info->screen_base = par->map_cpu + PAGE_SIZE; fbi->fb.screen_base = fbi->map_cpu + PAGE_SIZE;
par->screen_dma = par->map_dma + PAGE_SIZE; fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
info->fix.smem_start = par->screen_dma; 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 = { static struct fb_monspecs monspecs __initdata = {
30000, 70000, 50, 65, 0 /* Generic */ 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 sa1100fb_mach_info *inf;
struct fb_info *info; struct sa1100fb_info *fbi;
struct sa1100_par *par;
info = kmalloc(sizeof(struct fb_info) + sizeof(struct display) + fbi = kmalloc(sizeof(struct sa1100fb_info) + sizeof(struct display) +
sizeof(u16) * 16, GFP_KERNEL); sizeof(u16) * 16, GFP_KERNEL);
if (!info) if (!fbi)
return NULL; return NULL;
memset(info, 0, sizeof(struct fb_info) + sizeof(struct display)); memset(fbi, 0, sizeof(struct sa1100fb_info) + sizeof(struct display));
par = kmalloc(sizeof(struct sa1100_par), GFP_KERNEL); fbi->fb.currcon = -1;
memset(par, 0, sizeof(struct sa1100_par));
strcpy(fbi->fb.fix.id, SA1100_NAME);
info->currcon = -1;
fbi->fb.fix.type = FB_TYPE_PACKED_PIXELS;
strcpy(info->fix.id, SA1100_NAME); fbi->fb.fix.type_aux = 0;
fbi->fb.fix.xpanstep = 0;
info->fix.type = FB_TYPE_PACKED_PIXELS; fbi->fb.fix.ypanstep = 0;
info->fix.type_aux = 0; fbi->fb.fix.ywrapstep = 0;
info->fix.xpanstep = 0; fbi->fb.fix.accel = FB_ACCEL_NONE;
info->fix.ypanstep = 0;
info->fix.ywrapstep = 0; fbi->fb.var.nonstd = 0;
info->fix.accel = FB_ACCEL_NONE; fbi->fb.var.activate = FB_ACTIVATE_NOW;
fbi->fb.var.height = -1;
info->var.nonstd = 0; fbi->fb.var.width = -1;
info->var.activate = FB_ACTIVATE_NOW; fbi->fb.var.accel_flags = 0;
info->var.height = -1; fbi->fb.var.vmode = FB_VMODE_NONINTERLACED;
info->var.width = -1;
info->var.accel_flags = 0; strcpy(fbi->fb.modename, SA1100_NAME);
info->var.vmode = FB_VMODE_NONINTERLACED; strcpy(fbi->fb.fontname, "Acorn8x8");
strcpy(info->modename, info->fix.id); fbi->fb.fbops = &sa1100fb_ops;
strcpy(info->fontname, "Acorn8x8"); fbi->fb.changevar = NULL;
fbi->fb.switch_con = sa1100fb_switch;
info->fbops = &sa1100fb_ops; fbi->fb.updatevar = sa1100fb_updatevar;
info->changevar = NULL; fbi->fb.flags = FBINFO_FLAG_DEFAULT;
info->switch_con = gen_switch; fbi->fb.node = NODEV;
info->updatevar = gen_update_var; fbi->fb.monspecs = monspecs;
info->flags = FBINFO_FLAG_DEFAULT; fbi->fb.currcon = -1;
info->node = NODEV; fbi->fb.disp = (struct display *)(fbi + 1);
info->monspecs = monspecs; fbi->fb.pseudo_palette = (void *)(fbi->fb.disp + 1);
info->currcon = -1;
info->disp = (struct display *)(info + 1); fbi->rgb[RGB_8] = &rgb_8;
info->pseudo_palette = (void *)(info->disp + 1); fbi->rgb[RGB_16] = &def_rgb_16;
info->par = par;
inf = sa1100fb_get_machine_info(fbi);
par->rgb[RGB_8] = &rgb_8;
par->rgb[RGB_16] = &def_rgb_16; fbi->max_xres = inf->xres;
fbi->fb.var.xres = inf->xres;
inf = sa1100fb_get_machine_info(par); fbi->fb.var.xres_virtual = inf->xres;
fbi->max_yres = inf->yres;
par->max_xres = inf->xres; fbi->fb.var.yres = inf->yres;
info->var.xres = inf->xres; fbi->fb.var.yres_virtual = inf->yres;
info->var.xres_virtual = inf->xres; fbi->max_bpp = inf->bpp;
par->max_yres = inf->yres; fbi->fb.var.bits_per_pixel = inf->bpp;
info->var.yres = inf->yres; fbi->fb.var.pixclock = inf->pixclock;
info->var.yres_virtual = inf->yres; fbi->fb.var.hsync_len = inf->hsync_len;
par->max_bpp = inf->bpp; fbi->fb.var.left_margin = inf->left_margin;
info->var.bits_per_pixel = inf->bpp; fbi->fb.var.right_margin = inf->right_margin;
info->var.pixclock = inf->pixclock; fbi->fb.var.vsync_len = inf->vsync_len;
info->var.hsync_len = inf->hsync_len; fbi->fb.var.upper_margin = inf->upper_margin;
info->var.left_margin = inf->left_margin; fbi->fb.var.lower_margin = inf->lower_margin;
info->var.right_margin = inf->right_margin; fbi->fb.var.sync = inf->sync;
info->var.vsync_len = inf->vsync_len; fbi->fb.var.grayscale = inf->cmap_greyscale;
info->var.upper_margin = inf->upper_margin; fbi->cmap_inverse = inf->cmap_inverse;
info->var.lower_margin = inf->lower_margin; fbi->cmap_static = inf->cmap_static;
info->var.sync = inf->sync; fbi->lccr0 = inf->lccr0;
info->var.grayscale = inf->cmap_greyscale; fbi->lccr3 = inf->lccr3;
par->cmap_inverse = inf->cmap_inverse; fbi->state = C_DISABLE;
par->cmap_static = inf->cmap_static; fbi->task_state = (u_char)-1;
par->lccr0 = inf->lccr0; fbi->fb.fix.smem_len = fbi->max_xres * fbi->max_yres *
par->lccr3 = inf->lccr3; fbi->max_bpp / 8;
par->state = C_DISABLE;
par->task_state = (u_char)-1; init_waitqueue_head(&fbi->ctrlr_wait);
info->fix.smem_len = par->max_xres * par->max_yres * INIT_TQUEUE(&fbi->task, sa1100fb_task, fbi);
par->max_bpp / 8; init_MUTEX(&fbi->ctrlr_sem);
init_waitqueue_head(&par->ctrlr_wait); return fbi;
INIT_TQUEUE(&par->task, sa1100fb_task, info);
init_MUTEX(&par->ctrlr_sem);
fb_alloc_cmap(&info->cmap, 256, 0);
return info;
} }
int __init sa1100fb_init(void) int __init sa1100fb_init(void)
{ {
struct fb_info *info; struct sa1100fb_info *fbi;
struct sa1100_par *par;
int ret; int ret;
if (!request_mem_region(0xb0100000, 0x10000, "LCD")) if (!request_mem_region(0xb0100000, 0x10000, "LCD"))
return -EBUSY; return -EBUSY;
info = sa1100fb_init_fbinfo(); fbi = sa1100fb_init_fbinfo();
ret = -ENOMEM; ret = -ENOMEM;
if (!info) if (!fbi)
goto failed; goto failed;
/* Initialize video memory */ /* Initialize video memory */
ret = sa1100fb_map_video_memory(info); ret = sa1100fb_map_video_memory(fbi);
if (ret) if (ret)
goto failed; goto failed;
ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT, ret = request_irq(IRQ_LCD, sa1100fb_handle_irq, SA_INTERRUPT,
"LCD", info->par); "LCD", fbi);
if (ret) { if (ret) {
printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret); printk(KERN_ERR "sa1100fb: request_irq failed: %d\n", ret);
goto failed; goto failed;
...@@ -1873,32 +2122,30 @@ int __init sa1100fb_init(void) ...@@ -1873,32 +2122,30 @@ int __init sa1100fb_init(void)
} }
#endif #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) if (ret < 0)
goto failed; goto failed;
par = info->par;
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* /*
* Note that the console registers this as well, but we want to * Note that the console registers this as well, but we want to
* power down the display prior to sleeping. * power down the display prior to sleeping.
*/ */
par->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback); fbi->pm = pm_register(PM_SYS_DEV, PM_SYS_VGA, sa1100fb_pm_callback);
if (par->pm) if (fbi->pm)
par->pm->data = par; fbi->pm->data = fbi;
#endif #endif
#ifdef CONFIG_CPU_FREQ #ifdef CONFIG_CPU_FREQ
info->clockchg.notifier_call = sa1100fb_clkchg_notifier; fbi->clockchg.notifier_call = sa1100fb_clkchg_notifier;
cpufreq_register_notifier(&info->clockchg); cpufreq_register_notifier(&fbi->clockchg);
#endif #endif
/* /*
* Ok, now enable the LCD controller * 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 */ /* This driver cannot be unloaded at the moment */
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
...@@ -1906,8 +2153,8 @@ int __init sa1100fb_init(void) ...@@ -1906,8 +2153,8 @@ int __init sa1100fb_init(void)
return 0; return 0;
failed: failed:
if (info) if (fbi)
kfree(info); kfree(fbi);
release_mem_region(0xb0100000, 0x10000); release_mem_region(0xb0100000, 0x10000);
return ret; return ret;
} }
......
...@@ -61,13 +61,13 @@ struct sa1100fb_lcd_reg { ...@@ -61,13 +61,13 @@ struct sa1100fb_lcd_reg {
#define RGB_16 (1) #define RGB_16 (1)
#define NR_RGB 2 #define NR_RGB 2
struct sa1100_par { struct sa1100fb_info {
struct fb_info fb;
struct sa1100fb_rgb *rgb[NR_RGB]; struct sa1100fb_rgb *rgb[NR_RGB];
u_int max_bpp;
u_int max_xres; u_int max_xres;
u_int max_yres; u_int max_yres;
u_int max_bpp;
u_int bpp;
/* /*
* These are the addresses we mapped * These are the addresses we mapped
...@@ -86,13 +86,12 @@ struct sa1100_par { ...@@ -86,13 +86,12 @@ struct sa1100_par {
dma_addr_t dbar1; dma_addr_t dbar1;
dma_addr_t dbar2; dma_addr_t dbar2;
u_int lccr0;
u_int lccr3;
u_int cmap_inverse:1, u_int cmap_inverse:1,
cmap_static:1, cmap_static:1,
unused:30; unused:30;
u_int lccr0;
u_int lccr3;
u_int reg_lccr0; u_int reg_lccr0;
u_int reg_lccr1; u_int reg_lccr1;
u_int reg_lccr2; u_int reg_lccr2;
...@@ -103,14 +102,18 @@ struct sa1100_par { ...@@ -103,14 +102,18 @@ struct sa1100_par {
struct semaphore ctrlr_sem; struct semaphore ctrlr_sem;
wait_queue_head_t ctrlr_wait; wait_queue_head_t ctrlr_wait;
struct tq_struct task; struct tq_struct task;
#ifdef CONFIG_PM #ifdef CONFIG_PM
struct pm_dev *pm; struct pm_dev *pm;
#endif #endif
#ifdef CONFIG_CPU_FREQ
struct notifier_block clockchg;
#endif
}; };
#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member))) #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) #define SA1100_PALETTE_MODE_VAL(bpp) (((bpp) & 0x018) << 9)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment