Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
8d7c2813
Commit
8d7c2813
authored
Dec 11, 2002
by
James Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updates for the STI fbdev and console driver.
parent
0e2e212c
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
1173 additions
and
3196 deletions
+1173
-3196
drivers/video/Kconfig
drivers/video/Kconfig
+11
-17
drivers/video/Makefile
drivers/video/Makefile
+1
-1
drivers/video/console/Kconfig
drivers/video/console/Kconfig
+2
-1
drivers/video/console/Makefile
drivers/video/console/Makefile
+1
-3
drivers/video/console/fbcon-sti.c
drivers/video/console/fbcon-sti.c
+0
-289
drivers/video/console/sti.h
drivers/video/console/sti.h
+0
-289
drivers/video/console/sticon.c
drivers/video/console/sticon.c
+290
-100
drivers/video/console/sticore.c
drivers/video/console/sticore.c
+794
-336
drivers/video/fbmon.c
drivers/video/fbmon.c
+39
-28
drivers/video/i810/i810_main.c
drivers/video/i810/i810_main.c
+0
-3
drivers/video/riva/fbdev.c.new
drivers/video/riva/fbdev.c.new
+0
-2036
drivers/video/sticore.h
drivers/video/sticore.h
+3
-0
drivers/video/stifb.c
drivers/video/stifb.c
+32
-93
No files found.
drivers/video/Kconfig
View file @
8d7c2813
...
...
@@ -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"
...
...
drivers/video/Makefile
View file @
8d7c2813
...
...
@@ -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
...
...
drivers/video/console/Kconfig
View file @
8d7c2813
...
...
@@ -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.
...
...
drivers/video/console/Makefile
View file @
8d7c2813
...
...
@@ -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
...
...
drivers/video/console/fbcon-sti.c
deleted
100644 → 0
View file @
0e2e212c
/*
* 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"
);
drivers/video/console/sti.h
deleted
100644 → 0
View file @
0e2e212c
#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
;
drivers/video/console/sticon.c
View file @
8d7c2813
/*
* linux/drivers/video/
sticon.c
- console driver using HP's STI firmware
* linux/drivers/video/
console/sticon.c
- console driver using HP's STI firmware
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
* Copyright (C) 2002 Helge Deller <deller@gmx.de>
*
* Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
* which were
...
...
@@ -31,18 +32,7 @@
* 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.
*/
/*
* TODO:
* - call STI in virtual mode rather than in real mode
* - support for PCI-only STI ROMs (which don't have a traditional region
* list)
* - safe detection (i.e. verify there is a graphics device at a given
* address first, not just read a random device's io space)
* - support for multiple STI devices in one machine
* - support for byte-mode STI ROMs
* - support for just using STI to switch to a colour fb (stifb ?)
* - try to make it work on m68k hp workstations ;)
*
*/
#include <linux/init.h>
...
...
@@ -51,92 +41,193 @@
#include <linux/console.h>
#include <linux/errno.h>
#include <linux/vt_kern.h>
#include <linux/kd.h>
#include <linux/selection.h>
#include <asm/io.h>
#include "sti.h"
#include "../sticore.h"
/* switching to graphics mode */
#define BLANK 0
static
int
vga_is_gfx
;
/* Software scrollback */
static
unsigned
long
softback_buf
,
softback_curr
;
static
unsigned
long
softback_in
;
static
unsigned
long
/* softback_top, */
softback_end
;
static
int
softback_lines
;
/* STICON */
static
const
char
*
__init
sticon_startup
(
void
)
/* software cursor */
static
int
cursor_drawn
;
#define CURSOR_DRAW_DELAY (1)
#define DEFAULT_CURSOR_BLINK_RATE (20)
static
int
vbl_cursor_cnt
;
static
inline
void
cursor_undrawn
(
void
)
{
return
"STI console"
;
vbl_cursor_cnt
=
0
;
cursor_drawn
=
0
;
}
static
int
st
icon_set_palette
(
struct
vc_data
*
c
,
unsigned
char
*
table
)
st
atic
const
char
*
__init
sticon_startup
(
void
)
{
return
-
EINVAL
;
return
"STI console"
;
}
static
int
st
icon_font_op
(
struct
vc_data
*
c
,
struct
console_font_op
*
op
)
st
atic
int
sticon_set_palette
(
struct
vc_data
*
c
,
unsigned
char
*
table
)
{
return
-
ENOSYS
;
return
-
EINVAL
;
}
static
int
sticon_font_op
(
struct
vc_data
*
c
,
struct
console_font_op
*
op
)
{
return
-
ENOSYS
;
}
static
void
sticon_putc
(
struct
vc_data
*
conp
,
int
c
,
int
ypos
,
int
xpos
)
{
sti_putc
(
&
default_sti
,
c
,
ypos
,
xpos
);
int
unit
=
conp
->
vc_num
;
int
redraw_cursor
=
0
;
if
(
vga_is_gfx
||
console_blanked
)
return
;
if
(
vt_cons
[
unit
]
->
vc_mode
!=
KD_TEXT
)
return
;
#if 0
if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
cursor_undrawn();
redraw_cursor = 1;
}
#endif
sti_putc
(
default_sti
,
c
,
ypos
,
xpos
);
if
(
redraw_cursor
)
vbl_cursor_cnt
=
CURSOR_DRAW_DELAY
;
}
static
void
sticon_putcs
(
struct
vc_data
*
conp
,
const
unsigned
short
*
s
,
int
count
,
int
ypos
,
int
xpos
)
int
count
,
int
ypos
,
int
xpos
)
{
while
(
count
--
)
{
sti_putc
(
&
default_sti
,
scr_readw
(
s
++
),
ypos
,
xpos
++
);
}
int
unit
=
conp
->
vc_num
;
int
redraw_cursor
=
0
;
if
(
vga_is_gfx
||
console_blanked
)
return
;
if
(
vt_cons
[
unit
]
->
vc_mode
!=
KD_TEXT
)
return
;
#if 0
if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
(p->cursor_x < (xpos + count))) {
cursor_undrawn();
redraw_cursor = 1;
}
#endif
while
(
count
--
)
{
sti_putc
(
default_sti
,
scr_readw
(
s
++
),
ypos
,
xpos
++
);
}
if
(
redraw_cursor
)
vbl_cursor_cnt
=
CURSOR_DRAW_DELAY
;
}
static
void
sticon_cursor
(
struct
vc_data
*
conp
,
int
mode
)
{
unsigned
short
car1
;
car1
=
conp
->
vc_screenbuf
[
conp
->
vc_x
+
conp
->
vc_y
*
conp
->
vc_cols
];
switch
(
mode
)
{
case
CM_ERASE
:
sti_putc
(
default_sti
,
car1
,
conp
->
vc_y
,
conp
->
vc_x
);
break
;
case
CM_MOVE
:
case
CM_DRAW
:
switch
(
conp
->
vc_cursor_type
&
0x0f
)
{
case
CUR_UNDERLINE
:
case
CUR_LOWER_THIRD
:
case
CUR_LOWER_HALF
:
case
CUR_TWO_THIRDS
:
case
CUR_BLOCK
:
sti_putc
(
default_sti
,
(
car1
&
255
)
+
(
0
<<
8
)
+
(
7
<<
11
),
conp
->
vc_y
,
conp
->
vc_x
);
break
;
}
break
;
}
}
static
int
sticon_scroll
(
struct
vc_data
*
conp
,
int
t
,
int
b
,
int
dir
,
int
count
)
static
int
sticon_scroll
(
struct
vc_data
*
conp
,
int
t
,
int
b
,
int
dir
,
int
count
)
{
struct
sti_struct
*
sti
=
&
default_sti
;
if
(
console_blanked
)
return
0
;
sticon_cursor
(
conp
,
CM_ERASE
);
struct
sti_struct
*
sti
=
default_sti
;
switch
(
dir
)
{
case
SM_UP
:
sti_bmove
(
sti
,
t
+
count
,
0
,
t
,
0
,
b
-
t
-
count
,
conp
->
vc_cols
);
sti_clear
(
sti
,
b
-
count
,
0
,
count
,
conp
->
vc_cols
);
if
(
vga_is_gfx
)
return
0
;
break
;
sticon_cursor
(
conp
,
CM_ERASE
)
;
case
SM_DOWN
:
sti_bmove
(
sti
,
t
,
0
,
t
+
count
,
0
,
b
-
t
-
count
,
conp
->
vc_cols
);
sti_clear
(
sti
,
t
,
0
,
count
,
conp
->
vc_cols
);
switch
(
dir
)
{
case
SM_UP
:
sti_bmove
(
sti
,
t
+
count
,
0
,
t
,
0
,
b
-
t
-
count
,
conp
->
vc_cols
);
sti_clear
(
sti
,
b
-
count
,
0
,
count
,
conp
->
vc_cols
,
conp
->
vc_video_erase_char
);
break
;
break
;
}
case
SM_DOWN
:
sti_bmove
(
sti
,
t
,
0
,
t
+
count
,
0
,
b
-
t
-
count
,
conp
->
vc_cols
);
sti_clear
(
sti
,
t
,
0
,
count
,
conp
->
vc_cols
,
conp
->
vc_video_erase_char
);
break
;
}
return
0
;
return
0
;
}
static
void
sticon_bmove
(
struct
vc_data
*
conp
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
static
void
sticon_bmove
(
struct
vc_data
*
conp
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
{
sti_bmove
(
&
default_sti
,
sy
,
sx
,
dy
,
dx
,
height
,
width
);
if
(
!
width
||
!
height
)
return
;
#if 0
if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
(sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
(dx <= p->cursor_x) && (p->cursor_x < dx+width)))
sticon_cursor(p, CM_ERASE /*|CM_SOFTBACK*/);
#endif
sti_bmove
(
default_sti
,
sy
,
sx
,
dy
,
dx
,
height
,
width
);
}
static
void
sticon_init
(
struct
vc_data
*
c
,
int
init
)
{
struct
sti_struct
*
sti
=
&
default_sti
;
int
vc_cols
,
vc_rows
;
sti_set
(
sti
,
0
,
0
,
sti_onscreen_y
(
sti
),
sti_onscreen_x
(
sti
),
0
);
c
->
vc_can_do_color
=
1
;
vc_cols
=
PTR_STI
(
sti
->
glob_cfg
)
->
onscreen_x
/
sti_font_x
(
sti
);
vc_rows
=
PTR_STI
(
sti
->
glob_cfg
)
->
onscreen_y
/
sti_font_y
(
sti
);
vc_resize
(
c
->
vc_num
,
vc_cols
,
vc_rows
);
struct
sti_struct
*
sti
=
default_sti
;
int
vc_cols
,
vc_rows
;
sti_set
(
sti
,
0
,
0
,
sti_onscreen_y
(
sti
),
sti_onscreen_x
(
sti
),
0
);
vc_cols
=
sti_onscreen_x
(
sti
)
/
sti
->
font_width
;
vc_rows
=
sti_onscreen_y
(
sti
)
/
sti
->
font_height
;
c
->
vc_can_do_color
=
1
;
if
(
init
)
{
c
->
vc_cols
=
vc_cols
;
c
->
vc_rows
=
vc_rows
;
}
else
{
/* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
/* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
vc_resize
(
c
->
vc_num
,
vc_cols
,
vc_rows
);
/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
}
}
static
void
sticon_deinit
(
struct
vc_data
*
c
)
...
...
@@ -144,71 +235,170 @@ static void sticon_deinit(struct vc_data *c)
}
static
void
sticon_clear
(
struct
vc_data
*
conp
,
int
sy
,
int
sx
,
int
height
,
int
width
)
int
width
)
{
sti_clear
(
&
default_sti
,
sy
,
sx
,
height
,
width
);
if
(
!
height
||
!
width
)
return
;
sti_clear
(
default_sti
,
sy
,
sx
,
height
,
width
,
conp
->
vc_video_erase_char
);
}
static
int
sticon_switch
(
struct
vc_data
*
conp
)
{
return
0
;
return
1
;
/* needs refreshing */
}
static
int
sticon_
blank
(
struct
vc_data
*
conp
,
int
blank
)
static
int
sticon_
set_origin
(
struct
vc_data
*
conp
)
{
return
0
;
return
0
;
}
static
int
sticon_blank
(
struct
vc_data
*
c
,
int
blank
)
{
switch
(
blank
)
{
case
0
:
/* unblank */
vga_is_gfx
=
0
;
/* Tell console.c that it has to restore the screen itself */
return
1
;
case
1
:
/* normal blanking */
default:
/* VESA blanking */
if
(
vga_is_gfx
)
return
0
;
sticon_set_origin
(
c
);
sti_clear
(
default_sti
,
0
,
0
,
c
->
vc_rows
,
c
->
vc_cols
,
BLANK
);
return
1
;
case
-
1
:
/* Entering graphic mode */
sti_clear
(
default_sti
,
0
,
0
,
c
->
vc_rows
,
c
->
vc_cols
,
BLANK
);
vga_is_gfx
=
1
;
return
1
;
}
return
1
;
/* console needs to restore screen itself */
}
static
int
sticon_scrolldelta
(
struct
vc_data
*
conp
,
int
lines
)
{
return
0
;
return
0
;
}
static
int
sticon_set_origin
(
struct
vc_data
*
conp
)
static
u16
*
sticon_screen_pos
(
struct
vc_data
*
conp
,
int
offset
)
{
return
0
;
int
line
;
unsigned
long
p
;
if
(
conp
->
vc_num
!=
fg_console
||
!
softback_lines
)
return
(
u16
*
)(
conp
->
vc_origin
+
offset
);
line
=
offset
/
conp
->
vc_size_row
;
if
(
line
>=
softback_lines
)
return
(
u16
*
)(
conp
->
vc_origin
+
offset
-
softback_lines
*
conp
->
vc_size_row
);
p
=
softback_curr
+
offset
;
if
(
p
>=
softback_end
)
p
+=
softback_buf
-
softback_end
;
return
(
u16
*
)
p
;
}
static
u8
sticon_build_attr
(
struct
vc_data
*
conp
,
u8
color
,
u8
intens
,
u8
blink
,
u8
underline
,
u8
reverse
)
static
unsigned
long
sticon_getxy
(
struct
vc_data
*
conp
,
unsigned
long
pos
,
int
*
px
,
int
*
py
)
{
u8
attr
=
((
color
&
0x70
)
>>
1
)
|
((
color
&
7
));
int
x
,
y
;
unsigned
long
ret
;
if
(
pos
>=
conp
->
vc_origin
&&
pos
<
conp
->
vc_scr_end
)
{
unsigned
long
offset
=
(
pos
-
conp
->
vc_origin
)
/
2
;
x
=
offset
%
conp
->
vc_cols
;
y
=
offset
/
conp
->
vc_cols
;
if
(
conp
->
vc_num
==
fg_console
)
y
+=
softback_lines
;
ret
=
pos
+
(
conp
->
vc_cols
-
x
)
*
2
;
}
else
if
(
conp
->
vc_num
==
fg_console
&&
softback_lines
)
{
unsigned
long
offset
=
pos
-
softback_curr
;
if
(
pos
<
softback_curr
)
offset
+=
softback_end
-
softback_buf
;
offset
/=
2
;
x
=
offset
%
conp
->
vc_cols
;
y
=
offset
/
conp
->
vc_cols
;
ret
=
pos
+
(
conp
->
vc_cols
-
x
)
*
2
;
if
(
ret
==
softback_end
)
ret
=
softback_buf
;
if
(
ret
==
softback_in
)
ret
=
conp
->
vc_origin
;
}
else
{
/* Should not happen */
x
=
y
=
0
;
ret
=
conp
->
vc_origin
;
}
if
(
px
)
*
px
=
x
;
if
(
py
)
*
py
=
y
;
return
ret
;
}
if
(
reverse
)
{
color
=
((
color
>>
3
)
&
0x7
)
|
((
color
&
0x7
)
<<
3
);
}
static
u8
sticon_build_attr
(
struct
vc_data
*
conp
,
u8
color
,
u8
intens
,
u8
blink
,
u8
underline
,
u8
reverse
)
{
u8
attr
=
((
color
&
0x70
)
>>
1
)
|
((
color
&
7
));
if
(
reverse
)
{
color
=
((
color
>>
3
)
&
0x7
)
|
((
color
&
0x7
)
<<
3
);
}
return
attr
;
return
attr
;
}
void
sticon_invert_region
(
struct
vc_data
*
conp
,
u16
*
p
,
int
count
)
{
int
col
=
1
;
/* vga_can_do_color; */
while
(
count
--
)
{
u16
a
=
scr_readw
(
p
);
if
(
col
)
a
=
((
a
)
&
0x88ff
)
|
(((
a
)
&
0x7000
)
>>
4
)
|
(((
a
)
&
0x0700
)
<<
4
);
else
a
=
((
a
&
0x0700
)
==
0x0100
)
?
0x7000
:
0x7700
;
scr_writew
(
a
,
p
++
);
}
}
void
sticon_save_screen
(
struct
vc_data
*
conp
)
{
}
struct
consw
sti_con
=
{
.
con_startup
=
sticon_startup
,
.
con_init
=
sticon_init
,
.
con_deinit
=
sticon_deinit
,
.
con_clear
=
sticon_clear
,
.
con_putc
=
sticon_putc
,
.
con_putcs
=
sticon_putcs
,
.
con_cursor
=
sticon_cursor
,
.
con_scroll
=
sticon_scroll
,
.
con_bmove
=
sticon_bmove
,
.
con_switch
=
sticon_switch
,
.
con_blank
=
sticon_blank
,
.
con_font_op
=
sticon_font_op
,
.
con_set_palette
=
sticon_set_palette
,
.
con_scrolldelta
=
sticon_scrolldelta
,
.
con_set_origin
=
sticon_set_origin
,
.
con_build_attr
=
sticon_build_attr
,
con_startup:
sticon_startup
,
con_init:
sticon_init
,
con_deinit:
sticon_deinit
,
con_clear:
sticon_clear
,
con_putc:
sticon_putc
,
con_putcs:
sticon_putcs
,
con_cursor:
sticon_cursor
,
con_scroll:
sticon_scroll
,
con_bmove:
sticon_bmove
,
con_switch:
sticon_switch
,
con_blank:
sticon_blank
,
con_font_op:
sticon_font_op
,
con_set_palette:
sticon_set_palette
,
con_scrolldelta:
sticon_scrolldelta
,
con_set_origin:
sticon_set_origin
,
con_save_screen:
sticon_save_screen
,
con_build_attr:
sticon_build_attr
,
con_invert_region:
sticon_invert_region
,
con_screen_pos:
sticon_screen_pos
,
con_getxy:
sticon_getxy
,
};
static
int
__init
sti_init
(
void
)
int
__init
sticonsole_init
(
void
)
{
printk
(
"searching for word mode STI ROMs
\n
"
);
if
(
sti_init_roms
())
{
pdc_console_die
();
take_over_console
(
&
sti_con
,
0
,
MAX_NR_CONSOLES
-
1
,
1
);
return
0
;
}
else
return
-
ENODEV
;
if
(
sti_init_roms
())
{
if
(
conswitchp
==
&
dummy_con
)
{
printk
(
KERN_INFO
"sticon: Initializing STI text console.
\n
"
);
take_over_console
(
&
sti_con
,
0
,
MAX_NR_CONSOLES
-
1
,
1
);
}
return
0
;
}
else
return
-
ENODEV
;
}
module_init
(
sti
_init
)
module_init
(
sti
console_init
);
drivers/video/console/sticore.c
View file @
8d7c2813
/*
* linux/drivers/video/console/sticore.c -
* core code for console driver using HP's STI firmware
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
* Portions Copyright (C) 2001-2002 Helge Deller <deller@gmx.de>
* Portions Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*
* TODO:
* - call STI in virtual mode rather than in real mode
* - screen blanking with state_mgmt() in text mode STI ?
* - try to make it work on m68k hp workstations ;)
* - clean up the cache flushing functions
*
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/pci.h>
#include "font.h"
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
#include <asm/
io
.h>
#include <asm/
hardware
.h>
#include "
sti
.h"
#include "
../sticore
.h"
struct
sti_struct
default_sti
=
{
SPIN_LOCK_UNLOCKED
,
};
#define STI_DRIVERVERSION "0.9"
struct
sti_struct
*
default_sti
;
static
int
num_sti_roms
;
/* # of STI ROMS found */
static
struct
sti_struct
*
sti_roms
[
MAX_STI_ROMS
];
/* ptr to each sti_struct */
static
struct
sti_font_flags
default_font_flags
=
{
STI_WAIT
,
0
,
0
,
NULL
};
/* The colour indices used by STI are
* 0 - Black
...
...
@@ -31,31 +49,36 @@ static struct sti_font_flags default_font_flags = {
* So we have the same colours as VGA (basically one bit each for R, G, B),
* but have to translate them, anyway. */
static
u8
col_trans
[
8
]
=
{
static
const
u8
col_trans
[
8
]
=
{
0
,
6
,
4
,
5
,
2
,
7
,
3
,
1
};
#define c_fg(sti, c) col_trans[((c>> 8) & 7)]
#define c_bg(sti, c) col_trans[((c>>11) & 7)]
#define c_index(sti, c) (c&0xff)
static
struct
sti_init_flags
default_init_flags
=
{
STI_WAIT
,
1
,
1
,
1
,
0
,
0
,
0
,
0
,
0
,
0
,
1
,
1
,
1
,
0
,
0
,
0
,
NULL
#define c_index(sti, c) ((c) & 0xff)
static
const
struct
sti_init_flags
default_init_flags
=
{
.
wait
=
STI_WAIT
,
.
reset
=
1
,
.
text
=
1
,
.
nontext
=
1
,
.
no_chg_bet
=
1
,
.
no_chg_bei
=
1
,
.
init_cmap_tx
=
1
,
};
void
int
sti_init_graph
(
struct
sti_struct
*
sti
)
{
struct
sti_init_inptr_ext
inptr_ext
=
{
0
,
{
0
},
0
,
NULL
};
struct
sti_init_inptr_ext
inptr_ext
=
{
0
,
};
struct
sti_init_inptr
inptr
=
{
3
,
STI_PTR
(
&
inptr_ext
)
3
,
/* # of text planes (3 is maximum for STI) */
STI_PTR
(
&
inptr_ext
)
};
struct
sti_init_outptr
outptr
=
{
0
};
struct
sti_init_outptr
outptr
=
{
0
,
};
unsigned
long
flags
;
s32
ret
;
int
ret
;
spin_lock_irqsave
(
&
sti
->
lock
,
flags
);
...
...
@@ -64,42 +87,50 @@ sti_init_graph(struct sti_struct *sti)
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"STI init_graph failed (ret %d, errno %d)
\n
"
,
ret
,
outptr
.
errno
);
return
-
1
;
}
sti
->
text_planes
=
outptr
.
text_planes
;
return
0
;
}
static
struct
sti_conf_flags
default_conf_flags
=
{
STI_WAIT
,
0
,
NULL
};
static
const
struct
sti_conf_flags
default_conf_flags
=
{
wait:
STI_WAIT
,
};
void
sti_inq_conf
(
struct
sti_struct
*
sti
)
{
struct
sti_conf_inptr
inptr
=
{
NULL
};
struct
sti_conf_outptr_ext
outptr_ext
=
{
.
future_ptr
=
NULL
};
struct
sti_conf_outptr
outptr
=
{
.
ext_ptr
=
STI_PTR
(
&
outptr_ext
)
};
struct
sti_conf_inptr
inptr
=
{
0
};
unsigned
long
flags
;
s32
ret
;
sti
->
outptr
.
ext_ptr
=
STI_PTR
(
&
sti
->
outptr_ext
);
do
{
spin_lock_irqsave
(
&
sti
->
lock
,
flags
);
ret
=
STI_CALL
(
sti
->
inq_conf
,
&
default_conf_flags
,
&
inptr
,
&
outptr
,
sti
->
glob_cfg
);
&
inptr
,
&
sti
->
outptr
,
sti
->
glob_cfg
);
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
}
while
(
ret
==
1
);
}
while
(
ret
==
1
);
}
static
const
struct
sti_font_flags
default_font_flags
=
{
wait:
STI_WAIT
,
non_text:
0
,
};
void
sti_putc
(
struct
sti_struct
*
sti
,
int
c
,
int
y
,
int
x
)
{
struct
sti_font_inptr
inptr
=
{
(
u32
)
sti
->
font
,
c_index
(
sti
,
c
),
c_fg
(
sti
,
c
),
c_bg
(
sti
,
c
),
x
*
sti_font_x
(
sti
),
y
*
sti_font_y
(
sti
),
NULL
};
struct
sti_font_outptr
outptr
=
{
0
,
NULL
STI_PTR
(
sti
->
font
->
raw
),
c_index
(
sti
,
c
),
c_fg
(
sti
,
c
),
c_bg
(
sti
,
c
),
x
*
sti
->
font_width
,
y
*
sti
->
font_height
,
0
};
struct
sti_font_outptr
outptr
=
{
0
,
};
s32
ret
;
unsigned
long
flags
;
...
...
@@ -108,11 +139,13 @@ sti_putc(struct sti_struct *sti, int c, int y, int x)
ret
=
STI_CALL
(
sti
->
font_unpmv
,
&
default_font_flags
,
&
inptr
,
&
outptr
,
sti
->
glob_cfg
);
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
}
while
(
ret
==
1
);
}
while
(
ret
==
1
);
}
static
struct
sti_blkmv_flags
clear_blkmv_flags
=
{
STI_WAIT
,
1
,
1
,
0
,
0
,
NULL
static
const
struct
sti_blkmv_flags
clear_blkmv_flags
=
{
.
wait
=
STI_WAIT
,
.
color
=
1
,
.
clear
=
1
,
};
void
...
...
@@ -124,10 +157,10 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
src_x
,
src_y
,
src_x
,
src_y
,
width
,
height
,
NULL
0
};
struct
sti_blkmv_outptr
outptr
=
{
0
,
NULL
};
s32
ret
=
0
;
struct
sti_blkmv_outptr
outptr
=
{
0
,
};
s32
ret
;
unsigned
long
flags
;
do
{
...
...
@@ -135,22 +168,22 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
ret
=
STI_CALL
(
sti
->
block_move
,
&
clear_blkmv_flags
,
&
inptr
,
&
outptr
,
sti
->
glob_cfg
);
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
}
while
(
ret
==
1
);
}
while
(
ret
==
1
);
}
void
sti_clear
(
struct
sti_struct
*
sti
,
int
src_y
,
int
src_x
,
int
height
,
int
width
)
int
height
,
int
width
,
int
c
)
{
struct
sti_blkmv_inptr
inptr
=
{
0
,
0
,
src_x
*
sti
_font_x
(
sti
),
src_y
*
sti_font_y
(
sti
)
,
src_x
*
sti
_font_x
(
sti
),
src_y
*
sti_font_y
(
sti
)
,
width
*
sti
_font_x
(
sti
),
height
*
sti_font_y
(
sti
)
,
NULL
c_fg
(
sti
,
c
),
c_bg
(
sti
,
c
)
,
src_x
*
sti
->
font_width
,
src_y
*
sti
->
font_height
,
src_x
*
sti
->
font_width
,
src_y
*
sti
->
font_height
,
width
*
sti
->
font_width
,
height
*
sti
->
font_height
,
0
};
struct
sti_blkmv_outptr
outptr
=
{
0
,
NULL
};
s32
ret
=
0
;
struct
sti_blkmv_outptr
outptr
=
{
0
,
};
s32
ret
;
unsigned
long
flags
;
do
{
...
...
@@ -158,11 +191,11 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
ret
=
STI_CALL
(
sti
->
block_move
,
&
clear_blkmv_flags
,
&
inptr
,
&
outptr
,
sti
->
glob_cfg
);
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
}
while
(
ret
==
1
);
}
while
(
ret
==
1
);
}
static
struct
sti_blkmv_flags
default_blkmv_flags
=
{
STI_WAIT
,
0
,
0
,
0
,
0
,
NULL
static
const
struct
sti_blkmv_flags
default_blkmv_flags
=
{
.
wait
=
STI_WAIT
,
};
void
...
...
@@ -171,13 +204,13 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
{
struct
sti_blkmv_inptr
inptr
=
{
0
,
0
,
src_x
*
sti
_font_x
(
sti
),
src_y
*
sti_font_y
(
sti
)
,
dst_x
*
sti
_font_x
(
sti
),
dst_y
*
sti_font_y
(
sti
)
,
width
*
sti
_font_x
(
sti
),
height
*
sti_font_y
(
sti
)
,
NULL
src_x
*
sti
->
font_width
,
src_y
*
sti
->
font_height
,
dst_x
*
sti
->
font_width
,
dst_y
*
sti
->
font_height
,
width
*
sti
->
font_width
,
height
*
sti
->
font_height
,
0
};
struct
sti_blkmv_outptr
outptr
=
{
0
,
NULL
};
s32
ret
=
0
;
struct
sti_blkmv_outptr
outptr
=
{
0
,
};
s32
ret
;
unsigned
long
flags
;
do
{
...
...
@@ -185,170 +218,128 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
ret
=
STI_CALL
(
sti
->
block_move
,
&
default_blkmv_flags
,
&
inptr
,
&
outptr
,
sti
->
glob_cfg
);
spin_unlock_irqrestore
(
&
sti
->
lock
,
flags
);
}
while
(
ret
==
1
);
}
while
(
ret
==
1
);
}
static
void
__init
sti_rom_copy
(
unsigned
long
base
,
unsigned
long
offset
,
unsigned
long
count
,
void
*
dest
)
void
__init
sti_rom_copy
(
unsigned
long
base
,
unsigned
long
count
,
void
*
dest
)
{
void
*
savedest
=
des
t
;
int
savecount
=
coun
t
;
unsigned
long
dest_len
=
coun
t
;
unsigned
long
dest_start
=
(
unsigned
long
)
des
t
;
while
(
count
>=
4
)
{
/* this still needs to be revisited (see arch/parisc/mm/init.c:246) ! */
while
(
count
>=
4
)
{
count
-=
4
;
*
(
u32
*
)
dest
=
gsc_readl
(
base
+
offset
);
offset
+=
4
;
*
(
u32
*
)
dest
=
__raw_readl
(
base
);
base
+=
4
;
dest
+=
4
;
}
while
(
count
)
{
while
(
count
)
{
count
--
;
*
(
u8
*
)
dest
=
gsc_readb
(
base
+
offset
);
offset
++
;
*
(
u8
*
)
dest
=
__raw_readb
(
base
);
base
++
;
dest
++
;
}
flush_kernel_dcache_range
((
unsigned
long
)
dest
,
count
);
flush_icache_range
((
unsigned
long
)
dest
,
dest
+
count
);
}
static
void
dump_sti_rom
(
struct
sti_rom
*
rom
)
{
printk
(
"STI word mode ROM type %d
\n
"
,
rom
->
type
[
3
]);
printk
(
" supports %d monitors
\n
"
,
rom
->
num_mons
);
printk
(
" conforms to STI ROM spec revision %d.%02x
\n
"
,
rom
->
revno
[
0
]
>>
4
,
rom
->
revno
[
0
]
&
0x0f
);
printk
(
" graphics id %02x%02x%02x%02x%02x%02x%02x%02x
\n
"
,
rom
->
graphics_id
[
0
],
rom
->
graphics_id
[
1
],
rom
->
graphics_id
[
2
],
rom
->
graphics_id
[
3
],
rom
->
graphics_id
[
4
],
rom
->
graphics_id
[
5
],
rom
->
graphics_id
[
6
],
rom
->
graphics_id
[
7
]);
printk
(
" font start %08x
\n
"
,
rom
->
font_start
);
printk
(
" region list %08x
\n
"
,
rom
->
region_list
);
printk
(
" init_graph %08x
\n
"
,
rom
->
init_graph
);
printk
(
" alternate code type %d
\n
"
,
rom
->
alt_code_type
);
sti_flush
(
dest_start
,
dest_len
);
/* XXX */
}
static
void
__init
sti_cook_fonts
(
struct
sti_cooked_rom
*
cooked_rom
,
struct
sti_rom
*
raw_rom
)
{
struct
sti_rom_font
*
raw_font
;
struct
sti_cooked_font
*
cooked_font
;
struct
sti_rom_font
*
font_start
;
cooked_font
=
kmalloc
(
sizeof
*
cooked_font
,
GFP_KERNEL
);
if
(
!
cooked_font
)
return
;
cooked_rom
->
font_start
=
cooked_font
;
raw_font
=
((
void
*
)
raw_rom
)
+
(
raw_rom
->
font_start
);
font_start
=
raw_font
;
cooked_font
->
raw
=
raw_font
;
static
char
default_sti_path
[
21
];
while
(
raw_font
->
next_font
)
{
raw_font
=
((
void
*
)
font_start
)
+
(
raw_font
->
next_font
);
cooked_font
->
next_font
=
kmalloc
(
sizeof
*
cooked_font
,
GFP_KERNEL
);
if
(
!
cooked_font
->
next_font
)
return
;
static
int
__init
sti_setup
(
char
*
str
)
{
if
(
str
)
strncpy
(
default_sti_path
,
str
,
sizeof
(
default_sti_path
));
return
0
;
}
cooked_font
=
cooked_font
->
next_font
;
/* Assuming the machine has multiple STI consoles (=graphic cards) which
* all get detected by sticon, the user may define with the linux kernel
* parameter sti=<x> which of them will be the initial boot-console.
* <x> is a number between 0 and MAX_STI_ROMS, with 0 as the default
* STI screen.
*/
__setup
(
"sti="
,
sti_setup
);
cooked_font
->
raw
=
raw_font
;
}
cooked_font
->
next_font
=
NULL
;
}
static
int
font_index
,
font_height
,
font_width
;
static
char
__initdata
*
font_name
[
MAX_STI_ROMS
]
=
{
"VGA8x16"
,
};
static
int
__initdata
font_index
[
MAX_STI_ROMS
],
font_height
[
MAX_STI_ROMS
],
font_width
[
MAX_STI_ROMS
];
static
int
__init
sti_font_setup
(
char
*
str
)
{
char
*
x
;
int
i
=
0
;
/* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
* command lines. */
if
((
x
=
strchr
(
str
,
'x'
))
||
(
x
=
strchr
(
str
,
'*'
)))
{
font_height
=
simple_strtoul
(
str
,
NULL
,
0
);
font_width
=
simple_strtoul
(
x
+
1
,
NULL
,
0
);
}
else
{
font_index
=
simple_strtoul
(
str
,
NULL
,
0
);
}
return
0
;
}
/* we accept sti_font=VGA8x16, sti_font=10x20, sti_font=10*20
* or sti_font=7 style command lines. */
while
(
i
<
MAX_STI_ROMS
&&
str
&&
*
str
)
{
if
(
*
str
>=
'0'
&&
*
str
<=
'9'
)
{
if
((
x
=
strchr
(
str
,
'x'
))
||
(
x
=
strchr
(
str
,
'*'
)))
{
font_height
[
i
]
=
simple_strtoul
(
str
,
NULL
,
0
);
font_width
[
i
]
=
simple_strtoul
(
x
+
1
,
NULL
,
0
);
}
else
{
font_index
[
i
]
=
simple_strtoul
(
str
,
NULL
,
0
);
}
}
else
{
font_name
[
i
]
=
str
;
/* fb font name */
}
__setup
(
"sti_font="
,
sti_font_setup
);
if
((
x
=
strchr
(
str
,
','
)))
*
x
++
=
0
;
str
=
x
;
static
int
__init
sti_search_font
(
struct
sti_cooked_rom
*
rom
,
int
height
,
int
width
)
{
struct
sti_cooked_font
*
font
;
int
i
=
0
;
for
(
font
=
rom
->
font_start
;
font
;
font
=
font
->
next_font
,
i
++
)
{
if
((
font
->
raw
->
width
==
width
)
&&
(
font
->
raw
->
height
==
height
))
return
i
;
i
++
;
}
return
0
;
}
static
struct
sti_cooked_font
*
__init
sti_select_font
(
struct
sti_cooked_rom
*
rom
)
{
struct
sti_cooked_font
*
font
;
int
i
;
if
(
font_width
&&
font_height
)
font_index
=
sti_search_font
(
rom
,
font_height
,
font_width
);
/* The optional linux kernel parameter "sti_font" defines which font
* should be used by the sticon driver to draw characters to the screen.
* Possible values are:
* - sti_font=<fb_fontname>:
* <fb_fontname> is the name of one of the linux-kernel built-in
* framebuffer font names (e.g. VGA8x16, SUN22x18).
* This is only available if the fonts have been statically compiled
* in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options.
* - sti_font=<number>
* most STI ROMs have built-in HP specific fonts, which can be selected
* by giving the desired number to the sticon driver.
* NOTE: This number is machine and STI ROM dependend.
* - sti_font=<height>x<width> (e.g. sti_font=16x8)
* <height> and <width> gives hints to the height and width of the
* font which the user wants. The sticon driver will try to use
* a font with this height and width, but if no suitable font is
* found, sticon will use the default 8x8 font.
*/
__setup
(
"sti_font="
,
sti_font_setup
);
for
(
font
=
rom
->
font_start
,
i
=
font_index
;
font
&&
(
i
>
0
);
font
=
font
->
next_font
,
i
--
);
if
(
font
)
return
font
;
else
return
rom
->
font_start
;
}
static
void
__init
sti_dump_globcfg_ext
(
struct
sti_glob_cfg_ext
*
cfg
)
{
printk
(
"monitor %d
\n
"
"in friendly mode: %d
\n
"
"power consumption %d watts
\n
"
"freq ref %d
\n
"
"sti_mem_addr %p
\n
"
,
cfg
->
curr_mon
,
cfg
->
friendly_boot
,
cfg
->
power
,
cfg
->
freq_ref
,
cfg
->
sti_mem_addr
);
}
void
__init
sti_dump_globcfg
(
struct
sti_glob_cfg
*
glob_cfg
)
sti_dump_globcfg
(
struct
sti_glob_cfg
*
glob_cfg
,
unsigned
int
sti_mem_request
)
{
printk
(
"%d text planes
\n
"
struct
sti_glob_cfg_ext
*
cfg
;
DPRINTK
((
KERN_INFO
"%d text planes
\n
"
"%4d x %4d screen resolution
\n
"
"%4d x %4d offscreen
\n
"
"%4d x %4d layout
\n
"
"regions at %08x %08x %08x %08x
\n
"
"regions at %08x %08x %08x %08x
\n
"
"reent_lvl %d
\n
"
"save_addr %
p
\n
"
,
"save_addr %
08x
\n
"
,
glob_cfg
->
text_planes
,
glob_cfg
->
onscreen_x
,
glob_cfg
->
onscreen_y
,
glob_cfg
->
offscreen_x
,
glob_cfg
->
offscreen_y
,
...
...
@@ -358,105 +349,420 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
glob_cfg
->
region_ptrs
[
4
],
glob_cfg
->
region_ptrs
[
5
],
glob_cfg
->
region_ptrs
[
6
],
glob_cfg
->
region_ptrs
[
7
],
glob_cfg
->
reent_lvl
,
glob_cfg
->
save_addr
);
sti_dump_globcfg_ext
(
PTR_STI
(
glob_cfg
->
ext_ptr
));
glob_cfg
->
save_addr
));
/* dump extended cfg */
cfg
=
PTR_STI
(
glob_cfg
->
ext_ptr
);
DPRINTK
((
KERN_INFO
"monitor %d
\n
"
"in friendly mode: %d
\n
"
"power consumption %d watts
\n
"
"freq ref %d
\n
"
"sti_mem_addr %08x (size=%d bytes)
\n
"
,
cfg
->
curr_mon
,
cfg
->
friendly_boot
,
cfg
->
power
,
cfg
->
freq_ref
,
cfg
->
sti_mem_addr
,
sti_mem_request
));
}
static
void
__init
sti_init_glob_cfg
(
struct
sti_struct
*
sti
,
unsigned
long
hpa
,
unsigned
long
rom_address
)
void
__init
sti_dump_outptr
(
struct
sti_struct
*
sti
)
{
DPRINTK
((
KERN_INFO
"%d bits per pixel
\n
"
"%d used bits
\n
"
"%d planes
\n
"
"attributes %08x
\n
"
,
sti
->
outptr
.
bits_per_pixel
,
sti
->
outptr
.
bits_used
,
sti
->
outptr
.
planes
,
sti
->
outptr
.
attributes
));
}
int
__init
sti_init_glob_cfg
(
struct
sti_struct
*
sti
,
unsigned
long
rom_address
,
unsigned
long
hpa
)
{
struct
sti_glob_cfg
*
glob_cfg
;
struct
sti_glob_cfg_ext
*
glob_cfg_ext
;
void
*
save_addr
;
void
*
sti_mem_addr
;
const
int
save_addr_size
=
1024
;
/* XXX */
int
i
;
if
(
!
sti
->
sti_mem_request
)
sti
->
sti_mem_request
=
256
;
/* STI default */
glob_cfg
=
kmalloc
(
sizeof
*
sti
->
glob_cfg
,
GFP_KERNEL
);
glob_cfg_ext
=
kmalloc
(
sizeof
*
glob_cfg_ext
,
GFP_KERNEL
);
save_addr
=
kmalloc
(
1024
/*XXX*/
,
GFP_KERNEL
);
sti_mem_addr
=
kmalloc
(
1024
,
GFP_KERNEL
);
glob_cfg
=
kmalloc
(
sizeof
(
*
sti
->
glob_cfg
)
,
GFP_KERNEL
);
glob_cfg_ext
=
kmalloc
(
sizeof
(
*
glob_cfg_ext
)
,
GFP_KERNEL
);
save_addr
=
kmalloc
(
save_addr_size
,
GFP_KERNEL
);
sti_mem_addr
=
kmalloc
(
sti
->
sti_mem_request
,
GFP_KERNEL
);
if
((
!
glob_cfg
)
||
(
!
glob_cfg_ext
)
||
(
!
save_addr
)
||
(
!
sti_mem_addr
))
return
;
if
(
!
(
glob_cfg
&&
glob_cfg_ext
&&
save_addr
&&
sti_mem_addr
))
return
-
ENOMEM
;
memset
(
glob_cfg
,
0
,
sizeof
*
glob_cfg
);
memset
(
glob_cfg_ext
,
0
,
sizeof
*
glob_cfg_ext
);
memset
(
save_addr
,
0
,
1024
);
memset
(
sti_mem_addr
,
0
,
1024
);
memset
(
glob_cfg
,
0
,
sizeof
(
*
glob_cfg
)
);
memset
(
glob_cfg_ext
,
0
,
sizeof
(
*
glob_cfg_ext
)
);
memset
(
save_addr
,
0
,
save_addr_size
);
memset
(
sti_mem_addr
,
0
,
sti
->
sti_mem_request
);
glob_cfg
->
ext_ptr
=
STI_PTR
(
glob_cfg_ext
);
glob_cfg
->
save_addr
=
STI_PTR
(
save_addr
);
glob_cfg
->
region_ptrs
[
0
]
=
((
sti
->
regions
[
0
]
>>
18
)
<<
12
)
+
rom_address
;
glob_cfg
->
region_ptrs
[
1
]
=
((
sti
->
regions
[
1
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
2
]
=
((
sti
->
regions
[
2
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
3
]
=
((
sti
->
regions
[
3
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
4
]
=
((
sti
->
regions
[
4
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
5
]
=
((
sti
->
regions
[
5
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
6
]
=
((
sti
->
regions
[
6
]
>>
18
)
<<
12
)
+
hpa
;
glob_cfg
->
region_ptrs
[
7
]
=
((
sti
->
regions
[
7
]
>>
18
)
<<
12
)
+
hpa
;
for
(
i
=
0
;
i
<
8
;
i
++
)
{
unsigned
long
newhpa
,
len
;
if
(
sti
->
pd
)
{
unsigned
char
offs
=
sti
->
rm_entry
[
i
];
if
(
offs
==
0
)
continue
;
if
(
offs
!=
PCI_ROM_ADDRESS
&&
(
offs
<
PCI_BASE_ADDRESS_0
||
offs
>
PCI_BASE_ADDRESS_5
))
{
printk
(
KERN_WARNING
"STI pci region maping for region %d (%02x) can't be mapped
\n
"
,
i
,
sti
->
rm_entry
[
i
]);
continue
;
}
newhpa
=
pci_resource_start
(
sti
->
pd
,
(
offs
-
PCI_BASE_ADDRESS_0
)
/
4
);
}
else
newhpa
=
(
i
==
0
)
?
rom_address
:
hpa
;
sti
->
regions_phys
[
i
]
=
REGION_OFFSET_TO_PHYS
(
sti
->
regions
[
i
],
newhpa
);
/* remap virtually */
/* FIXME: add BTLB support if btlb==1 */
len
=
sti
->
regions
[
i
].
region_desc
.
length
*
4096
;
if
(
len
)
glob_cfg
->
region_ptrs
[
i
]
=
(
unsigned
long
)
(
sti
->
regions
[
i
].
region_desc
.
cache
?
ioremap
(
sti
->
regions_phys
[
i
],
len
)
:
ioremap_nocache
(
sti
->
regions_phys
[
i
],
len
)
);
DPRINTK
((
"region #%d: phys %08lx, virt %08x, len=%lukB, "
"btlb=%d, sysonly=%d, cache=%d, last=%d
\n
"
,
i
,
sti
->
regions_phys
[
i
],
glob_cfg
->
region_ptrs
[
i
],
len
/
1024
,
sti
->
regions
[
i
].
region_desc
.
btlb
,
sti
->
regions
[
i
].
region_desc
.
sys_only
,
sti
->
regions
[
i
].
region_desc
.
cache
,
sti
->
regions
[
i
].
region_desc
.
last
));
/* last entry reached ? */
if
(
sti
->
regions
[
i
].
region_desc
.
last
)
break
;
}
if
(
++
i
<
8
&&
sti
->
regions
[
i
].
region
)
printk
(
KERN_WARNING
"%s: *future ptr (0x%8x) not yet supported !
\n
"
,
__FILE__
,
sti
->
regions
[
i
].
region
);
glob_cfg_ext
->
sti_mem_addr
=
STI_PTR
(
sti_mem_addr
);
sti
->
glob_cfg
=
STI_PTR
(
glob_cfg
);
sti
->
glob_cfg
=
glob_cfg
;
return
0
;
}
/* address is a pointer to a word mode or pci rom */
st
atic
struct
sti_struc
t
*
__init
sti_
read_rom
(
unsigned
long
address
)
#ifdef CONFIG_FB
st
ruct
sti_cooked_fon
t
*
__init
sti_
select_fbfont
(
struct
sti_cooked_rom
*
cooked_rom
,
char
*
fbfont_name
)
{
struct
sti_struct
*
ret
=
NULL
;
struct
sti_cooked_rom
*
cooked
=
NULL
;
struct
sti_rom
*
raw
=
NULL
;
unsigned
long
size
;
struct
font_desc
*
fbfont
;
unsigned
int
size
,
bpc
;
void
*
dest
;
struct
sti_rom_font
*
nf
;
struct
sti_cooked_font
*
cooked_font
;
if
(
!
fbfont_name
||
!
strlen
(
fbfont_name
))
return
NULL
;
fbfont
=
find_font
(
fbfont_name
);
if
(
!
fbfont
)
fbfont
=
get_default_font
(
1024
,
768
);
if
(
!
fbfont
)
return
NULL
;
DPRINTK
((
KERN_DEBUG
"selected %dx%d fb-font %s
\n
"
,
fbfont
->
width
,
fbfont
->
height
,
fbfont
->
name
));
bpc
=
((
fbfont
->
width
+
7
)
/
8
)
*
fbfont
->
height
;
size
=
bpc
*
256
;
size
+=
sizeof
(
struct
sti_rom_font
);
nf
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
nf
)
return
NULL
;
memset
(
nf
,
0
,
size
);
nf
->
first_char
=
0
;
nf
->
last_char
=
255
;
nf
->
width
=
fbfont
->
width
;
nf
->
height
=
fbfont
->
height
;
nf
->
font_type
=
STI_FONT_HPROMAN8
;
nf
->
bytes_per_char
=
bpc
;
nf
->
next_font
=
0
;
nf
->
underline_height
=
1
;
nf
->
underline_pos
=
fbfont
->
height
-
nf
->
underline_height
;
dest
=
nf
;
dest
+=
sizeof
(
struct
sti_rom_font
);
memcpy
(
dest
,
fbfont
->
data
,
bpc
*
256
);
cooked_font
=
kmalloc
(
sizeof
(
*
cooked_font
),
GFP_KERNEL
);
if
(
!
cooked_font
)
{
kfree
(
nf
);
return
NULL
;
}
cooked_font
->
raw
=
nf
;
cooked_font
->
next_font
=
NULL
;
ret
=
&
default_sti
;
cooked_rom
->
font_start
=
cooked_font
;
if
(
!
ret
)
goto
out_err
;
return
cooked_font
;
}
#else
struct
sti_cooked_font
*
__init
sti_select_fbfont
(
struct
sti_cooked_rom
*
cooked_rom
,
char
*
fbfont_name
)
{
return
NULL
;
}
#endif
cooked
=
kmalloc
(
sizeof
*
cooked
,
GFP_KERNEL
);
raw
=
kmalloc
(
sizeof
*
raw
,
GFP_KERNEL
);
struct
sti_cooked_font
*
__init
sti_select_font
(
struct
sti_cooked_rom
*
rom
,
int
(
*
search_font_fnc
)
(
struct
sti_cooked_rom
*
,
int
,
int
)
)
{
struct
sti_cooked_font
*
font
;
int
i
;
int
index
=
num_sti_roms
;
/* check for framebuffer-font first */
if
((
font
=
sti_select_fbfont
(
rom
,
font_name
[
index
])))
return
font
;
if
(
font_width
[
index
]
&&
font_height
[
index
])
font_index
[
index
]
=
search_font_fnc
(
rom
,
font_height
[
index
],
font_width
[
index
]);
for
(
font
=
rom
->
font_start
,
i
=
font_index
[
index
];
font
&&
(
i
>
0
);
font
=
font
->
next_font
,
i
--
);
if
(
font
)
return
font
;
else
return
rom
->
font_start
;
}
static
void
__init
sti_dump_rom
(
struct
sti_rom
*
rom
)
{
printk
(
KERN_INFO
"STI id %04x-%04x, conforms to spec rev. %d.%02x
\n
"
,
rom
->
graphics_id
[
0
],
rom
->
graphics_id
[
1
],
rom
->
revno
[
0
]
>>
4
,
rom
->
revno
[
0
]
&
0x0f
);
DPRINTK
((
" supports %d monitors
\n
"
,
rom
->
num_mons
));
DPRINTK
((
" font start %08x
\n
"
,
rom
->
font_start
));
DPRINTK
((
" region list %08x
\n
"
,
rom
->
region_list
));
DPRINTK
((
" init_graph %08x
\n
"
,
rom
->
init_graph
));
DPRINTK
((
" bus support %02x
\n
"
,
rom
->
bus_support
));
DPRINTK
((
" ext bus support %02x
\n
"
,
rom
->
ext_bus_support
));
DPRINTK
((
" alternate code type %d
\n
"
,
rom
->
alt_code_type
));
}
static
int
__init
sti_cook_fonts
(
struct
sti_cooked_rom
*
cooked_rom
,
struct
sti_rom
*
raw_rom
)
{
struct
sti_rom_font
*
raw_font
,
*
font_start
;
struct
sti_cooked_font
*
cooked_font
;
if
(
!
(
raw
&&
cooked
))
goto
out_err
;
cooked_font
=
kmalloc
(
sizeof
(
*
cooked_font
),
GFP_KERNEL
);
if
(
!
cooked_font
)
return
0
;
/* reallocate raw */
sti_rom_copy
(
address
,
0
,
sizeof
*
raw
,
raw
);
cooked_rom
->
font_start
=
cooked_font
;
dump_sti_rom
(
raw
);
raw_font
=
((
void
*
)
raw_rom
)
+
(
raw_rom
->
font_start
);
size
=
raw
->
last_addr
;
/* kfree(raw); */
raw
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
raw
)
goto
out_err
;
sti_rom_copy
(
address
,
0
,
size
,
raw
);
font_start
=
raw_font
;
cooked_font
->
raw
=
raw_font
;
sti_cook_fonts
(
cooked
,
raw
);
#if 0
sti_cook_regions(cooked, raw);
sti_cook_functions(cooked, raw);
#endif
while
(
raw_font
->
next_font
)
{
raw_font
=
((
void
*
)
font_start
)
+
(
raw_font
->
next_font
);
cooked_font
->
next_font
=
kmalloc
(
sizeof
(
*
cooked_font
),
GFP_KERNEL
);
if
(
!
cooked_font
->
next_font
)
return
1
;
cooked_font
=
cooked_font
->
next_font
;
cooked_font
->
raw
=
raw_font
;
}
cooked_font
->
next_font
=
NULL
;
return
1
;
}
static
int
__init
sti_search_font
(
struct
sti_cooked_rom
*
rom
,
int
height
,
int
width
)
{
struct
sti_cooked_font
*
font
;
int
i
=
0
;
for
(
font
=
rom
->
font_start
;
font
;
font
=
font
->
next_font
,
i
++
)
{
if
((
font
->
raw
->
width
==
width
)
&&
(
font
->
raw
->
height
==
height
))
return
i
;
}
return
0
;
}
#define BMODE_RELOCATE(offset) offset = (offset) / 4;
#define BMODE_LAST_ADDR_OFFS 0x50
static
void
*
__init
sti_bmode_font_raw
(
struct
sti_cooked_font
*
f
)
{
unsigned
char
*
n
,
*
p
,
*
q
;
int
size
=
f
->
raw
->
bytes_per_char
*
256
+
sizeof
(
struct
sti_rom_font
);
n
=
kmalloc
(
4
*
size
,
GFP_KERNEL
);
if
(
!
n
)
return
NULL
;
memset
(
n
,
0
,
4
*
size
);
p
=
n
+
3
;
q
=
(
unsigned
char
*
)
f
->
raw
;
while
(
size
--
)
{
*
p
=
*
q
++
;
p
+=
4
;
}
return
n
+
3
;
}
if
(
raw
->
region_list
)
{
ret
->
regions
=
kmalloc
(
32
,
GFP_KERNEL
);
/* FIXME */
static
void
__init
sti_bmode_rom_copy
(
unsigned
long
base
,
unsigned
long
count
,
void
*
dest
)
{
unsigned
long
dest_len
=
count
;
unsigned
long
dest_start
=
(
unsigned
long
)
dest
;
memcpy
(
ret
->
regions
,
((
void
*
)
raw
)
+
raw
->
region_list
,
32
);
while
(
count
)
{
count
--
;
*
(
u8
*
)
dest
=
__raw_readl
(
base
);
base
+=
4
;
dest
++
;
}
sti_flush
(
dest_start
,
dest_len
);
/* XXX */
}
address
=
virt_to_phys
(
raw
);
struct
sti_rom
*
__init
sti_get_bmode_rom
(
unsigned
long
address
)
{
struct
sti_rom
*
raw
;
u32
size
;
struct
sti_rom_font
*
raw_font
,
*
font_start
;
sti_bmode_rom_copy
(
address
+
BMODE_LAST_ADDR_OFFS
,
sizeof
(
size
),
&
size
);
size
=
(
size
+
3
)
/
4
;
raw
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
raw
)
{
sti_bmode_rom_copy
(
address
,
size
,
raw
);
memmove
(
&
raw
->
res004
,
&
raw
->
type
[
0
],
0x3c
);
raw
->
type
[
3
]
=
raw
->
res004
;
BMODE_RELOCATE
(
raw
->
region_list
);
BMODE_RELOCATE
(
raw
->
font_start
);
BMODE_RELOCATE
(
raw
->
init_graph
);
BMODE_RELOCATE
(
raw
->
state_mgmt
);
BMODE_RELOCATE
(
raw
->
font_unpmv
);
BMODE_RELOCATE
(
raw
->
block_move
);
BMODE_RELOCATE
(
raw
->
inq_conf
);
raw_font
=
((
void
*
)
raw
)
+
raw
->
font_start
;
font_start
=
raw_font
;
while
(
raw_font
->
next_font
)
{
BMODE_RELOCATE
(
raw_font
->
next_font
);
raw_font
=
((
void
*
)
font_start
)
+
raw_font
->
next_font
;
}
}
return
raw
;
}
ret
->
font_unpmv
=
address
+
(
raw
->
font_unpmv
&
0x03ffffff
);
ret
->
block_move
=
address
+
(
raw
->
block_move
&
0x03ffffff
);
ret
->
init_graph
=
address
+
(
raw
->
init_graph
&
0x03ffffff
);
ret
->
inq_conf
=
address
+
(
raw
->
inq_conf
&
0x03ffffff
);
struct
sti_rom
*
__init
sti_get_wmode_rom
(
unsigned
long
address
)
{
struct
sti_rom
*
raw
;
unsigned
long
size
;
/* read the ROM size directly from the struct in ROM */
size
=
__raw_readl
(
address
+
offsetof
(
struct
sti_rom
,
last_addr
));
ret
->
rom
=
cooked
;
ret
->
rom
->
raw
=
raw
;
raw
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
raw
)
sti_rom_copy
(
address
,
size
,
raw
);
ret
->
font
=
(
struct
sti_rom_font
*
)
virt_to_phys
(
sti_select_font
(
ret
->
rom
)
->
raw
);
return
raw
;
}
return
ret
;
int
__init
sti_read_rom
(
int
wordmode
,
struct
sti_struct
*
sti
,
unsigned
long
address
)
{
struct
sti_cooked_rom
*
cooked
;
struct
sti_rom
*
raw
=
NULL
;
cooked
=
kmalloc
(
sizeof
*
cooked
,
GFP_KERNEL
);
if
(
!
cooked
)
goto
out_err
;
if
(
wordmode
)
raw
=
sti_get_wmode_rom
(
address
);
else
raw
=
sti_get_bmode_rom
(
address
);
if
(
!
raw
)
goto
out_err
;
if
(
!
sti_cook_fonts
(
cooked
,
raw
))
{
printk
(
KERN_ERR
"No font found for STI at %08lx
\n
"
,
address
);
goto
out_err
;
}
if
(
raw
->
region_list
)
memcpy
(
sti
->
regions
,
((
void
*
)
raw
)
+
raw
->
region_list
,
sizeof
(
sti
->
regions
));
address
=
(
unsigned
long
)
STI_PTR
(
raw
);
sti
->
font_unpmv
=
address
+
(
raw
->
font_unpmv
&
0x03ffffff
);
sti
->
block_move
=
address
+
(
raw
->
block_move
&
0x03ffffff
);
sti
->
init_graph
=
address
+
(
raw
->
init_graph
&
0x03ffffff
);
sti
->
inq_conf
=
address
+
(
raw
->
inq_conf
&
0x03ffffff
);
sti
->
rom
=
cooked
;
sti
->
rom
->
raw
=
raw
;
sti
->
font
=
sti_select_font
(
sti
->
rom
,
sti_search_font
);
sti
->
font_width
=
sti
->
font
->
raw
->
width
;
sti
->
font_height
=
sti
->
font
->
raw
->
height
;
if
(
!
wordmode
)
sti
->
font
->
raw
=
sti_bmode_font_raw
(
sti
->
font
);
sti
->
sti_mem_request
=
raw
->
sti_mem_req
;
sti
->
graphics_id
[
0
]
=
raw
->
graphics_id
[
0
];
sti
->
graphics_id
[
1
]
=
raw
->
graphics_id
[
1
];
sti_dump_rom
(
raw
);
return
1
;
out_err:
if
(
raw
)
...
...
@@ -464,138 +770,290 @@ sti_read_rom(unsigned long address)
if
(
cooked
)
kfree
(
cooked
);
return
NULL
;
return
0
;
}
static
struct
sti_struct
*
__init
sti_try_rom
(
unsigned
long
address
,
unsigned
long
hpa
)
sti_try_rom
_generic
(
unsigned
long
address
,
unsigned
long
hpa
,
struct
pci_dev
*
pd
)
{
struct
sti_struct
*
sti
=
NULL
;
u16
sig
;
struct
sti_struct
*
sti
;
int
ok
;
u32
sig
;
if
(
num_sti_roms
>=
MAX_STI_ROMS
)
{
printk
(
KERN_WARNING
"maximum number of STI ROMS reached !
\n
"
);
return
NULL
;
}
sti
=
kmalloc
(
sizeof
(
*
sti
),
GFP_KERNEL
);
if
(
!
sti
)
{
printk
(
KERN_ERR
"Not enough memory !
\n
"
);
return
NULL
;
}
memset
(
sti
,
0
,
sizeof
(
*
sti
));
sti
->
lock
=
SPIN_LOCK_UNLOCKED
;
test_rom:
/* if we can't read the ROM, bail out early. Not being able
* to read the hpa is okay, for romless sti */
if
(
pdc_add_valid
((
void
*
)
address
))
return
NULL
;
printk
(
"found potential STI ROM at %08lx
\n
"
,
address
);
sig
=
le16_to_cpu
(
gsc_readw
(
address
));
if
(
pdc_add_valid
(
address
))
goto
out_err
;
if
((
sig
==
0x55aa
)
||
(
sig
==
0xaa55
))
{
address
+=
le32_to_cpu
(
gsc_readl
(
address
+
8
));
printk
(
"sig %04x, PCI STI ROM at %08lx
\n
"
,
sig
,
address
);
sig
=
__raw_readl
(
address
);
/* check for a PCI ROM structure */
if
((
le32_to_cpu
(
sig
)
==
0xaa55
))
{
unsigned
int
i
,
rm_offset
;
u32
*
rm
;
i
=
__raw_readl
(
address
+
0x04
);
if
(
i
!=
1
)
{
/* The ROM could have multiple architecture
* dependent images (e.g. i386, parisc,...) */
printk
(
KERN_WARNING
"PCI ROM is not a STI ROM type image (0x%8x)
\n
"
,
i
);
goto
out_err
;
}
sti
->
pd
=
pd
;
i
=
__raw_readl
(
address
+
0x0c
);
DPRINTK
((
"PCI ROM size (from header) = %d kB
\n
"
,
le16_to_cpu
(
i
>>
16
)
*
512
/
1024
));
rm_offset
=
le16_to_cpu
(
i
&
0xffff
);
if
(
rm_offset
)
{
/* read 16 bytes from the pci region mapper array */
rm
=
(
u32
*
)
&
sti
->
rm_entry
;
*
rm
++
=
__raw_readl
(
address
+
rm_offset
+
0x00
);
*
rm
++
=
__raw_readl
(
address
+
rm_offset
+
0x04
);
*
rm
++
=
__raw_readl
(
address
+
rm_offset
+
0x08
);
*
rm
++
=
__raw_readl
(
address
+
rm_offset
+
0x0c
);
DPRINTK
((
"PCI region Mapper offset = %08x: "
,
rm_offset
));
for
(
i
=
0
;
i
<
16
;
i
++
)
DPRINTK
((
"%02x "
,
sti
->
rm_entry
[
i
]));
DPRINTK
((
"
\n
"
));
}
address
+=
le32_to_cpu
(
__raw_readl
(
address
+
8
));
DPRINTK
((
"sig %04x, PCI STI ROM at %08lx
\n
"
,
sig
,
address
));
goto
test_rom
;
}
if
((
sig
&
0xff
)
==
0x01
)
{
printk
(
"STI byte mode ROM at %08lx, ignored
\n
"
,
address
);
sti
=
NULL
;
ok
=
0
;
if
((
sig
&
0xff
)
==
0x01
)
{
printk
(
KERN_INFO
"STI byte mode ROM at %08lx, hpa at %08lx
\n
"
,
address
,
hpa
);
ok
=
sti_read_rom
(
0
,
sti
,
address
);
}
if
(
sig
==
0x0303
)
{
printk
(
"STI word mode ROM at %08lx
\n
"
,
address
);
sti
=
sti_read_rom
(
address
);
if
((
sig
&
0xffff
)
==
0x0303
)
{
printk
(
KERN_INFO
"STI word mode ROM at %08lx, hpa at %08lx
\n
"
,
address
,
hpa
);
ok
=
sti_read_rom
(
1
,
sti
,
address
);
}
if
(
!
sti
)
return
NULL
;
if
(
!
ok
)
goto
out_err
;
/* this is hacked. We need a better way to find out the HPA for
* romless STI (eg search for the graphics devices we know about
* by sversion) */
if
(
!
pdc_add_valid
((
void
*
)
0xf5000000
))
printk
(
"f4000000 g
\n
"
);
if
(
!
pdc_add_valid
((
void
*
)
0xf7000000
))
printk
(
"f6000000 g
\n
"
);
if
(
!
pdc_add_valid
((
void
*
)
0xf9000000
))
printk
(
"f8000000 g
\n
"
);
if
(
!
pdc_add_valid
((
void
*
)
0xfb000000
))
printk
(
"fa000000 g
\n
"
);
sti_init_glob_cfg
(
sti
,
hpa
,
address
);
if
(
sti_init_glob_cfg
(
sti
,
address
,
hpa
))
goto
out_err
;
/* not enough memory */
/* disable STI PCI ROM. ROM and card RAM overlap and
* leaving it enabled would force HPMCs
*/
if
(
sti
->
pd
)
{
unsigned
long
rom_base
;
rom_base
=
pci_resource_start
(
sti
->
pd
,
PCI_ROM_RESOURCE
);
pci_write_config_dword
(
sti
->
pd
,
PCI_ROM_ADDRESS
,
rom_base
&
~
PCI_ROM_ADDRESS_ENABLE
);
DPRINTK
((
KERN_DEBUG
"STI PCI ROM disabled
\n
"
));
}
sti_init_graph
(
sti
);
if
(
sti_init_graph
(
sti
))
goto
out_err
;
sti_inq_conf
(
sti
);
sti_dump_globcfg
(
PTR_STI
(
sti
->
glob_cfg
));
sti_dump_globcfg
(
sti
->
glob_cfg
,
sti
->
sti_mem_request
);
sti_dump_outptr
(
sti
);
printk
(
KERN_INFO
"STI device: %s
\n
"
,
sti
->
outptr
.
dev_name
);
sti_roms
[
num_sti_roms
]
=
sti
;
num_sti_roms
++
;
return
sti
;
out_err:
kfree
(
sti
);
return
NULL
;
}
static
unsigned
long
sti_address
;
static
unsigned
long
sti_hpa
;
static
void
__init
sticore_check_for_default_sti
(
struct
sti_struct
*
sti
,
char
*
path
)
{
if
(
strcmp
(
path
,
default_sti_path
)
==
0
)
default_sti
=
sti
;
}
/* XXX: should build a list of STI ROMs */
struct
sti_struct
*
__init
sti_init_roms
(
void
)
/*
* on newer systems PDC gives the address of the ROM
* in the additional address field addr[1] while on
* older Systems the PDC stores it in page0->proc_sti
*/
static
int
__init
sticore_pa_init
(
struct
parisc_device
*
dev
)
{
struct
sti_struct
*
tmp
=
NULL
,
*
sti
=
NULL
;
unsigned
long
rom
=
0
;
char
pa_path
[
21
];
struct
sti_struct
*
sti
=
NULL
;
if
(
dev
->
num_addrs
)
{
rom
=
dev
->
addr
[
0
];
}
if
(
!
rom
)
{
rom
=
dev
->
hpa
;
DPRINTK
((
KERN_DEBUG
"Trying STI ROM at %08lx, hpa at %08lx
\n
"
,
rom
,
dev
->
hpa
));
sti
=
sti_try_rom_generic
(
rom
,
dev
->
hpa
,
NULL
);
rom
=
PAGE0
->
proc_sti
;
}
if
(
!
sti
)
{
DPRINTK
((
KERN_DEBUG
"Trying STI ROM at %08lx, hpa at %08lx
\n
"
,
rom
,
dev
->
hpa
));
sti
=
sti_try_rom_generic
(
rom
,
dev
->
hpa
,
NULL
);
}
if
(
!
sti
)
return
1
;
print_pa_hwpath
(
dev
,
pa_path
);
sticore_check_for_default_sti
(
sti
,
pa_path
);
return
0
;
}
/* handle the command line */
if
(
sti_address
&&
sti_hpa
)
{
return
sti_try_rom
(
sti_address
,
sti_hpa
);
static
int
__devinit
sticore_pci_init
(
struct
pci_dev
*
pd
,
const
struct
pci_device_id
*
ent
)
{
#ifdef CONFIG_PCI
unsigned
long
fb_base
,
rom_base
;
unsigned
int
fb_len
,
rom_len
;
struct
sti_struct
*
sti
;
pci_enable_device
(
pd
);
fb_base
=
pci_resource_start
(
pd
,
0
);
fb_len
=
pci_resource_len
(
pd
,
0
);
rom_base
=
pci_resource_start
(
pd
,
PCI_ROM_RESOURCE
);
rom_len
=
pci_resource_len
(
pd
,
PCI_ROM_RESOURCE
);
if
(
rom_base
)
{
pci_write_config_dword
(
pd
,
PCI_ROM_ADDRESS
,
rom_base
|
PCI_ROM_ADDRESS_ENABLE
);
DPRINTK
((
KERN_DEBUG
"STI PCI ROM enabled at 0x%08lx
\n
"
,
rom_base
));
}
/* 712, 715, some other boxes don't have a separate STI ROM,
* but use part of the regular flash */
if
(
PAGE0
->
proc_sti
)
{
printk
(
"STI ROM from PDC at %08x
\n
"
,
PAGE0
->
proc_sti
);
if
(
!
pdc_add_valid
((
void
*
)
0xf9000000
))
sti
=
sti_try_rom
(
PAGE0
->
proc_sti
,
0xf8000000
);
else
if
(
!
pdc_add_valid
((
void
*
)
0xf5000000
))
sti
=
sti_try_rom
(
PAGE0
->
proc_sti
,
0xf4000000
);
else
if
(
!
pdc_add_valid
((
void
*
)
0xf7000000
))
sti
=
sti_try_rom
(
PAGE0
->
proc_sti
,
0xf6000000
);
else
if
(
!
pdc_add_valid
((
void
*
)
0xfb000000
))
sti
=
sti_try_rom
(
PAGE0
->
proc_sti
,
0xfa000000
);
printk
(
KERN_INFO
"STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)
\n
"
,
rom_base
,
rom_len
/
1024
,
fb_base
,
fb_len
/
1024
/
1024
);
DPRINTK
((
KERN_DEBUG
"Trying PCI STI ROM at %08lx, PCI hpa at %08lx
\n
"
,
rom_base
,
fb_base
));
sti
=
sti_try_rom_generic
(
rom_base
,
fb_base
,
pd
);
if
(
sti
)
{
char
pa_path
[
30
];
print_pci_hwpath
(
pd
,
pa_path
);
sticore_check_for_default_sti
(
sti
,
pa_path
);
}
if
(
!
sti
)
{
printk
(
KERN_WARNING
"Unable to handle STI device '%s'
\n
"
,
pd
->
dev
.
name
);
return
-
ENODEV
;
}
#endif
/* CONFIG_PCI */
return
0
;
}
/* standard locations for GSC graphic devices */
if
(
!
pdc_add_valid
((
void
*
)
0xf4000000
))
tmp
=
sti_try_rom
(
0xf4000000
,
0xf4000000
);
sti
=
tmp
?
tmp
:
sti
;
if
(
!
pdc_add_valid
((
void
*
)
0xf6000000
))
tmp
=
sti_try_rom
(
0xf6000000
,
0xf6000000
);
sti
=
tmp
?
tmp
:
sti
;
if
(
!
pdc_add_valid
((
void
*
)
0xf8000000
))
tmp
=
sti_try_rom
(
0xf8000000
,
0xf8000000
);
sti
=
tmp
?
tmp
:
sti
;
if
(
!
pdc_add_valid
((
void
*
)
0xfa000000
))
tmp
=
sti_try_rom
(
0xfa000000
,
0xfa000000
);
sti
=
tmp
?
tmp
:
sti
;
return
sti
;
static
void
__devexit
sticore_pci_remove
(
struct
pci_dev
*
pd
)
{
BUG
();
}
static
int
__init
sti_setup
(
char
*
str
)
#define PCI_DEVICE_ID_VISUALIZE_EG 0x1005
#define PCI_DEVICE_ID_VISUALIZE_FX 0x1008
#define PCI_DEVICE_ID_VISUALIZE_FX_NEW 0x108b
static
struct
pci_device_id
sti_pci_tbl
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_HP
,
PCI_DEVICE_ID_VISUALIZE_EG
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
PCI_VENDOR_ID_HP
,
PCI_DEVICE_ID_VISUALIZE_FX
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
PCI_VENDOR_ID_HP
,
PCI_DEVICE_ID_VISUALIZE_FX_NEW
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
0
},
{
0
,
}
/* terminate list */
};
MODULE_DEVICE_TABLE
(
pci
,
sti_pci_tbl
);
static
struct
pci_driver
pci_sti_driver
=
{
.
name
=
"sti (pci)"
,
.
id_table
=
sti_pci_tbl
,
.
probe
=
sticore_pci_init
,
.
remove
=
sticore_pci_remove
,
};
static
struct
parisc_device_id
sti_pa_tbl
[]
=
{
{
HPHW_FIO
,
HVERSION_REV_ANY_ID
,
HVERSION_ANY_ID
,
0x00077
},
{
HPHW_FIO
,
HVERSION_REV_ANY_ID
,
HVERSION_ANY_ID
,
0x00085
},
{
0
,
}
};
struct
parisc_driver
pa_sti_driver
=
{
.
name
=
"sti (native)"
,
.
id_table
=
sti_pa_tbl
,
.
probe
=
sticore_pa_init
,
};
struct
sti_struct
*
__init
sti_init_roms
(
void
)
{
char
*
en
d
;
static
int
initialize
d
;
if
(
strcmp
(
str
,
"pdc"
)
==
0
)
{
sti_address
=
PAGE0
->
proc_sti
;
if
(
initialized
)
goto
out
;
return
1
;
}
else
{
sti_address
=
simple_strtoul
(
str
,
&
end
,
16
);
printk
(
KERN_INFO
"STI GSC/PCI graphics driver version %s
\n
"
,
STI_DRIVERVERSION
);
if
((
end
==
str
)
||
(
sti_address
<
0xf0000000
))
{
sti_address
=
0
;
return
0
;
}
/* Register drivers for native & PCI cards */
register_parisc_driver
(
&
pa_sti_driver
);
pci_module_init
(
&
pci_sti_driver
);
sti_hpa
=
sti_address
;
/* if we didn't find the given default sti, take the first one */
if
(
!
default_sti
)
default_sti
=
sti_roms
[
0
];
return
1
;
out:
/* return default STI if available */
if
(
num_sti_roms
&&
default_sti
&&
default_sti
->
init_graph
)
{
initialized
=
1
;
return
default_sti
;
}
return
0
;
return
NULL
;
}
__setup
(
"sti="
,
sti_setup
);
MODULE_LICENSE
(
"GPL"
);
/*
* index = 0 gives default sti
* index > 0 gives other stis in detection order
*/
struct
sti_struct
*
__init
sti_get_rom
(
int
index
)
{
int
i
;
if
(
index
==
0
)
return
default_sti
;
i
=
-
1
;
while
(
index
>
0
)
{
i
++
;
if
(
i
>
num_sti_roms
)
return
NULL
;
if
(
sti_roms
[
i
]
==
default_sti
)
continue
;
index
--
;
}
return
sti_roms
[
i
];
}
drivers/video/fbmon.c
View file @
8d7c2813
...
...
@@ -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
drivers/video/i810/i810_main.c
View file @
8d7c2813
...
...
@@ -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>
...
...
drivers/video/riva/fbdev.c.new
deleted
100644 → 0
View file @
0e2e212c
/*
* linux/drivers/video/riva/fbdev.c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
*
* Copyright 1999-2000 Jeff Garzik
*
* Contributors:
*
* Ani Joshi: Lots of debugging and cleanup work, really helped
* get the driver going
*
* Ferenc Bakonyi: Bug fixes, cleanup, modularization
*
* Jindrich Makovicka: Accel code help, hw cursor, mtrr
*
* Paul Richards: Bug fixes and updates.
*
* Initial template from skeletonfb.c, created 28 Dec 1997 by Geert Uytterhoeven
* Includes riva_hw.c from nVidia, see copyright below.
* KGI code provided the basis for state storage, init, and mode switching.
*
* 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.
*
* Known bugs and issues:
* restoring text mode fails
* doublescan modes are broken
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
#include "rivafb.h"
#include "nvreg.h"
#ifndef CONFIG_PCI /* sanity check */
#error This driver requires PCI support.
#endif
/* version number of this driver */
#define RIVAFB_VERSION "0.9.4"
/* ------------------------------------------------------------------------- *
*
* various helpful macros and constants
*
* ------------------------------------------------------------------------- */
#undef RIVAFBDEBUG
#ifdef RIVAFBDEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
#else
#define DPRINTK(fmt, args...)
#endif
#ifndef RIVA_NDEBUG
#define assert(expr) \
if(!(expr)) { \
printk( "Assertion failed! %s,%s,%s,line=%d\n",\
#expr,__FILE__,__FUNCTION__,__LINE__); \
BUG(); \
}
#else
#define assert(expr)
#endif
#define PFX "rivafb: "
/* macro that allows you to set overflow bits */
#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))
#define SetBit(n) (1<<(n))
#define Set8Bits(value) ((value)&0xff)
/* HW cursor parameters */
#define MAX_CURS 32
/* ------------------------------------------------------------------------- *
*
* prototypes
*
* ------------------------------------------------------------------------- */
static int rivafb_blank(int blank, struct fb_info *info);
extern inline void wait_for_idle(struct riva_par *par);
/* ------------------------------------------------------------------------- *
*
* card identification
*
* ------------------------------------------------------------------------- */
enum riva_chips {
CH_RIVA_128 = 0,
CH_RIVA_TNT,
CH_RIVA_TNT2,
CH_RIVA_UTNT2,
CH_RIVA_VTNT2,
CH_RIVA_UVTNT2,
CH_RIVA_ITNT2,
CH_GEFORCE_SDR,
CH_GEFORCE_DDR,
CH_QUADRO,
CH_GEFORCE2_MX,
CH_GEFORCE2_MX2,
CH_GEFORCE2_GO,
CH_QUADRO2_MXR,
CH_GEFORCE2_GTS,
CH_GEFORCE2_GTS2,
CH_GEFORCE2_ULTRA,
CH_QUADRO2_PRO,
CH_GEFORCE4_MX_460,
CH_GEFORCE4_MX_440,
CH_GEFORCE4_MX_420,
CH_GEFORCE4_440_GO,
CH_GEFORCE4_420_GO,
CH_GEFORCE4_420_GO_M32,
CH_QUADRO4_500XGL,
CH_GEFORCE4_440_GO_M64,
CH_QUADRO4_200,
CH_QUADRO4_550XGL,
CH_QUADRO4_500_GOGL,
CH_IGEFORCE2,
CH_GEFORCE3,
CH_GEFORCE3_1,
CH_GEFORCE3_2,
CH_QUADRO_DDC,
CH_GEFORCE4_TI_4600,
CH_GEFORCE4_TI_4400,
CH_GEFORCE4_TI_4200,
CH_QUADRO4_900XGL,
CH_QUADRO4_750XGL,
CH_QUADRO4_700XGL
};
/* directly indexed by riva_chips enum, above */
static struct riva_chip_info {
const char *name;
unsigned arch_rev;
} riva_chip_info[] __devinitdata = {
{ "RIVA-128", NV_ARCH_03 },
{ "RIVA-TNT", NV_ARCH_04 },
{ "RIVA-TNT2", NV_ARCH_04 },
{ "RIVA-UTNT2", NV_ARCH_04 },
{ "RIVA-VTNT2", NV_ARCH_04 },
{ "RIVA-UVTNT2", NV_ARCH_04 },
{ "RIVA-ITNT2", NV_ARCH_04 },
{ "GeForce-SDR", NV_ARCH_10},
{ "GeForce-DDR", NV_ARCH_10},
{ "Quadro", NV_ARCH_10},
{ "GeForce2-MX", NV_ARCH_10},
{ "GeForce2-MX", NV_ARCH_10},
{ "GeForce2-GO", NV_ARCH_10},
{ "Quadro2-MXR", NV_ARCH_10},
{ "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-GTS", NV_ARCH_10},
{ "GeForce2-ULTRA", NV_ARCH_10},
{ "Quadro2-PRO", NV_ARCH_10},
{ "GeForce4-MX-460", NV_ARCH_20 },
{ "GeForce4-MX-440", NV_ARCH_20 },
{ "GeForce4-MX-420", NV_ARCH_20 },
{ "GeForce4-440-GO", NV_ARCH_20 },
{ "GeForce4-420-GO", NV_ARCH_20 },
{ "GeForce4-420-GO-M32", NV_ARCH_20 },
{ "Quadro4-500-XGL", NV_ARCH_20 },
{ "GeForce4-440-GO-M64", NV_ARCH_20 },
{ "Quadro4-200", NV_ARCH_20 },
{ "Quadro4-550-XGL", NV_ARCH_20 },
{ "Quadro4-500-GOGL", NV_ARCH_20 },
{ "GeForce2", NV_ARCH_20 },
{ "GeForce3", NV_ARCH_20 },
{ "GeForce3 Ti 200", NV_ARCH_20 },
{ "GeForce3 Ti 500", NV_ARCH_20 },
{ "Quadro DDC", NV_ARCH_20 },
{ "GeForce4 Ti 4600", NV_ARCH_20 },
{ "GeForce4 Ti 4400", NV_ARCH_20 },
{ "GeForce4 Ti 4200", NV_ARCH_20 },
{ "Quadro4-900-XGL", NV_ARCH_20 },
{ "Quadro4-750-XGL", NV_ARCH_20 },
{ "Quadro4-700-XGL", NV_ARCH_20 }
};
static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_NVIDIA_SGS, PCI_DEVICE_ID_NVIDIA_SGS_RIVA128,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_128 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_TNT2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_TNT2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UTNT2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_UTNT2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_VTNT2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_UVTNT2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_VTNT2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_ITNT2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_RIVA_ITNT2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_SDR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_SDR },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_DDR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE_DDR },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_MX2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_MX2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_MXR,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_MXR },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_GTS2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_GTS2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE2_ULTRA,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE2_ULTRA },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO2_PRO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_460,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_460 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_440,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_440 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_MX_420,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_MX_420 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_420_GO_M32,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_420_GO_M32 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500XGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500XGL },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_440_GO_M64,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_440_GO_M64 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_200,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_200 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_550XGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_550XGL },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_500_GOGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_500_GOGL },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_IGEFORCE2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_IGEFORCE2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_1,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_1 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE3_2,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE3_2 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO_DDC,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO_DDC },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4600,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4600 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4400,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4400 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4200,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_GEFORCE4_TI_4200 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_900XGL },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_750XGL },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, CH_QUADRO4_700XGL },
{ 0, } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, rivafb_pci_tbl);
/* ------------------------------------------------------------------------- *
*
* global variables
*
* ------------------------------------------------------------------------- */
/* command line data, set in rivafb_setup() */
static u32 pseudo_palette[17];
#ifdef CONFIG_MTRR
static char nomtrr __initdata = 0;
#endif
#ifndef MODULE
static char *mode_option __initdata = NULL;
#endif
static struct fb_fix_screeninfo rivafb_fix = {
id: "nVidia",
type: FB_TYPE_PACKED_PIXELS,
xpanstep: 1,
ypanstep: 1,
};
static struct fb_var_screeninfo rivafb_default_var = {
xres: 640,
yres: 480,
xres_virtual: 640,
yres_virtual: 480,
xoffset: 0,
yoffset: 0,
bits_per_pixel: 8,
grayscale: 0,
red: {0, 6, 0},
green: {0, 6, 0},
blue: {0, 6, 0},
transp: {0, 0, 0},
nonstd: 0,
activate: 0,
height: -1,
width: -1,
accel_flags: FB_ACCELF_TEXT,
pixclock: 39721,
left_margin: 40,
right_margin: 24,
upper_margin: 32,
lower_margin: 11,
hsync_len: 96,
vsync_len: 2,
sync: 0,
vmode: FB_VMODE_NONINTERLACED
};
/* from GGI */
static const struct riva_regs reg_template = {
{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, /* ATTR */
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x41, 0x01, 0x0F, 0x00, 0x00},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* CRT */
0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE3, /* 0x10 */
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x30 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, /* 0x40 */
},
{0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, /* GRA */
0xFF},
{0x03, 0x01, 0x0F, 0x00, 0x0E}, /* SEQ */
0xEB /* MISC */
};
/* ------------------------------------------------------------------------- *
*
* MMIO access macros
*
* ------------------------------------------------------------------------- */
static inline void CRTCout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(par->riva.PCIO, 0x3d4, index);
VGA_WR08(par->riva.PCIO, 0x3d5, val);
}
static inline unsigned char CRTCin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(par->riva.PCIO, 0x3d4, index);
return (VGA_RD08(par->riva.PCIO, 0x3d5));
}
static inline void GRAout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(par->riva.PVIO, 0x3ce, index);
VGA_WR08(par->riva.PVIO, 0x3cf, val);
}
static inline unsigned char GRAin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(par->riva.PVIO, 0x3ce, index);
return (VGA_RD08(par->riva.PVIO, 0x3cf));
}
static inline void SEQout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(par->riva.PVIO, 0x3c4, index);
VGA_WR08(par->riva.PVIO, 0x3c5, val);
}
static inline unsigned char SEQin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(par->riva.PVIO, 0x3c4, index);
return (VGA_RD08(par->riva.PVIO, 0x3c5));
}
static inline void ATTRout(struct riva_par *par, unsigned char index,
unsigned char val)
{
VGA_WR08(par->riva.PCIO, 0x3c0, index);
VGA_WR08(par->riva.PCIO, 0x3c0, val);
}
static inline unsigned char ATTRin(struct riva_par *par,
unsigned char index)
{
VGA_WR08(par->riva.PCIO, 0x3c0, index);
return (VGA_RD08(par->riva.PCIO, 0x3c1));
}
static inline void MISCout(struct riva_par *par, unsigned char val)
{
VGA_WR08(par->riva.PVIO, 0x3c2, val);
}
static inline unsigned char MISCin(struct riva_par *par)
{
return (VGA_RD08(par->riva.PVIO, 0x3cc));
}
/* ------------------------------------------------------------------------- *
*
* cursor stuff
*
* ------------------------------------------------------------------------- */
/**
* rivafb_load_cursor_image - load cursor image to hardware
* @data: address to monochrome bitmap (1 = foreground color, 0 = background)
* @mask: address to mask (1 = write image pixel, 0 = do not write pixel)
* @par: pointer to private data
* @w: width of cursor image in pixels
* @h: height of cursor image in scanlines
* @bg: background color (ARGB1555) - alpha bit determines opacity
* @fg: foreground color (ARGB1555)
*
* DESCRIPTiON:
* Loads cursor image based on a monochrome source and mask bitmap. The
* mask bit determines if the image pixel is to be written to the framebuffer
* or not. The imaage bits determines the color of the pixel, 0 for
* background, 1 for foreground. Only the affected region (as determined
* by @w and @h parameters) will be updated.
*
* CALLED FROM:
* rivafb_cursor()
*/
static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par,
int w, int h, u16 bg, u16 fg)
{
int i, j, k = 0;
u32 b, m, tmp;
for (i = 0; i < h; i++) {
b = *((u32 *)data)++;
m = *((u32 *)mask)++;
for (j = 0; j < w/2; j++) {
tmp = 0;
#if defined (__BIG_ENDIAN__)
if (m & (1 << 31))
tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
b <<= 1;
m <<= 1;
if (m & (1 << 31))
tmp |= (b & (1 << 31)) ? fg : bg;
b <<= 1;
m <<= 1;
#else
if (m & 1)
tmp = (b & 1) ? fg : bg;
b >>= 1;
m >>= 1;
if (m & 1)
tmp |= (b & 1) ? fg << 16 : bg << 16;
b >>= 1;
m >>= 1;
#endif
writel(tmp, par->riva.CURSOR + k++);
}
k += (MAX_CURS - w)/2;
}
}
/* ------------------------------------------------------------------------- *
*
* general utility functions
*
* ------------------------------------------------------------------------- */
/**
* riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object
* @regnum: register number
* @red: red component
* @green: green component
* @blue: blue component
*
* DESCRIPTION:
* Sets color register @regnum.
*
* CALLED FROM:
* rivafb_setcolreg()
*/
static void riva_wclut(RIVA_HW_INST *chip,
unsigned char regnum, unsigned char red,
unsigned char green, unsigned char blue)
{
VGA_WR08(chip->PDIO, 0x3c8, regnum);
VGA_WR08(chip->PDIO, 0x3c9, red);
VGA_WR08(chip->PDIO, 0x3c9, green);
VGA_WR08(chip->PDIO, 0x3c9, blue);
}
/**
* riva_save_state - saves current chip state
* @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
* Saves current chip state to @regs.
*
* CALLED FROM:
* rivafb_init_one()
*/
/* from GGI */
static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
{
int i;
par->riva.LockUnlock(&par->riva, 0);
par->riva.UnloadStateExt(&par->riva, ®s->ext);
regs->misc_output = MISCin(par);
for (i = 0; i < NUM_CRT_REGS; i++) {
regs->crtc[i] = CRTCin(par, i);
}
for (i = 0; i < NUM_ATC_REGS; i++) {
regs->attr[i] = ATTRin(par, i);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
regs->gra[i] = GRAin(par, i);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
regs->seq[i] = SEQin(par, i);
}
}
/**
* riva_load_state - loads current chip state
* @par: pointer to riva_par object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
* Loads chip state from @regs.
*
* CALLED FROM:
* riva_load_video_mode()
* rivafb_init_one()
* rivafb_remove_one()
*/
/* from GGI */
static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
{
RIVA_HW_STATE *state = ®s->ext;
int i;
CRTCout(par, 0x11, 0x00);
par->riva.LockUnlock(&par->riva, 0);
par->riva.LoadStateExt(&par->riva, state);
MISCout(par, regs->misc_output);
for (i = 0; i < NUM_CRT_REGS; i++) {
switch (i) {
case 0x19:
case 0x20 ... 0x40:
break;
default:
CRTCout(par, i, regs->crtc[i]);
}
}
for (i = 0; i < NUM_ATC_REGS; i++) {
ATTRout(par, i, regs->attr[i]);
}
for (i = 0; i < NUM_GRC_REGS; i++) {
GRAout(par, i, regs->gra[i]);
}
for (i = 0; i < NUM_SEQ_REGS; i++) {
SEQout(par, i, regs->seq[i]);
}
}
/**
* riva_load_video_mode - calculate timings
* @info: pointer to fb_info object containing info for current riva board
* @video_mode: video mode to set
*
* DESCRIPTION:
* Calculate some timings and then send em off to riva_load_state().
*
* CALLED FROM:
* rivafb_set_var()
*/
static void riva_load_video_mode(struct fb_info *info)
{
int bpp, width, hDisplaySize, hDisplay, hStart,
hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock;
int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd;
struct riva_par *par = (struct riva_par *) info->par;
struct riva_regs newmode;
/* time to calculate */
rivafb_blank(1, info);
bpp = info->var.bits_per_pixel;
if (bpp == 16 && info->var.green.length == 5)
bpp = 15;
width = info->var.xres_virtual;
hDisplaySize = info->var.xres;
hDisplay = (hDisplaySize / 8) - 1;
hStart = (hDisplaySize + info->var.right_margin) / 8 + 2;
hEnd = (hDisplaySize + info->var.right_margin +
info->var.hsync_len) / 8 - 1;
hTotal = (hDisplaySize + info->var.right_margin +
info->var.hsync_len + info->var.left_margin) / 8 - 5;
hBlankStart = hDisplay;
hBlankEnd = hTotal + 4;
height = info->var.yres_virtual;
vDisplay = info->var.yres - 1;
vStart = info->var.yres + info->var.lower_margin - 1;
vEnd = info->var.yres + info->var.lower_margin +
info->var.vsync_len - 1;
vTotal = info->var.yres + info->var.lower_margin +
info->var.vsync_len + info->var.upper_margin + 2;
vBlankStart = vDisplay;
vBlankEnd = vTotal + 1;
dotClock = PICOS2KHZ(info->var.pixclock);
memcpy(&newmode, ®_template, sizeof(struct riva_regs));
newmode.crtc[0x0] = Set8Bits (hTotal - 4);
if (par->FlatPanel) {
vStart = vTotal - 3;
vEnd = vTotal - 2;
vBlankStart = vStart;
hStart = hTotal - 3;
hEnd = hTotal - 2;
hBlankEnd = hTotal + 4;
}
newmode.crtc[0x0] = Set8Bits (hTotal);
newmode.crtc[0x1] = Set8Bits (hDisplay);
newmode.crtc[0x2] = Set8Bits (hBlankStart);
newmode.crtc[0x3] = SetBitField (hBlankEnd, 4: 0, 4:0) | SetBit (7);
newmode.crtc[0x4] = Set8Bits (hStart);
newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7)
| SetBitField (hEnd, 4: 0, 4:0);
newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0);
newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0)
| SetBitField (vDisplay, 8: 8, 1:1)
| SetBitField (vStart, 8: 8, 2:2)
| SetBitField (vBlankStart, 8: 8, 3:3)
| SetBit (4)
| SetBitField (vTotal, 9: 9, 5:5)
| SetBitField (vDisplay, 9: 9, 6:6)
| SetBitField (vStart, 9: 9, 7:7);
newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5)
| SetBit (6);
newmode.crtc[0x10] = Set8Bits (vStart);
newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0)
| SetBit (5);
newmode.crtc[0x12] = Set8Bits (vDisplay);
newmode.crtc[0x13] = (width / 8) * ((bpp + 1) / 8);
newmode.crtc[0x15] = Set8Bits (vBlankStart);
newmode.crtc[0x16] = Set8Bits (vBlankEnd + 1);
newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4)
| SetBitField(vBlankStart,10:10,3:3)
| SetBitField(vStart,10:10,2:2)
| SetBitField(vDisplay,10:10,1:1)
| SetBitField(vTotal,10:10,0:0);
newmode.ext.horiz = SetBitField(hTotal,8:8,0:0)
| SetBitField(hDisplay,8:8,1:1)
| SetBitField(hBlankStart,8:8,2:2)
| SetBitField(hStart,8:8,3:3);
newmode.ext.extra = SetBitField(vTotal,11:11,0:0)
| SetBitField(vDisplay,11:11,2:2)
| SetBitField(vStart,11:11,4:4)
| SetBitField(vBlankStart,11:11,6:6);
newmode.ext.interlace = 0xff; /* interlace off */
if(par->riva.Architecture >= NV_ARCH_10)
par->riva.CURSOR = (U032 *)(info->screen_base + par->riva.CursorStart);
par->riva.CalcStateExt(&par->riva, &newmode.ext, bpp, width,
hDisplaySize, height, dotClock);
newmode.ext.scale = par->riva.PRAMDAC[0x00000848/4] & 0xfff000ff;
if(par->FlatPanel == 1) {
newmode.ext.pixel |= (1 << 7);
newmode.ext.scale |= (1 << 8) ;
}
if(par->SecondCRTC) {
newmode.ext.head = par->riva.PCRTC0[0x00000860/4] & ~0x00001000;
newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] | 0x00001000;
newmode.ext.crtcOwner = 3;
newmode.ext.pllsel |= 0x20000800;
newmode.ext.vpll2 = newmode.ext.vpll;
} else if(par->riva.twoHeads) {
newmode.ext.head = par->riva.PCRTC0[0x00000860/4] | 0x00001000;
newmode.ext.head2 = par->riva.PCRTC0[0x00002860/4] & ~0x00001000;
newmode.ext.crtcOwner = 0;
newmode.ext.vpll2 = par->riva.PRAMDAC0[0x00000520/4];
}
newmode.ext.cursorConfig = 0x02000100;
par->current_state = newmode;
riva_load_state(par, &par->current_state);
rivafb_blank(0, info);
}
/**
* rivafb_do_maximize -
* @info: pointer to fb_info object containing info for current riva board
* @var:
* @nom:
* @den:
*
* DESCRIPTION:
* .
*
* RETURNS:
* -EINVAL on failure, 0 on success
*
*
* CALLED FROM:
* rivafb_set_var()
*/
static int rivafb_do_maximize(struct fb_info *info,
struct fb_var_screeninfo *var,
int nom, int den)
{
static struct {
int xres, yres;
} modes[] = {
{1600, 1280},
{1280, 1024},
{1024, 768},
{800, 600},
{640, 480},
{-1, -1}
};
int i;
/* use highest possible virtual resolution */
if (var->xres_virtual == -1 && var->yres_virtual == -1) {
printk(KERN_WARNING PFX
"using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
if (modes[i].xres * nom / den * modes[i].yres <
info->fix.smem_len / 2)
break;
}
if (modes[i].xres == -1) {
printk(KERN_ERR PFX
"could not find a virtual resolution that fits into video memory!!\n");
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
var->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres;
printk(KERN_INFO PFX
"virtual resolution set to maximum of %dx%d\n",
var->xres_virtual, var->yres_virtual);
} else if (var->xres_virtual == -1) {
var->xres_virtual = (info->fix.smem_len * den /
(nom * var->yres_virtual * 2)) & ~15;
printk(KERN_WARNING PFX
"setting virtual X resolution to %d\n", var->xres_virtual);
} else if (var->yres_virtual == -1) {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
var->yres_virtual = info->fix.smem_len * den /
(nom * var->xres_virtual * 2);
printk(KERN_WARNING PFX
"setting virtual Y resolution to %d\n", var->yres_virtual);
} else {
var->xres_virtual = (var->xres_virtual + 15) & ~15;
if (var->xres_virtual * nom / den * var->yres_virtual > info->fix.smem_len) {
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
}
if (var->xres_virtual * nom / den >= 8192) {
printk(KERN_WARNING PFX
"virtual X resolution (%d) is too high, lowering to %d\n",
var->xres_virtual, 8192 * den / nom - 16);
var->xres_virtual = 8192 * den / nom - 16;
}
if (var->xres_virtual < var->xres) {
printk(KERN_ERR PFX
"virtual X resolution (%d) is smaller than real\n", var->xres_virtual);
return -EINVAL;
}
if (var->yres_virtual < var->yres) {
printk(KERN_ERR PFX
"virtual Y resolution (%d) is smaller than real\n", var->yres_virtual);
return -EINVAL;
}
return 0;
}
/* acceleration routines */
inline void wait_for_idle(struct riva_par *par)
{
while (par->riva.Busy(&par->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Patt, 5);
par->riva.Patt->Shape = 0;
par->riva.Patt->Color0 = 0xffffffff;
par->riva.Patt->Color1 = 0xffffffff;
par->riva.Patt->Monochrome[0] = 0xffffffff;
par->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct riva_par *par)
{
RIVA_FIFO_FREE(par->riva, Clip, 2);
par->riva.Clip->TopLeft = 0x0;
par->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(par);
}
/**
* rivafb_fillrect - hardware accelerated color fill function
* @info: pointer to fb_info structure
* @rect: pointer to fb_fillrect structure
*
* DESCRIPTION:
* This function fills up a region of framebuffer memory with a solid
* color with a choice of two different ROP's, copy or invert.
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{
struct riva_par *par = (struct riva_par *) info->par;
u_int color, rop = 0;
if (info->var.bits_per_pixel == 8)
color = rect->color;
else
color = par->riva_palette[rect->color];
switch (rect->rop) {
case ROP_XOR:
rop = 0x66;
break;
case ROP_COPY:
default:
rop = 0xCC;
break;
}
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = rop;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
par->riva.Bitmap->Color1A = color;
RIVA_FIFO_FREE(par->riva, Bitmap, 2);
par->riva.Bitmap->UnclippedRectangle[0].TopLeft =
(rect->dx << 16) | rect->dy;
par->riva.Bitmap->UnclippedRectangle[0].WidthHeight =
(rect->width << 16) | rect->height;
}
/**
* rivafb_copyarea - hardware accelerated blit function
* @info: pointer to fb_info structure
* @region: pointer to fb_copyarea structure
*
* DESCRIPTION:
* This copies an area of pixels from one location to another
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *region)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_FIFO_FREE(par->riva, Blt, 3);
par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx;
par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx;
par->riva.Blt->WidthHeight = (region->height << 16) | region->width;
wait_for_idle(par);
}
static u8 byte_rev[256] = {
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
};
/**
* rivafb_imageblit: hardware accelerated color expand function
* @info: pointer to fb_info structure
* @image: pointer to fb_image structure
*
* DESCRIPTION:
* If the source is a monochrome bitmap, the function fills up a a region
* of framebuffer memory with pixels whose color is determined by the bit
* setting of the bitmap, 1 - foreground, 0 - background.
*
* If the source is not a monochrome bitmap, color expansion is not done.
* In this case, it is channeled to a software function.
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
{
struct riva_par *par = (struct riva_par *) info->par;
u8 *cdat = image->data, *dat;
int w, h, dx, dy;
volatile u32 *d;
u32 fgx = 0, bgx = 0, size, width, mod;
int i, j;
if (image->depth != 1) {
wait_for_idle(par);
cfb_imageblit(info, image);
return;
}
w = image->width;
h = image->height;
dx = image->dx;
dy = image->dy;
width = (w + 7)/8;
size = width * h;
dat = cdat;
for (i = 0; i < size; i++) {
*dat = byte_rev[*dat];
dat++;
}
switch (info->var.bits_per_pixel) {
case 8:
fgx = image->fg_color | ~((1 << 8) - 1);
bgx = image->bg_color | ~((1 << 8) - 1);
break;
case 16:
/* set alpha bit */
if (info->var.green.length == 5) {
fgx = 1 << 15;
bgx = fgx;
}
/* Fall through... */
case 32:
fgx |= par->riva_palette[image->fg_color];
bgx |= par->riva_palette[image->bg_color];
break;
}
RIVA_FIFO_FREE(par->riva, Bitmap, 7);
par->riva.Bitmap->ClipE.TopLeft = (dy << 16) | (dx & 0xFFFF);
par->riva.Bitmap->ClipE.BottomRight = (((dy + h) << 16) |
((dx + w) & 0xffff));
par->riva.Bitmap->Color0E = bgx;
par->riva.Bitmap->Color1E = fgx;
par->riva.Bitmap->WidthHeightInE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->WidthHeightOutE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->PointE = (dy << 16) | (dx & 0xFFFF);
d = &par->riva.Bitmap->MonochromeData01E;
mod = width % 4;
if (width >= 4) {
while (h--) {
size = width / 4;
while (size >= 16) {
RIVA_FIFO_FREE(par->riva, Bitmap, 16);
for (i = 0; i < 16; i++)
d[i] = *((u32 *)cdat)++;
size -= 16;
}
if (size) {
RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (i = 0; i < size; i++)
d[i] = *((u32 *) cdat)++;
}
if (mod) {
u32 tmp;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
for (i = 0; i < mod; i++)
((u8 *)&tmp)[i] = *cdat++;
d[i] = tmp;
}
}
}
else {
u32 k, tmp;
for (i = h; i > 0; i-=16) {
if (i >= 16)
size = 16;
else
size = i;
RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (j = 0; j < size; j++) {
for (k = 0; k < width; k++)
((u8 *)&tmp)[k] = *cdat++;
d[j] = tmp;
}
}
}
}
/**
* rivafb_cursor - hardware cursor function
* @info: pointer to info structure
* @cursor: pointer to fbcursor structure
*
* DESCRIPTION:
* A cursor function that supports displaying a cursor image via hardware.
* Within the kernel, copy and invert rops are supported. If exported
* to user space, only the copy rop will be supported.
*
* CALLED FROM
* framebuffer hook
*/
static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8];
struct riva_par *par = (struct riva_par *) info->par;
int i, j, d_idx = 0, s_idx = 0;
u16 flags = cursor->set, fg, bg;
/*
* Can't do invert if one of the operands (dest) is missing,
* ie, only opaque cursor supported. This should be
* standard for GUI apps.
*/
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
return 1;
if (par->cursor_reset) {
flags = FB_CUR_SETALL;
par->cursor_reset = 0;
}
par->riva.ShowHideCursor(&par->riva, 0);
if (flags & FB_CUR_SETPOS) {
u32 xx, yy, temp;
yy = cursor->image.dy - info->var.yoffset;
xx = cursor->image.dx - info->var.xoffset;
temp = xx & 0xFFFF;
temp |= yy << 16;
par->riva.PRAMDAC[0x0000300/4] = temp;
}
if (flags & FB_CUR_SETSIZE) {
memset(data, 0, MAX_CURS * MAX_CURS/8);
memset(mask, 0, MAX_CURS * MAX_CURS/8);
memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
}
if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) {
int bg_idx = cursor->image.bg_color;
int fg_idx = cursor->image.fg_color;
switch (cursor->rop) {
case ROP_XOR:
for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8;
j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx] ^
((u8 *)cursor->dest)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
case ROP_COPY:
default:
for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8; j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
}
bg = ((par->cmap[bg_idx].red & 0xf8) << 7) |
((par->cmap[bg_idx].green & 0xf8) << 2) |
((par->cmap[bg_idx].blue & 0xf8) >> 3) | 1 << 15;
fg = ((par->cmap[fg_idx].red & 0xf8) << 7) |
((par->cmap[fg_idx].green & 0xf8) << 2) |
((par->cmap[fg_idx].blue & 0xf8) >> 3) | 1 << 15;
par->riva.LockUnlock(&par->riva, 0);
rivafb_load_cursor_image(data, mask, par, cursor->image.width,
cursor->image.height, bg, fg);
}
if (cursor->enable)
par->riva.ShowHideCursor(&par->riva, 1);
return 0;
}
static int rivafb_sync(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
wait_for_idle(par);
return 0;
}
/* ------------------------------------------------------------------------- *
*
* internal fb_ops helper functions
*
* ------------------------------------------------------------------------- */
/**
* riva_get_cmap_len - query current color map length
* @var: standard kernel fb changeable data
*
* DESCRIPTION:
* Get current color map length.
*
* RETURNS:
* Length of color map
*
* CALLED FROM:
* riva_getcolreg()
* rivafb_setcolreg()
* rivafb_get_cmap()
* rivafb_set_cmap()
*/
static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
{
int rc = 16; /* reasonable default */
assert(var != NULL);
switch (var->green.length) {
case 5:
rc = 32; /* fix for 15 bpp depths on Riva 128 based cards */
break;
case 6:
rc = 64; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
default:
rc = 256; /* pseudocolor... 256 entries HW palette */
break;
}
return rc;
}
/* ------------------------------------------------------------------------- *
*
* framebuffer operations
*
* ------------------------------------------------------------------------- */
static int rivafb_open(struct fb_info *info, int user)
{
struct riva_par *par = (struct riva_par *) info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt) {
memset(&par->state, 0, sizeof(struct vgastate));
par->state.flags = VGA_SAVE_MODE | VGA_SAVE_FONT0;
/* save the DAC for Riva128 */
if (par->riva.Architecture == NV_ARCH_03)
par->state.flags |= VGA_SAVE_CMAP;
save_vga(&par->state);
RivaGetConfig(&par->riva, par->Chipset);
riva_save_state(par, &par->initial_state);
}
atomic_inc(&par->ref_count);
return 0;
}
static int rivafb_release(struct fb_info *info, int user)
{
struct riva_par *par = (struct riva_par *) info->par;
int cnt = atomic_read(&par->ref_count);
if (!cnt)
return -EINVAL;
if (cnt == 1) {
riva_load_state(par, &par->initial_state);
par->riva.LockUnlock(&par->riva, 1);
restore_vga(&par->state);
}
atomic_dec(&par->ref_count);
return 0;
}
static int rivafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
int nom, den; /* translating from pixels->bytes */
if (par->riva.Architecture == NV_ARCH_03 &&
var->bits_per_pixel == 16)
var->bits_per_pixel = 15;
switch (var->bits_per_pixel) {
case 1 ... 8:
var->bits_per_pixel = 8;
nom = 1;
den = 1;
var->red.offset = 0;
var->red.length = 8;
var->green.offset = 0;
var->green.length = 8;
var->blue.offset = 0;
var->blue.length = 8;
break;
case 9 ... 15:
var->green.length = 5;
/* fall through */
case 16:
var->bits_per_pixel = 16;
nom = 2;
den = 1;
if (var->green.length == 5) {
/* 0rrrrrgg gggbbbbb */
var->red.offset = 10;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 5;
var->blue.length = 5;
} else {
/* rrrrrggg gggbbbbb */
var->red.offset = 11;
var->green.offset = 5;
var->blue.offset = 0;
var->red.length = 5;
var->green.length = 6;
var->blue.length = 5;
}
break;
case 17 ... 32:
var->bits_per_pixel = 32;
nom = 4;
den = 1;
var->red.offset = 16;
var->green.offset = 8;
var->blue.offset = 0;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
break;
default:
printk(KERN_ERR PFX
"mode %dx%dx%d rejected...color depth not supported.\n",
var->xres, var->yres, var->bits_per_pixel);
DPRINTK("EXIT, returning -EINVAL\n");
return -EINVAL;
}
if (rivafb_do_maximize(info, var, nom, den) < 0)
return -EINVAL;
if (var->xoffset < 0)
var->xoffset = 0;
if (var->yoffset < 0)
var->yoffset = 0;
/* truncate xoffset and yoffset to maximum if too high */
if (var->xoffset > var->xres_virtual - var->xres)
var->xoffset = var->xres_virtual - var->xres - 1;
if (var->yoffset > var->yres_virtual - var->yres)
var->yoffset = var->yres_virtual - var->yres - 1;
var->red.msb_right =
var->green.msb_right =
var->blue.msb_right =
var->transp.offset = var->transp.length = var->transp.msb_right = 0;
return 0;
}
static int rivafb_set_par(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
riva_load_video_mode(info);
if (info->var.accel_flags) {
riva_setup_accel(par);
info->fbops->fb_fillrect = rivafb_fillrect;
info->fbops->fb_copyarea = rivafb_copyarea;
info->fbops->fb_imageblit = rivafb_imageblit;
info->fbops->fb_cursor = rivafb_cursor;
info->fbops->fb_sync = rivafb_sync;
}
else {
info->fbops->fb_fillrect = cfb_fillrect;
info->fbops->fb_copyarea = cfb_copyarea;
info->fbops->fb_imageblit = cfb_imageblit;
info->fbops->fb_cursor = soft_cursor;
info->fbops->fb_sync = NULL;
}
info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
return 0;
}
/**
* rivafb_pan_display
* @var: standard kernel fb changeable data
* @con: TODO
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the
* `xoffset' and `yoffset' fields of the `var' structure.
* If the values don't fit, return -EINVAL.
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int rivafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
unsigned int base;
if (var->xoffset > (var->xres_virtual - var->xres))
return -EINVAL;
if (var->yoffset > (var->yres_virtual - var->yres))
return -EINVAL;
if (var->vmode & FB_VMODE_YWRAP) {
if (var->yoffset < 0
|| var->yoffset >= info->var.yres_virtual
|| var->xoffset) return -EINVAL;
} else {
if (var->xoffset + info->var.xres > info->var.xres_virtual ||
var->yoffset + info->var.yres > info->var.yres_virtual)
return -EINVAL;
}
base = var->yoffset * info->fix.line_length + var->xoffset;
par->riva.SetStartAddress(&par->riva, base);
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
if (var->vmode & FB_VMODE_YWRAP)
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
/*
* HACK: The hardware cursor occasionally disappears during fast scrolling.
* We just reset the cursor each time we change the start address.
* This also has a beneficial side effect of restoring the cursor
* image when switching from X.
*/
par->cursor_reset = 1;
DPRINTK("EXIT, returning 0\n");
return 0;
}
static int rivafb_blank(int blank, struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
unsigned char tmp, vesa;
tmp = SEQin(par, 0x01) & ~0x20; /* screen on/off */
vesa = CRTCin(par, 0x1a) & ~0xc0; /* sync on/off */
if (blank) {
tmp |= 0x20;
switch (blank - 1) {
case VESA_NO_BLANKING:
break;
case VESA_VSYNC_SUSPEND:
vesa |= 0x80;
break;
case VESA_HSYNC_SUSPEND:
vesa |= 0x40;
break;
case VESA_POWERDOWN:
vesa |= 0xc0;
break;
}
}
SEQout(par, 0x01, tmp);
CRTCout(par, 0x1a, vesa);
DPRINTK("EXIT\n");
return 0;
}
/**
* rivafb_setcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
* magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:do_install_cmap()
* fbgen.c:fbgen_set_var()
* fbgen.c:fbgen_switch()
* fbgen.c:fbgen_blank()
* fbgen.c:fbgen_blank()
*/
static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_HW_INST *chip = &par->riva;
int i;
if (regno >= riva_get_cmap_len(&info->var))
return -EINVAL;
if (info->var.grayscale) {
/* gray = 0.30*R + 0.59*G + 0.11*B */
red = green = blue =
(red * 77 + green * 151 + blue * 28) >> 8;
}
if (!regno) {
for (i = 0; i < 256; i++) {
par->cmap[i].red = 0;
par->cmap[i].green = 0;
par->cmap[i].blue = 0;
}
}
par->cmap[regno].red = (u8) red;
par->cmap[regno].green = (u8) green;
par->cmap[regno].blue = (u8) blue;
if (info->var.green.length == 5) {
/* RGB555: all components have 32 entries, 8 indices apart */
for (i = 0; i < 8; i++)
riva_wclut(chip, (regno*8)+i, (u8) red, (u8) green, (u8) blue);
}
else if (info->var.green.length == 6) {
/*
* RGB 565: red and blue have 32 entries, 8 indices apart, while
* green has 64 entries, 4 indices apart
*/
if (regno < 32) {
for (i = 0; i < 8; i++) {
riva_wclut(chip, (regno*8)+i, (u8) red,
par->cmap[regno*2].green,
(u8) blue);
}
}
for (i = 0; i < 4; i++) {
riva_wclut(chip, (regno*4)+i, par->cmap[regno/2].red,
(u8) green, par->cmap[regno/2].blue);
}
}
else {
riva_wclut(chip, regno, (u8) red, (u8) green, (u8) blue);
}
if (regno < 16) {
switch (info->var.bits_per_pixel) {
case 16:
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
((u32 *)(info->pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno;
par->riva_palette[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
((u32 *)(info->pseudo_palette))[regno] =
(regno << 11) | (regno << 6) | regno;
par->riva_palette[regno] = ((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
case 32:
((u32 *)(info->pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno;
par->riva_palette[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
default:
/* do nothing */
break;
}
}
return 0;
}
/* ------------------------------------------------------------------------- *
*
* initialization helper functions
*
* ------------------------------------------------------------------------- */
/* kernel interface */
static struct fb_ops riva_fb_ops = {
.owner = THIS_MODULE,
.fb_open = rivafb_open,
.fb_release = rivafb_release,
.fb_check_var = rivafb_check_var,
.fb_set_par = rivafb_set_par,
.fb_setcolreg = rivafb_setcolreg,
.fb_pan_display=rivafb_pan_display,
.fb_blank = rivafb_blank,
.fb_fillrect = rivafb_fillrect,
.fb_copyarea = rivafb_copyarea,
.fb_imageblit = rivafb_imageblit,
.fb_cursor = rivafb_cursor,
.fb_sync = rivafb_sync,
};
static int __devinit riva_set_fbinfo(struct fb_info *info)
{
unsigned int cmap_len;
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
info->var = rivafb_default_var;
info->fix = rivafb_fix;
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
info->pseudo_palette = pseudo_palette;
cmap_len = riva_get_cmap_len(&info->var);
fb_alloc_cmap(&info->cmap, cmap_len, 0);
#ifndef MODULE
if (mode_option)
fb_find_mode(&info->var, info, mode_option,
NULL, 0, NULL, 8);
#endif
info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
info->fix.visual = (info->var.bits_per_pixel == 8) ?
FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_DIRECTCOLOR;
return 0;
}
/* ------------------------------------------------------------------------- *
*
* PCI bus
*
* ------------------------------------------------------------------------- */
static void __devinit rivafb_get_mem_len(struct riva_par *par,
struct fb_fix_screeninfo *fix)
{
RIVA_HW_INST *chip = &par->riva;
switch (chip->Architecture) {
case NV_ARCH_03:
if (chip->PFB[0x00000000/4] & 0x00000020) {
if (((chip->PMC[0x00000000/4] & 0xF0) == 0x20)
&& ((chip->PMC[0x00000000/4] & 0x0F) >= 0x02)) {
/*
* SDRAM 128 ZX.
*/
switch (chip->PFB[0x00000000/4] & 0x03) {
case 2:
fix->smem_len = 1024 * 1024 * 4;
break;
case 1:
fix->smem_len = 1024 * 1024 * 2;
break;
default:
fix->smem_len = 1024 * 1024 * 8;
break;
}
}
else {
fix->smem_len = 1024 * 1024 * 8;
}
}
else {
/*
* SGRAM 128.
*/
switch (chip->PFB[0x00000000/4] & 0x00000003) {
case 0:
fix->smem_len = 1024 * 1024 * 8;
break;
case 2:
fix->smem_len = 1024 * 1024 * 4;
break;
default:
fix->smem_len = 1024 * 1024 * 2;
break;
}
}
break;
case NV_ARCH_04:
if (chip->PFB[0x00000000/4] & 0x00000100) {
fix->smem_len = (((chip->PFB[0x00000000/4] >> 12)
& 0x0F) * 1024 * 2 + 1024 * 2) * 1024;
}
else {
switch (chip->PFB[0x00000000/4] & 0x00000003) {
case 0:
fix->smem_len = 1024 * 1024 * 32;
break;
case 1:
fix->smem_len = 1024 * 1024 * 4;
break;
case 2:
fix->smem_len = 1024 * 1024 * 8;
break;
case 3:
default:
fix->smem_len = 1024 * 1024 * 16;
break;
}
}
break;
case NV_ARCH_10:
case NV_ARCH_20:
switch ((chip->PFB[0x0000020C/4] >> 20) & 0x000000FF) {
case 0x02:
fix->smem_len = 1024 * 1024 * 2;
break;
case 0x04:
fix->smem_len = 1024 * 1024 * 4;
break;
case 0x08:
fix->smem_len = 1024 * 1024 * 8;
break;
case 0x10:
fix->smem_len = 1024 * 1024 * 16;
break;
case 0x20:
fix->smem_len = 1024 * 1024 * 32;
break;
case 0x40:
fix->smem_len = 1024 * 1024 * 64;
break;
case 0x80:
fix->smem_len = 1024 * 1024 * 128;
break;
default:
fix->smem_len = 1024 * 1024 * 16;
break;
}
}
}
static int __devinit rivafb_init_one(struct pci_dev *pd,
const struct pci_device_id *ent)
{
struct riva_chip_info *rci = &riva_chip_info[ent->driver_data];
struct riva_par *default_par;
struct fb_info *info;
assert(pd != NULL);
assert(rci != NULL);
info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);
if (!info)
goto err_out;
default_par = kmalloc(sizeof(struct riva_par), GFP_KERNEL);
if (!default_par)
goto err_out_kfree;
memset(info, 0, sizeof(struct fb_info));
memset(default_par, 0, sizeof(struct riva_par));
strcat(rivafb_fix.id, rci->name);
default_par->riva.Architecture = rci->arch_rev;
default_par->Chipset = pd->device;
printk(KERN_INFO PFX "nVidia device/chipset %X\n",default_par->Chipset);
/*default_par->FlatPanel = flatpanel;
if (flatpanel == 1)
printk(KERN_INFO PFX "flatpanel support enabled\n");
default_par->forceCRTC = forceCRTC;
*/
rivafb_fix.mmio_len = pci_resource_len(pd, 0);
rivafb_fix.smem_len = pci_resource_len(pd, 1);
rivafb_fix.mmio_start = pci_resource_start(pd, 0);
rivafb_fix.smem_start = pci_resource_start(pd, 1);
if (!request_mem_region(rivafb_fix.mmio_start,
rivafb_fix.mmio_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve MMIO region\n");
goto err_out_kfree;
}
default_par->ctrl_base = ioremap(rivafb_fix.mmio_start,
rivafb_fix.mmio_len);
if (!default_par->ctrl_base) {
printk(KERN_ERR PFX "cannot ioremap MMIO base\n");
goto err_out_free_base0;
}
info->screen_base = ioremap(rivafb_fix.smem_start,
rivafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
default_par->riva.EnableIRQ = 0;
default_par->riva.PRAMDAC = (unsigned *)(default_par->ctrl_base +
0x00680000);
default_par->riva.PFB = (unsigned *)(default_par->ctrl_base +
0x00100000);
default_par->riva.PFIFO = (unsigned *)(default_par->ctrl_base +
0x00002000);
default_par->riva.PGRAPH = (unsigned *)(default_par->ctrl_base +
0x00400000);
default_par->riva.PEXTDEV = (unsigned *)(default_par->ctrl_base +
0x00101000);
default_par->riva.PTIMER = (unsigned *)(default_par->ctrl_base +
0x00009000);
default_par->riva.PMC = (unsigned *)(default_par->ctrl_base +
0x00000000);
default_par->riva.FIFO = (unsigned *)(default_par->ctrl_base +
0x00800000);
default_par->riva.PCIO = (U008 *)(default_par->ctrl_base + 0x00601000);
default_par->riva.PDIO = (U008 *)(default_par->ctrl_base + 0x00681000);
default_par->riva.PVIO = (U008 *)(default_par->ctrl_base + 0x000C0000);
default_par->riva.IO = (MISCin(default_par) & 0x01) ? 0x3D0 : 0x3B0;
switch (default_par->riva.Architecture) {
case NV_ARCH_03:
default_par->riva.PRAMIN = (unsigned *)(info->screen_base +
0x00C00000);
default_par->dclk_max = 256000000;
rivafb_fix.accel = FB_ACCEL_NV3;
break;
case NV_ARCH_04:
case NV_ARCH_10:
case NV_ARCH_20:
default_par->riva.PCRTC = (unsigned *)(default_par->ctrl_base
+ 0x00600000);
default_par->riva.PRAMIN = (unsigned *)(default_par->ctrl_base
+ 0x00710000);
default_par->dclk_max = 250000000;
rivafb_fix.accel = FB_ACCEL_NV4;
break;
}
rivafb_get_mem_len(default_par, &rivafb_fix);
info->par = default_par;
if (!request_mem_region(rivafb_fix.smem_start,
rivafb_fix.smem_len, "rivafb")) {
printk(KERN_ERR PFX "cannot reserve FB region\n");
goto err_out_free_base0;
}
info->screen_base = ioremap(rivafb_fix.smem_start,
rivafb_fix.smem_len);
if (!info->screen_base) {
printk(KERN_ERR PFX "cannot ioremap FB base\n");
goto err_out_iounmap_ctrl;
}
#ifdef CONFIG_MTRR
if (!nomtrr) {
default_par->mtrr.vram = mtrr_add(rivafb_fix.smem_start,
rivafb_fix.smem_len,
MTRR_TYPE_WRCOMB, 1);
if (default_par->mtrr.vram < 0) {
printk(KERN_ERR PFX "unable to setup MTRR\n");
} else {
default_par->mtrr.vram_valid = 1;
/* let there be speed */
printk(KERN_INFO PFX "RIVA MTRR set to ON\n");
}
}
#endif /* CONFIG_MTRR */
if (riva_set_fbinfo(info) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor;
}
if (register_framebuffer(info) < 0) {
printk(KERN_ERR PFX
"error registering riva framebuffer\n");
goto err_out_load_state;
}
pci_set_drvdata(pd,info);
printk(KERN_INFO PFX
"PCI nVidia NV%x framebuffer ver %s (%s, %dMB @ 0x%lX)\n",
default_par->riva.Architecture,
RIVAFB_VERSION,
info->fix.id,
info->fix.smem_len / (1024 * 1024),
info->fix.smem_start);
return 0;
err_out_load_state:
err_out_cursor:
/* err_out_iounmap_fb: */
iounmap(info->screen_base);
err_out_iounmap_ctrl:
iounmap(default_par->ctrl_base);
err_out_free_base1:
release_mem_region(info->fix.smem_start, info->fix.smem_len);
err_out_free_base0:
release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
err_out_kfree:
kfree(info);
err_out:
return -ENODEV;
}
static void __devexit rivafb_remove_one(struct pci_dev *pd)
{
struct fb_info *info = pci_get_drvdata(pd);
struct riva_par *par = (struct riva_par *) info->par;
if (!info)
return;
unregister_framebuffer(info);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fix.smem_start,
info->fix.smem_len);
#endif /* CONFIG_MTRR */
iounmap(par->ctrl_base);
iounmap(info->screen_base);
release_mem_region(info->fix.mmio_start,
info->fix.mmio_len);
release_mem_region(info->fix.smem_start,
info->fix.smem_len);
kfree(info);
pci_set_drvdata(pd, NULL);
}
/* ------------------------------------------------------------------------- *
*
* initialization
*
* ------------------------------------------------------------------------- */
#ifndef MODULE
int __init rivafb_setup(char *options)
{
char *this_opt;
if (!options || !*options)
return 0;
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
#ifdef CONFIG_MTRR
if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1;
} else
#endif
mode_option = this_opt;
}
return 0;
}
#endif /* !MODULE */
static struct pci_driver rivafb_driver = {
name: "rivafb",
id_table: rivafb_pci_tbl,
probe: rivafb_init_one,
remove: __devexit_p(rivafb_remove_one),
};
/* ------------------------------------------------------------------------- *
*
* modularization
*
* ------------------------------------------------------------------------- */
int __init rivafb_init(void)
{
pci_register_driver(&rivafb_driver);
return 0;
}
#ifdef MODULE
static void __exit rivafb_exit(void)
{
pci_unregister_driver(&rivafb_driver);
}
module_init(rivafb_init);
module_exit(rivafb_exit);
MODULE_PARM(flatpanel, "i");
MODULE_PARM_DESC(flatpanel, "Enables experimental flat panel support for some chipsets. (0 or 1=enabled) (default=0)");
MODULE_PARM(forceCRTC, "i");
MODULE_PARM_DESC(forceCRTC, "Forces usage of a particular CRTC in case autodetection fails. (0 or 1) (default=autodetect)");
MODULE_PARM(noaccel, "i");
MODULE_PARM_DESC(noaccel, "Disables hardware acceleration (0 or 1=disabled) (default=0)");
#ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
#endif
#endif /* MODULE */
MODULE_AUTHOR("Ani Joshi, maintainer");
MODULE_DESCRIPTION("Framebuffer driver for nVidia Riva 128, TNT, TNT2, GeForce Series");
MODULE_LICENSE("GPL");
drivers/video/sticore.h
View file @
8d7c2813
...
...
@@ -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
;
};
...
...
drivers/video/stifb.c
View file @
8d7c2813
/*
* linux/drivers/video/sti
/sti
fb.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
),
f
b
->
info
.
modename
,
disp
->
var
.
xres
,
disp
->
var
.
yres
,
disp
->
var
.
bits_per_pixel
,
f
ix
->
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment