Commit 8d7c2813 authored by James Simmons's avatar James Simmons

Updates for the STI fbdev and console driver.

parent 0e2e212c
......@@ -295,27 +295,21 @@ config FB_VGA16
vga16fb.o.
config FB_STI
bool "Generic STI frame buffer device support"
bool "HP STI frame buffer device support"
depends on FB && PARISC
default y
---help---
STI refers to the HP "Standard Text Interface" which is a set of
BIOS routines contained in a ROM chip in HP PA-RISC based machines.
Enabling this option will implement the linux framebuffer device and
an fbcon color text console using calls to the STI BIOS routines.
The HP framebuffer device is usually planar, uses a strange memory
layout, and changing the plane mask to create colored pixels
requires a call to the STI routines, so do not expect /dev/fb to
actually be useful. However, it is the best we have as far as
graphics on the HP chipsets due to lack of hardware level
documentation for the various on-board HP chipsets used in these
systems. It is sufficient for basic text console functions,
including fonts.
You should probably enable this option, unless you are having
trouble getting video when booting the kernel (make sure it isn't
just that you are running the console on the serial port, though).
Really old HP boxes may not have STI, and must use the PDC BIOS
console or the IODC BIOS.
Enabling this option will implement the linux framebuffer device
using calls to the STI BIOS routines for initialisation.
If you enable this option, you will get a planar framebuffer device
/dev/fb which will work on the most common HP graphic cards of the
NGLE family, including the artist chips (in the 7xx and Bxxx series),
HCRX, HCRX24, CRX, CRX24 and VisEG series.
It is safe to enable this option, so you should probably say "Y".
config FB_MAC
bool "Generic Macintosh display support"
......
......@@ -62,7 +62,7 @@ obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o
obj-$(CONFIG_FB_CGFOURTEEN) += cgfourteenfb.o sbusfb.o
obj-$(CONFIG_FB_P9100) += p9100fb.o sbusfb.o
obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
obj-$(CONFIG_FB_STI) += stifb.o console/sticore.o
obj-$(CONFIG_FB_STI) += stifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
......
......@@ -66,8 +66,9 @@ config SGI_NEWPORT_CONSOLE
# bool 'IODC console' CONFIG_IODC_CONSOLE
config STI_CONSOLE
bool "STI console"
bool "STI text console"
depends on PARISC
default y
help
The STI console is the builtin display/keyboard on HP-PARISC
machines. Say Y here to build support for it into your kernel.
......
......@@ -45,9 +45,7 @@ obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o font.o
# Generic Low Level Drivers
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FB_STI) += sticore.o
# Files generated that shall be removed upon make clean
clean-files := promcon_tbl.c
......
/*
* linux/drivers/video/fbcon-sti.c -- Low level frame buffer
* operations for generic HP video boards using STI (standard
* text interface) firmware
*
* Based on linux/drivers/video/fbcon-artist.c
* Created 5 Apr 1997 by Geert Uytterhoeven
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive for
* more details. */
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/delay.h>
#include <asm/gsc.h> /* for gsc_read/write */
#include <asm/types.h>
#include <video/fbcon.h>
#include <video/fbcon-mfb.h>
#include "../sticore.h"
static inline u32
ram2log(void * addr)
{
return (unsigned long) addr;
}
/* All those functions need better names. */
static void
memcpy_fromhp_tohp(void *dest, void *src, int count)
{
unsigned long d = ram2log(dest);
unsigned long s = ram2log(src);
count += 3;
count &= ~3; /* XXX */
while(count) {
count --;
gsc_writel(~gsc_readl(s), d);
d += 32*4;
s += 32*4;
}
}
static void
memset_tohp(void *dest, u32 word, int count)
{
unsigned long d = ram2log(dest);
count += 3;
count &= ~3;
while(count) {
count--;
gsc_writel(word, d);
d += 32;
}
}
static u8
readb_hp(void *src)
{
unsigned long s = ram2log(src);
return ~gsc_readb(s);
}
static void
writeb_hp(u8 b, void *dst)
{
unsigned long d = ram2log(dst);
if((d&0xf0000000) != 0xf0000000) {
printk("writeb_hp %02x %p (%08lx) (%p)\n",
b, dst, d, __builtin_return_address(0));
return;
}
gsc_writeb(b, d);
}
static void
fbcon_sti_setup(struct display *p)
{
/* in kernel 2.5 the value of sadly line_length disapeared */
if (p->var.xres_virtual /*line_length*/)
p->next_line = p->var.xres_virtual>>3;
else
p->next_line = 2048; /* default STI value */
p->next_plane = 0;
}
static void
fbcon_sti_bmove(struct display *p, int sy, int sx,
int dy, int dx,
int height, int width)
{
#if 0 /* Unfortunately, still broken */
sti_bmove(default_sti /* FIXME */, sy, sx, dy, dx, height, width);
#else
u8 *src, *dest;
u_int rows;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info->screen_base+sy*fontheight(p)*width;
dest = p->fb_info->screen_base+dy*fontheight(p)*width;
memcpy_fromhp_tohp(dest, src, height*fontheight(p)*width);
} else if (dy <= sy) {
src = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
dest = p->fb_info->screen_base+dy*fontheight(p)*p->next_line+dx;
for (rows = height*fontheight(p); rows--;) {
memcpy_fromhp_tohp(dest, src, width);
src += p->next_line;
dest += p->next_line;
}
} else {
src = p->fb_info->screen_base+((sy+height)*fontheight(p)-1)*p->next_line+sx;
dest = p->fb_info->screen_base+((dy+height)*fontheight(p)-1)*p->next_line+dx;
for (rows = height*fontheight(p); rows--;) {
memcpy_fromhp_tohp(dest, src, width);
src -= p->next_line;
dest -= p->next_line;
}
}
#endif
}
static void
fbcon_sti_clear(struct vc_data *conp,
struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest;
u_int rows;
int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
dest = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
if (sx == 0 && width == p->next_line) {
if (inverse)
memset_tohp(dest, ~0, height*fontheight(p)*width);
else
memset_tohp(dest, 0, height*fontheight(p)*width);
} else
for (rows = height*fontheight(p); rows--; dest += p->next_line)
if (inverse)
memset_tohp(dest, 0xffffffff, width);
else
memset_tohp(dest, 0x00000000, width);
}
static void fbcon_sti_putc(struct vc_data *conp,
struct display *p, int c,
int yy, int xx)
{
u8 *dest, *cdat;
u_int rows, bold, revs, underl;
u8 d;
dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
cdat = p->fontdata+(c&p->charmask)*fontheight(p);
bold = attr_bold(p,c);
revs = attr_reverse(p,c);
underl = attr_underline(p,c);
for (rows = fontheight(p); rows--; dest += p->next_line) {
d = *cdat++;
if (underl && !rows)
d = 0xff;
else if (bold)
d |= d>>1;
if (revs)
d = ~d;
writeb_hp (d, dest);
}
}
static void fbcon_sti_putcs(struct vc_data *conp,
struct display *p,
const unsigned short *s,
int count, int yy, int xx)
{
u8 *dest, *dest0, *cdat;
u_int rows, bold, revs, underl;
u8 d;
u16 c;
if(((unsigned)xx > 200) || ((unsigned) yy > 200)) {
printk("refusing to putcs %p %p %p %d %d %d (%p)\n",
conp, p, s, count, yy, xx, __builtin_return_address(0));
return;
}
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
if(((u32)dest0&0xf0000000)!=0xf0000000) {
printk("refusing to putcs %p %p %p %d %d %d (%p) %p = %p + %d * %d * %ld + %d\n",
conp, p, s, count, yy, xx, __builtin_return_address(0),
dest0, p->fb_info->screen_base, yy, fontheight(p), p->next_line,
xx);
return;
}
c = scr_readw(s);
bold = attr_bold(p, c);
revs = attr_reverse(p, c);
underl = attr_underline(p, c);
while (count--) {
c = scr_readw(s++) & p->charmask;
dest = dest0++;
cdat = p->fontdata+c*fontheight(p);
for (rows = fontheight(p); rows--; dest += p->next_line) {
d = *cdat++;
if (0 && underl && !rows)
d = 0xff;
else if (0 && bold)
d |= d>>1;
if (revs)
d = ~d;
writeb_hp (d, dest);
}
}
}
static void fbcon_sti_revc(struct display *p,
int xx, int yy)
{
u8 *dest, d;
u_int rows;
dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
for (rows = fontheight(p); rows--; dest += p->next_line) {
d = readb_hp(dest);
writeb_hp (~d, dest);
}
}
static void
fbcon_sti_clear_margins(struct vc_data *conp,
struct display *p,
int bottom_only)
{
u8 *dest;
int height, bottom;
int inverse = conp ? attr_reverse(p,conp->vc_video_erase_char) : 0;
/* XXX Need to handle right margin? */
height = p->var.yres - conp->vc_rows * fontheight(p);
if (!height)
return;
bottom = conp->vc_rows + p->yscroll;
if (bottom >= p->vrows)
bottom -= p->vrows;
dest = p->fb_info->screen_base + bottom * fontheight(p) * p->next_line;
if (inverse)
memset_tohp(dest, 0xffffffff, height * p->next_line);
else
memset_tohp(dest, 0x00000000, height * p->next_line);
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_sti = {
.setup = fbcon_sti_setup,
.bmove = fbcon_sti_bmove,
.clear = fbcon_sti_clear,
.putc = fbcon_sti_putc,
.putcs = fbcon_sti_putcs,
.revc = fbcon_sti_revc,
.clear_margins =fbcon_sti_clear_margins,
.fontwidthmask =FONTWIDTH(8)
};
MODULE_LICENSE("GPL");
#define STI_REGION_MAX 8
#define STI_DEV_NAME_LENGTH 32
struct sti_rom_font {
u16 first_char;
u16 last_char;
u8 width;
u8 height;
u8 font_type;
u8 bytes_per_char;
u32 next_font;
u8 underline_height;
u8 underline_pos;
u8 res008[2];
};
struct sti_rom {
u8 type[4];
u8 res004;
u8 num_mons;
u8 revno[2];
u8 graphics_id[8];
u32 font_start;
u32 statesize;
u32 last_addr;
u32 region_list;
u16 reentsize;
u16 maxtime;
u32 mon_tbl_addr;
u32 user_data_addr;
u32 sti_mem_req;
u32 user_data_size;
u16 power;
u8 bus_support;
u8 ext_bus_support;
u8 alt_code_type;
u8 ext_dd_struct[3];
u32 cfb_addr;
u32 init_graph;
u32 state_mgmt;
u32 font_unpmv;
u32 block_move;
u32 self_test;
u32 excep_hdlr;
u32 inq_conf;
u32 set_cm_entry;
u32 dma_ctrl;
u8 res040[7 * 4];
u32 init_graph_m68k;
u32 flow_ctrl;
u32 user_timing;
u32 process_mgr;
u32 sti_util;
u32 end_addr;
u32 res0b8;
u32 res0bc;
};
struct sti_cooked_font {
struct sti_rom_font *raw;
struct sti_cooked_font *next_font;
};
struct sti_cooked_rom {
struct sti_rom *raw;
struct sti_cooked_font *font_start;
u32 *region_list;
};
struct sti_glob_cfg_ext {
u8 curr_mon;
u8 friendly_boot;
s16 power;
s32 freq_ref;
s32 *sti_mem_addr;
s32 *future_ptr;
};
struct sti_glob_cfg {
s32 text_planes;
s16 onscreen_x;
s16 onscreen_y;
s16 offscreen_x;
s16 offscreen_y;
s16 total_x;
s16 total_y;
u32 region_ptrs[STI_REGION_MAX];
s32 reent_lvl;
s32 *save_addr;
struct sti_glob_cfg_ext *ext_ptr;
};
struct sti_init_flags {
u32 wait : 1;
u32 reset : 1;
u32 text : 1;
u32 nontext : 1;
u32 clear : 1;
u32 cmap_blk : 1;
u32 enable_be_timer : 1;
u32 enable_be_int : 1;
u32 no_chg_tx : 1;
u32 no_chg_ntx : 1;
u32 no_chg_bet : 1;
u32 no_chg_bei : 1;
u32 init_cmap_tx : 1;
u32 cmt_chg : 1;
u32 retain_ie : 1;
u32 pad : 17;
s32 *future_ptr;
};
struct sti_init_inptr_ext {
u8 config_mon_type;
u8 pad[1];
u16 inflight_data;
s32 *future_ptr;
};
struct sti_init_inptr {
s32 text_planes;
struct sti_init_inptr_ext *ext_ptr;
};
struct sti_init_outptr {
s32 errno;
s32 text_planes;
s32 *future_ptr;
};
struct sti_conf_flags {
u32 wait : 1;
u32 pad : 31;
s32 *future_ptr;
};
struct sti_conf_inptr {
s32 *future_ptr;
};
struct sti_conf_outptr_ext {
u32 crt_config[3];
u32 crt_hdw[3];
s32 *future_ptr;
};
struct sti_conf_outptr {
s32 errno;
s16 onscreen_x;
s16 onscreen_y;
s16 offscreen_x;
s16 offscreen_y;
s16 total_x;
s16 total_y;
s32 bits_per_pixel;
s32 bits_used;
s32 planes;
u8 dev_name[STI_DEV_NAME_LENGTH];
u32 attributes;
struct sti_conf_outptr_ext *ext_ptr;
};
struct sti_font_inptr {
u32 font_start_addr;
s16 index;
u8 fg_color;
u8 bg_color;
s16 dest_x;
s16 dest_y;
s32 *future_ptr;
};
struct sti_font_flags {
u32 wait : 1;
u32 non_text : 1;
u32 pad : 30;
s32 *future_ptr;
};
struct sti_font_outptr {
s32 errno;
s32 *future_ptr;
};
struct sti_blkmv_flags {
u32 wait : 1;
u32 color : 1;
u32 clear : 1;
u32 non_text : 1;
u32 pad : 28;
s32 *future_ptr;
};
struct sti_blkmv_inptr {
u8 fg_color;
u8 bg_color;
s16 src_x;
s16 src_y;
s16 dest_x;
s16 dest_y;
s16 width;
s16 height;
s32 *future_ptr;
};
struct sti_blkmv_outptr {
s32 errno;
s32 *future_ptr;
};
struct sti_struct {
spinlock_t lock;
struct sti_cooked_rom *rom;
unsigned long font_unpmv;
unsigned long block_move;
unsigned long init_graph;
unsigned long inq_conf;
struct sti_glob_cfg *glob_cfg;
struct sti_rom_font *font;
s32 text_planes;
char **mon_strings;
u32 *regions;
u8 *pci_regions;
};
#define STI_CALL(func, flags, inptr, outptr, glob_cfg) \
({ \
real32_call( func, (unsigned long)STI_PTR(flags), \
STI_PTR(inptr), STI_PTR(outptr), \
glob_cfg); \
})
/* The latency of the STI functions cannot really be reduced by setting
* this to 0; STI doesn't seem to be designed to allow calling a different
* function (or the same function with different arguments) after a
* function exited with 1 as return value.
*
* As all of the functions below could be called from interrupt context,
* we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
* block. Really bad latency there.
*
* Probably the best solution to all this is have the generic code manage
* the screen buffer and a kernel thread to call STI occasionally.
*
* Luckily, the frame buffer guys have the same problem so we can just wait
* for them to fix it and steal their solution. prumpf
*
* Actually, another long-term viable solution is to completely do STI
* support in userspace - that way we avoid the potential license issues
* of using proprietary fonts, too. */
#define STI_WAIT 1
#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
#define sti_font_x(sti) (PTR_STI(sti->font)->width)
#define sti_font_y(sti) (PTR_STI(sti->font)->height)
extern struct sti_struct * sti_init_roms(void);
void sti_init_graph(struct sti_struct *sti);
void sti_inq_conf(struct sti_struct *sti);
void sti_putc(struct sti_struct *sti, int c, int y, int x);
void sti_set(struct sti_struct *sti, int src_y, int src_x,
int height, int width, u8 color);
void sti_clear(struct sti_struct *sti, int src_y, int src_x,
int height, int width);
void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
int dst_y, int dst_x, int height, int width);
/* XXX: this probably should not be here, but we rely on STI being
initialized early and independently of stifb at the moment, so
there's no other way for stifb to find it. */
extern struct sti_struct default_sti;
This diff is collapsed.
This diff is collapsed.
......@@ -11,6 +11,9 @@
#include <linux/tty.h>
#include <linux/fb.h>
#include <linux/module.h>
#ifdef CONFIG_PCI
#include <linux/pci.h>
#endif
/*
* EDID parser
......@@ -19,37 +22,37 @@
* John Fremlin <vii@users.sourceforge.net> and Ani Joshi <ajoshi@unixbox.com>
*/
#define EDID_LENGTH 0x80
#define EDID_HEADER 0x00
#define EDID_HEADER_END 0x07
#define EDID_LENGTH 0x80
#define EDID_HEADER 0x00
#define EDID_HEADER_END 0x07
#define ID_MANUFACTURER_NAME 0x08
#define ID_MANUFACTURER_NAME_END 0x09
#define ID_MODEL 0x0a
#define ID_MANUFACTURER_NAME 0x08
#define ID_MANUFACTURER_NAME_END 0x09
#define ID_MODEL 0x0a
#define ID_SERIAL_NUMBER 0x0c
#define ID_SERIAL_NUMBER 0x0c
#define MANUFACTURE_WEEK 0x10
#define MANUFACTURE_YEAR 0x11
#define MANUFACTURE_WEEK 0x10
#define MANUFACTURE_YEAR 0x11
#define EDID_STRUCT_VERSION 0x12
#define EDID_STRUCT_REVISION 0x13
#define EDID_STRUCT_VERSION 0x12
#define EDID_STRUCT_REVISION 0x13
#define DPMS_FLAGS 0x18
#define ESTABLISHED_TIMING_1 0x23
#define ESTABLISHED_TIMING_2 0x24
#define MANUFACTURERS_TIMINGS 0x25
#define DPMS_FLAGS 0x18
#define ESTABLISHED_TIMING_1 0x23
#define ESTABLISHED_TIMING_2 0x24
#define MANUFACTURERS_TIMINGS 0x25
#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
#define DETAILED_TIMING_DESCRIPTION_SIZE 18
#define NO_DETAILED_TIMING_DESCRIPTIONS 4
#define DETAILED_TIMING_DESCRIPTIONS_START 0x36
#define DETAILED_TIMING_DESCRIPTION_SIZE 18
#define NO_DETAILED_TIMING_DESCRIPTIONS 4
#define DETAILED_TIMING_DESCRIPTION_1 0x36
#define DETAILED_TIMING_DESCRIPTION_2 0x48
#define DETAILED_TIMING_DESCRIPTION_3 0x5a
#define DETAILED_TIMING_DESCRIPTION_4 0x6c
#define DETAILED_TIMING_DESCRIPTION_1 0x36
#define DETAILED_TIMING_DESCRIPTION_2 0x48
#define DETAILED_TIMING_DESCRIPTION_3 0x5a
#define DETAILED_TIMING_DESCRIPTION_4 0x6c
#define DESCRIPTOR_DATA 5
#define DESCRIPTOR_DATA 5
#define UPPER_NIBBLE( x ) \
(((128|64|32|16) & (x)) >> 4)
......@@ -65,7 +68,7 @@
#define PIXEL_CLOCK_LO (unsigned)block[ 0 ]
#define PIXEL_CLOCK_HI (unsigned)block[ 1 ]
#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*1000
#define PIXEL_CLOCK (COMBINE_HI_8LO( PIXEL_CLOCK_HI,PIXEL_CLOCK_LO )*1000)
#define H_ACTIVE_LO (unsigned)block[ 2 ]
#define H_BLANKING_LO (unsigned)block[ 3 ]
#define H_ACTIVE_HI UPPER_NIBBLE( (unsigned)block[ 4 ] )
......@@ -223,8 +226,8 @@ static void parse_timing_block(unsigned char *block,
int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
{
unsigned char *block, *vendor, *monitor = NULL;
int i;
unsigned char *block, *vendor, *monitor;
if (!(edid_checksum(edid)))
return 0;
......@@ -257,10 +260,12 @@ int parse_edid(unsigned char *edid, struct fb_var_screeninfo *var)
return 1;
}
#ifdef CONFIG_PCI
char *get_EDID(struct pci_dev *pdev)
{
#ifdef CONFIG_ALL_PPC
static char *propnames[] = { "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
static char *propnames[] =
{ "DFP,EDID", "LCD,EDID", "EDID", "EDID1", NULL };
unsigned char *pedid = NULL;
struct device_node *dp;
int i;
......@@ -268,7 +273,10 @@ char *get_EDID(struct pci_dev *pdev)
dp = pci_device_to_OF_node(pdev);
while (dp != NULL) {
for (i = 0; propnames[i] != NULL; ++i) {
pedid = (unsigned char *) get_property(dp, propnames[i], NULL);
pedid =
(unsigned char *) get_property(dp,
propnames[i],
NULL);
if (pedid != NULL)
return pedid;
}
......@@ -278,7 +286,10 @@ char *get_EDID(struct pci_dev *pdev)
#else
return NULL;
#endif
}
}
#endif
EXPORT_SYMBOL(parse_edid);
#ifdef CONFIG_PCI
EXPORT_SYMBOL(get_EDID);
#endif
......@@ -41,9 +41,6 @@
#include <linux/pci.h>
#include <linux/pci_ids.h>
#include <linux/resource.h>
#include <linux/selection.h>
#include <linux/console.h>
#include <linux/vt_kern.h>
#include <linux/unistd.h>
#include <asm/io.h>
......
This diff is collapsed.
......@@ -378,6 +378,9 @@ struct sti_struct {
/* PCI data structures (pg. 17ff from sti.pdf) */
struct pci_dev *pd;
u8 rm_entry[16]; /* pci region mapper array == pci config space offset */
/* pointer to the fb_info where this STI device is used */
struct fb_info *info;
};
......
/*
* linux/drivers/video/sti/stifb.c -
* Frame buffer driver for HP workstations with STI (standard text interface)
* video firmware.
* linux/drivers/video/stifb.c -
* Low level Frame buffer driver for HP workstations with
* STI (standard text interface) video firmware.
*
* Copyright (C) 2001-2002 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
......@@ -40,10 +40,9 @@
/* TODO:
* - remove the static fb_info to support multiple cards
* - remove the completely untested 1bpp mode
* - 1bpp mode is completely untested
* - add support for h/w acceleration
* - add hardware cursor
* -
*/
......@@ -68,21 +67,18 @@
#include <linux/ioport.h>
#include <linux/pci.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb32.h>
#include "console/fbcon.h"
#include <asm/grfioctl.h> /* for HP-UX compatibility */
#include "sticore.h"
/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
#ifdef __LP64__
/* return virtual address */
#define REGION_BASE(fb_info, index) \
#define REGION_BASE(fb_info, index) \
(fb_info->sti->glob_cfg->region_ptrs[index] | 0xffffffff00000000)
#else
/* return virtual address */
#define REGION_BASE(fb_info, index) \
#define REGION_BASE(fb_info, index) \
fb_info->sti->glob_cfg->region_ptrs[index]
#endif
......@@ -936,53 +932,6 @@ stifb_setcolreg(u_int regno, u_int red, u_int green,
return 0;
}
#if 0
static void
stifb_loadcmap(struct stifb_info *fb)
{
u32 color;
int i;
if (!fb->cmap_reload)
return;
START_IMAGE_COLORMAP_ACCESS(fb);
for (i = 0; i < 256; i++) {
if (fb->info.var.bits_per_pixel > 8) {
color = (i << 16) | (i << 8) | i;
} else {
if (fb->info.var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
color = ((fb->palette[i].red * 77) +
(fb->palette[i].green * 151) +
(fb->palette[i].blue * 28)) >> 8;
} else {
color = ((fb->palette[i].red << 16) |
(fb->palette[i].green << 8) |
(fb->palette[i].blue));
}
}
WRITE_IMAGE_COLOR(fb, i, color);
}
if (fb->id == S9000_ID_HCRX) {
NgleLutBltCtl lutBltCtl;
lutBltCtl = setHyperLutBltCtl(fb,
0, /* Offset w/i LUT */
256); /* Load entire LUT */
NGLE_BINC_SET_SRCADDR(fb,
NGLE_LONG_FB_ADDRESS(0, 0x100, 0));
/* 0x100 is same as used in WRITE_IMAGE_COLOR() */
START_COLORMAPLOAD(fb, lutBltCtl.all);
SETUP_FB(fb);
} else {
/* cleanup colormap hardware */
FINISH_IMAGE_COLORMAP_ACCESS(fb);
}
fb->cmap_reload = 0;
}
#endif
static int
stifb_blank(int blank_mode, struct fb_info *info)
{
......@@ -1075,24 +1024,18 @@ stifb_init_display(struct stifb_info *fb)
static struct fb_ops stifb_ops = {
.owner = THIS_MODULE,
.fb_set_var = gen_set_var,
.fb_get_cmap = gen_get_cmap,
.fb_set_cmap = gen_set_cmap,
.fb_setcolreg = stifb_setcolreg,
/* .fb_pan_display = stifb_pan_display, */
.fb_blank = stifb_blank,
/*
.fb_fillrect = cfb_fillrect,
.fb_copyarea = cfb_copyarea,
.fb_imageblit = cfb_imageblit,
*/
.fb_imageblit = cfb_imageblit,
.fb_cursor = soft_cursor,
};
/*
* Initialization
*/
/*
* Initialization
*/
int __init
stifb_init_fb(struct sti_struct *sti, int force_bpp)
......@@ -1100,7 +1043,6 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
struct fb_fix_screeninfo *fix;
struct fb_var_screeninfo *var;
struct display *disp;
struct display_switch *dispsw;
struct stifb_info *fb;
struct fb_info *info;
unsigned long sti_rom_address;
......@@ -1120,7 +1062,6 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
fix = &info->fix;
var = &info->var;
disp = &fb->disp;
info->disp = &fb->disp;
fb->sti = sti;
/* store upper 32bits of the graphics id */
......@@ -1234,30 +1175,22 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
case 1:
fix->type = FB_TYPE_PLANES; /* well, sort of */
fix->visual = FB_VISUAL_MONO10;
dispsw = &fbcon_sti;
break;
#ifdef FBCON_HAS_CFB8
case 8:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_PSEUDOCOLOR;
dispsw = &fbcon_cfb8;
var->red.length = var->green.length = var->blue.length = 8;
break;
#endif
#ifdef FBCON_HAS_CFB32
case 32:
fix->type = FB_TYPE_PACKED_PIXELS;
fix->visual = FB_VISUAL_TRUECOLOR;
dispsw = &fbcon_cfb32;
var->red.length = var->green.length = var->blue.length = var->transp.length = 8;
var->blue.offset = 0;
var->green.offset = 8;
var->red.offset = 16;
var->transp.offset = 24;
break;
#endif
default:
dispsw = &fbcon_dummy;
break;
}
......@@ -1265,22 +1198,16 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
var->yres = var->yres_virtual = yres;
var->bits_per_pixel = bpp;
strcpy(info->modename, "stifb");
strcpy(fix->id, "stifb");
info->node = NODEV;
info->fbops = &stifb_ops;
info->screen_base = (void*) REGION_BASE(fb,1);
info->disp = disp;
info->changevar = NULL;
info->switch_con = gen_switch;
info->updatevar = &gen_update_var;
info->flags = FBINFO_FLAG_DEFAULT;
info->currcon = -1;
/* This has to been done !!! */
fb_alloc_cmap(&info->cmap, 256, 0);
stifb_init_display(fb);
gen_set_disp(-1, info);
disp->dispsw = dispsw;
if (!request_mem_region(fix->smem_start, fix->smem_len, "stifb")) {
printk(KERN_ERR "stifb: cannot reserve fb region 0x%04lx-0x%04lx\n",
......@@ -1297,13 +1224,15 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
if (register_framebuffer(&fb->info) < 0)
goto out_err3;
sti->info = info; /* save for unregister_framebuffer() */
printk(KERN_INFO
"fb%d: %s %dx%d-%d frame buffer device, id: %04x, mmio: 0x%04lx\n",
minor(fb->info.node),
fb->info.modename,
disp->var.xres,
disp->var.yres,
disp->var.bits_per_pixel,
fix->id,
var->xres,
var->yres,
var->bits_per_pixel,
fb->id,
fix->mmio_start);
......@@ -1315,6 +1244,7 @@ stifb_init_fb(struct sti_struct *sti, int force_bpp)
out_err2:
release_mem_region(fix->smem_start, fix->smem_len);
out_err1:
fb_dealloc_cmap(&info->cmap);
kfree(fb);
return -ENXIO;
}
......@@ -1325,7 +1255,6 @@ stifb_init(void)
struct sti_struct *sti;
int i;
if (sti_init_roms() == NULL)
return -ENXIO; /* no STI cards available */
......@@ -1346,7 +1275,17 @@ stifb_init(void)
static void __exit
stifb_cleanup(void)
{
// unregister_framebuffer();
struct sti_struct *sti;
int i;
for (i = 0; i < MAX_STI_ROMS; i++) {
sti = sti_get_rom(i);
if (!sti)
break;
if (sti->info)
unregister_framebuffer(sti->info);
sti->info = NULL;
}
}
int __init
......
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