Commit c72757b4 authored by James Simmons's avatar James Simmons

Voodoo 1 ported to new api. STI and NVIDIA updates. MDA console fixes. Moved...

Voodoo 1 ported to new api. STI and NVIDIA updates. MDA console fixes. Moved the logo code from fbcon to fbdev.
parent c198ff87
...@@ -130,7 +130,7 @@ extern void console_map_init(void); ...@@ -130,7 +130,7 @@ extern void console_map_init(void);
extern void prom_con_init(void); extern void prom_con_init(void);
#endif #endif
#ifdef CONFIG_MDA_CONSOLE #ifdef CONFIG_MDA_CONSOLE
extern void mda_console_init(void); extern int mda_console_init(void);
#endif #endif
#ifdef CONFIG_FRAMEBUFFER_CONSOLE #ifdef CONFIG_FRAMEBUFFER_CONSOLE
extern int fb_console_init(void); extern int fb_console_init(void);
......
...@@ -84,7 +84,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt ...@@ -84,7 +84,7 @@ obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt
obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_E1355) += epson1355fb.o obj-$(CONFIG_FB_E1355) += epson1355fb.o
obj-$(CONFIG_FB_PVR2) += pvr2fb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1) += sstfb.o obj-$(CONFIG_FB_VOODOO1) += sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
# Files generated that shall be removed upon make clean # Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c clean-files := promcon_tbl.c
......
...@@ -56,8 +56,6 @@ ...@@ -56,8 +56,6 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/selection.h>
#include <linux/console.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <asm/io.h> #include <asm/io.h>
......
...@@ -102,10 +102,9 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -102,10 +102,9 @@ static inline void color_imageblit(struct fb_image *image, struct fb_info *p, u8
unsigned long start_index, unsigned long pitch_index) unsigned long start_index, unsigned long pitch_index)
{ {
/* Draw the penguin */ /* Draw the penguin */
int i, n;
int bpp = p->var.bits_per_pixel;
unsigned long *palette = (unsigned long *) p->pseudo_palette; unsigned long *palette = (unsigned long *) p->pseudo_palette;
unsigned long *dst, *dst2, color = 0, val, shift; unsigned long *dst, *dst2, color = 0, val, shift;
int i, n, bpp = p->var.bits_per_pixel;
unsigned long null_bits = BITS_PER_LONG - bpp; unsigned long null_bits = BITS_PER_LONG - bpp;
u8 *src = image->data; u8 *src = image->data;
...@@ -189,6 +188,7 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8 ...@@ -189,6 +188,7 @@ static inline void slow_imageblit(struct fb_image *image, struct fb_info *p, u8
color = fgcolor; color = fgcolor;
else else
color = bgcolor; color = bgcolor;
color <<= LEFT_POS(bpp);
val |= SHIFT_HIGH(color, shift); val |= SHIFT_HIGH(color, shift);
/* Did the bitshift spill bits to the next long? */ /* Did the bitshift spill bits to the next long? */
......
...@@ -74,6 +74,22 @@ config STI_CONSOLE ...@@ -74,6 +74,22 @@ config STI_CONSOLE
machines. Say Y here to build support for it into your kernel. machines. Say Y here to build support for it into your kernel.
The alternative is to use your primary serial port as a console. The alternative is to use your primary serial port as a console.
config DUMMY_CONSOLE_COLUMNS
int "Initial number of STI console screen columns" if STI_CONSOLE
depends on STI_CONSOLE || FB_STI
default "160"
help
The default value is 160, which should fit a 1280x1024 monitor.
Select 80 if you use a 640x480 resolution by default.
config DUMMY_CONSOLE_ROWS
int "Initial number of STI console screen rows" if STI_CONSOLE
depends on STI_CONSOLE || FB_STI
default "64"
help
The default value is 64, which should fit a 1280x1024 monitor.
Select 25 if you use a 640x480 resolution by default.
config PROM_CONSOLE config PROM_CONSOLE
bool "PROM console" bool "PROM console"
depends on SPARC32 || SPARC64 depends on SPARC32 || SPARC64
...@@ -121,10 +137,6 @@ config FBCON_ADVANCED ...@@ -121,10 +137,6 @@ config FBCON_ADVANCED
If unsure, say N. If unsure, say N.
# Guess what we need # Guess what we need
config FBCON_STI
tristate
depends on !FBCON_ADVANCED && FRAMEBUFFER_CONSOLE && FB_STI
default y
config FONTWIDTH8_ONLY config FONTWIDTH8_ONLY
bool "Support only 8 pixels wide fonts" bool "Support only 8 pixels wide fonts"
......
...@@ -20,8 +20,10 @@ ...@@ -20,8 +20,10 @@
#define DUMMY_COLUMNS ORIG_VIDEO_COLS #define DUMMY_COLUMNS ORIG_VIDEO_COLS
#define DUMMY_ROWS ORIG_VIDEO_LINES #define DUMMY_ROWS ORIG_VIDEO_LINES
#elif defined(__hppa__) #elif defined(__hppa__)
#define DUMMY_COLUMNS 80 /* fixme ! (mine uses 160x64 at 1280x1024) */ /* set by Kconfig. Use 80x25 for 640x480 and 160x64 for 1280x1024 */
#define DUMMY_ROWS 25 #include <linux/config.h>
#define DUMMY_COLUMNS CONFIG_DUMMY_CONSOLE_COLUMNS
#define DUMMY_ROWS CONFIG_DUMMY_CONSOLE_ROWS
#else #else
#define DUMMY_COLUMNS 80 #define DUMMY_COLUMNS 80
#define DUMMY_ROWS 25 #define DUMMY_ROWS 25
......
...@@ -93,8 +93,6 @@ ...@@ -93,8 +93,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/setup.h> #include <asm/setup.h>
#endif #endif
#define INCLUDE_LINUX_LOGO_DATA
#include <asm/linux_logo.h>
#include "fbcon.h" #include "fbcon.h"
#include "font.h" #include "font.h"
...@@ -203,8 +201,6 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc, ...@@ -203,8 +201,6 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy,
int dx, int height, int width, u_int y_break); int dx, int height, int width, u_int y_break);
static int fbcon_show_logo(void);
#ifdef CONFIG_MAC #ifdef CONFIG_MAC
/* /*
* On the Macintoy, there may or may not be a working VBL int. We need to probe * On the Macintoy, there may or may not be a working VBL int. We need to probe
...@@ -1945,7 +1941,7 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1945,7 +1941,7 @@ static int fbcon_switch(struct vc_data *vc)
accel_clear_margins(vc, p, 0); accel_clear_margins(vc, p, 0);
if (logo_shown == -2) { if (logo_shown == -2) {
logo_shown = fg_console; logo_shown = fg_console;
fbcon_show_logo(); /* This is protected above by initmem_freed */ fb_show_logo(info); /* This is protected above by initmem_freed */
update_region(fg_console, update_region(fg_console,
vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_origin + vc->vc_size_row * vc->vc_top,
vc->vc_size_row * (vc->vc_bottom - vc->vc_size_row * (vc->vc_bottom -
...@@ -2347,8 +2343,7 @@ static struct fb_cmap palette_cmap = { ...@@ -2347,8 +2343,7 @@ static struct fb_cmap palette_cmap = {
static int fbcon_set_palette(struct vc_data *vc, unsigned char *table) static int fbcon_set_palette(struct vc_data *vc, unsigned char *table)
{ {
int unit = vc->vc_num; struct display *p = &fb_display[vc->vc_num];
struct display *p = &fb_display[unit];
struct fb_info *info = p->fb_info; struct fb_info *info = p->fb_info;
int i, j, k; int i, j, k;
u8 val; u8 val;
...@@ -2548,253 +2543,6 @@ static int fbcon_set_origin(struct vc_data *vc) ...@@ -2548,253 +2543,6 @@ static int fbcon_set_origin(struct vc_data *vc)
return 0; return 0;
} }
static inline unsigned safe_shift(unsigned d, int n)
{
return n < 0 ? d >> -n : d << n;
}
static void __init fbcon_set_logocmap(struct fb_info *info)
{
int i, j, n;
for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
n = LINUX_LOGO_COLORS - i;
if (n > 16)
/* palette_cmap provides space for only 16 colors at once */
n = 16;
palette_cmap.start = 32 + i;
palette_cmap.len = n;
for (j = 0; j < n; ++j) {
palette_cmap.red[j] =
(linux_logo_red[i + j] << 8) |
linux_logo_red[i + j];
palette_cmap.green[j] =
(linux_logo_green[i + j] << 8) |
linux_logo_green[i + j];
palette_cmap.blue[j] =
(linux_logo_blue[i + j] << 8) |
linux_logo_blue[i + j];
}
fb_set_cmap(&palette_cmap, 1, info);
}
}
static void __init fbcon_set_logo_truepalette(struct fb_info *info, u32 *palette)
{
unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
unsigned char redmask, greenmask, bluemask;
int redshift, greenshift, blueshift;
int i;
/*
* We have to create a temporary palette since console palette is only
* 16 colors long.
*/
/* Bug: Doesn't obey msb_right ... (who needs that?) */
redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
redshift = info->var.red.offset - (8 - info->var.red.length);
greenshift = info->var.green.offset - (8 - info->var.green.length);
blueshift = info->var.blue.offset - (8 - info->var.blue.length);
for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
palette[i+32] = (safe_shift((linux_logo_red[i] & redmask), redshift) |
safe_shift((linux_logo_green[i] & greenmask), greenshift) |
safe_shift((linux_logo_blue[i] & bluemask), blueshift));
}
}
static void __init fbcon_set_logo_directpalette(struct fb_info *info, u32 *palette)
{
int redshift, greenshift, blueshift;
int i;
redshift = info->var.red.offset;
greenshift = info->var.green.offset;
blueshift = info->var.blue.offset;
for (i = 32; i < LINUX_LOGO_COLORS; i++)
palette[i] = i << redshift | i << greenshift | i << blueshift;
}
static void __init fbcon_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
{
int i, j;
switch (needs_logo) {
case 4:
for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
logo[i*2] = linux_logo16[i] >> 4;
logo[(i*2)+1] = linux_logo16[i] & 0xf;
}
break;
case 1:
case ~1:
default:
for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
for (j = 0; j < 8; j++)
logo[i*8 + j] = (linux_logo_bw[i] & (7 - j)) ?
((needs_logo == 1) ? 1 : 0) :
((needs_logo == 1) ? 0 : 1);
break;
}
}
/*
* Three (3) kinds of logo maps exist. linux_logo (>16 colors), linux_logo_16
* (16 colors) and linux_logo_bw (2 colors). Depending on the visual format and
* color depth of the framebuffer, the DAC, the pseudo_palette, and the logo data
* will be adjusted accordingly.
*
* Case 1 - linux_logo:
* Color exceeds the number of console colors (16), thus we set the hardware DAC
* using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
*
* For visuals that require color info from the pseudo_palette, we also construct
* one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
* will be set.
*
* Case 2 - linux_logo_16:
* The number of colors just matches the console colors, thus there is no need
* to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
* each byte contains color information for two pixels (upper and lower nibble).
* To be consistent with fb_imageblit() usage, we therefore separate the two
* nibbles into separate bytes. The "needs_logo" flag will be set to 4.
*
* Case 3 - linux_logo_bw:
* This is similar with Case 2. Each byte contains information for 8 pixels.
* We isolate each bit and expand each into a byte. The "needs_logo" flag will
* be set to 1.
*/
static int __init fbcon_show_logo(void)
{
struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */
struct fb_info *info = p->fb_info;
struct vc_data *vc = info->display_fg;
struct fb_image image;
u32 *palette = NULL, *saved_palette = NULL;
unsigned char *fb = info->screen_base, *logo_new = NULL;
int done = 0, x;
int needs_cmapreset = 0;
int needs_truepalette = 0;
int needs_directpalette = 0;
int needs_logo = 0;
/* Return if the frame buffer is not mapped */
if (!fb || !info->fbops->fb_imageblit)
return 0;
image.depth = info->var.bits_per_pixel;
/* reasonable default */
if (image.depth >= 8)
image.data = linux_logo;
else if (image.depth >= 4)
image.data = linux_logo16;
else
image.data = linux_logo_bw;
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
needs_truepalette = 1;
if (image.depth >= 4 && image.depth <= 8)
needs_logo = 4;
else if (image.depth < 4)
needs_logo = 1;
break;
case FB_VISUAL_DIRECTCOLOR:
if (image.depth >= 24) {
needs_directpalette = 1;
needs_cmapreset = 1;
}
/* 16 colors */
else if (image.depth >= 16)
needs_logo = 4;
/* 2 colors */
else
needs_logo = 1;
break;
case FB_VISUAL_MONO01:
/* reversed 0 = fg, 1 = bg */
needs_logo = ~1;
break;
case FB_VISUAL_MONO10:
needs_logo = 1;
break;
case FB_VISUAL_PSEUDOCOLOR:
default:
if (image.depth >= 8)
needs_cmapreset = 1;
/* fall through */
case FB_VISUAL_STATIC_PSEUDOCOLOR:
/* 16 colors */
if (image.depth >= 4 && image.depth < 8)
needs_logo = 4;
/* 2 colors */
else if (image.depth < 4)
needs_logo = 1;
break;
}
if (needs_cmapreset)
fbcon_set_logocmap(info);
if (needs_truepalette || needs_directpalette) {
palette = kmalloc(256 * 4, GFP_KERNEL);
if (palette == NULL)
return 1;
if (needs_truepalette)
fbcon_set_logo_truepalette(info, palette);
else
fbcon_set_logo_directpalette(info, palette);
saved_palette = info->pseudo_palette;
info->pseudo_palette = palette;
}
if (needs_logo) {
logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
if (logo_new == NULL) {
if (palette)
kfree(palette);
if (saved_palette)
info->pseudo_palette = saved_palette;
return 1;
}
image.data = logo_new;
fbcon_set_logo(info, logo_new, needs_logo);
}
image.width = LOGO_W;
image.height = LOGO_H;
image.dy = 0;
for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
image.dx = x;
info->fbops->fb_imageblit(info, &image);
done = 1;
}
if (palette != NULL)
kfree(palette);
if (saved_palette != NULL)
info->pseudo_palette = saved_palette;
if (logo_new != NULL)
kfree(logo_new);
/*
* Modes not yet supported: packed pixels with depth != 8 (does such a
* thing exist in reality?)
*/
return done ? (LOGO_H + vc->vc_font.height - 1) / vc->vc_font.height : 0;
}
/* /*
* The console `switch' structure for the frame buffer based console * The console `switch' structure for the frame buffer based console
*/ */
......
...@@ -51,8 +51,6 @@ extern struct display fb_display[MAX_NR_CONSOLES]; ...@@ -51,8 +51,6 @@ extern struct display fb_display[MAX_NR_CONSOLES];
extern char con2fb_map[MAX_NR_CONSOLES]; extern char con2fb_map[MAX_NR_CONSOLES];
extern void set_con2fb_map(int unit, int newidx); extern void set_con2fb_map(int unit, int newidx);
#define fontheight(p) ((p)->_fontheight)
#ifdef CONFIG_FONTWIDTH8_ONLY #ifdef CONFIG_FONTWIDTH8_ONLY
/* fontwidth w is supported by dispsw */ /* fontwidth w is supported by dispsw */
...@@ -60,8 +58,6 @@ extern void set_con2fb_map(int unit, int newidx); ...@@ -60,8 +58,6 @@ extern void set_con2fb_map(int unit, int newidx);
/* fontwidths w1-w2 inclusive are supported by dispsw */ /* fontwidths w1-w2 inclusive are supported by dispsw */
#define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8) #define FONTWIDTHRANGE(w1,w2) FONTWIDTH(8)
#define fontwidth(p) (8)
#else #else
/* fontwidth w is supported by dispsw */ /* fontwidth w is supported by dispsw */
...@@ -69,8 +65,6 @@ extern void set_con2fb_map(int unit, int newidx); ...@@ -69,8 +65,6 @@ extern void set_con2fb_map(int unit, int newidx);
/* fontwidths w1-w2 inclusive are supported by dispsw */ /* fontwidths w1-w2 inclusive are supported by dispsw */
#define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1)) #define FONTWIDTHRANGE(w1,w2) (FONTWIDTH(w2+1) - FONTWIDTH(w1))
#define fontwidth(p) ((p)->_fontwidth)
#endif #endif
/* /*
......
...@@ -74,7 +74,7 @@ static char *mda_type_name; ...@@ -74,7 +74,7 @@ static char *mda_type_name;
/* console information */ /* console information */
static int mda_first_vc = 13; static int mda_first_vc = 1;
static int mda_last_vc = 16; static int mda_last_vc = 16;
static struct vc_data *mda_display_fg = NULL; static struct vc_data *mda_display_fg = NULL;
...@@ -604,28 +604,22 @@ const struct consw mda_con = { ...@@ -604,28 +604,22 @@ const struct consw mda_con = {
.con_invert_region = mdacon_invert_region, .con_invert_region = mdacon_invert_region,
}; };
void __init mda_console_init(void) int __init mda_console_init(void)
{ {
if (mda_first_vc > mda_last_vc) if (mda_first_vc > mda_last_vc)
return; return 1;
take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0); take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);
}
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
mda_console_init();
return 0; return 0;
} }
void cleanup_module(void) void __exit mda_console_exit(void)
{ {
give_up_console(&mda_con); give_up_console(&mda_con);
} }
#endif module_init(mda_console_init);
module_exit(mda_console_exit);
MODULE_LICENSE("GPL");
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
#include <linux/fb.h> #include <linux/fb.h>
#define INCLUDE_LINUX_LOGO_DATA
#include <asm/linux_logo.h>
#ifdef CONFIG_FRAMEBUFFER_CONSOLE #ifdef CONFIG_FRAMEBUFFER_CONSOLE
#include "console/fbcon.h" #include "console/fbcon.h"
#endif #endif
...@@ -157,11 +160,9 @@ static struct { ...@@ -157,11 +160,9 @@ static struct {
*/ */
{ "sbus", sbusfb_init, sbusfb_setup }, { "sbus", sbusfb_init, sbusfb_setup },
#endif #endif
/* /*
* Chipset specific drivers that use resource management * Chipset specific drivers that use resource management
*/ */
#ifdef CONFIG_FB_RETINAZ3 #ifdef CONFIG_FB_RETINAZ3
{ "retz3", retz3fb_init, retz3fb_setup }, { "retz3", retz3fb_init, retz3fb_setup },
#endif #endif
...@@ -240,6 +241,9 @@ static struct { ...@@ -240,6 +241,9 @@ static struct {
#ifdef CONFIG_FB_I810 #ifdef CONFIG_FB_I810
{ "i810fb", i810fb_init, i810fb_setup }, { "i810fb", i810fb_init, i810fb_setup },
#endif #endif
#ifdef CONFIG_FB_STI
{ "stifb", stifb_init, stifb_setup },
#endif
/* /*
* Generic drivers that are used as fallbacks * Generic drivers that are used as fallbacks
...@@ -333,9 +337,6 @@ static struct { ...@@ -333,9 +337,6 @@ static struct {
#ifdef CONFIG_FB_VGA16 #ifdef CONFIG_FB_VGA16
{ "vga16", vga16fb_init, vga16fb_setup }, { "vga16", vga16fb_init, vga16fb_setup },
#endif #endif
#ifdef CONFIG_FB_STI
{ "stifb", stifb_init, stifb_setup },
#endif
#ifdef CONFIG_GSP_RESOLVER #ifdef CONFIG_GSP_RESOLVER
/* Not a real frame buffer device... */ /* Not a real frame buffer device... */
...@@ -357,15 +358,264 @@ extern const char *global_mode_option; ...@@ -357,15 +358,264 @@ extern const char *global_mode_option;
static initcall_t pref_init_funcs[FB_MAX]; static initcall_t pref_init_funcs[FB_MAX];
static int num_pref_init_funcs __initdata = 0; static int num_pref_init_funcs __initdata = 0;
struct fb_info *registered_fb[FB_MAX]; struct fb_info *registered_fb[FB_MAX];
int num_registered_fb; int num_registered_fb;
static int nologo;
#ifdef CONFIG_FB_OF #ifdef CONFIG_FB_OF
static int ofonly __initdata = 0; static int ofonly __initdata = 0;
#endif #endif
#define LOGO_H 80
#define LOGO_W 80
static inline unsigned safe_shift(unsigned d, int n)
{
return n < 0 ? d >> -n : d << n;
}
static void __init fb_set_logocmap(struct fb_info *info)
{
struct fb_cmap palette_cmap;
u16 palette_green[16];
u16 palette_blue[16];
u16 palette_red[16];
int i, j, n;
palette_cmap.start = 0;
palette_cmap.len = 16;
palette_cmap.red = palette_red;
palette_cmap.green = palette_green;
palette_cmap.blue = palette_blue;
for (i = 0; i < LINUX_LOGO_COLORS; i += n) {
n = LINUX_LOGO_COLORS - i;
/* palette_cmap provides space for only 16 colors at once */
if (n > 16)
n = 16;
palette_cmap.start = 32 + i;
palette_cmap.len = n;
for (j = 0; j < n; ++j) {
palette_cmap.red[j] =
(linux_logo_red[i + j] << 8) |
linux_logo_red[i + j];
palette_cmap.green[j] =
(linux_logo_green[i + j] << 8) |
linux_logo_green[i + j];
palette_cmap.blue[j] =
(linux_logo_blue[i + j] << 8) |
linux_logo_blue[i + j];
}
fb_set_cmap(&palette_cmap, 1, info);
}
}
static void __init fb_set_logo_truepalette(struct fb_info *info, u32 *palette)
{
unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };
unsigned char redmask, greenmask, bluemask;
int redshift, greenshift, blueshift;
int i;
/*
* We have to create a temporary palette since console palette is only
* 16 colors long.
*/
/* Bug: Doesn't obey msb_right ... (who needs that?) */
redmask = mask[info->var.red.length < 8 ? info->var.red.length : 8];
greenmask = mask[info->var.green.length < 8 ? info->var.green.length : 8];
bluemask = mask[info->var.blue.length < 8 ? info->var.blue.length : 8];
redshift = info->var.red.offset - (8 - info->var.red.length);
greenshift = info->var.green.offset - (8 - info->var.green.length);
blueshift = info->var.blue.offset - (8 - info->var.blue.length);
for ( i = 0; i < LINUX_LOGO_COLORS; i++) {
palette[i+32] = (safe_shift((linux_logo_red[i] & redmask), redshift) |
safe_shift((linux_logo_green[i] & greenmask), greenshift) |
safe_shift((linux_logo_blue[i] & bluemask), blueshift));
}
}
static void __init fb_set_logo_directpalette(struct fb_info *info, u32 *palette)
{
int redshift, greenshift, blueshift;
int i;
redshift = info->var.red.offset;
greenshift = info->var.green.offset;
blueshift = info->var.blue.offset;
for (i = 32; i < LINUX_LOGO_COLORS; i++)
palette[i] = i << redshift | i << greenshift | i << blueshift;
}
static void __init fb_set_logo(struct fb_info *info, u8 *logo, int needs_logo)
{
int i, j;
switch (needs_logo) {
case 4:
for (i = 0; i < (LOGO_W * LOGO_H)/2; i++) {
logo[i*2] = linux_logo16[i] >> 4;
logo[(i*2)+1] = linux_logo16[i] & 0xf;
}
break;
case 1:
case ~1:
default:
for (i = 0; i < (LOGO_W * LOGO_H)/8; i++)
for (j = 0; j < 8; j++)
logo[i*8 + j] = (linux_logo_bw[i] & (7 - j)) ?
((needs_logo == 1) ? 1 : 0) :
((needs_logo == 1) ? 0 : 1);
break;
}
}
/*
* Three (3) kinds of logo maps exist. linux_logo (>16 colors), linux_logo_16
* (16 colors) and linux_logo_bw (2 colors). Depending on the visual format and
* color depth of the framebuffer, the DAC, the pseudo_palette, and the logo data
* will be adjusted accordingly.
*
* Case 1 - linux_logo:
* Color exceeds the number of console colors (16), thus we set the hardware DAC
* using fb_set_cmap() appropriately. The "needs_cmapreset" flag will be set.
*
* For visuals that require color info from the pseudo_palette, we also construct
* one for temporary use. The "needs_directpalette" or "needs_truepalette" flags
* will be set.
*
* Case 2 - linux_logo_16:
* The number of colors just matches the console colors, thus there is no need
* to set the DAC or the pseudo_palette. However, the bitmap is packed, ie,
* each byte contains color information for two pixels (upper and lower nibble).
* To be consistent with fb_imageblit() usage, we therefore separate the two
* nibbles into separate bytes. The "needs_logo" flag will be set to 4.
*
* Case 3 - linux_logo_bw:
* This is similar with Case 2. Each byte contains information for 8 pixels.
* We isolate each bit and expand each into a byte. The "needs_logo" flag will
* be set to 1.
*/
int fb_show_logo(struct fb_info *info)
{
unsigned char *fb = info->screen_base, *logo_new = NULL;
u32 *palette = NULL, *saved_palette = NULL;
int needs_directpalette = 0;
int needs_truepalette = 0;
int needs_cmapreset = 0;
struct fb_image image;
int needs_logo = 0;
int done = 0, x;
/* Return if the frame buffer is not mapped */
if (!fb || !info->fbops->fb_imageblit)
return 0;
image.depth = info->var.bits_per_pixel;
/* reasonable default */
if (image.depth >= 8)
image.data = linux_logo;
else if (image.depth >= 4)
image.data = linux_logo16;
else
image.data = linux_logo_bw;
switch (info->fix.visual) {
case FB_VISUAL_TRUECOLOR:
needs_truepalette = 1;
if (image.depth >= 4 && image.depth <= 8)
needs_logo = 4;
else if (image.depth < 4)
needs_logo = 1;
break;
case FB_VISUAL_DIRECTCOLOR:
if (image.depth >= 24) {
needs_directpalette = 1;
needs_cmapreset = 1;
}
/* 16 colors */
else if (image.depth >= 16)
needs_logo = 4;
/* 2 colors */
else
needs_logo = 1;
break;
case FB_VISUAL_MONO01:
/* reversed 0 = fg, 1 = bg */
needs_logo = ~1;
break;
case FB_VISUAL_MONO10:
needs_logo = 1;
break;
case FB_VISUAL_PSEUDOCOLOR:
default:
if (image.depth >= 8)
needs_cmapreset = 1;
/* fall through */
case FB_VISUAL_STATIC_PSEUDOCOLOR:
/* 16 colors */
if (image.depth >= 4 && image.depth < 8)
needs_logo = 4;
/* 2 colors */
else if (image.depth < 4)
needs_logo = 1;
break;
}
if (needs_cmapreset)
fb_set_logocmap(info);
if (needs_truepalette || needs_directpalette) {
palette = kmalloc(256 * 4, GFP_KERNEL);
if (palette == NULL)
return 1;
if (needs_truepalette)
fb_set_logo_truepalette(info, palette);
else
fb_set_logo_directpalette(info, palette);
saved_palette = info->pseudo_palette;
info->pseudo_palette = palette;
}
if (needs_logo) {
logo_new = kmalloc(LOGO_W * LOGO_H, GFP_KERNEL);
if (logo_new == NULL) {
if (palette)
kfree(palette);
if (saved_palette)
info->pseudo_palette = saved_palette;
return 1;
}
image.data = logo_new;
fb_set_logo(info, logo_new, needs_logo);
}
image.width = LOGO_W;
image.height = LOGO_H;
image.dy = 0;
for (x = 0; x < num_online_cpus() * (LOGO_W + 8) &&
x < info->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {
image.dx = x;
info->fbops->fb_imageblit(info, &image);
done = 1;
}
if (palette != NULL)
kfree(palette);
if (saved_palette != NULL)
info->pseudo_palette = saved_palette;
if (logo_new != NULL)
kfree(logo_new);
return 0;
}
static int fbmem_read_proc(char *buf, char **start, off_t offset, static int fbmem_read_proc(char *buf, char **start, off_t offset,
int len, int *eof, void *private) int len, int *eof, void *private)
{ {
...@@ -465,7 +715,8 @@ static void try_to_load(int fb) ...@@ -465,7 +715,8 @@ static void try_to_load(int fb)
} }
#endif /* CONFIG_KMOD */ #endif /* CONFIG_KMOD */
int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) int
fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
{ {
int xoffset = var->xoffset; int xoffset = var->xoffset;
int yoffset = var->yoffset; int yoffset = var->yoffset;
...@@ -486,7 +737,8 @@ int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) ...@@ -486,7 +737,8 @@ int fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
return 0; return 0;
} }
int fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info) int
fb_set_var(struct fb_var_screeninfo *var, struct fb_info *info)
{ {
int err; int err;
...@@ -706,6 +958,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma) ...@@ -706,6 +958,8 @@ fb_mmap(struct file *file, struct vm_area_struct * vma)
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#elif defined(__sh__) #elif defined(__sh__)
pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE; pgprot_val(vma->vm_page_prot) &= ~_PAGE_CACHABLE;
#elif defined(__hppa__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE;
#elif defined(__ia64__) #elif defined(__ia64__)
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
#else #else
...@@ -739,6 +993,8 @@ fb_open(struct inode *inode, struct file *file) ...@@ -739,6 +993,8 @@ fb_open(struct inode *inode, struct file *file)
if (res) if (res)
module_put(info->fbops->owner); module_put(info->fbops->owner);
} }
if (!nologo)
fb_show_logo(info);
return res; return res;
} }
...@@ -880,46 +1136,49 @@ fbmem_init(void) ...@@ -880,46 +1136,49 @@ fbmem_init(void)
int __init video_setup(char *options) int __init video_setup(char *options)
{ {
int i, j; int i, j;
if (!options || !*options) if (!options || !*options)
return 0; return 0;
#ifdef CONFIG_FB_OF #ifdef CONFIG_FB_OF
if (!strcmp(options, "ofonly")) { if (!strcmp(options, "ofonly")) {
ofonly = 1; ofonly = 1;
return 0; return 0;
} }
#endif #endif
if (num_pref_init_funcs == FB_MAX) if (!strcmp(options, "nologo"))
return 0; nologo = 1;
for (i = 0; i < NUM_FB_DRIVERS; i++) { if (num_pref_init_funcs == FB_MAX)
j = strlen(fb_drivers[i].name); return 0;
if (!strncmp(options, fb_drivers[i].name, j) &&
options[j] == ':') {
if (!strcmp(options+j+1, "off"))
fb_drivers[i].init = NULL;
else {
if (fb_drivers[i].init) {
pref_init_funcs[num_pref_init_funcs++] =
fb_drivers[i].init;
fb_drivers[i].init = NULL;
}
if (fb_drivers[i].setup)
fb_drivers[i].setup(options+j+1);
}
return 0;
}
}
/* for (i = 0; i < NUM_FB_DRIVERS; i++) {
* If we get here no fb was specified. j = strlen(fb_drivers[i].name);
* We consider the argument to be a global video mode option. if (!strncmp(options, fb_drivers[i].name, j) &&
*/ options[j] == ':') {
global_mode_option = options; if (!strcmp(options+j+1, "off"))
return 0; fb_drivers[i].init = NULL;
else {
if (fb_drivers[i].init) {
pref_init_funcs[num_pref_init_funcs++] =
fb_drivers[i].init;
fb_drivers[i].init = NULL;
}
if (fb_drivers[i].setup)
fb_drivers[i].setup(options+j+1);
}
return 0;
}
}
/*
* If we get here no fb was specified.
* We consider the argument to be a global video mode option.
*/
global_mode_option = options;
return 0;
} }
__setup("video=", video_setup); __setup("video=", video_setup);
...@@ -932,6 +1191,8 @@ EXPORT_SYMBOL(register_framebuffer); ...@@ -932,6 +1191,8 @@ EXPORT_SYMBOL(register_framebuffer);
EXPORT_SYMBOL(unregister_framebuffer); EXPORT_SYMBOL(unregister_framebuffer);
EXPORT_SYMBOL(num_registered_fb); EXPORT_SYMBOL(num_registered_fb);
EXPORT_SYMBOL(registered_fb); EXPORT_SYMBOL(registered_fb);
EXPORT_SYMBOL(fb_show_logo);
EXPORT_SYMBOL(fb_set_var);
EXPORT_SYMBOL(fb_blank); EXPORT_SYMBOL(fb_blank);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -722,9 +722,7 @@ static void riva_load_video_mode(struct fb_info *info) ...@@ -722,9 +722,7 @@ static void riva_load_video_mode(struct fb_info *info)
newmode.ext.interlace = 0xff; /* interlace off */ newmode.ext.interlace = 0xff; /* interlace off */
par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width, par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
hDisplaySize, hDisplay, hStart, hEnd, hDisplaySize, height, dotClock);
hTotal, height, vDisplay, vStart, vEnd,
vTotal, dotClock);
if (par->SecondCRTC) { if (par->SecondCRTC) {
newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000; newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000;
newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000; newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000;
...@@ -1135,7 +1133,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor) ...@@ -1135,7 +1133,7 @@ static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
temp = xx & 0xFFFF; temp = xx & 0xFFFF;
temp |= yy << 16; temp |= yy << 16;
*(par->riva.CURSORPOS) = temp; par->riva.PRAMDAC[0x0000300/4] = temp;
} }
if (flags & FB_CUR_SETSIZE) { if (flags & FB_CUR_SETSIZE) {
...@@ -1263,7 +1261,7 @@ static int rivafb_open(struct fb_info *info, int user) ...@@ -1263,7 +1261,7 @@ static int rivafb_open(struct fb_info *info, int user)
par->state.flags |= VGA_SAVE_CMAP; par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state); save_vga(&par->state);
RivaGetConfig(&par->riva); RivaGetConfig(&par->riva, par->Chipset);
CRTCout(par, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */ CRTCout(par, 0x11, 0xFF); /* vgaHWunlock() + riva unlock (0x7F) */
par->riva.LockUnlock(&par->riva, 0); par->riva.LockUnlock(&par->riva, 0);
...@@ -1791,7 +1789,9 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1791,7 +1789,9 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
strcat(rivafb_fix.id, rci->name); strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev; default_par->riva.Architecture = rci->arch_rev;
default_par->riva.Chipset = pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n", pd->device);
rivafb_fix.mmio_len = pci_resource_len(pd, 0); rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1); rivafb_fix.smem_len = pci_resource_len(pd, 1);
...@@ -1828,11 +1828,9 @@ static int __devinit rivafb_init_one(struct pci_dev *pd, ...@@ -1828,11 +1828,9 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
0x00000000); 0x00000000);
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base + default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base +
0x00800000); 0x00800000);
default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000); default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000); default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000); default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0; default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
if (default_par->riva.Architecture == NV_ARCH_03) { if (default_par->riva.Architecture == NV_ARCH_03) {
......
...@@ -77,25 +77,31 @@ static int nv10Busy ...@@ -77,25 +77,31 @@ static int nv10Busy
{ {
return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01)); return ((chip->Rop->FifoFree < chip->FifoEmptyCount) || (chip->PGRAPH[0x00000700/4] & 0x01));
} }
static void nv3LockUnlock
static void vgaLockUnlock
( (
RIVA_HW_INST *chip, RIVA_HW_INST *chip,
int Lock int Lock
) )
{ {
VGA_WR08(chip->PVIO, 0x3C4, 0x06); U008 cr11;
VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57); VGA_WR08(chip->PCIO, 0x3D4, 0x11);
cr11 = VGA_RD08(chip->PCIO, 0x3D5);
if(Lock) cr11 |= 0x80;
else cr11 &= ~0x80;
VGA_WR08(chip->PCIO, 0x3D5, cr11);
} }
static void nv4LockUnlock static void nv3LockUnlock
( (
RIVA_HW_INST *chip, RIVA_HW_INST *chip,
int Lock int Lock
) )
{ {
VGA_WR08(chip->PCIO, 0x3D4, 0x1F); VGA_WR08(chip->PVIO, 0x3C4, 0x06);
VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57); VGA_WR08(chip->PVIO, 0x3C5, Lock ? 0x99 : 0x57);
vgaLockUnlock(chip, Lock);
} }
static void nv10LockUnlock static void nv4LockUnlock
( (
RIVA_HW_INST *chip, RIVA_HW_INST *chip,
int Lock int Lock
...@@ -103,6 +109,7 @@ static void nv10LockUnlock ...@@ -103,6 +109,7 @@ static void nv10LockUnlock
{ {
VGA_WR08(chip->PCIO, 0x3D4, 0x1F); VGA_WR08(chip->PCIO, 0x3D4, 0x1F);
VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57); VGA_WR08(chip->PCIO, 0x3D5, Lock ? 0x99 : 0x57);
vgaLockUnlock(chip, Lock);
} }
static int ShowHideCursor static int ShowHideCursor
...@@ -1097,7 +1104,6 @@ static void nv10UpdateArbitrationSettings ...@@ -1097,7 +1104,6 @@ static void nv10UpdateArbitrationSettings
static int CalcVClock static int CalcVClock
( (
int clockIn, int clockIn,
int double_scan,
int *clockOut, int *clockOut,
int *mOut, int *mOut,
int *nOut, int *nOut,
...@@ -1113,18 +1119,16 @@ static int CalcVClock ...@@ -1113,18 +1119,16 @@ static int CalcVClock
DeltaOld = 0xFFFFFFFF; DeltaOld = 0xFFFFFFFF;
VClk = (unsigned)clockIn; VClk = (unsigned)clockIn;
if (double_scan)
VClk *= 2;
if (chip->CrystalFreqKHz == 14318) if (chip->CrystalFreqKHz == 13500)
{ {
lowM = 8; lowM = 7;
highM = 14 - (chip->Architecture == NV_ARCH_03); highM = 13 - (chip->Architecture == NV_ARCH_03);
} }
else else
{ {
lowM = 7; lowM = 8;
highM = 13 - (chip->Architecture == NV_ARCH_03); highM = 14 - (chip->Architecture == NV_ARCH_03);
} }
highP = 4 - (chip->Architecture == NV_ARCH_03); highP = 4 - (chip->Architecture == NV_ARCH_03);
...@@ -1135,8 +1139,9 @@ static int CalcVClock ...@@ -1135,8 +1139,9 @@ static int CalcVClock
{ {
for (M = lowM; M <= highM; M++) for (M = lowM; M <= highM; M++)
{ {
N = (VClk * M / chip->CrystalFreqKHz) << P; N = (VClk << P) * M / chip->CrystalFreqKHz;
Freq = (chip->CrystalFreqKHz * N / M) >> P; if(N <= 255) {
Freq = (chip->CrystalFreqKHz * N / M) >> P;
if (Freq > VClk) if (Freq > VClk)
DeltaNew = Freq - VClk; DeltaNew = Freq - VClk;
else else
...@@ -1152,6 +1157,7 @@ static int CalcVClock ...@@ -1152,6 +1157,7 @@ static int CalcVClock
} }
} }
} }
}
return (DeltaOld != 0xFFFFFFFF); return (DeltaOld != 0xFFFFFFFF);
} }
/* /*
...@@ -1165,15 +1171,7 @@ static void CalcStateExt ...@@ -1165,15 +1171,7 @@ static void CalcStateExt
int bpp, int bpp,
int width, int width,
int hDisplaySize, int hDisplaySize,
int hDisplay,
int hStart,
int hEnd,
int hTotal,
int height, int height,
int vDisplay,
int vStart,
int vEnd,
int vTotal,
int dotClock int dotClock
) )
{ {
...@@ -1188,8 +1186,7 @@ static void CalcStateExt ...@@ -1188,8 +1186,7 @@ static void CalcStateExt
* Extended RIVA registers. * Extended RIVA registers.
*/ */
pixelDepth = (bpp + 1)/8; pixelDepth = (bpp + 1)/8;
CalcVClock(dotClock, hDisplaySize < 512, /* double scan? */ CalcVClock(dotClock, &VClk, &m, &n, &p, chip);
&VClk, &m, &n, &p, chip);
switch (chip->Architecture) switch (chip->Architecture)
{ {
...@@ -1229,9 +1226,9 @@ static void CalcStateExt ...@@ -1229,9 +1226,9 @@ static void CalcStateExt
&(state->arbitration0), &(state->arbitration0),
&(state->arbitration1), &(state->arbitration1),
chip); chip);
state->cursor0 = 0x00; state->cursor0 = 0x00;
state->cursor1 = 0xFC; state->cursor1 = 0xFC;
state->cursor2 = 0x00000000; state->cursor2 = 0x00000000;
state->pllsel = 0x10000700; state->pllsel = 0x10000700;
state->config = chip->PFB[0x00000200/4]; state->config = chip->PFB[0x00000200/4];
state->general = bpp == 16 ? 0x00101100 : 0x00100100; state->general = bpp == 16 ? 0x00101100 : 0x00100100;
...@@ -1239,13 +1236,7 @@ static void CalcStateExt ...@@ -1239,13 +1236,7 @@ static void CalcStateExt
break; break;
} }
state->vpll = (p << 16) | (n << 8) | m; state->vpll = (p << 16) | (n << 8) | m;
state->screen = ((hTotal & 0x040) >> 2)
| ((vDisplay & 0x400) >> 7)
| ((vStart & 0x400) >> 8)
| ((vDisplay & 0x400) >> 9)
| ((vTotal & 0x400) >> 10);
state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3; state->repaint0 = (((width/8)*pixelDepth) & 0x700) >> 3;
state->horiz = hTotal < 260 ? 0x00 : 0x01;
state->pixel = pixelDepth > 2 ? 3 : pixelDepth; state->pixel = pixelDepth > 2 ? 3 : pixelDepth;
state->offset0 = state->offset0 =
state->offset1 = state->offset1 =
...@@ -1508,7 +1499,7 @@ static void LoadStateExt ...@@ -1508,7 +1499,7 @@ static void LoadStateExt
chip->PGRAPH[0x00000F50/4] = 0x00000040; chip->PGRAPH[0x00000F50/4] = 0x00000040;
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
chip->PGRAPH[0x00000F54/4] = 0x00000000; chip->PGRAPH[0x00000F54/4] = 0x00000000;
break; break;
} }
LOAD_FIXED_STATE(Riva,FIFO); LOAD_FIXED_STATE(Riva,FIFO);
UpdateFifoState(chip); UpdateFifoState(chip);
...@@ -1537,11 +1528,12 @@ static void LoadStateExt ...@@ -1537,11 +1528,12 @@ static void LoadStateExt
chip->PRAMDAC[0x00000508/4] = state->vpll; chip->PRAMDAC[0x00000508/4] = state->vpll;
chip->PRAMDAC[0x0000050C/4] = state->pllsel; chip->PRAMDAC[0x0000050C/4] = state->pllsel;
chip->PRAMDAC[0x00000600/4] = state->general; chip->PRAMDAC[0x00000600/4] = state->general;
/* /*
* Turn off VBlank enable and reset. * Turn off VBlank enable and reset.
*/ */
*(chip->VBLANKENABLE) = 0; chip->PCRTC[0x00000140/4] = 0;
*(chip->VBLANK) = chip->VBlankBit; chip->PCRTC[0x00000100/4] = chip->VBlankBit;
/* /*
* Set interrupt enable. * Set interrupt enable.
*/ */
...@@ -1811,9 +1803,6 @@ static void nv3GetConfig ...@@ -1811,9 +1803,6 @@ static void nv3GetConfig
} }
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500; chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000020) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]); chip->CURSOR = &(chip->PRAMIN[0x00008000/4 - 0x0800/4]);
chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
chip->VBLANKENABLE = &(chip->PGRAPH[0x0140/4]);
chip->VBLANK = &(chip->PGRAPH[0x0100/4]);
chip->VBlankBit = 0x00000100; chip->VBlankBit = 0x00000100;
chip->MaxVClockFreqKHz = 256000; chip->MaxVClockFreqKHz = 256000;
/* /*
...@@ -1872,9 +1861,6 @@ static void nv4GetConfig ...@@ -1872,9 +1861,6 @@ static void nv4GetConfig
} }
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]); chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
chip->VBLANKENABLE = &(chip->PCRTC[0x0140/4]);
chip->VBLANK = &(chip->PCRTC[0x0100/4]);
chip->VBlankBit = 0x00000001; chip->VBlankBit = 0x00000001;
chip->MaxVClockFreqKHz = 350000; chip->MaxVClockFreqKHz = 350000;
/* /*
...@@ -1892,12 +1878,30 @@ static void nv4GetConfig ...@@ -1892,12 +1878,30 @@ static void nv4GetConfig
} }
static void nv10GetConfig static void nv10GetConfig
( (
RIVA_HW_INST *chip RIVA_HW_INST *chip,
unsigned int chipset
) )
{ {
struct pci_dev* dev;
int amt;
#ifdef __BIG_ENDIAN
/* turn on big endian register access */
chip->PMC[0x00000004/4] = 0x01000001;
#endif
/* /*
* Fill in chip configuration. * Fill in chip configuration.
*/ */
if(chipset == NV_CHIP_IGEFORCE2) {
dev = pci_find_slot(0, 1);
pci_read_config_dword(dev, 0x7C, &amt);
chip->RamAmountKBytes = (((amt >> 6) & 31) + 1) * 1024;
} else if(chipset == NV_CHIP_0x01F0) {
dev = pci_find_slot(0, 1);
pci_read_config_dword(dev, 0x84, &amt);
chip->RamAmountKBytes = (((amt >> 4) & 127) + 1) * 1024;
} else {
switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF)
{ {
case 0x02: case 0x02:
...@@ -1925,6 +1929,7 @@ static void nv10GetConfig ...@@ -1925,6 +1929,7 @@ static void nv10GetConfig
chip->RamAmountKBytes = 1024 * 16; chip->RamAmountKBytes = 1024 * 16;
break; break;
} }
}
switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003) switch ((chip->PFB[0x00000000/4] >> 3) & 0x00000003)
{ {
case 3: case 3:
...@@ -1936,9 +1941,6 @@ static void nv10GetConfig ...@@ -1936,9 +1941,6 @@ static void nv10GetConfig
} }
chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500; chip->CrystalFreqKHz = (chip->PEXTDEV[0x00000000/4] & 0x00000040) ? 14318 : 13500;
chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]); chip->CURSOR = &(chip->PRAMIN[0x00010000/4 - 0x0800/4]);
chip->CURSORPOS = &(chip->PRAMDAC[0x0300/4]);
chip->VBLANKENABLE = &(chip->PCRTC[0x0140/4]);
chip->VBLANK = &(chip->PCRTC[0x0100/4]);
chip->VBlankBit = 0x00000001; chip->VBlankBit = 0x00000001;
chip->MaxVClockFreqKHz = 350000; chip->MaxVClockFreqKHz = 350000;
/* /*
...@@ -1952,11 +1954,12 @@ static void nv10GetConfig ...@@ -1952,11 +1954,12 @@ static void nv10GetConfig
chip->SetStartAddress = SetStartAddress; chip->SetStartAddress = SetStartAddress;
chip->SetSurfaces2D = nv10SetSurfaces2D; chip->SetSurfaces2D = nv10SetSurfaces2D;
chip->SetSurfaces3D = nv10SetSurfaces3D; chip->SetSurfaces3D = nv10SetSurfaces3D;
chip->LockUnlock = nv10LockUnlock; chip->LockUnlock = nv4LockUnlock;
} }
int RivaGetConfig int RivaGetConfig
( (
RIVA_HW_INST *chip RIVA_HW_INST *chip,
unsigned int chipset
) )
{ {
/* /*
...@@ -1975,11 +1978,13 @@ int RivaGetConfig ...@@ -1975,11 +1978,13 @@ int RivaGetConfig
nv4GetConfig(chip); nv4GetConfig(chip);
break; break;
case NV_ARCH_10: case NV_ARCH_10:
nv10GetConfig(chip); case NV_ARCH_20:
nv10GetConfig(chip, chipset);
break; break;
default: default:
return (-1); return (-1);
} }
chip->Chipset = chipset;
/* /*
* Fill in FIFO pointers. * Fill in FIFO pointers.
*/ */
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
* from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99 * from this source. -- Jeff Garzik <jgarzik@pobox.com>, 01/Nov/99
*/ */
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.6 2000/02/08 17:19:12 dawes Exp $ */ /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/nv/riva_hw.h,v 1.21 2002/10/14 18:22:46 mvojkovi Exp $ */
#ifndef __RIVA_HW_H__ #ifndef __RIVA_HW_H__
#define __RIVA_HW_H__ #define __RIVA_HW_H__
#define RIVA_SW_VERSION 0x00010003 #define RIVA_SW_VERSION 0x00010003
...@@ -78,8 +78,8 @@ typedef unsigned int U032; ...@@ -78,8 +78,8 @@ typedef unsigned int U032;
#define NV_WR08(p,i,d) out_8(p+i, d) #define NV_WR08(p,i,d) out_8(p+i, d)
#define NV_RD08(p,i) in_8(p+i) #define NV_RD08(p,i) in_8(p+i)
#else #else
#define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d)) #define NV_WR08(p,i,d) (((U008 *)(p))[i]=(d))
#define NV_RD08(p,i) (((U008 *)(p))[i]) #define NV_RD08(p,i) (((U008 *)(p))[i])
#endif #endif
#define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d)) #define NV_WR16(p,i,d) (((U016 *)(p))[(i)/2]=(d))
#define NV_RD16(p,i) (((U016 *)(p))[(i)/2]) #define NV_RD16(p,i) (((U016 *)(p))[(i)/2])
...@@ -426,7 +426,7 @@ typedef struct _riva_hw_inst ...@@ -426,7 +426,7 @@ typedef struct _riva_hw_inst
*/ */
U032 Architecture; U032 Architecture;
U032 Version; U032 Version;
U032 Chipset; U032 Chipset;
U032 CrystalFreqKHz; U032 CrystalFreqKHz;
U032 RamAmountKBytes; U032 RamAmountKBytes;
U032 MaxVClockFreqKHz; U032 MaxVClockFreqKHz;
...@@ -454,10 +454,7 @@ typedef struct _riva_hw_inst ...@@ -454,10 +454,7 @@ typedef struct _riva_hw_inst
volatile U032 *PRAMIN; volatile U032 *PRAMIN;
volatile U032 *FIFO; volatile U032 *FIFO;
volatile U032 *CURSOR; volatile U032 *CURSOR;
volatile U032 *CURSORPOS; volatile U008 *PCIO0;
volatile U032 *VBLANKENABLE;
volatile U032 *VBLANK;
volatile U008 *PCIO0;
volatile U008 *PCIO; volatile U008 *PCIO;
volatile U008 *PVIO; volatile U008 *PVIO;
volatile U008 *PDIO0; volatile U008 *PDIO0;
...@@ -467,7 +464,7 @@ typedef struct _riva_hw_inst ...@@ -467,7 +464,7 @@ typedef struct _riva_hw_inst
* Common chip functions. * Common chip functions.
*/ */
int (*Busy)(struct _riva_hw_inst *); int (*Busy)(struct _riva_hw_inst *);
void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int,int,int,int,int,int,int,int,int); void (*CalcStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *,int,int,int,int,int);
void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*LoadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *); void (*UnloadStateExt)(struct _riva_hw_inst *,struct _riva_hw_state *);
void (*SetStartAddress)(struct _riva_hw_inst *,U032); void (*SetStartAddress)(struct _riva_hw_inst *,U032);
...@@ -516,10 +513,10 @@ typedef struct _riva_hw_state ...@@ -516,10 +513,10 @@ typedef struct _riva_hw_state
U032 pllsel; U032 pllsel;
U032 general; U032 general;
U032 crtcOwner; U032 crtcOwner;
U032 head; U032 head;
U032 head2; U032 head2;
U032 config; U032 config;
U032 cursorConfig; U032 cursorConfig;
U032 cursor0; U032 cursor0;
U032 cursor1; U032 cursor1;
U032 cursor2; U032 cursor2;
...@@ -535,16 +532,16 @@ typedef struct _riva_hw_state ...@@ -535,16 +532,16 @@ typedef struct _riva_hw_state
/* /*
* External routines. * External routines.
*/ */
int RivaGetConfig(RIVA_HW_INST *); int RivaGetConfig(RIVA_HW_INST *, unsigned int);
/* /*
* FIFO Free Count. Should attempt to yield processor if RIVA is busy. * FIFO Free Count. Should attempt to yield processor if RIVA is busy.
*/ */
#define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \ #define RIVA_FIFO_FREE(hwinst,hwptr,cnt) \
{ \ { \
while ((hwinst).FifoFreeCount < (cnt)) \ while ((hwinst).FifoFreeCount < (cnt)) \
(hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \ (hwinst).FifoFreeCount = (hwinst).hwptr->FifoFree >> 2; \
(hwinst).FifoFreeCount -= (cnt); \ (hwinst).FifoFreeCount -= (cnt); \
} }
#endif /* __RIVA_HW_H__ */ #endif /* __RIVA_HW_H__ */
...@@ -41,9 +41,16 @@ struct riva_par { ...@@ -41,9 +41,16 @@ struct riva_par {
u32 riva_palette[16]; u32 riva_palette[16];
u32 cursor_data[32 * 32/4]; u32 cursor_data[32 * 32/4];
int cursor_reset; int cursor_reset;
unsigned char *EDID;
unsigned int Chipset;
int forceCRTC;
Bool SecondCRTC;
int FlatPanel;
#ifdef CONFIG_MTRR #ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr; struct { int vram; int vram_valid; } mtrr;
#endif #endif
}; };
void riva_common_setup(struct riva_par *);
#endif /* __RIVAFB_H */ #endif /* __RIVAFB_H */
...@@ -7,13 +7,15 @@ ...@@ -7,13 +7,15 @@
* *
* Contributions (and many thanks) : * Contributions (and many thanks) :
* *
* 03/2001 James Simmons <jsimmons@linux-fbdev.org> * 03/2001 James Simmons <jsimmons@infradead.org>
* 04/2001 Paul Mundt <lethal@chaoticdreams.org> * 04/2001 Paul Mundt <lethal@chaoticdreams.org>
* 05/2001 Urs Ganse <ursg@uni.de> * 05/2001 Urs Ganse <ursg@uni.de>
* (initial work on voodoo2 port, interlace) * (initial work on voodoo2 port, interlace)
* 09/2002 Helge Deller <deller@gmx.de>
* (enable driver on big-endian machines (hppa), ioctl fixes)
* 12/2002 Helge Deller <deller@gmx.de>
* (port driver to new frambuffer infrastructure)
* *
*
* $Id: sstfb.c,v 1.37 2002/05/10 19:35:11 ghoz Exp $
*/ */
/* /*
...@@ -27,13 +29,9 @@ ...@@ -27,13 +29,9 @@
* misc notes, TODOs, toASKs, and deep thoughts * misc notes, TODOs, toASKs, and deep thoughts
-TODO: at one time or another test that the mode is acceptable by the monitor -TODO: at one time or another test that the mode is acceptable by the monitor
-ASK: I can choose different ordering for the color bitfields (rgba argb ...) -ASK: Can I choose different ordering for the color bitfields (rgba argb ...)
wich one should i use ? is there any preferred one ? It seems ARGB is wich one should i use ? is there any preferred one ? It seems ARGB is
the one ... the one ...
-ASK: later: how to cope with endianness ? the fbi chip has builtin functions
to do byte swizling /swapping, maybe use that ...
-TODO: check the error paths . if something get wrong, the error doesn't seem
to be very well handled...if handled at all.. not good.
-TODO: in set_var check the validity of timings (hsync vsync)... -TODO: in set_var check the validity of timings (hsync vsync)...
-TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via -TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via
a nop command . so it's ok as long as the commands we pass don't go a nop command . so it's ok as long as the commands we pass don't go
...@@ -42,9 +40,7 @@ ...@@ -42,9 +40,7 @@
state. state.
-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20) -FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)
-ASK: I stole "inverse" but seems it doesn't work... check what it realy does... -ASK: I stole "inverse" but seems it doesn't work... check what it realy does...
-TODO: change struct sst_info fb_info from static to array/dynamic -TODO: change struct fb_info fb_info from static to array/dynamic
*
*/ */
/* /*
...@@ -62,24 +58,20 @@ ...@@ -62,24 +58,20 @@
* SST_DEBUG_VAR : debug display/var structs * SST_DEBUG_VAR : debug display/var structs
* 0 : no debug * 0 : no debug
* 1 : dumps display, fb_var * 1 : dumps display, fb_var
* SST_DEBUG_IOCTL : enable sstfb specific ioctls *
* 0 : disable * sstfb specific ioctls:
* 1 : enable debug ioctls :
* toggle vga (0x46db) : toggle vga_pass_through * toggle vga (0x46db) : toggle vga_pass_through
* fill fb (0x46dc) : fills fb * fill fb (0x46dc) : fills fb
* dump var (0x46dd) : logs display[0-5].var * test disp (0x46de) : draws a test image
* test disp (0x46de) : draws a test motif
*/ */
#define SST_DEBUG #undef SST_DEBUG
//#undef SST_DEBUG
#define SST_DEBUG_REG 0 #define SST_DEBUG_REG 0
#define SST_DEBUG_FUNC 0 #define SST_DEBUG_FUNC 0
#define SST_DEBUG_VAR 0 #define SST_DEBUG_VAR 0
#define SST_DEBUG_IOCTL 1
/* #define EN_24_32_BPP *//* enable 24/32 bpp functions for testing only */ /* enable 24/32 bpp functions ? (completely untested!) */
#undef EN_24_32_BPP #undef EN_24_32_BPP
/* /*
...@@ -88,16 +80,16 @@ ...@@ -88,16 +80,16 @@
1 640x480@75 took from glide 1 640x480@75 took from glide
2 1024x768@76 std fb.mode 2 1024x768@76 std fb.mode
3 640x480@60 glide default */ 3 640x480@60 glide default */
#define DEFAULT_MODE 1 #define DEFAULT_MODE 3
/* /*
* Includes * Includes
*/ */
#include <linux/string.h>
#include <linux/config.h> #include <linux/config.h>
#include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/tty.h>
#include <linux/fb.h> #include <linux/fb.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
...@@ -107,145 +99,33 @@ ...@@ -107,145 +99,33 @@
#include <asm/io.h> #include <asm/io.h>
#include <asm/ioctl.h> #include <asm/ioctl.h>
#include <asm/uaccess.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
#ifdef EN_24_32_BPP
# include <video/fbcon-cfb24.h>
# include <video/fbcon-cfb32.h>
#endif
#include "sstfb.h" #include "sstfb.h"
void __Dump_regs(struct sstfb_info *);
#define Dump_regs __Dump_regs(sst_info) //XXX
/********/
/* initialized by setup */ /* initialized by setup */
static int inverse; /* =0 */ /* invert colormap */
static int vgapass; /* =0 */ /* enable Vga passthrough cable */ static int inverse; /* invert colormap */
static int mem; /* =0 */ /* mem size in Mb , 0 = autodetect */ static int vgapass; /* enable Vga passthrough cable */
static int mem; /* mem size in Mb , 0 = autodetect */
static int clipping = 1; /* use clipping (slower, safer) */ static int clipping = 1; /* use clipping (slower, safer) */
static int gfxclk; /* =0 */ /* force FBI freq in Mhz . Dangerous */ static int gfxclk; /* force FBI freq in Mhz . Dangerous */
static int slowpci; /* =0 */ /* slow PCI settings */ static int slowpci; /* slow PCI settings */
static int dev = -2; /* specify device (0..n) -2=all -1=none*/ static int dev = -2; /* specify device (0..n) -2=all -1=none*/
static char * mode_option ; static char *mode_option __devinitdata;
/********/
int sstfb_init(void);
int sstfb_setup(char *options);
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);
static void __devexit sstfb_remove(struct pci_dev *pdev);
/* Framebuffer API */
static int sstfb_open(struct fb_info *info, int user);
static int sstfb_release(struct fb_info *info, int user);
static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
int con, struct fb_info *info);
static int sstfb_get_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info);
static int sstfb_set_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info);
static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info);
static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info);
static int sstfb_pan_display(struct fb_var_screeninfo *var,
int con, struct fb_info *info);
static int sstfb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con,
struct fb_info *info);
/* Interface to the low level console driver */
static int sstfbcon_switch(int con, struct fb_info *info);
static int sstfbcon_updatevar(int con, struct fb_info *info);
static void sstfbcon_blank(int blank, struct fb_info *info);
/* Internal routines */
static void sstfb_install_cmap(int con, struct fb_info *info);
static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
u_int *transp, struct fb_info *info);
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info);
static int sstfb_set_par(const struct sstfb_par *par,
struct sstfb_info *sst_info);
static int sstfb_decode_var (const struct fb_var_screeninfo *var,
struct sstfb_par *par,
const struct sstfb_info *sst_info);
static int sstfb_encode_var (struct fb_var_screeninfo *var,
const struct sstfb_par *par,
const struct sstfb_info *sst_info);
static void sstfb_test16(struct sstfb_info *sst_info);
#ifdef EN_24_32_BPP
static void sstfb_test32(struct sstfb_info *sst_info);
#endif
/* Low level routines */
static int sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize);
static int __sst_wait_idle(u_long vbase);
#define sst_wait_idle() __sst_wait_idle(sst_info->mmio.vbase)
static int sst_detect_dactype(struct sstfb_info *sst_info);
static int sst_detect_att(struct sstfb_info *sst_info);
static int sst_detect_ti(struct sstfb_info *sst_info);
static int sst_detect_ics(struct sstfb_info *sst_info);
static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t);
static int sst_set_pll_att_ti(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
static int sst_set_pll_ics(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);
static void sst_set_vidmod_att_ti(struct sstfb_info *sst_info, const int bpp);
static void sst_set_vidmod_ics(struct sstfb_info *sst_info, const int bpp);
static int sst_init(struct sstfb_info *sst_info);
static void sst_shutdown(struct sstfb_info *sst_info);
static struct fb_ops sstfb_ops = {
.owner = THIS_MODULE,
.fb_open = sstfb_open,
.fb_release = sstfb_release,
.fb_get_fix = sstfb_get_fix,
.fb_get_var = sstfb_get_var,
.fb_set_var = sstfb_set_var,
.fb_get_cmap = sstfb_get_cmap,
.fb_set_cmap = sstfb_set_cmap,
.fb_pan_display = sstfb_pan_display,
.fb_ioctl = sstfb_ioctl,
};
enum { enum {
ID_VOODOO1 = 0, ID_VOODOO1 = 0,
ID_VOODOO2 = 1, ID_VOODOO2 = 1,
}; };
#define IS_VOODOO2(info) ((info)->type == ID_VOODOO2 ) #define IS_VOODOO2(par) ((par)->type == ID_VOODOO2 )
static struct sst_spec voodoo_spec[] __devinitdata = { static struct sst_spec voodoo_spec[] __devinitdata = {
{ .name = "Voodoo Graphics", { .name = "Voodoo Graphics", .default_gfx_clock = 50000, .max_gfxclk = 60 },
.default_gfx_clock = 50000, { .name = "Voodoo2", .default_gfx_clock = 75000, .max_gfxclk = 85 },
.max_gfxclk = 60, },
{ .name = "Voodoo2",
.default_gfx_clock = 75000,
.max_gfxclk = 85, },
};
static struct pci_device_id sstfb_id_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
{ PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
{ 0 },
};
static struct pci_driver sstfb_driver = {
.name = "sstfb",
.id_table = sstfb_id_tbl,
.probe = sstfb_probe,
.remove = __devexit_p(sstfb_remove),
}; };
static struct fb_var_screeninfo sstfb_default = static struct fb_var_screeninfo sstfb_default =
...@@ -256,55 +136,88 @@ static struct fb_var_screeninfo sstfb_default = ...@@ -256,55 +136,88 @@ static struct fb_var_screeninfo sstfb_default =
0, 0, -1, -1, 0, 0, 0, -1, -1, 0,
25000, 86, 41, 23, 1, 127, 4, 25000, 86, 41, 23, 1, 127, 4,
0, FB_VMODE_NONINTERLACED }; 0, FB_VMODE_NONINTERLACED };
#endif #elif ( DEFAULT_MODE == 1 )
#if ( DEFAULT_MODE == 1 )
{/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */ {/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */
640, 480, 640, 480, 0, 0, 16, 0, 640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 0, 0, -1, -1, 0,
31746, 118, 17, 16, 1, 63, 3, 31746, 118, 17, 16, 1, 63, 3,
0, FB_VMODE_NONINTERLACED }; 0, FB_VMODE_NONINTERLACED };
#endif #elif ( DEFAULT_MODE == 2 )
#if ( DEFAULT_MODE == 2 )
{ /* 1024x768@76 took from my /etc/fb.modes */ { /* 1024x768@76 took from my /etc/fb.modes */
1024, 768, 1024, 768,0, 0, 16,0, 1024, 768, 1024, 768,0, 0, 16,0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 0, 0, -1, -1, 0,
11764, 208, 8, 36, 16, 120, 3 , 11764, 208, 8, 36, 16, 120, 3 ,
0, FB_VMODE_NONINTERLACED }; 0, FB_VMODE_NONINTERLACED };
#endif #elif ( DEFAULT_MODE == 3 )
#if ( DEFAULT_MODE == 3 )
{ /* 640x480@60 , 16bpp glide default ?*/ { /* 640x480@60 , 16bpp glide default ?*/
640, 480, 640, 480, 0, 0, 16, 0, 640, 480, 640, 480, 0, 0, 16, 0,
{11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0},
0, 0, -1, -1, 0, 0, 0, -1, -1, 0,
39721 , 38, 26 , 25 ,18 , 96 ,2, 39721 , 38, 26 , 25 ,18 , 96 ,2,
0, FB_VMODE_NONINTERLACED }; 0, FB_VMODE_NONINTERLACED };
#elif
#error "Invalid DEFAULT_MODE value !"
#endif #endif
static struct dac_switch dacs[] __devinitdata = {
{ .name = "TI TVP3409",
.detect = sst_detect_ti,
.set_pll = sst_set_pll_att_ti,
.set_vidmod = sst_set_vidmod_att_ti },
{ .name = "AT&T ATT20C409",
.detect = sst_detect_att,
.set_pll = sst_set_pll_att_ti,
.set_vidmod = sst_set_vidmod_att_ti },
{ .name = "ICS ICS5342",
.detect = sst_detect_ics,
.set_pll = sst_set_pll_ics,
.set_vidmod = sst_set_vidmod_ics },
};
/* /*
* * debug functions
* Definitions
*
*/ */
static void sstfb_test16(struct fb_info *info);
#if EN_24_32_BPP
static void sstfb_test32(struct fb_info *info);
#endif
#if 0
static void __Dump_regs (struct sstfb_info *sst_info)
{
struct { u32 reg ; char * reg_name;} pci_regs [] = {
{ PCI_INIT_ENABLE, "initenable"},
{ PCI_VCLK_ENABLE, "enable vclk"},
{ PCI_VCLK_DISABLE, "disable vclk"},
};
struct { u32 reg ; char * reg_name;} sst_regs [] = {
{FBIINIT0,"fbiinit0"},
{FBIINIT1,"fbiinit1"},
{FBIINIT2,"fbiinit2"},
{FBIINIT3,"fbiinit3"},
{FBIINIT4,"fbiinit4"},
{FBIINIT5,"fbiinit5"},
{FBIINIT6,"fbiinit6"},
{FBIINIT7,"fbiinit7"},
{LFBMODE,"lfbmode"},
{FBZMODE,"fbzmode"},
};
int pci_s = sizeof(pci_regs)/sizeof(*pci_regs);
int sst_s = sizeof(sst_regs)/sizeof(*sst_regs);
u32 pci_res[pci_s];
u32 sst_res[sst_s];
struct pci_dev * dev = sst_info->dev;
int i;
for (i=0; i < pci_s ; i++ ) {
pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
sst_res[i]=sst_read(sst_regs[i].reg);
}
dprintk ("Dump regs\n");
for (i=0; i < pci_s ; i++ ) {
dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
}
}
#endif
#if (SST_DEBUG_VAR > 0) #if (SST_DEBUG_VAR > 0)
/* debug info / dump a fb_var_screeninfo */ /* debug info / dump a fb_var_screeninfo */
static void sst_dbg_print_var(struct fb_var_screeninfo *var) { static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
...@@ -331,15 +244,16 @@ static void sst_dbg_print_var(struct fb_var_screeninfo *var) { ...@@ -331,15 +244,16 @@ static void sst_dbg_print_var(struct fb_var_screeninfo *var) {
#if (SST_DEBUG_REG > 0) #if (SST_DEBUG_REG > 0)
static void sst_dbg_print_read_reg (u32 reg, u32 val) { static void sst_dbg_print_read_reg (u32 reg, u32 val) {
char * regname =NULL; const char *regname;
switch (reg) { switch (reg) {
case FBIINIT0: regname="FbiInit0"; break; case FBIINIT0: regname = "FbiInit0"; break;
case FBIINIT1: regname="FbiInit1"; break; case FBIINIT1: regname = "FbiInit1"; break;
case FBIINIT2: regname="FbiInit2"; break; case FBIINIT2: regname = "FbiInit2"; break;
case FBIINIT3: regname="FbiInit3"; break; case FBIINIT3: regname = "FbiInit3"; break;
case FBIINIT4: regname="FbiInit4"; break; case FBIINIT4: regname = "FbiInit4"; break;
case FBIINIT5: regname="FbiInit5"; break; case FBIINIT5: regname = "FbiInit5"; break;
case FBIINIT6: regname="FbiInit6"; break; case FBIINIT6: regname = "FbiInit6"; break;
default: regname = NULL; break;
} }
if (regname == NULL) if (regname == NULL)
r_ddprintk("sst_read(%#x): %#x\n", reg, val); r_ddprintk("sst_read(%#x): %#x\n", reg, val);
...@@ -348,16 +262,16 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) { ...@@ -348,16 +262,16 @@ static void sst_dbg_print_read_reg (u32 reg, u32 val) {
} }
static void sst_dbg_print_write_reg (u32 reg, u32 val) { static void sst_dbg_print_write_reg (u32 reg, u32 val) {
char * regname = NULL; const char *regname;
switch (reg) { switch (reg) {
case FBIINIT0: regname="FbiInit0"; break; case FBIINIT0: regname = "FbiInit0"; break;
case FBIINIT1: regname="FbiInit1"; break; case FBIINIT1: regname = "FbiInit1"; break;
case FBIINIT2: regname="FbiInit2"; break; case FBIINIT2: regname = "FbiInit2"; break;
case FBIINIT3: regname="FbiInit3"; break; case FBIINIT3: regname = "FbiInit3"; break;
case FBIINIT4: regname="FbiInit4"; break; case FBIINIT4: regname = "FbiInit4"; break;
case FBIINIT5: regname="FbiInit5"; break; case FBIINIT5: regname = "FbiInit5"; break;
case FBIINIT6: regname="FbiInit6"; break; case FBIINIT6: regname = "FbiInit6"; break;
default: regname = NULL; break;
} }
if (regname == NULL) if (regname == NULL)
r_ddprintk("sst_write(%#x, %#x)\n", reg, val); r_ddprintk("sst_write(%#x, %#x)\n", reg, val);
...@@ -365,25 +279,27 @@ static void sst_dbg_print_write_reg (u32 reg, u32 val) { ...@@ -365,25 +279,27 @@ static void sst_dbg_print_write_reg (u32 reg, u32 val) {
r_dprintk(" sst_write(%s, %#x)\n", regname, val); r_dprintk(" sst_write(%s, %#x)\n", regname, val);
} }
#else /* (SST_DEBUG_REG > 0) */ #else /* (SST_DEBUG_REG > 0) */
# define sst_dbg_print_read_reg(reg, val) do {}while(0) # define sst_dbg_print_read_reg(reg, val) do {} while(0)
# define sst_dbg_print_write_reg(reg, val) do {}while(0) # define sst_dbg_print_write_reg(reg, val) do {} while(0)
#endif /* (SST_DEBUG_REG > 0) */ #endif /* (SST_DEBUG_REG > 0) */
/*
* hardware access functions
*/
/* register access */ /* register access */
#define sst_read(reg) __sst_read(sst_info->mmio.vbase, reg) #define sst_read(reg) __sst_read(par->mmio_vbase, reg)
#define sst_write(reg,val) __sst_write(sst_info->mmio.vbase, reg, val) #define sst_write(reg,val) __sst_write(par->mmio_vbase, reg, val)
#define sst_set_bits(reg,val) __sst_set_bits(sst_info->mmio.vbase, reg, val) #define sst_set_bits(reg,val) __sst_set_bits(par->mmio_vbase, reg, val)
#define sst_unset_bits(reg,val) __sst_unset_bits(sst_info->mmio.vbase, reg, val) #define sst_unset_bits(reg,val) __sst_unset_bits(par->mmio_vbase, reg, val)
#define sst_dac_read(reg) __sst_dac_read(sst_info->mmio.vbase, reg) #define sst_dac_read(reg) __sst_dac_read(par->mmio_vbase, reg)
#define sst_dac_write(reg,val) __sst_dac_write(sst_info->mmio.vbase, reg, val) #define sst_dac_write(reg,val) __sst_dac_write(par->mmio_vbase, reg, val)
#define dac_i_read(reg) __dac_i_read(sst_info->mmio.vbase, reg) #define dac_i_read(reg) __dac_i_read(par->mmio_vbase, reg)
#define dac_i_write(reg,val) __dac_i_write(sst_info->mmio.vbase, reg, val) #define dac_i_write(reg,val) __dac_i_write(par->mmio_vbase, reg, val)
static inline u32 __sst_read(u_long vbase, u32 reg) static inline u32 __sst_read(u_long vbase, u32 reg)
{ {
u32 ret; u32 ret = readl(vbase + reg);
ret = readl(vbase + reg);
sst_dbg_print_read_reg(reg, ret); sst_dbg_print_read_reg(reg, ret);
return ret; return ret;
} }
...@@ -406,6 +322,37 @@ static inline void __sst_unset_bits(u_long vbase, u32 reg, u32 val) ...@@ -406,6 +322,37 @@ static inline void __sst_unset_bits(u_long vbase, u32 reg, u32 val)
__sst_write(vbase, reg, __sst_read(vbase, reg) & ~val); __sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);
} }
/*
* wait for the fbi chip. ASK: what happens if the fbi is stuck ?
*
* the FBI is supposed to be ready if we receive 5 time
* in a row a "idle" answer to our requests
*/
#define sst_wait_idle() __sst_wait_idle(par->mmio_vbase)
static int __sst_wait_idle(u_long vbase)
{
int count = 0;
f_ddprintk("sst_wait_idle\n");
while(1) {
if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
f_dddprintk("status: busy\n");
/* FIXME basicaly, this is a busy wait. maybe not that good. oh well;
* this is a small loop after all.
* Or maybe we should use mdelay() or udelay() here instead ? */
count = 0;
} else {
count++;
f_dddprintk("status: idle(%d)\n", count);
}
if (count >= 5) return 1;
/* XXX do something to avoid hanging the machine if the voodoo is out */
}
}
/* dac access */ /* dac access */
/* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */ /* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */
static u8 __sst_dac_read(u_long vbase, u8 reg) static u8 __sst_dac_read(u_long vbase, u8 reg)
...@@ -421,10 +368,10 @@ static u8 __sst_dac_read(u_long vbase, u8 reg) ...@@ -421,10 +368,10 @@ static u8 __sst_dac_read(u_long vbase, u8 reg)
reg &= 0x07; reg &= 0x07;
__sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD ); __sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );
__sst_wait_idle(vbase); __sst_wait_idle(vbase);
/*udelay(10);*/ /* udelay(10); */
ret=(__sst_read(vbase, DAC_READ) & 0xff); ret = __sst_read(vbase, DAC_READ) & 0xff;
r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret); r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);
return (u8)ret; return ret;
} }
static void __sst_dac_write(u_long vbase, u8 reg, u8 val) static void __sst_dac_write(u_long vbase, u8 reg, u8 val)
...@@ -456,105 +403,91 @@ static void __dac_i_write(u_long vbase, u8 reg,u8 val) ...@@ -456,105 +403,91 @@ static void __dac_i_write(u_long vbase, u8 reg,u8 val)
__sst_dac_write(vbase, DACREG_DATA_I, val); __sst_dac_write(vbase, DACREG_DATA_I, val);
} }
/*
* /* compute the m,n,p , returns the real freq
* Internal routines * (ics datasheet : N <-> N1 , P <-> N2)
* *
* Fout= Fref * (M+2)/( 2^P * (N+2))
* we try to get close to the asked freq
* with P as high, and M as low as possible
* range:
* ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
* ics : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
* we'll use the lowest limitation, should be precise enouth
*/ */
static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
static void sstfb_install_cmap(int con, struct fb_info *info)
{ {
#define sst_info ((struct sstfb_info *) info) int m, m2, n, p, best_err, fout;
f_dprintk("sstfb_install_cmap(con: %d)\n",con); int best_n = -1;
f_ddprintk("currcon: %d\n", sst_info->currcon); int best_m = -1;
if (con != sst_info->currcon)
return;
if (fb_display[con].cmap.len)
fb_set_cmap(&fb_display[con].cmap, 1, sstfb_setcolreg, info);
else
fb_set_cmap(
fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
1, sstfb_setcolreg, info);
#undef sst_info
}
static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, f_dprintk("sst_calc_pll(%dKhz)\n", freq);
u_int *transp, struct fb_info *info) best_err = freq;
{ p = 3;
#define sst_info ((struct sstfb_info *) info) /* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
f_dddprintk("sstfb_getcolreg\n"); while (((1 << p) * freq > VCO_MAX) && (p >= 0))
if (regno >= 16) return 1; p--;
if (p == -1)
return -EINVAL;
for (n = 1; n < 32; n++) {
/* calc 2 * m so we can round it later*/
m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
*red = sst_info->palette[regno].red; m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
*green = sst_info->palette[regno].green; if (m >= 128)
*blue = sst_info->palette[regno].blue; break;
*transp = sst_info->palette[regno].transp; fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", if ((ABS(fout - freq) < best_err) && (m > 0)) {
regno,*red, *green, *blue, *transp); best_n = n;
best_m = m;
best_err = ABS(fout - freq);
/* we get the lowest m , allowing 0.5% error in freq*/
if (200*best_err < freq) break;
}
}
if (best_n == -1) /* unlikely, but who knows ? */
return -EINVAL;
t->p = p;
t->n = best_n;
t->m = best_m;
*freq_out = (DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
t->m, t->n, t->p, *freq_out);
return 0; return 0;
#undef sst_info
} }
/*
*
* Internal routines
*
*/
static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
u_int transp, struct fb_info *info) u_int transp, struct fb_info *info)
{ {
#define sst_info ((struct sstfb_info *) info)
u32 col; u32 col;
struct display * disp;
f_dddprintk("sstfb_setcolreg\n"); f_dddprintk("sstfb_setcolreg\n");
f_dddprintk("%-2d rvba: %#x, %#x, %#x, %#x\n", f_dddprintk("%-2d rgbt: %#x, %#x, %#x, %#x\n",
regno, red, green, blue, transp); regno, red, green, blue, transp);
if (regno >= 16) return 1; if (regno >= 16) return 1;
sst_info->palette[regno].red = red; red >>= (16 - info->var.red.length);
sst_info->palette[regno].green = green; green >>= (16 - info->var.green.length);
sst_info->palette[regno].blue = blue; blue >>= (16 - info->var.blue.length);
sst_info->palette[regno].transp= transp; transp >>= (16 - info->var.transp.length);
col = (red << info->var.red.offset)
disp=&sst_info->disp; | (green << info->var.green.offset)
red >>= (16 - disp->var.red.length); | (blue << info->var.blue.offset)
green >>= (16 - disp->var.green.length); | (transp << info->var.transp.offset);
blue >>= (16 - disp->var.blue.length);
transp >>= (16 - disp->var.transp.length);
col = (red << disp->var.red.offset)
| (green << disp->var.green.offset)
| (blue << disp->var.blue.offset)
| (transp << disp->var.transp.offset);
switch(disp->var.bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
sst_info->fbcon_cmap.cfb16[regno]=(u16)col;
break;
#endif
#ifdef EN_24_32_BPP
#ifdef FBCON_HAS_CFB24
case 24:
sst_info->fbcon_cmap.cfb32[regno]=col;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
sst_info->fbcon_cmap.cfb32[regno]=col;
break;
#endif
#endif
default:
eprintk("bug line %d: bad depth '%u'\n",__LINE__,
disp->var.bits_per_pixel);
break;
}
f_dddprintk("bpp: %d . encoded color: %#x\n",
disp->var.bits_per_pixel, col);
return 0; return 0;
#undef sst_info
} }
/* set par according to var ( checks var ) */ /* set par according to var ( checks var ) */
static int sstfb_decode_var (const struct fb_var_screeninfo *var, static int sstfb_decode_var( const struct fb_var_screeninfo *var,
struct sstfb_par *par, struct sstfb_par *par,
const struct sstfb_info *sst_info) struct fb_info *info)
{ {
int real_length; int real_length;
...@@ -572,14 +505,14 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -572,14 +505,14 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
par->vSyncOff = var->yres + var->lower_margin + var->upper_margin; par->vSyncOff = var->yres + var->lower_margin + var->upper_margin;
par->vBackPorch = var->upper_margin; par->vBackPorch = var->upper_margin;
if(sst_calc_pll (PS2KHZ(var->pixclock), &par->freq, &par->pll)) { if(sst_calc_pll(PICOS2KHZ(var->pixclock), &par->freq, &par->pll)) {
eprintk("Pixclock %d out of range\n", var->pixclock); eprintk("Pixclock at %ld KHZ out of range\n", PICOS2KHZ(var->pixclock));
return -EINVAL; //XXX return -EINVAL;
} }
par->sync=var->sync & (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT); par->sync=var->sync & (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
par->vmode=var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
par->vmode=var->vmode & (FB_VMODE_INTERLACED | FB_VMODE_DOUBLE);
/* in laced mode, vBackPorch should be even. odd -> funky display */ /* in laced mode, vBackPorch should be even. odd -> funky display */
if (par->vmode & FB_VMODE_INTERLACED) if (par->vmode & FB_VMODE_INTERLACED)
par->vBackPorch += (par->vBackPorch % 2); par->vBackPorch += (par->vBackPorch % 2);
...@@ -603,18 +536,18 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -603,18 +536,18 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
break; break;
#endif #endif
default : default :
eprintk ("Unsupported bpp %d\n", par->bpp); eprintk("Unsupported bpp %d\n", par->bpp);
return -EINVAL; return -EINVAL;
break; break;
} }
if (IS_VOODOO2(sst_info)) { if (IS_VOODOO2(par)) {
/* voodoo2 has 32 pixel wide tiles , BUT stange things /* voodoo2 has 32 pixel wide tiles , BUT stange things
happen with odd number of tiles */ happen with odd number of tiles */
par->tiles_in_X= (par->xDim + 63 ) / 64 * 2; par->tiles_in_X = (par->xDim + 63 ) / 64 * 2;
} else { } else {
/* voodoo1 has 64 pixels wide tiles. */ /* voodoo1 has 64 pixels wide tiles. */
par->tiles_in_X= (par->xDim + 63 ) / 64; par->tiles_in_X = (par->xDim + 63 ) / 64;
} }
/* validity tests */ /* validity tests */
...@@ -628,10 +561,10 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -628,10 +561,10 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
|| (par->tiles_in_X <= 0)) { || (par->tiles_in_X <= 0)) {
return -EINVAL; return -EINVAL;
} }
if (IS_VOODOO2(sst_info)) { if (IS_VOODOO2(par)) {
/* Voodoo 2 limits */ /* Voodoo 2 limits */
if(((par->xDim-1) >= POW2(11)) || (par->yDim >= POW2(11))) { if(((par->xDim-1) >= POW2(11)) || (par->yDim >= POW2(11))) {
eprintk ("Unsupported resolution %dx%d\n", eprintk("Unsupported resolution %dx%d\n",
var->xres, var->yres); var->xres, var->yres);
return -EINVAL; return -EINVAL;
} }
...@@ -642,7 +575,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -642,7 +575,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
|| (par->vSyncOff >= POW2(13)) || (par->vSyncOff >= POW2(13))
|| (par->vBackPorch >= POW2(9)) || (par->vBackPorch >= POW2(9))
|| (par->tiles_in_X >= POW2(6))) { || (par->tiles_in_X >= POW2(6))) {
eprintk ("Unsupported Timing\n"); eprintk("Unsupported Timing\n");
return -EINVAL; return -EINVAL;
} }
} else { } else {
...@@ -653,7 +586,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -653,7 +586,7 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
return -EINVAL; return -EINVAL;
} }
if(((par->xDim-1) >= POW2(10)) || (par->yDim >= POW2(10))) { if(((par->xDim-1) >= POW2(10)) || (par->yDim >= POW2(10))) {
eprintk ("Unsupported resolution %dx%d\n", eprintk("Unsupported resolution %dx%d\n",
var->xres, var->yres); var->xres, var->yres);
return -EINVAL; return -EINVAL;
} }
...@@ -664,40 +597,40 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var, ...@@ -664,40 +597,40 @@ static int sstfb_decode_var (const struct fb_var_screeninfo *var,
|| (par->vSyncOff >= POW2(12)) || (par->vSyncOff >= POW2(12))
|| (par->vBackPorch >= POW2(8)) || (par->vBackPorch >= POW2(8))
|| (par->tiles_in_X >= POW2(4))) { || (par->tiles_in_X >= POW2(4))) {
eprintk ("Unsupported Timings\n"); eprintk("Unsupported Timings\n");
return -EINVAL; return -EINVAL;
} }
} }
/* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem*/ /* it seems that the fbi uses tiles of 64x16 pixels to "map" the mem */
/* FIXME: i don't like this... looks wrong*/ /* FIXME: i don't like this... looks wrong */
real_length = par->tiles_in_X * (IS_VOODOO2(sst_info) ? 32 : 64 ) real_length = par->tiles_in_X * (IS_VOODOO2(par) ? 32 : 64 )
* ((par->bpp == 16) ? 2 : 4); * ((par->bpp == 16) ? 2 : 4);
if ((real_length * var->yres) > sst_info->video.len) { if ((real_length * var->yres) > info->fix.smem_len) {
eprintk ("Not enough video memory\n"); eprintk("Not enough video memory\n");
return -ENOMEM; return -ENOMEM;
} }
par->valid=1; par->valid = 1;
return 0; return 0;
} }
/* sets var according to par (basicaly, sets sane values) */ /* sets var according to par (basically, sets sane values) */
static int sstfb_encode_var (struct fb_var_screeninfo *var, static int sstfb_encode_var( struct fb_var_screeninfo *var,
const struct sstfb_par *par, const struct sstfb_par *par,
const struct sstfb_info *sst_info) struct fb_info *info)
{ {
memset(var,0,sizeof(struct fb_var_screeninfo)); memset(var, 0, sizeof(*var));
var->xres = par->xDim; var->xres = par->xDim;
var->yres = par->yDim; var->yres = par->yDim;
var->xres_virtual = par->xDim; var->xres_virtual = par->xDim;
var->yres_virtual = par->yDim; var->yres_virtual = par->yDim;
var->bits_per_pixel = par->bpp; var->bits_per_pixel = par->bpp;
/* {x|y}offset = 0 */ /* {x|y}offset = 0 ; sync=0 */
var->height = -1; var->height = -1;
var->width = -1; var->width = -1;
var->pixclock = KHZ2PS(par->freq); var->pixclock = KHZ2PICOS(par->freq);
var->left_margin = par->hBackPorch; var->left_margin = par->hBackPorch;
var->right_margin = par->hSyncOff - par->xDim - par->hBackPorch; var->right_margin = par->hSyncOff - par->xDim - par->hBackPorch;
var->upper_margin = par->vBackPorch; var->upper_margin = par->vBackPorch;
...@@ -717,7 +650,7 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var, ...@@ -717,7 +650,7 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
/* /*
* correct the color bit fields * correct the color bit fields
*/ */
/* var->{red|green|blue}.msb_right = 0; */ /* var->{red|green|blue}.msb_right = 0; */
switch (par->bpp) { switch (par->bpp) {
case 16: /* RGB 565 LfbMode 0 */ case 16: /* RGB 565 LfbMode 0 */
...@@ -730,6 +663,7 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var, ...@@ -730,6 +663,7 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
var->green.offset = 5; var->green.offset = 5;
var->blue.offset = 0; var->blue.offset = 0;
var->transp.offset = 0; var->transp.offset = 0;
info->fix.line_length = 2048;
break; break;
#ifdef EN_24_32_BPP #ifdef EN_24_32_BPP
case 24: /* RGB 888 LfbMode 4 */ case 24: /* RGB 888 LfbMode 4 */
...@@ -743,12 +677,14 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var, ...@@ -743,12 +677,14 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
var->green.offset = 8; var->green.offset = 8;
var->blue.offset = 0; var->blue.offset = 0;
var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */ var->transp.offset = 0; /* in 24bpp we fake a 32 bpp mode */
info->fix.line_length = 4096;
break; break;
#endif #endif
default: default:
eprintk ("bug line %d: bad depth '%u'\n", __LINE__, par->bpp); BUG();
break; return -EINVAL;
} }
return 0; return 0;
} }
...@@ -756,299 +692,94 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var, ...@@ -756,299 +692,94 @@ static int sstfb_encode_var (struct fb_var_screeninfo *var,
* Frame buffer API * Frame buffer API
*/ */
static int sstfb_open(struct fb_info *info, int user) static int sstfb_check_var(struct fb_var_screeninfo *var,
{ struct fb_info *info)
f_dprintk("sstfb_open(user: %d)\n",user);
return 0;
}
static int sstfb_release(struct fb_info *info, int user)
{ {
f_dprintk("sstfb_release(user: %d)\n",user);
return 0;
}
static int sstfb_get_fix(struct fb_fix_screeninfo *fix,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
struct fb_var_screeninfo *var;
f_dprintk("sstfb_get_fix(con: %d)\n",con);
if (con == -1)
sstfb_encode_var(var, &sst_info->current_par, sst_info);
else
var = &fb_display[con].var;
strcpy(fix->id, sst_info->info.modename);
/* lfb phys address = membase + 4Mb */
fix->smem_start = sst_info->video.base;
fix->smem_len = sst_info->video.len;
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR;
/*
* According to the specs, the linelength must be of 1024 *pixels*.
* and the 24bpp mode is in fact a 32 bpp mode.
*/
fix->line_length = (var->bits_per_pixel == 16) ? 2048 : 4096 ;
return 0;
#undef sst_info
}
static int sstfb_get_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
f_dprintk("sstfb_get_var(con: %d)\n",con);
if (con == -1)
sstfb_encode_var(var, &sst_info->current_par, sst_info);
else
*var = fb_display[con].var;
print_var(var, "var");
return 0;
#undef sst_info
}
static int sstfb_set_var(struct fb_var_screeninfo *var,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
struct sstfb_par par; struct sstfb_par par;
struct display *display; int res;
int err;
int old_bpp,old_xres,old_yres;
f_dprintk("sstfb_set_var(con: %d)\n",con);
f_ddprintk("xres yres vxres vyres bpp activate\n");
f_ddprintk("%-4d %-4d %-5d %-5d %-3d %#-8x\n",
var->xres,var->yres,var->xres_virtual,var->yres_virtual,
var->bits_per_pixel,var->activate);
if (con < 0)
display = &sst_info->disp;
else
display = &fb_display[con];
if ((err = sstfb_decode_var(var, &par, sst_info)))
return err;
sstfb_encode_var (var, &par, sst_info);
switch (var->activate & FB_ACTIVATE_MASK) {
case FB_ACTIVATE_TEST:
return 0;
case FB_ACTIVATE_NXTOPEN:
case FB_ACTIVATE_NOW:
break;
default:
return -EINVAL;
}
old_xres = display->var.xres;
old_yres = display->var.yres;
old_bpp = display->var.bits_per_pixel;
display->var = *var;
if ((old_xres != var->xres) || (old_yres != var->yres)
|| (old_bpp != var->bits_per_pixel)) {
/* 2-3 lignes redondantes avec get_fix */
display->screen_base = (char *) sst_info->video.vbase;
display->visual = FB_VISUAL_TRUECOLOR;
display->type = FB_TYPE_PACKED_PIXELS;
display->type_aux = 0;
display->ypanstep = 0;
display->ywrapstep = 0;
display->line_length = (var->bits_per_pixel==16) ? 2048 : 4096;
display->inverse = 0;
switch (var->bits_per_pixel) {
#ifdef FBCON_HAS_CFB16
case 16:
display->dispsw = &fbcon_cfb16;
display->dispsw_data = sst_info->fbcon_cmap.cfb16;
break;
#endif
#ifdef EN_24_32_BPP
#if defined (FBCON_HAS_CFB24) || defined (FBCON_HAS_CFB32 )
case 24: /*24bpp non packed <=> 32 bpp */
case 32:
display->dispsw = &fbcon_cfb32;
display->dispsw_data = sst_info->fbcon_cmap.cfb32;
break;
#endif
#endif
default:
display->dispsw = &fbcon_dummy;
break;
}
display->scrollmode = SCROLL_YREDRAW;
if (sst_info->info.changevar) {
v_dprintk("fb_info.changevar(con: %d)\n", con);
(*sst_info->info.changevar)(con);
v_dprintk("fb_info.changevar: done \n");
} else {
v_dprintk("fb_info.changevar() == NULL . \n");
}
}
if ((con == -1) || (con==sst_info->currcon)) { f_dprintk("sstfb_check_var()\n");
sstfb_set_par (&par, sst_info);
}
print_var(var, "var"); print_var(var, "var");
print_var(&display->var, "&display->var"); if ((res = sstfb_decode_var(var, &par, info)))
return res;
if (old_bpp != var->bits_per_pixel) {
if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))
return err;
sstfb_install_cmap(con, info);
}
return 0; return 0;
#undef sst_info
} }
static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
struct display *d = (con<0) ? info->disp : fb_display + con;
f_dprintk("sstfb_set_cmap\n");
f_ddprintk("con: %d, currcon: %d, d->cmap.len %d\n",
con, sst_info->currcon, d->cmap.len);
if (d->cmap.len != 16 ) { /* or test if cmap.len == 0 ? */
int err;
err = fb_alloc_cmap(&d->cmap, 16, 0); /* cmap size=16 */
if (err) return err;
}
if (con == sst_info->currcon) {
return fb_set_cmap(cmap, kspc, sstfb_setcolreg, info);
} else {
fb_copy_cmap(cmap, &d->cmap, kspc ? 0 : 1);
}
return 0;
#undef sst_info
}
static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc,
int con, struct fb_info *info)
{
#define sst_info ((struct sstfb_info *) info)
f_dprintk("sstfb_get_cmap\n");
f_ddprintk("con %d, curcon %d, cmap.len %d\n",
con, sst_info->currcon, fb_display[con].cmap.len);
/* FIXME: check if con = -1 ? cf sstfb_set_cmap... */
if (con == sst_info->currcon)
return fb_get_cmap(cmap, kspc, sstfb_getcolreg, info);
else if (fb_display[con].cmap.len)
fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2);
else
fb_copy_cmap(
fb_default_cmap(1<<fb_display[con].var.bits_per_pixel),
cmap, kspc ? 0 : 2);
return 0;
#undef sst_info
}
/* TODO */
static int sstfb_pan_display(struct fb_var_screeninfo *var,
int con, struct fb_info *info)
{
f_dprintk("sstfb_pan_display\n");
return -EINVAL;
}
static int sstfb_ioctl(struct inode *inode, struct file *file, static int sstfb_ioctl(struct inode *inode, struct file *file,
u_int cmd, u_long arg, int con, u_int cmd, u_long arg, struct fb_info *info )
struct fb_info *info)
{ {
#define sst_info ((struct sstfb_info *) info) struct sstfb_par *par = (struct sstfb_par *) info->par;
#if (SST_DEBUG_IOCTL >0) struct pci_dev *sst_dev = par->dev;
int i; u32 fbiinit0, tmp, val;
u_long p; u_long p;
u32 tmp;
u32 fbiinit0;
struct pci_dev * sst_dev = sst_info->dev;
#endif
f_dprintk("sstfb_ioctl(%x)\n", cmd); f_dprintk("sstfb_ioctl(%x)\n", cmd);
#if (SST_DEBUG_IOCTL >0)
switch (cmd) { switch (cmd) {
# if (SST_DEBUG_VAR >0)
/* tmp ioctl : dumps fb_display[0-5] */ /* fills lfb with #arg pixels */
case _IO('F', 0xdb): /* 0x46db */
f_dprintk("dumping fb_display[0-5].var\n");
for (i = 0 ; i< 6 ; i++) {
print_var(&fb_display[i].var, "var(%d)", i);
}
return 0;
# endif /* (SST_DEBUG_VAR >0) */
/* fills the lfb up to *(u32*)arg */
case _IOW('F', 0xdc, u32): /* 0x46dc */ case _IOW('F', 0xdc, u32): /* 0x46dc */
if (*(u32*)arg > 0x400000 ) if (copy_from_user(&val, (void *) arg, sizeof(val)))
*(u32*) arg = 0x400000; return -EFAULT;
f_dprintk("filling %#x \n", *(u32*)arg); if (val > info->fix.smem_len)
for (p = 0 ; p < *(u32*)arg; p+=2) val = info->fix.smem_len;
writew( p >> 6 , sst_info->video.vbase + p); f_dprintk("filling %#x \n", val);
for (p = 0 ; p < val; p+=2)
writew( p >> 6 , info->screen_base + p);
return 0; return 0;
/* change VGA pass_through */
/* change VGA pass_through mode */
case _IOW('F', 0xdd, u32): /* 0x46dd */ case _IOW('F', 0xdd, u32): /* 0x46dd */
if (copy_from_user(&val, (void *) arg, sizeof(val)))
return -EFAULT;
f_dprintk("switch VGA pass-through\n"); f_dprintk("switch VGA pass-through\n");
pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp); pci_read_config_dword(sst_dev, PCI_INIT_ENABLE, &tmp);
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
tmp | PCI_EN_INIT_WR ); tmp | PCI_EN_INIT_WR );
fbiinit0 = sst_read (FBIINIT0); fbiinit0 = sst_read (FBIINIT0);
if (* (u32*)arg) { if (val) {
sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH); sst_write(FBIINIT0, fbiinit0 & ~EN_VGA_PASSTHROUGH);
iprintk ( "Disabling VGA pass-through\n"); iprintk( "Disabling VGA pass-through\n");
} else { } else {
sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH); sst_write(FBIINIT0, fbiinit0 | EN_VGA_PASSTHROUGH);
iprintk ( "Enabling VGA pass-through\n"); iprintk( "Enabling VGA pass-through\n");
} }
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp); pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, tmp);
return 0; return 0;
/* draw test image */
case _IO('F', 0xde): /* 0x46de */ case _IO('F', 0xde): /* 0x46de */
f_dprintk("test color display\n"); f_dprintk("test color display\n");
f_ddprintk("currcon: %d, bpp %d\n", sst_info->currcon, f_ddprintk("bpp %d\n",
sst_info->current_par.bpp); sst_info->par.bpp);
memset_io(sst_info->video.vbase, 0, sst_info->video.len); memset_io(info->screen_base, 0, info->fix.smem_len);
switch (sst_info->current_par.bpp) { switch (info->var.bits_per_pixel) {
/* FIXME broken : if we call this ioctl from a tty not bound to the fb, we use its depth and not the current one ... */ case 16:
case 16: sstfb_test16(info);
sstfb_test16(sst_info);
break; break;
# ifdef EN_24_32_BPP #ifdef EN_24_32_BPP
case 24: case 24:
case 32: case 32:
sstfb_test32(sst_info); sstfb_test32(info);
break; break;
# endif #endif
default: default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, BUG();
sst_info->current_par.bpp); }
}
return 0;
case _IO('F', 0xdf): /* 0x46db */
Dump_regs;
return 0; return 0;
} }
#endif /* (SST_DEBUG_IOCTL >0) */
return -EINVAL; return -EINVAL;
#undef sst_info
} }
/* /*
* Low level routines * Low level routines
*/ */
/* get lfb size */ /* get lfb size */
static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize) static int __devinit sst_get_memsize(struct fb_info *info, u_long *memsize)
{ {
u_long fbbase_virt = sst_info->video.vbase; u_long fbbase_virt = (ulong) info->screen_base;
f_dprintk("sst_get_memsize\n"); f_dprintk("sst_get_memsize\n");
/* force memsize */ /* force memsize */
...@@ -1084,62 +815,21 @@ static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsiz ...@@ -1084,62 +815,21 @@ static int __devinit sst_get_memsize(struct sstfb_info *sst_info, u_long *memsiz
} }
/* /*
* wait for the fbi chip. ASK: what happens if the fbi is stuck ? * DAC detection routines
*
* the FBI is supposed to be ready if we receive 5 time
* in a row a "idle" answer to our requests
*/ */
static int __sst_wait_idle(u_long vbase)
{
int count = 0;
f_ddprintk("sst_wait_idle\n");
while(1) {
if (__sst_read(vbase, STATUS) & STATUS_FBI_BUSY) {
f_dddprintk("status: busy\n");
/* FIXME basicaly, this is a busy wait. maybe not that good. oh well; this is a small loop after all ...*/
count = 0;
} else {
count++;
f_dddprintk("status: idle(%d)\n", count);
}
if (count >= 5) return 1;
//XXX do something to avoid hanging the machine if the voodoo is out
}
}
/*
* detect dac type
* prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
* dram refresh disabled, FbiInit remaped.
* TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
*/
static int __devinit sst_detect_dactype(struct sstfb_info * sst_info)
{
int ret=0,i;
f_dprintk("sst_detect_dactype\n");
for (i=0; i< sizeof(dacs)/sizeof(dacs[0]) ; i++) {
ret = dacs[i].detect(sst_info);
if (ret) break;
}
if (!ret)
return 0;
f_dprintk("found %s\n", dacs[i].name);
sst_info->dac_sw=dacs[i];
return 1;
}
/* fbi should be idle, and fifo emty and mem disabled */ /* fbi should be idle, and fifo emty and mem disabled */
/* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */ /* supposed to detect AT&T ATT20C409 and Ti TVP3409 ramdacs */
static int __devinit sst_detect_att(struct sstfb_info * sst_info) static int __devinit sst_detect_att(struct fb_info *info)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir; int i, mir, dir;
f_dprintk("sst_detect_att\n"); f_dprintk("sst_detect_att\n");
for (i = 0; i<3; i++) { for (i=0; i<3; i++) {
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */ sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR); sst_dac_read(DACREG_RMR);
...@@ -1159,8 +849,9 @@ static int __devinit sst_detect_att(struct sstfb_info * sst_info) ...@@ -1159,8 +849,9 @@ static int __devinit sst_detect_att(struct sstfb_info * sst_info)
return 0; return 0;
} }
static int __devinit sst_detect_ti(struct sstfb_info * sst_info) static int __devinit sst_detect_ti(struct fb_info *info)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par;
int i, mir, dir; int i, mir, dir;
f_dprintk("sst_detect_ti\n"); f_dprintk("sst_detect_ti\n");
...@@ -1195,11 +886,13 @@ static int __devinit sst_detect_ti(struct sstfb_info * sst_info) ...@@ -1195,11 +886,13 @@ static int __devinit sst_detect_ti(struct sstfb_info * sst_info)
* touched... * touched...
* is it realy safe ? how can i reset this ramdac ? geee... * is it realy safe ? how can i reset this ramdac ? geee...
*/ */
static int __devinit sst_detect_ics(struct sstfb_info * sst_info) static int __devinit sst_detect_ics(struct fb_info *info)
{ {
int i; struct sstfb_par *par = (struct sstfb_par *) info->par;
int m_clk0_1, m_clk0_7, m_clk1_b; int m_clk0_1, m_clk0_7, m_clk1_b;
int n_clk0_1, n_clk0_7, n_clk1_b; int n_clk0_1, n_clk0_7, n_clk1_b;
int i;
f_dprintk("sst_detect_ics\n"); f_dprintk("sst_detect_ics\n");
for (i = 0; i<5; i++ ) { for (i = 0; i<5; i++ ) {
sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */ sst_dac_write(DACREG_ICS_PLLRMA, 0x1); /* f1 */
...@@ -1224,68 +917,19 @@ static int __devinit sst_detect_ics(struct sstfb_info * sst_info) ...@@ -1224,68 +917,19 @@ static int __devinit sst_detect_ics(struct sstfb_info * sst_info)
return 0; return 0;
} }
/* compute the m,n,p , returns the real freq
* (ics datasheet : N <-> N1 , P <-> N2)
*
* Fout= Fref * (M+2)/( 2^P * (N+2))
* we try to get close to the asked freq
* with P as high, and M as low as possible
* range:
* ti/att : 0 <= M <= 255; 0 <= P <= 3; 0<= N <= 63
* ics : 1 <= M <= 127; 0 <= P <= 3; 1<= N <= 31
* we'll use the lowest limitation, should be precise enouth
*/
static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t)
{
int m, m2, n, p, best_err, fout;
int best_n=-1;
int best_m=-1;
f_dprintk("sst_calc_pll(%dKhz)\n", freq);
best_err = freq;
p=3;
/* f * 2^P = vco should be less than VCOmax ~ 250 MHz for ics*/
while (((1 << p) * freq > VCO_MAX) && (p >= 0))
p--;
if (p == -1)
return -EINVAL;
for (n = 1; n < 32; n++) {
/* calc 2 * m so we can round it later*/
m2 = (2 * freq * (1 << p) * (n + 2) ) / DAC_FREF - 4 ;
m = (m2 % 2 ) ? m2/2+1 : m2/2 ;
if (m >= 128)
break;
fout = (DAC_FREF * (m + 2)) / ((1 << p) * (n + 2));
if ((ABS(fout - freq) < best_err) && (m > 0)) {
best_n = n;
best_m = m;
best_err = ABS(fout - freq);
/* we get the lowest m , allowing 0.5% error in freq*/
if (200*best_err < freq) break;
}
}
if (best_n == -1) /* unlikely, but who knows ? */
return -EINVAL;
t->p=p;
t->n=best_n;
t->m=best_m;
*freq_out=(DAC_FREF * (t->m + 2)) / ((1 << t->p) * (t->n + 2));
f_ddprintk ("m: %d, n: %d, p: %d, F: %dKhz\n",
t->m, t->n, t->p, *freq_out);
return 0;
}
/* /*
* gfx, video, pci fifo should be reset, dram refresh disabled * gfx, video, pci fifo should be reset, dram refresh disabled
* see detect_dac * see detect_dac
*/ */
static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock) static int sst_set_pll_att_ti(struct fb_info *info,
const struct pll_timing *t, const int clock)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0, cc; u8 cr0, cc;
f_dprintk("sst_set_pll_att_ti\n");
f_dprintk("sst_set_pll_att_ti\n");
/* enable indexed mode */ /* enable indexed mode */
sst_dac_write(DACREG_WMA, 0); /* backdoor */ sst_dac_write(DACREG_WMA, 0); /* backdoor */
...@@ -1335,49 +979,154 @@ static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_tim ...@@ -1335,49 +979,154 @@ static int sst_set_pll_att_ti(struct sstfb_info * sst_info, const struct pll_tim
return 1; return 1;
} }
static int sst_set_pll_ics(struct sstfb_info * sst_info, const struct pll_timing *t, const int clock) static int sst_set_pll_ics(struct fb_info *info,
{ const struct pll_timing *t, const int clock)
u8 pll_ctrl; {
struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 pll_ctrl;
f_dprintk("sst_set_pll_ics\n");
sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL);
pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA);
switch(clock) {
case VID_CLOCK:
sst_dac_write(DACREG_ICS_PLLWMA, 0x0); /* CLK0, f0 */
sst_dac_write(DACREG_ICS_PLLDATA, t->m);
sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
/* selects freq f0 for clock 0 */
sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
sst_dac_write(DACREG_ICS_PLLDATA,
(pll_ctrl & 0xd8)
| DACREG_ICS_CLK0
| DACREG_ICS_CLK0_0);
break;
case GFX_CLOCK :
sst_dac_write(DACREG_ICS_PLLWMA, 0xa); /* CLK1, fA */
sst_dac_write(DACREG_ICS_PLLDATA, t->m);
sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n);
/* selects freq fA for clock 1 */
sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
sst_dac_write(DACREG_ICS_PLLDATA,
(pll_ctrl & 0xef) | DACREG_ICS_CLK1_A);
break;
default:
dprintk("bug line %d: wrong clock code '%d'\n",
__LINE__, clock);
return 0;
}
udelay(300);
return 1;
}
static void sst_set_vidmod_att_ti(struct fb_info *info, const int bpp)
{
struct sstfb_par *par = (struct sstfb_par *) info->par;
u8 cr0;
f_dprintk("sst_set_vidmod_att_ti(bpp: %d)\n", bpp);
sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
/* the fifth time, CR0 is read */
cr0 = sst_dac_read(DACREG_RMR);
sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
/* cr0 */
switch(bpp) {
case 16:
sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
break;
#ifdef EN_24_32_BPP
case 24:
case 32:
sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_24BPP);
break;
#endif
default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
break;
}
}
static void sst_set_vidmod_ics(struct fb_info *info, const int bpp)
{
struct sstfb_par *par = (struct sstfb_par *) info->par;
f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);
switch(bpp) {
case 16:
sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
break;
#ifdef EN_24_32_BPP
case 24:
case 32:
sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_24BPP);
break;
#endif
default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
break;
}
}
/*
* detect dac type
* prerequisite : write to FbiInitx enabled, video and fbi and pci fifo reset,
* dram refresh disabled, FbiInit remaped.
* TODO: mmh.. maybe i shoud put the "prerequisite" in the func ...
*/
f_dprintk("sst_set_pll_ics\n");
sst_dac_write(DACREG_ICS_PLLRMA, DACREG_ICS_PLL_CTRL); static struct dac_switch dacs[] __devinitdata = {
pll_ctrl = sst_dac_read(DACREG_ICS_PLLDATA); { .name = "TI TVP3409",
switch(clock) { .detect = sst_detect_ti,
case VID_CLOCK: .set_pll = sst_set_pll_att_ti,
sst_dac_write(DACREG_ICS_PLLWMA, 0x0); /* CLK0, f0 */ .set_vidmod = sst_set_vidmod_att_ti },
sst_dac_write(DACREG_ICS_PLLDATA, t->m);
sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); { .name = "AT&T ATT20C409",
/* selects freq f0 for clock 0 */ .detect = sst_detect_att,
sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL); .set_pll = sst_set_pll_att_ti,
sst_dac_write(DACREG_ICS_PLLDATA, .set_vidmod = sst_set_vidmod_att_ti },
(pll_ctrl & 0xd8) { .name = "ICS ICS5342",
| DACREG_ICS_CLK0 .detect = sst_detect_ics,
| DACREG_ICS_CLK0_0); .set_pll = sst_set_pll_ics,
break; .set_vidmod = sst_set_vidmod_ics },
case GFX_CLOCK : };
sst_dac_write(DACREG_ICS_PLLWMA, 0xa); /* CLK1, fA */
sst_dac_write(DACREG_ICS_PLLDATA, t->m); static int __devinit sst_detect_dactype(struct fb_info *info, struct sstfb_par *par)
sst_dac_write(DACREG_ICS_PLLDATA, t->p << 5 | t->n); {
/* selects freq fA for clock 1 */ int ret = 0,i;
sst_dac_write(DACREG_ICS_PLLWMA, DACREG_ICS_PLL_CTRL);
sst_dac_write(DACREG_ICS_PLLDATA, f_dprintk("sst_detect_dactype\n");
(pll_ctrl & 0xef) | DACREG_ICS_CLK1_A); for (i=0; i<sizeof(dacs)/sizeof(dacs[0]); i++) {
break; ret = dacs[i].detect(info);
default: if (ret) break;
dprintk("bug line %d: wrong clock code '%d'\n", }
__LINE__, clock); if (!ret)
return 0; return 0;
} f_dprintk("found %s\n", dacs[i].name);
udelay(300); par->dac_sw = dacs[i];
return 1; return 1;
} }
static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_info)
static int sstfb_set_par(struct fb_info *info)
{ {
struct sstfb_par *par = (struct sstfb_par *) info->par;
u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0; u32 lfbmode, fbiinit1, fbiinit2, fbiinit3, fbiinit5, fbiinit6=0;
struct pci_dev *sst_dev = par->dev;
int ntiles; int ntiles;
struct pci_dev * sst_dev = sst_info->dev;
sstfb_encode_var(&info->var, par, info);
f_dprintk("sst_set_par(%dx%d)\n", par->xDim, par->yDim); f_dprintk("sst_set_par(%dx%d)\n", par->xDim, par->yDim);
f_ddprintk("hSyncOn hSyncOff vSyncOn vSyncOff\n"); f_ddprintk("hSyncOn hSyncOff vSyncOn vSyncOff\n");
...@@ -1391,7 +1140,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1391,7 +1140,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
if (!par->valid) { if (!par->valid) {
BUG(); BUG();
return -1; return -EINVAL;
} }
sst_write(NOPCMD, 0); sst_write(NOPCMD, 0);
sst_wait_idle(); sst_wait_idle();
...@@ -1415,10 +1164,10 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1415,10 +1164,10 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC ); PCI_EN_INIT_WR | PCI_REMAP_DAC );
sst_info->dac_sw.set_vidmod(sst_info, par->bpp); par->dac_sw.set_vidmod(info, par->bpp);
/* set video clock */ /* set video clock */
sst_info->dac_sw.set_pll(sst_info, &par->pll, VID_CLOCK); par->dac_sw.set_pll(info, &par->pll, VID_CLOCK);
/* disable fbiinit2/3 remap */ /* disable fbiinit2/3 remap */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(sst_dev, PCI_INIT_ENABLE,
...@@ -1446,7 +1195,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1446,7 +1195,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
*/ */
ntiles = par->tiles_in_X; ntiles = par->tiles_in_X;
if (IS_VOODOO2(sst_info)) { if (IS_VOODOO2(par)) {
fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT fbiinit1 |= ((ntiles & 0x20) >> 5) << TILES_IN_X_MSB_SHIFT
| ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ; | ((ntiles & 0x1e) >> 1) << TILES_IN_X_SHIFT ;
/* as the only value of importance for us in fbiinit6 is tiles in X (lsb), /* as the only value of importance for us in fbiinit6 is tiles in X (lsb),
...@@ -1476,7 +1225,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1476,7 +1225,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
break; break;
} }
sst_write(FBIINIT1, fbiinit1); sst_write(FBIINIT1, fbiinit1);
if (IS_VOODOO2(sst_info)) { if (IS_VOODOO2(par)) {
sst_write(FBIINIT6, fbiinit6); sst_write(FBIINIT6, fbiinit6);
fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ; fbiinit5=sst_read(FBIINIT5) & FBIINIT5_MASK ;
if (par->vmode & FB_VMODE_INTERLACED) if (par->vmode & FB_VMODE_INTERLACED)
...@@ -1497,7 +1246,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1497,7 +1246,7 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR); pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR);
/* set lfbmode : set mode + front buffer for reads/writes /* set lfbmode : set mode + front buffer for reads/writes
+ disable pipeline + disable byte swapping */ + disable pipeline */
switch(par->bpp) { switch(par->bpp) {
case 16: case 16:
lfbmode = LFB_565; lfbmode = LFB_565;
...@@ -1517,6 +1266,16 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1517,6 +1266,16 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
break; break;
} }
#if defined(__BIG_ENDIAN)
/* Enable byte-swizzle functionality in hardware.
* With this enabled, all our read- and write-accesses to
* the voodoo framebuffer can be done in native format, and
* the hardware will automatically convert it to little-endian.
* (tested on HP-PARISC, deller@gmx.de) */
lfbmode |= ( LFB_WORD_SWIZZLE_WR | LFB_BYTE_SWIZZLE_WR |
LFB_WORD_SWIZZLE_RD | LFB_BYTE_SWIZZLE_RD );
#endif
if (clipping) { if (clipping) {
sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE); sst_write(LFBMODE, lfbmode | EN_PXL_PIPELINE);
/* /*
...@@ -1539,77 +1298,19 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i ...@@ -1539,77 +1298,19 @@ static int sstfb_set_par(const struct sstfb_par * par, struct sstfb_info * sst_i
sst_write(LFBMODE, lfbmode ); sst_write(LFBMODE, lfbmode );
} }
sst_info->current_par = *par ;
return 1; return 1;
} }
static void sst_set_vidmod_att_ti(struct sstfb_info * sst_info, const int bpp)
{
u8 cr0;
f_dprintk("sst_set_vidmod_att_ti(bpp: %d)\n", bpp);
sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
/* the fifth time, CR0 is read */
cr0 = sst_dac_read(DACREG_RMR);
sst_dac_write(DACREG_WMA, 0); /* backdoor */
sst_dac_read(DACREG_RMR); /* read 4 times RMR */
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
sst_dac_read(DACREG_RMR);
/* cr0 */
switch(bpp) {
case 16:
sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_16BPP);
break;
#ifdef EN_24_32_BPP
case 24:
case 32:
sst_dac_write(DACREG_RMR, (cr0 & 0x0f) | DACREG_CR0_24BPP);
break;
#endif
default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
break;
}
}
static void sst_set_vidmod_ics(struct sstfb_info * sst_info, const int bpp)
{
f_dprintk("sst_set_vidmod_ics(bpp: %d)\n", bpp);
switch(bpp) {
case 16:
sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_16BPP);
break;
#ifdef EN_24_32_BPP
case 24:
case 32:
sst_dac_write(DACREG_ICS_CMD, DACREG_ICS_CMD_24BPP);
break;
#endif
default:
dprintk("bug line %d: bad depth '%u'\n", __LINE__, bpp);
break;
}
}
static int __devinit sst_init(struct sstfb_info *sst_info) static int __devinit sst_init(struct fb_info *info, struct sstfb_par *par)
{ {
u32 fbiinit0, fbiinit1, fbiinit4;
struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings; struct pll_timing gfx_timings;
struct sst_spec * spec; struct sst_spec * spec;
struct pci_dev * sst_dev = sst_info->dev;
int Fout; int Fout;
u32 fbiinit0, fbiinit1, fbiinit4;
dprintk("sst_init\n"); //XXX spec = &voodoo_spec[par->type];
Dump_regs; //XXX
spec = &voodoo_spec[sst_info->type];
f_dprintk("sst_init\n"); f_dprintk("sst_init\n");
f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 " f_ddprintk(" fbiinit0 fbiinit1 fbiinit2 fbiinit3 fbiinit4 "
" fbiinit6\n"); " fbiinit6\n");
...@@ -1617,10 +1318,10 @@ static int __devinit sst_init(struct sstfb_info *sst_info) ...@@ -1617,10 +1318,10 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2), sst_read(FBIINIT0), sst_read(FBIINIT1), sst_read(FBIINIT2),
sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6)); sst_read(FBIINIT3), sst_read(FBIINIT4), sst_read(FBIINIT6));
/* disable video clock */ /* disable video clock */
pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0); pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* enable writing to init registers ,disable pci fifo*/ /* enable writing to init registers ,disable pci fifo*/
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
/* reset video */ /* reset video */
sst_set_bits(FBIINIT1, VIDEO_RESET); sst_set_bits(FBIINIT1, VIDEO_RESET);
sst_wait_idle(); sst_wait_idle();
...@@ -1639,29 +1340,29 @@ static int __devinit sst_init(struct sstfb_info *sst_info) ...@@ -1639,29 +1340,29 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH); sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
sst_wait_idle(); sst_wait_idle();
/* remap fbinit2/3 to dac */ /* remap fbinit2/3 to dac */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC ); PCI_EN_INIT_WR | PCI_REMAP_DAC );
/* detect dac type */ /* detect dac type */
if (!sst_detect_dactype(sst_info)) { if (!sst_detect_dactype(info, par)) {
eprintk("Unknown dac type\n"); eprintk("Unknown dac type\n");
//FIXME watch it : we are not in a safe state , bad bad bad . //FIXME watch it : we are not in a safe state, bad bad bad .
return 0; return 0;
} }
/* set graphic clock */ /* set graphic clock */
sst_info->gfx_clock = spec->default_gfx_clock; par->gfx_clock = spec->default_gfx_clock;
if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) { if ((gfxclk >10 ) && (gfxclk < spec->max_gfxclk)) {
iprintk ("Using supplied graphic freq : %dMHz\n", gfxclk); iprintk("Using supplied graphic freq : %dMHz\n", gfxclk);
sst_info->gfx_clock = gfxclk *1000; par->gfx_clock = gfxclk *1000;
} else if (gfxclk) { } else if (gfxclk) {
wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk); wprintk ("You fool, %dMhz is way out of spec! Using default\n", gfxclk);
} }
sst_calc_pll(sst_info->gfx_clock, &Fout, &gfx_timings); sst_calc_pll(par->gfx_clock, &Fout, &gfx_timings);
sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK); par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* disable fbiinit remap */ /* disable fbiinit remap */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR| PCI_EN_FIFO_WR ); PCI_EN_INIT_WR| PCI_EN_FIFO_WR );
/* defaults init registers */ /* defaults init registers */
/* FbiInit0: unreset gfx, unreset fifo */ /* FbiInit0: unreset gfx, unreset fifo */
...@@ -1689,42 +1390,42 @@ static int __devinit sst_init(struct sstfb_info *sst_info) ...@@ -1689,42 +1390,42 @@ static int __devinit sst_init(struct sstfb_info *sst_info)
sst_wait_idle(); sst_wait_idle();
sst_write(FBIINIT4, fbiinit4); sst_write(FBIINIT4, fbiinit4);
sst_wait_idle(); sst_wait_idle();
if (IS_VOODOO2(sst_info)) { if (IS_VOODOO2(par)) {
sst_write(FBIINIT6, FBIINIT6_DEFAULT); sst_write(FBIINIT6, FBIINIT6_DEFAULT);
sst_wait_idle(); sst_wait_idle();
} }
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR ); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_FIFO_WR );
pci_write_config_dword(sst_dev, PCI_VCLK_ENABLE, 0); pci_write_config_dword(dev, PCI_VCLK_ENABLE, 0);
return 1; return 1;
} }
static void __devexit sst_shutdown(struct sstfb_info *sst_info) static void __devexit sst_shutdown(struct fb_info *info)
{ {
struct pci_dev * sst_dev = sst_info->dev; struct sstfb_par *par = (struct sstfb_par *) info->par;
struct pci_dev *dev = par->dev;
struct pll_timing gfx_timings; struct pll_timing gfx_timings;
int Fout; int Fout;
f_dprintk("sst_shutdown\n"); f_dprintk("sst_shutdown\n");
/* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */ /* reset video, gfx, fifo, disable dram + remap fbiinit2/3 */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR); pci_write_config_dword(dev, PCI_INIT_ENABLE, PCI_EN_INIT_WR);
sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING); sst_set_bits(FBIINIT1, VIDEO_RESET | EN_BLANKING);
sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH); sst_unset_bits(FBIINIT2, EN_DRAM_REFRESH);
sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET); sst_set_bits(FBIINIT0, FBI_RESET | FIFO_RESET);
sst_wait_idle(); sst_wait_idle();
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR | PCI_REMAP_DAC ); PCI_EN_INIT_WR | PCI_REMAP_DAC );
/*set 20Mhz gfx clock */ /*set 20Mhz gfx clock */
sst_calc_pll(20000, &Fout, &gfx_timings); sst_calc_pll(20000, &Fout, &gfx_timings);
sst_info->dac_sw.set_pll(sst_info, &gfx_timings, GFX_CLOCK); par->dac_sw.set_pll(info, &gfx_timings, GFX_CLOCK);
/* TODO maybe shutdown the dac, vrefresh and so on... */ /* TODO maybe shutdown the dac, vrefresh and so on... */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, pci_write_config_dword(dev, PCI_INIT_ENABLE,
PCI_EN_INIT_WR); PCI_EN_INIT_WR);
sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH); sst_unset_bits(FBIINIT0, FBI_RESET | FIFO_RESET | EN_VGA_PASSTHROUGH);
pci_write_config_dword(sst_dev, PCI_VCLK_DISABLE,0); pci_write_config_dword(dev, PCI_VCLK_DISABLE,0);
/* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct at the beginining ? */ /* maybe keep fbiinit* and PCI_INIT_enable in the fb_info struct at the beginining ? */
pci_write_config_dword(sst_dev, PCI_INIT_ENABLE, 0); pci_write_config_dword(dev, PCI_INIT_ENABLE, 0);
} }
...@@ -1769,35 +1470,31 @@ int __init sstfb_setup(char *options) ...@@ -1769,35 +1470,31 @@ int __init sstfb_setup(char *options)
else if (!strncmp(this_opt, "dev:",4)) else if (!strncmp(this_opt, "dev:",4))
dev=simple_strtoul (this_opt+4, NULL, 0); dev=simple_strtoul (this_opt+4, NULL, 0);
else else
mode_option=this_opt; mode_option = this_opt;
} }
return 0; return 0;
} }
int __devinit sstfb_init(void) static struct fb_ops sstfb_ops = {
{ .owner = THIS_MODULE,
f_dprintk("sstfb_init\n"); .fb_check_var = sstfb_check_var,
dprintk("Compile date: "__DATE__" "__TIME__"\n"); .fb_set_par = sstfb_set_par,
return pci_module_init(&sstfb_driver); .fb_setcolreg = sstfb_setcolreg,
} .fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
void __devexit sstfb_exit(void) .fb_imageblit = cfb_imageblit,
{ .fb_cursor = soft_cursor,
f_dprintk("sstfb_exit\n"); .fb_ioctl = sstfb_ioctl,
pci_unregister_driver(&sstfb_driver); };
}
#ifdef MODULE
module_init(sstfb_init);
module_exit(sstfb_exit);
#endif
static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{ {
struct sstfb_par *default_par;
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo var; struct fb_var_screeninfo var;
struct sstfb_info * sst_info; struct sst_spec *spec;
struct sst_spec * spec; struct fb_info *info;
int tmp,err; int err;
f_dprintk("sstfb_probe\n"); f_dprintk("sstfb_probe\n");
/* dev > 0 the device is not the one asked for. skip */ /* dev > 0 the device is not the one asked for. skip */
...@@ -1805,268 +1502,275 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i ...@@ -1805,268 +1502,275 @@ static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_i
/* dev == -1 we already inited the asked device. skip */ /* dev == -1 we already inited the asked device. skip */
/* dev < -1 init all devices. including this one. init */ /* dev < -1 init all devices. including this one. init */
if ((dev == -1 ) || (dev-- > 0)) if ((dev == -1 ) || (dev-- > 0))
return -1; return -ENODEV;
if ((err=pci_enable_device(pdev))) { if ((err=pci_enable_device(pdev))) {
eprintk("cannot enable device\n"); eprintk("cannot enable device\n");
return err; return err;
} }
sst_info = (struct sstfb_info*)kmalloc(sizeof(*sst_info), GFP_KERNEL); info = kmalloc(sizeof(struct fb_info) + sizeof(struct sstfb_par), GFP_KERNEL);
if (!sst_info) if (!info)
goto fail_kmalloc; return -ENOMEM;
pci_set_drvdata(pdev, sst_info); default_par = (struct sstfb_par *) (info + 1);
sst_info->type = id->driver_data; fix = &info->fix;
spec = &voodoo_spec[sst_info->type];
pci_set_drvdata(pdev, info);
default_par->type = id->driver_data;
spec = &voodoo_spec[default_par->type];
f_ddprintk("found device : %s\n", spec->name); f_ddprintk("found device : %s\n", spec->name);
sst_info->dev = pdev; default_par->dev = pdev;
pci_read_config_byte(pdev, PCI_REVISION_ID, &sst_info->revision); pci_read_config_byte(pdev, PCI_REVISION_ID, &default_par->revision);
sst_info->mmio.base = pci_resource_start(pdev,0); fix->mmio_start = pci_resource_start(pdev,0);
sst_info->video.base = sst_info->mmio.base+0x400000; fix->smem_start = fix->mmio_start + 0x400000;
if (!request_mem_region(sst_info->mmio.base,0x400000,"sstfb MMIO")) { if (!request_mem_region(fix->mmio_start, 0x400000,"sstfb MMIO")) {
eprintk ("cannot reserve mmio memory\n"); eprintk("cannot reserve mmio memory\n");
goto fail_mmio_mem; goto fail_mmio_mem;
} }
if (!request_mem_region(sst_info->video.base,0x400000,"sstfb FB")) { if (!request_mem_region(fix->smem_start, 0x400000,"sstfb FB")) {
eprintk ("cannot reserve fb memory\n"); eprintk("cannot reserve fb memory\n");
goto fail_fb_mem; goto fail_fb_mem;
} }
sst_info->mmio.vbase = (u_long) ioremap_nocache(sst_info->mmio.base, 0x400000); default_par->mmio_vbase = (u_long) ioremap_nocache(fix->mmio_start, 0x400000);
if (!sst_info->mmio.vbase) { if (!default_par->mmio_vbase) {
eprintk("cannot remap register area %#lx\n", eprintk("cannot remap register area %#lx\n",
sst_info->mmio.base); fix->mmio_start);
goto fail_mmio_remap; goto fail_mmio_remap;
} }
sst_info->video.vbase = (u_long) ioremap_nocache(sst_info->video.base, 0x400000); info->screen_base = ioremap_nocache(fix->smem_start, 0x400000);
if (!sst_info->video.vbase) { if (!info->screen_base) {
eprintk("cannot remap framebuffer %#lx\n", eprintk("cannot remap framebuffer %#lx\n",
sst_info->video.base); fix->smem_start);
goto fail_fb_remap; goto fail_fb_remap;
} }
if(!sst_init(sst_info)) { if(!sst_init(info, default_par)) {
eprintk("Init failed\n"); eprintk("Init failed\n");
goto fail; goto fail;
} }
sst_get_memsize(sst_info, &sst_info->video.len); sst_get_memsize(info, (unsigned long *) &fix->smem_len);
strncpy(sst_info->info.modename, spec->name, 16); strncpy(fix->id, spec->name, sizeof(fix->id));
iprintk("%s with %s dac\n", sst_info->info.modename, sst_info->dac_sw.name); iprintk("%s with %s dac\n", fix->id, default_par->dac_sw.name);
iprintk("framebuffer at %#lx, mapped to %#lx," iprintk("framebuffer at %#lx, mapped to %#lx,"
" size %ldMb\n", " size %dMb\n",
sst_info->video.base, sst_info->video.vbase, fix->smem_start, (unsigned long) info->screen_base,
sst_info->video.len >> 20); fix->smem_len >> 20);
f_ddprintk("revision: %d\n", sst_info->revision); f_ddprintk("revision: %d\n", default_par->revision);
f_ddprintk("regbase_virt: %#lx\n", sst_info->mmio.vbase); f_ddprintk("regbase_virt: %#lx\n", default_par->mmio_vbase);
f_ddprintk("membase_phys: %#lx\n", sst_info->video.base); f_ddprintk("membase_phys: %#lx\n", fix->smem_start);
f_ddprintk("fbbase_virt: %#lx\n", sst_info->video.vbase); f_ddprintk("fbbase_virt: %#lx\n", info->screen_base);
sst_info->info.node = -1 ; info->node = NODEV;
sst_info->info.flags = FBINFO_FLAG_DEFAULT; info->flags = FBINFO_FLAG_DEFAULT;
sst_info->info.fbops = &sstfb_ops; info->fbops = &sstfb_ops;
sst_info->info.disp = &sst_info->disp; info->par = default_par;
sst_info->info.changevar = NULL;
sst_info->info.switch_con = &sstfbcon_switch; fix->mmio_len = 0x400000;
sst_info->info.updatevar = &sstfbcon_updatevar; fix->type = FB_TYPE_PACKED_PIXELS;
sst_info->info.blank = &sstfbcon_blank; fix->visual = FB_VISUAL_TRUECOLOR;
fix->accel = FB_ACCEL_NONE; /* FIXME */
tmp=0; /*
var = sstfb_default; * According to the specs, the linelength must be of 1024 *pixels*.
if ( mode_option && * and the 24bpp mode is in fact a 32 bpp mode.
fb_find_mode(&var, &sst_info->info, mode_option, */
NULL, 0, NULL, 16)) { fix->line_length= 2048; /* default value, for 24 or 32bit: 4096*/
if (sstfb_set_var(&var, -1, &sst_info->info)) {
if ( mode_option &&
fb_find_mode(&var, info, mode_option, NULL, 0, NULL, 16)) {
if (sstfb_check_var(&var, info)) {
eprintk("can't set supplied video mode. Using default\n"); eprintk("can't set supplied video mode. Using default\n");
var = sstfb_default; var = sstfb_default;
} else {
/* set the new default */
sstfb_default = var;
tmp=1; /* no need to set the mode. */
} }
} }
if (!tmp && sstfb_set_var(&var, -1, &sst_info->info)) { if (sstfb_check_var(&var, info)) {
eprintk("can't set default video mode.\n"); eprintk("can't set default video mode.\n");
goto fail; goto fail;
} }
/*clear fb */
memset_io(sst_info->video.vbase, 0, sst_info->video.len); fb_alloc_cmap(&info->cmap, 16, 0);
/* print some squares ... */
sstfb_test16(sst_info); /* FIXME this is only for 16bpp */ /* set the video mode */
sstfb_set_par(info);
/* sstfb_test16(info); */
/* register fb */ /* register fb */
if (register_framebuffer(&sst_info->info) < 0) { if (register_framebuffer(info) < 0) {
eprintk("can't register framebuffer.\n"); eprintk("can't register framebuffer.\n");
goto fail; goto fail;
} }
printk(KERN_INFO "fb%d: %s frame buffer device\n", printk(KERN_INFO "fb%d: %s frame buffer device\n",
minor(sst_info->info.node),sst_info->info.modename); minor(info->node), fix->id);
return 0; return 0;
fail: fail:
iounmap((void *)sst_info->video.base); iounmap(info->screen_base);
fail_fb_remap: fail_fb_remap:
iounmap((void *)sst_info->mmio.base); iounmap((void *)default_par->mmio_vbase);
fail_mmio_remap: fail_mmio_remap:
release_mem_region(sst_info->video.base,0x400000); release_mem_region(fix->smem_start, 0x400000);
fail_fb_mem: fail_fb_mem:
release_mem_region(sst_info->mmio.base,0x400000); release_mem_region(fix->mmio_start, 0x400000);
fail_mmio_mem: fail_mmio_mem:
kfree(sst_info); kfree(info);
fail_kmalloc:
return -ENXIO; /* no voodoo detected */ return -ENXIO; /* no voodoo detected */
} }
static void __devexit sstfb_remove(struct pci_dev *pdev) static void __devexit sstfb_remove(struct pci_dev *pdev)
{ {
struct sstfb_info * sst_info; struct sstfb_par *par;
struct fb_info *info;
f_dprintk("sstfb_remove\n"); f_dprintk("sstfb_remove\n");
sst_info=pci_get_drvdata(pdev); info = pci_get_drvdata(pdev);
sst_shutdown(sst_info); par = (struct sstfb_par *) info->par;
unregister_framebuffer(&sst_info->info); sst_shutdown(info);
iounmap((void*)sst_info->video.vbase); unregister_framebuffer(info);
iounmap((void*)sst_info->mmio.vbase); iounmap(info->screen_base);
release_mem_region(sst_info->video.base,0x400000); iounmap((void*)par->mmio_vbase);
release_mem_region(sst_info->mmio.base,0x400000); release_mem_region(info->fix.smem_start, info->fix.smem_len);
kfree(sst_info); release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
kfree(info);
} }
/* static struct pci_device_id sstfb_id_tbl[] __devinitdata = {
* console driver { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO,
*/ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 },
static int sstfbcon_switch(int con, struct fb_info *info) { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2,
{ PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 },
#define sst_info ((struct sstfb_info *) info) { 0 },
struct sstfb_par par; };
f_dprintk("sstfbcon_switch(con: %d)\n",con);
f_ddprintk("currcon: %d\n", sst_info->currcon);
v_dprintk("currcon: %d\n", sst_info->currcon);
if (sst_info->currcon >= 0) { static struct pci_driver sstfb_driver = {
if (fb_display[sst_info->currcon].cmap.len) .name = "sstfb",
fb_get_cmap(&fb_display[sst_info->currcon].cmap, 1, .id_table = sstfb_id_tbl,
sstfb_getcolreg, info); .probe = sstfb_probe,
} .remove = __devexit_p(sstfb_remove),
sst_info->currcon = con; };
fb_display[con].var.activate = FB_ACTIVATE_NOW;
print_var(&fb_display[con].var, "&fb_display[con: %d].var",con);
sstfb_decode_var(&fb_display[con].var, &par, sst_info);
if (memcmp(&par,&(sst_info->current_par),sizeof(par))) {
sstfb_set_par(&par, sst_info);
}
sstfb_install_cmap(con, info);
return 0;
#undef sst_info
}
static int sstfbcon_updatevar(int con, struct fb_info *info) int __devinit sstfb_init(void)
{ {
f_dprintk("sstfbcon_updatevar\n"); f_dprintk("sstfb_init\n");
return -EINVAL; dprintk("Compile date: "__DATE__" "__TIME__"\n");
return pci_module_init(&sstfb_driver);
} }
static void sstfbcon_blank(int blank, struct fb_info *info) void __devexit sstfb_exit(void)
{ {
f_dprintk("sstfbcon_blank(level %d)\n", blank); f_dprintk("sstfb_exit\n");
pci_unregister_driver(&sstfb_driver);
} }
/*
* console driver
*/
#if 1
/* print some squares on the fb (presuming 16bpp) */ /* print some squares on the fb (presuming 16bpp) */
static void sstfb_test16(struct sstfb_info *sst_info) static void sstfb_test16(struct fb_info *info)
{ {
int i,j; u_long fbbase_virt = (u_long) info->screen_base;
u_long p; u_long p;
u_long fbbase_virt = sst_info->video.vbase; int i,j;
f_dprintk("sstfb_test16\n"); f_dprintk("sstfb_test16\n");
/* rect blanc 20x100+200+0 */ /* draw white rect 20x100+200+0 */
for (i=0 ; i< 100; i++) { for (i=0 ; i<100; i++) {
p = fbbase_virt + 2048 *i+400; p = fbbase_virt + 2048*i+400;
for (j=0 ; j < 10 ; j++) { for (j=0 ; j<10 ; j++) {
writel( 0xffffffff, p); writel(0xffffffff, p);
p+=4; p += 4;
} }
} }
/* rect bleu 180x200+0+0 */ /* draw blue rect 180x200+0+0 */
for (i=0 ; i< 200; i++) { for (i=0 ; i<200; i++) {
p = fbbase_virt + 2048 *i; p = fbbase_virt + 2048*i;
for (j=0 ; j < 90 ; j++) { for (j=0 ; j<90 ; j++) {
writel(0x001f001f,p); writel(0x001f001f, p);
p+=4; p += 4;
} }
} }
/* carre vert 40x40+100+0 */ /* draw green rect 40x40+100+0 */
for (i=0 ; i< 40 ; i++) { for (i=0 ; i<40 ; i++) {
p = fbbase_virt + 2048 *i + 200; p = fbbase_virt + 2048*i + 200;
for (j=0; j <20;j++) { for (j=0; j <20;j++) {
writel(0x07e007e0, p); writel(0x07e007e0, p);
p+=4; p += 4;
} }
} }
/*carre rouge 40x40+100+40 */ /* draw red rect 40x40+100+40 */
for (i=0; i<40; i++) { for (i=0; i<40; i++) {
p = fbbase_virt + 2048 * (i+40) + 200; p = fbbase_virt + 2048 * (i+40) + 200;
for (j=0; j <20;j++) { for (j=0; j<20;j++) {
writel( 0xf800f800, p); writel(0xf800f800, p);
p+=4; p += 4;
} }
} }
} }
#endif
/* print some squares on the fb (24/32bpp) */
#ifdef EN_24_32_BPP #ifdef EN_24_32_BPP
static void sstfb_test32(struct sstfb_info *sst_info) /* print some squares on the fb (24/32bpp) */
static void sstfb_test32(struct fb_info *info)
{ {
int i,j; int i,j;
u_long p; u_long p;
u_long fbbase_virt = sst_info->video.vbase; u_long fbbase_virt = info->screen_base;
f_dprintk("sstfb_test32\n"); f_dprintk("sstfb_test32\n");
/* rect blanc 20x100+200+0 */ /* draw white rect 20x100+200+0 */
for (i=0 ; i< 100; i++) { for (i=0 ; i<100; i++) {
p = fbbase_virt + 4096*i + 800; p = fbbase_virt + 4096*i + 800;
for (j=0 ; j < 20 ; j++) { for (j=0 ; j<20; j++) {
writel( 0x00ffffff, p); writel(0x00ffffff, p);
p+=4; p += 4;
} }
} }
/* rect bleu 180x200+0+0 */ /* draw blue rect 180x200+0+0 */
for (i=0 ; i< 200; i++) { for (i=0 ; i<200; i++) {
p = fbbase_virt + 4096 * i; p = fbbase_virt + 4096*i;
for (j=0 ; j < 180 ; j++) { for (j=0 ; j<180; j++) {
writel(0x000000ff,p); writel(0x000000ff,p);
p+=4; p += 4;
} }
} }
/* carre vert 40x40+100+0 */ /* draw green rect 40x40+100+0 */
for (i=0 ; i< 40 ; i++) { for (i=0 ; i<40 ; i++) {
p = fbbase_virt + 4096 *i + 400; p = fbbase_virt + 4096*i + 400;
for (j=0; j <40;j++) { for (j=0; j<40; j++) {
writel(0x0000ff00, p); writel(0x0000ff00, p);
p+=4; p += 4;
} }
} }
/*carre rouge 40x40+100+10 */ /* draw red rect 40x40+100+10 */
for (i=0; i<40; i++) { for (i=0; i<40; i++) {
p = fbbase_virt + 4096 * (i+40) + 400; p = fbbase_virt + 4096 * (i+40) + 400;
for (j=0; j <40;j++) { for (j=0; j<40; j++) {
writel( 0x00ff0000, p); writel(0x00ff0000, p);
p+=4; p += 4;
} }
} }
} }
#endif /* EN_24_32_BPP */ #endif
#ifdef MODULE
module_init(sstfb_init);
module_exit(sstfb_exit);
#endif
MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>"); MODULE_AUTHOR("(c) 2000,2002 Ghozlane Toumi <gtoumi@laposte.net>");
MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards"); MODULE_DESCRIPTION("FBDev driver for 3dfx Voodoo Graphics and Voodoo2 based video boards");
...@@ -2087,57 +1791,3 @@ MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)"); ...@@ -2087,57 +1791,3 @@ MODULE_PARM_DESC(slowpci, "Uses slow PCI settings (0 or 1) (default=0)");
MODULE_PARM(dev,"i"); MODULE_PARM(dev,"i");
MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)"); MODULE_PARM_DESC(dev , "Attach to device ID (0..n) (default=1st device)");
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* ---------------------------------------------------------------------------
* Local variables:
* c-basic-offset: 8
* End:
*/
#if 1
void __Dump_regs (struct sstfb_info * sst_info)
{
struct { u32 reg ; char * reg_name;} pci_regs [] = {
{ PCI_INIT_ENABLE, "initenable"},
{ PCI_VCLK_ENABLE, "enable vclk"},
{ PCI_VCLK_DISABLE, "disable vclk"},
};
struct { u32 reg ; char * reg_name;} sst_regs [] = {
{FBIINIT0,"fbiinit0"},
{FBIINIT1,"fbiinit1"},
{FBIINIT2,"fbiinit2"},
{FBIINIT3,"fbiinit3"},
{FBIINIT4,"fbiinit4"},
{FBIINIT5,"fbiinit5"},
{FBIINIT6,"fbiinit6"},
{FBIINIT7,"fbiinit7"},
{LFBMODE,"lfbmode"},
{FBZMODE,"fbzmode"},
};
int pci_s = sizeof(pci_regs)/sizeof(*pci_regs);
int sst_s = sizeof(sst_regs)/sizeof(*sst_regs);
u32 pci_res[pci_s];
u32 sst_res[sst_s];
struct pci_dev * dev = sst_info->dev;
int i;
for (i=0; i < pci_s ; i++ ) {
pci_read_config_dword ( dev, pci_regs[i].reg , &pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
sst_res[i]=sst_read(sst_regs[i].reg);
}
dprintk ("Dump regs\n");
for (i=0; i < pci_s ; i++ ) {
dprintk("%s = %0#10x\n", pci_regs[i].reg_name , pci_res[i]) ;
}
for (i=0; i < sst_s ; i++ ) {
dprintk("%s = %0#10x\n", sst_regs[i].reg_name , sst_res[i]) ;
}
}
#endif
...@@ -4,8 +4,6 @@ ...@@ -4,8 +4,6 @@
* Copyright (c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr> * Copyright (c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr>
* *
* Created 28 Aug 2001 by Ghozlane Toumi * Created 28 Aug 2001 by Ghozlane Toumi
*
* $Id: sstfb.h,v 1.8 2002/05/10 19:35:11 ghoz Exp $
*/ */
...@@ -25,7 +23,6 @@ ...@@ -25,7 +23,6 @@
# undef SST_DEBUG_REG # undef SST_DEBUG_REG
# undef SST_DEBUG_FUNC # undef SST_DEBUG_FUNC
# undef SST_DEBUG_VAR # undef SST_DEBUG_VAR
# undef SST_DEBUG_IOCTL
#endif #endif
#if (SST_DEBUG_REG > 0) #if (SST_DEBUG_REG > 0)
...@@ -73,8 +70,6 @@ ...@@ -73,8 +70,6 @@
#define wprintk(X...) printk(KERN_WARNING "sstfb: " X) #define wprintk(X...) printk(KERN_WARNING "sstfb: " X)
#define BIT(x) (1ul<<(x)) #define BIT(x) (1ul<<(x))
#define PS2KHZ(a) (1000000000UL/(a)) /* picoseconds to KHz */
#define KHZ2PS(a) (1000000000UL/(a))
#define POW2(x) (1ul<<(x)) #define POW2(x) (1ul<<(x))
#ifndef ABS #ifndef ABS
...@@ -114,7 +109,11 @@ ...@@ -114,7 +109,11 @@
# define RD_BUFF_FRONT 0 /* read buff select (front) */ # define RD_BUFF_FRONT 0 /* read buff select (front) */
# define RD_BUFF_BACK (1 << 6) /* back */ # define RD_BUFF_BACK (1 << 6) /* back */
# define EN_PXL_PIPELINE BIT(8) /* pixel pipeline (clip..)*/ # define EN_PXL_PIPELINE BIT(8) /* pixel pipeline (clip..)*/
# define LFB_WORD_SWIZZLE_WR BIT(11) /* enable write-wordswap (big-endian) */
# define LFB_BYTE_SWIZZLE_WR BIT(12) /* enable write-byteswap (big-endian) */
# define LFB_INVERT_Y BIT(13) /* invert Y origin (LFB) */ # define LFB_INVERT_Y BIT(13) /* invert Y origin (LFB) */
# define LFB_WORD_SWIZZLE_RD BIT(15) /* enable read-wordswap (big-endian) */
# define LFB_BYTE_SWIZZLE_RD BIT(16) /* enable read-byteswap (big-endian) */
#define CLIP_LEFT_RIGHT 0x0118 #define CLIP_LEFT_RIGHT 0x0118
#define CLIP_LOWY_HIGHY 0x011c #define CLIP_LOWY_HIGHY 0x011c
#define NOPCMD 0x0120 #define NOPCMD 0x0120
...@@ -305,9 +304,9 @@ struct sstfb_info; ...@@ -305,9 +304,9 @@ struct sstfb_info;
struct dac_switch { struct dac_switch {
char * name; char * name;
int (*detect) (struct sstfb_info *sst_info); int (*detect) (struct fb_info *info);
int (*set_pll) (struct sstfb_info *sst_info, const struct pll_timing *t, const int clock); int (*set_pll) (struct fb_info *info, const struct pll_timing *t, const int clock);
void (*set_vidmod) (struct sstfb_info *sst_info, const int bpp); void (*set_vidmod) (struct fb_info *info, const int bpp);
}; };
struct sst_spec { struct sst_spec {
...@@ -332,51 +331,12 @@ struct sstfb_par { ...@@ -332,51 +331,12 @@ struct sstfb_par {
unsigned int vmode; /* doublescan/interlaced */ unsigned int vmode; /* doublescan/interlaced */
unsigned int sync; /* H/V sync polarity */ unsigned int sync; /* H/V sync polarity */
unsigned int valid; /* par is correct (fool proof) */ unsigned int valid; /* par is correct (fool proof) */
}; unsigned long mmio_vbase;
struct sstfb_info {
struct fb_info info;
struct sstfb_par current_par;
struct pci_dev * dev;
struct {
unsigned long base; /* physical */
unsigned long vbase; /* virtual (CPU view) */
unsigned long len;
} video; /* fb memory info */
struct {
unsigned long base;
unsigned long vbase;
} mmio; /* registers memory info */
struct dac_switch dac_sw; /* dac specific functions */ struct dac_switch dac_sw; /* dac specific functions */
struct pci_dev *dev;
int type; int type;
u8 revision; u8 revision;
int gfx_clock; /* status */
/* status */
/*XXX int configured;
int indexed_mode;
int vgapass;
int clipping; */
int gfx_clock;
int currcon;
struct display disp; /* current display */
struct { u_int red, green, blue, transp; } palette[16];
union {
#ifdef FBCON_HAS_CFB16
u16 cfb16[16];
#endif
#ifdef EN_24_32_BPP
#if defined (FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
u32 cfb32[16];
#endif
#endif
} fbcon_cmap;
}; };
#endif /* _SSTFB_H_ */ #endif /* _SSTFB_H_ */
...@@ -1212,9 +1212,6 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev, ...@@ -1212,9 +1212,6 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10); printk("fb: %s memory = %dK\n", tdfx_fix.id, tdfx_fix.smem_len >> 10);
/* clear framebuffer memory */
memset_io(info->screen_base, 0, tdfx_fix.smem_len);
tdfx_fix.ypanstep = nopan ? 0 : 1; tdfx_fix.ypanstep = nopan ? 0 : 1;
tdfx_fix.ywrapstep = nowrap ? 0 : 1; tdfx_fix.ywrapstep = nowrap ? 0 : 1;
......
...@@ -457,9 +457,9 @@ extern void cfb_imageblit(struct fb_info *info, struct fb_image *image); ...@@ -457,9 +457,9 @@ extern void cfb_imageblit(struct fb_info *info, struct fb_image *image);
/* drivers/video/fbmem.c */ /* drivers/video/fbmem.c */
extern int register_framebuffer(struct fb_info *fb_info); extern int register_framebuffer(struct fb_info *fb_info);
extern int unregister_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info);
extern int fb_show_logo(struct fb_info *fb_info);
extern int num_registered_fb;
extern struct fb_info *registered_fb[FB_MAX]; extern struct fb_info *registered_fb[FB_MAX];
extern int num_registered_fb;
/* drivers/video/fbmon.c */ /* drivers/video/fbmon.c */
extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal, extern int fbmon_valid_timings(u_int pixclock, u_int htotal, u_int vtotal,
......
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