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
34dfe0cd
Commit
34dfe0cd
authored
May 30, 2002
by
James Simmons
Browse files
Options
Browse Files
Download
Plain Diff
Merge heisenberg.transvirtual.com:/tmp/linus-2.5
into heisenberg.transvirtual.com:/tmp/fbdev-2.5
parents
65f0361a
8364a826
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
2410 additions
and
3787 deletions
+2410
-3787
drivers/video/Config.in
drivers/video/Config.in
+8
-10
drivers/video/Makefile
drivers/video/Makefile
+2
-2
drivers/video/anakinfb.c
drivers/video/anakinfb.c
+0
-1
drivers/video/clps711xfb.c
drivers/video/clps711xfb.c
+3
-0
drivers/video/cyber2000fb.c
drivers/video/cyber2000fb.c
+3
-2
drivers/video/neofb.c
drivers/video/neofb.c
+1671
-1946
drivers/video/tdfxfb.c
drivers/video/tdfxfb.c
+670
-1746
include/video/neomagic.h
include/video/neomagic.h
+53
-80
No files found.
drivers/video/Config.in
View file @
34dfe0cd
...
...
@@ -262,7 +262,7 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "y" -o \
"$CONFIG_FB_
NEOMAGIC
" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_
TX3912
" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
...
...
@@ -275,13 +275,13 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_SIS" = "y" -o \
"$CONFIG_FB_PMAG_BA" = "y" -o "$CONFIG_FB_PMAGB_B" = "y" -o \
"$CONFIG_FB_MAXINE" = "y"
-o "$CONFIG_FB_TX3912" = "y"
]; then
"$CONFIG_FB_MAXINE" = "y" ]; then
define_tristate CONFIG_FBCON_CFB8 y
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "m" -o \
"$CONFIG_FB_
NEOMAGIC
" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_
SIS
" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
...
...
@@ -294,12 +294,12 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "m" -o \
"$CONFIG_FB_MAXINE" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m"
-o "$CONFIG_FB_SIS" = "m"
]; then
"$CONFIG_FB_SA1100" = "m" ]; then
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_
NEOMAGIC
" = "y" -o \
"$CONFIG_FB_MAC" = "y" -o "$CONFIG_FB_
PVR2
" = "y" -o \
"$CONFIG_FB_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
...
...
@@ -309,12 +309,11 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
"$CONFIG_FB_PVR2" = "y" ]; then
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_
NEOMAGIC
" = "m" -o \
"$CONFIG_FB_MAC" = "m" -o "$CONFIG_FB_
PVR2
" = "m" -o \
"$CONFIG_FB_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
...
...
@@ -324,8 +323,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_PVR2" = "m" ]; then
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
...
...
drivers/video/Makefile
View file @
34dfe0cd
...
...
@@ -48,13 +48,13 @@ obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgb
obj-$(CONFIG_FB_ATARI)
+=
atafb.o
obj-$(CONFIG_FB_ATY128)
+=
aty128fb.o
obj-$(CONFIG_FB_RADEON)
+=
radeonfb.o
obj-$(CONFIG_FB_NEOMAGIC)
+=
neofb.o
obj-$(CONFIG_FB_NEOMAGIC)
+=
neofb.o
cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_IGA)
+=
igafb.o
obj-$(CONFIG_FB_CONTROL)
+=
controlfb.o
obj-$(CONFIG_FB_PLATINUM)
+=
platinumfb.o
obj-$(CONFIG_FB_VALKYRIE)
+=
valkyriefb.o
obj-$(CONFIG_FB_CT65550)
+=
chipsfb.o
obj-$(CONFIG_FB_ANAKIN)
+=
anakinfb.o
obj-$(CONFIG_FB_ANAKIN)
+=
anakinfb.o
cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CLPS711X)
+=
clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CYBER)
+=
cyberfb.o
obj-$(CONFIG_FB_CYBER2000)
+=
cyber2000fb.o
...
...
drivers/video/anakinfb.c
View file @
34dfe0cd
...
...
@@ -21,7 +21,6 @@
#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
static
u32
colreg
[
16
];
static
struct
fb_info
fb_info
;
...
...
drivers/video/clps711xfb.c
View file @
34dfe0cd
...
...
@@ -203,6 +203,9 @@ static struct fb_ops clps7111fb_ops = {
fb_get_cmap:
gen_get_cmap
,
fb_setcolreg:
clps7111fb_setcolreg
,
fb_blank:
clps7111fb_blank
,
fb_fillrect:
cfb_fillrect
,
fb_copyarea:
cfb_copyarea
,
fb_imageblit:
cfb_imageblit
,
};
static
int
...
...
drivers/video/cyber2000fb.c
View file @
34dfe0cd
...
...
@@ -1729,8 +1729,9 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
}
static
struct
pci_device_id
cyberpro_pci_table
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_1682
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
ID_IGA_1682
},
// Not yet
// { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_1682,
// PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_IGA_1682 },
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_2000
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
ID_CYBERPRO_2000
},
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_2010
,
...
...
drivers/video/neofb.c
View file @
34dfe0cd
...
...
@@ -11,6 +11,8 @@
* Public License. See the file COPYING in the main directory of this
* archive for more details.
*
* 0.3.3
* - Porting over to new fbdev api. (jsimmons)
*
* 0.3.2
* - got rid of all floating point (dok)
...
...
@@ -66,768 +68,117 @@
#endif
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.h>
#include <video/neomagic.h>
#
include "neofb.h
"
#
define NEOFB_VERSION "0.3.3
"
struct
neofb_par
default_par
;
#define NEOFB_VERSION "0.3.2"
/* --------------------------------------------------------------------- */
static
int
disabled
=
0
;
static
int
internal
=
0
;
static
int
external
=
0
;
static
int
nostretch
=
0
;
static
int
nopciburst
=
0
;
#ifdef MODULE
MODULE_AUTHOR
(
"(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"FBDev driver for NeoMagic PCI Chips"
);
MODULE_PARM
(
disabled
,
"i"
);
MODULE_PARM_DESC
(
disabled
,
"Disable this driver's initialization."
);
MODULE_PARM
(
internal
,
"i"
);
MODULE_PARM_DESC
(
internal
,
"Enable output on internal LCD Display."
);
MODULE_PARM
(
external
,
"i"
);
MODULE_PARM_DESC
(
external
,
"Enable output on external CRT."
);
MODULE_PARM
(
nostretch
,
"i"
);
MODULE_PARM_DESC
(
nostretch
,
"Disable stretching of modes smaller than LCD."
);
MODULE_PARM
(
nopciburst
,
"i"
);
MODULE_PARM_DESC
(
nopciburst
,
"Disable PCI burst mode."
);
#endif
/* --------------------------------------------------------------------- */
static
biosMode
bios8
[]
=
{
{
320
,
240
,
0x40
},
{
300
,
400
,
0x42
},
{
640
,
400
,
0x20
},
{
640
,
480
,
0x21
},
{
800
,
600
,
0x23
},
{
1024
,
768
,
0x25
},
};
static
biosMode
bios16
[]
=
{
{
320
,
200
,
0x2e
},
{
320
,
240
,
0x41
},
{
300
,
400
,
0x43
},
{
640
,
480
,
0x31
},
{
800
,
600
,
0x34
},
{
1024
,
768
,
0x37
},
};
static
biosMode
bios24
[]
=
{
{
640
,
480
,
0x32
},
{
800
,
600
,
0x35
},
{
1024
,
768
,
0x38
}
};
#ifdef NO_32BIT_SUPPORT_YET
/* FIXME: guessed values, wrong */
static
biosMode
bios32
[]
=
{
{
640
,
480
,
0x33
},
{
800
,
600
,
0x36
},
{
1024
,
768
,
0x39
}
};
#endif
static
int
neoFindMode
(
int
xres
,
int
yres
,
int
depth
)
{
int
xres_s
;
int
i
,
size
;
biosMode
*
mode
;
switch
(
depth
)
{
case
8
:
size
=
sizeof
(
bios8
)
/
sizeof
(
biosMode
);
mode
=
bios8
;
break
;
case
16
:
size
=
sizeof
(
bios16
)
/
sizeof
(
biosMode
);
mode
=
bios16
;
break
;
case
24
:
size
=
sizeof
(
bios24
)
/
sizeof
(
biosMode
);
mode
=
bios24
;
break
;
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
size
=
sizeof
(
bios32
)
/
sizeof
(
biosMode
);
mode
=
bios32
;
break
;
#endif
default:
return
0
;
}
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
xres
<=
mode
[
i
].
x_res
)
{
xres_s
=
mode
[
i
].
x_res
;
for
(;
i
<
size
;
i
++
)
{
if
(
mode
[
i
].
x_res
!=
xres_s
)
return
mode
[
i
-
1
].
mode
;
if
(
yres
<=
mode
[
i
].
y_res
)
return
mode
[
i
].
mode
;
}
}
}
return
mode
[
size
-
1
].
mode
;
}
/* -------------------- Hardware specific routines ------------------------- */
/*
* Hardware Acceleration for Neo2200+
*/
static
inline
void
neo2200_wait_idle
(
struct
neofb_info
*
fb
)
{
int
waitcycles
;
while
(
fb
->
neo2200
->
bltStat
&
1
)
waitcycles
++
;
}
static
inline
void
neo2200_wait_fifo
(
struct
neofb_info
*
fb
,
int
requested_fifo_space
)
{
// ndev->neo.waitfifo_calls++;
// ndev->neo.waitfifo_sum += requested_fifo_space;
/* FIXME: does not work
if (neo_fifo_space < requested_fifo_space)
{
neo_fifo_waitcycles++;
while (1)
{
neo_fifo_space = (neo2200->bltStat >> 8);
if (neo_fifo_space >= requested_fifo_space)
break;
}
}
else
{
neo_fifo_cache_hits++;
}
neo_fifo_space -= requested_fifo_space;
*/
neo2200_wait_idle
(
fb
);
}
static
inline
void
neo2200_accel_init
(
struct
neofb_info
*
fb
,
struct
fb_var_screeninfo
*
var
)
{
Neo2200
*
neo2200
=
fb
->
neo2200
;
u32
bltMod
,
pitch
;
neo2200_wait_idle
(
fb
);
switch
(
var
->
bits_per_pixel
)
{
case
8
:
bltMod
=
NEO_MODE1_DEPTH8
;
pitch
=
var
->
xres_virtual
;
break
;
case
15
:
case
16
:
bltMod
=
NEO_MODE1_DEPTH16
;
pitch
=
var
->
xres_virtual
*
2
;
break
;
default:
printk
(
KERN_ERR
"neofb: neo2200_accel_init: unexpected bits per pixel!
\n
"
);
return
;
}
neo2200
->
bltStat
=
bltMod
<<
16
;
neo2200
->
pitch
=
(
pitch
<<
16
)
|
pitch
;
}
static
void
neo2200_accel_setup
(
struct
display
*
p
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
struct
fb_var_screeninfo
*
var
=
&
p
->
fb_info
->
var
;
fb
->
dispsw
->
setup
(
p
);
neo2200_accel_init
(
fb
,
var
);
}
static
void
neo2200_accel_bmove
(
struct
display
*
p
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
struct
fb_var_screeninfo
*
var
=
&
p
->
fb_info
->
var
;
Neo2200
*
neo2200
=
fb
->
neo2200
;
u_long
src
,
dst
;
int
bpp
,
pitch
,
inc_y
;
u_int
fh
,
fw
;
/* setting blitting direction does not work, so this case is unaccelerated */
if
(
sx
!=
dx
)
{
neo2200_wait_idle
(
fb
);
fb
->
dispsw
->
bmove
(
p
,
sy
,
sx
,
dy
,
dx
,
height
,
width
);
return
;
}
bpp
=
(
var
->
bits_per_pixel
+
7
)
/
8
;
pitch
=
var
->
xres_virtual
*
bpp
;
fw
=
fontwidth
(
p
);
sx
*=
fw
*
bpp
;
dx
*=
fw
*
bpp
;
width
*=
fw
;
fh
=
fontheight
(
p
);
sy
*=
fh
;
dy
*=
fh
;
if
(
sy
>
dy
)
inc_y
=
fh
;
else
{
inc_y
=
-
fh
;
sy
+=
(
height
-
1
)
*
fh
;
dy
+=
(
height
-
1
)
*
fh
;
}
neo2200_wait_fifo
(
fb
,
1
);
/* set blt control */
neo2200
->
bltCntl
=
NEO_BC3_FIFO_EN
|
NEO_BC3_SKIP_MAPPING
|
0x0c0000
;
/* looks silly, but setting the blitting direction did not work */
while
(
height
--
)
{
src
=
sx
+
sy
*
pitch
;
dst
=
dx
+
dy
*
pitch
;
neo2200_wait_fifo
(
fb
,
3
);
neo2200
->
srcStart
=
src
;
neo2200
->
dstStart
=
dst
;
neo2200
->
xyExt
=
(
fh
<<
16
)
|
(
width
&
0xffff
);
sy
+=
inc_y
;
dy
+=
inc_y
;
}
}
static
void
neo2200_accel_clear
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
sy
,
int
sx
,
int
height
,
int
width
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
struct
fb_var_screeninfo
*
var
=
&
p
->
fb_info
->
var
;
Neo2200
*
neo2200
=
fb
->
neo2200
;
u_long
dst
;
u_int
fw
,
fh
;
u32
bgx
=
attr_bgcol_ec
(
p
,
conp
);
fw
=
fontwidth
(
p
);
fh
=
fontheight
(
p
);
dst
=
sx
*
fw
+
sy
*
var
->
xres_virtual
*
fh
;
width
=
width
*
fw
;
height
=
height
*
fh
;
neo2200_wait_fifo
(
fb
,
4
);
/* set blt control */
neo2200
->
bltCntl
=
NEO_BC3_FIFO_EN
|
NEO_BC0_SRC_IS_FG
|
NEO_BC3_SKIP_MAPPING
|
0x0c0000
;
switch
(
var
->
bits_per_pixel
)
{
case
8
:
neo2200
->
fgColor
=
bgx
;
break
;
case
16
:
neo2200
->
fgColor
=
((
u16
*
)(
p
->
fb_info
)
->
pseudo_palette
)[
bgx
];
break
;
}
neo2200
->
dstStart
=
dst
*
((
var
->
bits_per_pixel
+
7
)
/
8
);
neo2200
->
xyExt
=
(
height
<<
16
)
|
(
width
&
0xffff
);
}
static
void
neo2200_accel_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
neo2200_wait_idle
(
fb
);
fb
->
dispsw
->
putc
(
conp
,
p
,
c
,
yy
,
xx
);
}
static
void
neo2200_accel_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
neo2200_wait_idle
(
fb
);
fb
->
dispsw
->
putcs
(
conp
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
neo2200_accel_revc
(
struct
display
*
p
,
int
xx
,
int
yy
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
neo2200_wait_idle
(
fb
);
fb
->
dispsw
->
revc
(
p
,
xx
,
yy
);
}
static
void
neo2200_accel_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
{
struct
neofb_info
*
fb
=
(
struct
neofb_info
*
)
p
->
fb_info
;
fb
->
dispsw
->
clear_margins
(
conp
,
p
,
bottom_only
);
}
static
struct
display_switch
fbcon_neo2200_accel
=
{
setup:
neo2200_accel_setup
,
bmove:
neo2200_accel_bmove
,
clear:
neo2200_accel_clear
,
putc:
neo2200_accel_putc
,
putcs:
neo2200_accel_putcs
,
revc:
neo2200_accel_revc
,
clear_margins:
neo2200_accel_clear_margins
,
fontwidthmask:
FONTWIDTH
(
8
)
|
FONTWIDTH
(
16
)
};
/* --------------------------------------------------------------------- */
/*
* Set a single color register. Return != 0 for invalid regno.
*/
static
int
neofb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
fb
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
if
(
regno
>=
NR_PALETTE
)
return
-
EINVAL
;
info
->
palette
[
regno
].
red
=
red
;
info
->
palette
[
regno
].
green
=
green
;
info
->
palette
[
regno
].
blue
=
blue
;
info
->
palette
[
regno
].
transp
=
transp
;
switch
(
fb
->
var
.
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
outb
(
regno
,
0x3c8
);
outb
(
red
>>
10
,
0x3c9
);
outb
(
green
>>
10
,
0x3c9
);
outb
(
blue
>>
10
,
0x3c9
);
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
if
(
regno
<
16
)
((
u16
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
red
&
0xf800
)
)
|
((
green
&
0xfc00
)
>>
5
)
|
((
blue
&
0xf800
)
>>
11
);
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
if
(
regno
<
16
)
((
u32
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
red
&
0xff00
)
<<
8
)
|
((
green
&
0xff00
)
)
|
((
blue
&
0xff00
)
>>
8
);
break
;
#endif
#ifdef NO_32BIT_SUPPORT_YET
#ifdef FBCON_HAS_CFB32
case
32
:
if
(
regno
<
16
)
((
u32
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
transp
&
0xff00
)
<<
16
)
|
((
red
&
0xff00
)
<<
8
)
|
((
green
&
0xff00
)
)
|
((
blue
&
0xff00
)
>>
8
);
break
;
#endif
#endif
default:
return
1
;
}
return
0
;
}
static
void
vgaHWLock
(
void
)
{
/* Protect CRTC[0-7] */
VGAwCR
(
0x11
,
VGArCR
(
0x11
)
|
0x80
);
}
static
void
vgaHWUnlock
(
void
)
{
/* Unprotect CRTC[0-7] */
VGAwCR
(
0x11
,
VGArCR
(
0x11
)
&
~
0x80
);
}
static
void
neoLock
(
void
)
{
VGAwGR
(
0x09
,
0x00
);
vgaHWLock
();
}
static
void
neoUnlock
(
void
)
{
vgaHWUnlock
();
VGAwGR
(
0x09
,
0x26
);
}
/*
* vgaHWSeqReset
* perform a sequencer reset.
*/
void
vgaHWSeqReset
(
int
start
)
{
if
(
start
)
VGAwSEQ
(
0x00
,
0x01
);
/* Synchronous Reset */
else
VGAwSEQ
(
0x00
,
0x03
);
/* End Reset */
}
void
vgaHWProtect
(
int
on
)
{
unsigned
char
tmp
;
if
(
on
)
{
/*
* Turn off screen and disable sequencer.
*/
tmp
=
VGArSEQ
(
0x01
);
vgaHWSeqReset
(
1
);
/* start synchronous reset */
VGAwSEQ
(
0x01
,
tmp
|
0x20
);
/* disable the display */
VGAenablePalette
();
}
else
{
/*
* Reenable sequencer, then turn on screen.
*/
tmp
=
VGArSEQ
(
0x01
);
VGAwSEQ
(
0x01
,
tmp
&
~
0x20
);
/* reenable display */
vgaHWSeqReset
(
0
);
/* clear synchronousreset */
VGAdisablePalette
();
}
}
static
void
vgaHWRestore
(
const
struct
neofb_info
*
info
,
const
struct
neofb_par
*
par
)
{
int
i
;
VGAwMISC
(
par
->
MiscOutReg
);
for
(
i
=
1
;
i
<
5
;
i
++
)
VGAwSEQ
(
i
,
par
->
Sequencer
[
i
]);
/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
VGAwCR
(
17
,
par
->
CRTC
[
17
]
&
~
0x80
);
for
(
i
=
0
;
i
<
25
;
i
++
)
VGAwCR
(
i
,
par
->
CRTC
[
i
]);
for
(
i
=
0
;
i
<
9
;
i
++
)
VGAwGR
(
i
,
par
->
Graphics
[
i
]);
VGAenablePalette
();
for
(
i
=
0
;
i
<
21
;
i
++
)
VGAwATTR
(
i
,
par
->
Attribute
[
i
]);
VGAdisablePalette
();
}
static
void
neofb_set_par
(
struct
neofb_info
*
info
,
const
struct
neofb_par
*
par
)
{
unsigned
char
temp
;
int
i
;
int
clock_hi
=
0
;
DBG
(
"neofb_set_par"
);
neoUnlock
();
vgaHWProtect
(
1
);
/* Blank the screen */
/* linear colormap for non palettized modes */
switch
(
par
->
depth
)
{
case
8
:
break
;
case
16
:
for
(
i
=
0
;
i
<
64
;
i
++
)
{
outb
(
i
,
0x3c8
);
outb
(
i
<<
1
,
0x3c9
);
outb
(
i
,
0x3c9
);
outb
(
i
<<
1
,
0x3c9
);
}
break
;
case
24
:
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
#endif
for
(
i
=
0
;
i
<
256
;
i
++
)
{
outb
(
i
,
0x3c8
);
outb
(
i
,
0x3c9
);
outb
(
i
,
0x3c9
);
outb
(
i
,
0x3c9
);
}
break
;
}
/* alread unlocked above */
/* BOGUS VGAwGR (0x09, 0x26);*/
/* don't know what this is, but it's 0 from bootup anyway */
VGAwGR
(
0x15
,
0x00
);
/* was set to 0x01 by my bios in text and vesa modes */
VGAwGR
(
0x0A
,
par
->
GeneralLockReg
);
/*
* The color mode needs to be set before calling vgaHWRestore
* to ensure the DAC is initialized properly.
*
* NOTE: Make sure we don't change bits make sure we don't change
* any reserved bits.
*/
temp
=
VGArGR
(
0x90
);
switch
(
info
->
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
temp
&=
0xF0
;
/* Save bits 7:4 */
temp
|=
(
par
->
ExtColorModeSelect
&
~
0xF0
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
case
FB_ACCEL_NEOMAGIC_NM2093
:
case
FB_ACCEL_NEOMAGIC_NM2097
:
case
FB_ACCEL_NEOMAGIC_NM2160
:
case
FB_ACCEL_NEOMAGIC_NM2200
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
temp
&=
0x70
;
/* Save bits 6:4 */
temp
|=
(
par
->
ExtColorModeSelect
&
~
0x70
);
break
;
}
VGAwGR
(
0x90
,
temp
);
/*
* In some rare cases a lockup might occur if we don't delay
* here. (Reported by Miles Lane)
*/
//mdelay(200);
/*
* Disable horizontal and vertical graphics and text expansions so
* that vgaHWRestore works properly.
*/
temp
=
VGArGR
(
0x25
);
temp
&=
0x39
;
VGAwGR
(
0x25
,
temp
);
/*
* Sleep for 200ms to make sure that the two operations above have
* had time to take effect.
*/
mdelay
(
200
);
/*
* This function handles restoring the generic VGA registers. */
vgaHWRestore
(
info
,
par
);
VGAwGR
(
0x0E
,
par
->
ExtCRTDispAddr
);
VGAwGR
(
0x0F
,
par
->
ExtCRTOffset
);
temp
=
VGArGR
(
0x10
);
temp
&=
0x0F
;
/* Save bits 3:0 */
temp
|=
(
par
->
SysIfaceCntl1
&
~
0x0F
);
/* VESA Bios sets bit 1! */
VGAwGR
(
0x10
,
temp
);
VGAwGR
(
0x11
,
par
->
SysIfaceCntl2
);
VGAwGR
(
0x15
,
0
/*par->SingleAddrPage*/
);
VGAwGR
(
0x16
,
0
/*par->DualAddrPage*/
);
temp
=
VGArGR
(
0x20
);
switch
(
info
->
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
temp
&=
0xFC
;
/* Save bits 7:2 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0xFC
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
case
FB_ACCEL_NEOMAGIC_NM2093
:
case
FB_ACCEL_NEOMAGIC_NM2097
:
case
FB_ACCEL_NEOMAGIC_NM2160
:
temp
&=
0xDC
;
/* Save bits 7:6,4:2 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0xDC
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2200
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
temp
&=
0x98
;
/* Save bits 7,4:3 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0x98
);
break
;
}
VGAwGR
(
0x20
,
temp
);
temp
=
VGArGR
(
0x25
);
temp
&=
0x38
;
/* Save bits 5:3 */
temp
|=
(
par
->
PanelDispCntlReg2
&
~
0x38
);
VGAwGR
(
0x25
,
temp
);
if
(
info
->
accel
!=
FB_ACCEL_NEOMAGIC_NM2070
)
{
temp
=
VGArGR
(
0x30
);
temp
&=
0xEF
;
/* Save bits 7:5 and bits 3:0 */
temp
|=
(
par
->
PanelDispCntlReg3
&
~
0xEF
);
VGAwGR
(
0x30
,
temp
);
}
VGAwGR
(
0x28
,
par
->
PanelVertCenterReg1
);
VGAwGR
(
0x29
,
par
->
PanelVertCenterReg2
);
VGAwGR
(
0x2a
,
par
->
PanelVertCenterReg3
);
if
(
info
->
accel
!=
FB_ACCEL_NEOMAGIC_NM2070
)
{
VGAwGR
(
0x32
,
par
->
PanelVertCenterReg4
);
VGAwGR
(
0x33
,
par
->
PanelHorizCenterReg1
);
VGAwGR
(
0x34
,
par
->
PanelHorizCenterReg2
);
VGAwGR
(
0x35
,
par
->
PanelHorizCenterReg3
);
}
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2160
)
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
VGAwGR
(
0x37
,
par
->
PanelVertCenterReg5
);
VGAwGR
(
0x38
,
par
->
PanelHorizCenterReg5
);
clock_hi
=
1
;
}
/* --------------------------------------------------------------------- */
/* Program VCLK3 if needed. */
if
(
par
->
ProgramVCLK
&&
((
VGArGR
(
0x9B
)
!=
par
->
VCLK3NumeratorLow
)
||
(
VGArGR
(
0x9F
)
!=
par
->
VCLK3Denominator
)
||
(
clock_hi
&&
((
VGArGR
(
0x8F
)
&
~
0x0f
)
!=
(
par
->
VCLK3NumeratorHigh
&
~
0x0F
)))))
{
VGAwGR
(
0x9B
,
par
->
VCLK3NumeratorLow
);
if
(
clock_hi
)
{
temp
=
VGArGR
(
0x8F
);
temp
&=
0x0F
;
/* Save bits 3:0 */
temp
|=
(
par
->
VCLK3NumeratorHigh
&
~
0x0F
);
VGAwGR
(
0x8F
,
temp
);
}
VGAwGR
(
0x9F
,
par
->
VCLK3Denominator
);
}
static
int
disabled
=
0
;
static
int
internal
=
0
;
static
int
external
=
0
;
static
int
nostretch
=
0
;
static
int
nopciburst
=
0
;
if
(
par
->
biosMode
)
VGAwCR
(
0x23
,
par
->
biosMode
);
VGAwGR
(
0x93
,
0xc0
);
/* Gives 5x faster framebuffer writes !!! */
#ifdef MODULE
/* Program vertical extension register */
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
VGAwCR
(
0x70
,
par
->
VerticalExt
);
}
MODULE_AUTHOR
(
"(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_DESCRIPTION
(
"FBDev driver for NeoMagic PCI Chips"
);
MODULE_PARM
(
disabled
,
"i"
);
MODULE_PARM_DESC
(
disabled
,
"Disable this driver's initialization."
);
MODULE_PARM
(
internal
,
"i"
);
MODULE_PARM_DESC
(
internal
,
"Enable output on internal LCD Display."
);
MODULE_PARM
(
external
,
"i"
);
MODULE_PARM_DESC
(
external
,
"Enable output on external CRT."
);
MODULE_PARM
(
nostretch
,
"i"
);
MODULE_PARM_DESC
(
nostretch
,
"Disable stretching of modes smaller than LCD."
);
MODULE_PARM
(
nopciburst
,
"i"
);
MODULE_PARM_DESC
(
nopciburst
,
"Disable PCI burst mode."
);
#endif
vgaHWProtect
(
0
);
/* Turn on screen */
/* Calling this also locks offset registers required in update_start */
neoLock
();
}
/* --------------------------------------------------------------------- */
static
void
neofb_update_start
(
struct
neofb_info
*
info
,
struct
fb_var_screeninfo
*
var
)
{
int
oldExtCRTDispAddr
;
int
Base
;
static
biosMode
bios8
[]
=
{
{
320
,
240
,
0x40
},
{
300
,
400
,
0x42
},
{
640
,
400
,
0x20
},
{
640
,
480
,
0x21
},
{
800
,
600
,
0x23
},
{
1024
,
768
,
0x25
},
};
DBG
(
"neofb_update_start"
);
static
biosMode
bios16
[]
=
{
{
320
,
200
,
0x2e
},
{
320
,
240
,
0x41
},
{
300
,
400
,
0x43
},
{
640
,
480
,
0x31
},
{
800
,
600
,
0x34
},
{
1024
,
768
,
0x37
},
};
Base
=
(
var
->
yoffset
*
var
->
xres_virtual
+
var
->
xoffset
)
>>
2
;
Base
*=
(
var
->
bits_per_pixel
+
7
)
/
8
;
static
biosMode
bios24
[]
=
{
{
640
,
480
,
0x32
},
{
800
,
600
,
0x35
},
{
1024
,
768
,
0x38
}
};
neoUnlock
();
#ifdef NO_32BIT_SUPPORT_YET
/* FIXME: guessed values, wrong */
static
biosMode
bios32
[]
=
{
{
640
,
480
,
0x33
},
{
800
,
600
,
0x36
},
{
1024
,
768
,
0x39
}
};
#endif
/*
* These are the generic starting address registers.
*/
VGAwCR
(
0x0C
,
(
Base
&
0x00FF00
)
>>
8
)
;
VGAwCR
(
0x0D
,
(
Base
&
0x00FF
))
;
static
int
neoFindMode
(
int
xres
,
int
yres
,
int
depth
)
{
int
xres_s
;
int
i
,
size
;
biosMode
*
mode
;
/*
* Make sure we don't clobber some other bits that might already
* have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
* be needed.
*/
oldExtCRTDispAddr
=
VGArGR
(
0x0E
);
VGAwGR
(
0x0E
,(((
Base
>>
16
)
&
0x0f
)
|
(
oldExtCRTDispAddr
&
0xf0
)));
switch
(
depth
)
{
case
8
:
size
=
sizeof
(
bios8
)
/
sizeof
(
biosMode
);
mode
=
bios8
;
break
;
case
16
:
size
=
sizeof
(
bios16
)
/
sizeof
(
biosMode
);
mode
=
bios16
;
break
;
case
24
:
size
=
sizeof
(
bios24
)
/
sizeof
(
biosMode
);
mode
=
bios24
;
break
;
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
size
=
sizeof
(
bios32
)
/
sizeof
(
biosMode
);
mode
=
bios32
;
break
;
#endif
default:
return
0
;
}
neoLock
();
for
(
i
=
0
;
i
<
size
;
i
++
)
{
if
(
xres
<=
mode
[
i
].
x_res
)
{
xres_s
=
mode
[
i
].
x_res
;
for
(;
i
<
size
;
i
++
)
{
if
(
mode
[
i
].
x_res
!=
xres_s
)
return
mode
[
i
-
1
].
mode
;
if
(
yres
<=
mode
[
i
].
y_res
)
return
mode
[
i
].
mode
;
}
}
}
return
mode
[
size
-
1
].
mode
;
}
/*
...
...
@@ -840,7 +191,8 @@ static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninf
#define MAX_D 31
#define MAX_F 1
static
void
neoCalcVCLK
(
const
struct
neofb_info
*
info
,
struct
neofb_par
*
par
,
long
freq
)
static
void
neoCalcVCLK
(
const
struct
fb_info
*
info
,
struct
neofb_par
*
par
,
long
freq
)
{
int
n
,
d
,
f
;
int
n_best
=
0
,
d_best
=
0
,
f_best
=
0
;
...
...
@@ -849,15 +201,17 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
for
(
f
=
0
;
f
<=
MAX_F
;
f
++
)
for
(
n
=
0
;
n
<=
MAX_N
;
n
++
)
for
(
d
=
0
;
d
<=
MAX_D
;
d
++
)
{
for
(
d
=
0
;
d
<=
MAX_D
;
d
++
)
{
long
f_out
;
/* 20.12 */
long
f_diff
;
/* 20.12 */
f_out
=
((((
n
+
1
)
<<
12
)
/
((
d
+
1
)
*
(
1
<<
f
)))
>>
12
)
*
REF_FREQ
;
f_diff
=
abs
(
f_out
-
f_target
);
if
(
f_diff
<
f_best_diff
)
{
f_out
=
((((
n
+
1
)
<<
12
)
/
((
d
+
1
)
*
(
1
<<
f
)))
>>
12
)
*
REF_FREQ
;
f_diff
=
abs
(
f_out
-
f_target
);
if
(
f_diff
<
f_best_diff
)
{
f_best_diff
=
f_diff
;
n_best
=
n
;
d_best
=
d
;
...
...
@@ -865,28 +219,25 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
}
}
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
/* NOT_DONE: We are trying the full range of the 2200 clock.
We should be able to try n up to 2047 */
par
->
VCLK3NumeratorLow
=
n_best
;
par
->
VCLK3NumeratorHigh
=
(
f_best
<<
7
);
}
else
}
else
par
->
VCLK3NumeratorLow
=
n_best
|
(
f_best
<<
7
);
par
->
VCLK3Denominator
=
d_best
;
#ifdef NEOFB_DEBUG
printk
(
"neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d
\n
"
,
printk
(
"neoVCLK: f:%d NumLow=%d NumHi=%d Den=%d Df=%d
\n
"
,
f_target
>>
12
,
par
->
VCLK3NumeratorLow
,
par
->
VCLK3NumeratorHigh
,
par
->
VCLK3Denominator
,
f_best_diff
>>
12
);
par
->
VCLK3Denominator
,
f_best_diff
>>
12
);
#endif
}
...
...
@@ -896,10 +247,9 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
* Return FALSE on failure.
*/
static
int
vgaHWInit
(
const
struct
fb_var_screeninfo
*
var
,
const
struct
neofb_info
*
info
,
struct
neofb_par
*
par
,
struct
xtimings
*
timings
)
static
int
vgaHWInit
(
const
struct
fb_var_screeninfo
*
var
,
const
struct
fb_info
*
info
,
struct
neofb_par
*
par
,
struct
xtimings
*
timings
)
{
par
->
MiscOutReg
=
0x23
;
...
...
@@ -933,8 +283,7 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
7
)
|
((
timings
->
VSyncStart
&
0x100
)
>>
6
)
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
5
)
|
0x10
|
(((
timings
->
VTotal
-
2
)
&
0x200
)
>>
4
)
|
0x10
|
(((
timings
->
VTotal
-
2
)
&
0x200
)
>>
4
)
|
(((
timings
->
VDisplay
-
1
)
&
0x200
)
>>
3
)
|
((
timings
->
VSyncStart
&
0x200
)
>>
2
);
par
->
CRTC
[
8
]
=
0x00
;
...
...
@@ -979,47 +328,216 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
par
->
Graphics
[
8
]
=
0xFF
;
par
->
Attribute
[
0
]
=
0x00
;
/* standard colormap translation */
par
->
Attribute
[
1
]
=
0x01
;
par
->
Attribute
[
2
]
=
0x02
;
par
->
Attribute
[
3
]
=
0x03
;
par
->
Attribute
[
4
]
=
0x04
;
par
->
Attribute
[
5
]
=
0x05
;
par
->
Attribute
[
6
]
=
0x06
;
par
->
Attribute
[
7
]
=
0x07
;
par
->
Attribute
[
8
]
=
0x08
;
par
->
Attribute
[
9
]
=
0x09
;
par
->
Attribute
[
10
]
=
0x0A
;
par
->
Attribute
[
11
]
=
0x0B
;
par
->
Attribute
[
12
]
=
0x0C
;
par
->
Attribute
[
13
]
=
0x0D
;
par
->
Attribute
[
14
]
=
0x0E
;
par
->
Attribute
[
15
]
=
0x0F
;
par
->
Attribute
[
16
]
=
0x41
;
par
->
Attribute
[
17
]
=
0xFF
;
par
->
Attribute
[
18
]
=
0x0F
;
par
->
Attribute
[
19
]
=
0x00
;
par
->
Attribute
[
20
]
=
0x00
;
par
->
Attribute
[
0
]
=
0x00
;
/* standard colormap translation */
par
->
Attribute
[
1
]
=
0x01
;
par
->
Attribute
[
2
]
=
0x02
;
par
->
Attribute
[
3
]
=
0x03
;
par
->
Attribute
[
4
]
=
0x04
;
par
->
Attribute
[
5
]
=
0x05
;
par
->
Attribute
[
6
]
=
0x06
;
par
->
Attribute
[
7
]
=
0x07
;
par
->
Attribute
[
8
]
=
0x08
;
par
->
Attribute
[
9
]
=
0x09
;
par
->
Attribute
[
10
]
=
0x0A
;
par
->
Attribute
[
11
]
=
0x0B
;
par
->
Attribute
[
12
]
=
0x0C
;
par
->
Attribute
[
13
]
=
0x0D
;
par
->
Attribute
[
14
]
=
0x0E
;
par
->
Attribute
[
15
]
=
0x0F
;
par
->
Attribute
[
16
]
=
0x41
;
par
->
Attribute
[
17
]
=
0xFF
;
par
->
Attribute
[
18
]
=
0x0F
;
par
->
Attribute
[
19
]
=
0x00
;
par
->
Attribute
[
20
]
=
0x00
;
return
0
;
}
static
void
vgaHWLock
(
void
)
{
/* Protect CRTC[0-7] */
VGAwCR
(
0x11
,
VGArCR
(
0x11
)
|
0x80
);
}
static
void
vgaHWUnlock
(
void
)
{
/* Unprotect CRTC[0-7] */
VGAwCR
(
0x11
,
VGArCR
(
0x11
)
&
~
0x80
);
}
static
void
neoLock
(
void
)
{
VGAwGR
(
0x09
,
0x00
);
vgaHWLock
();
}
static
void
neoUnlock
(
void
)
{
vgaHWUnlock
();
VGAwGR
(
0x09
,
0x26
);
}
/*
* vgaHWSeqReset
* perform a sequencer reset.
*/
void
vgaHWSeqReset
(
int
start
)
{
if
(
start
)
VGAwSEQ
(
0x00
,
0x01
);
/* Synchronous Reset */
else
VGAwSEQ
(
0x00
,
0x03
);
/* End Reset */
}
void
vgaHWProtect
(
int
on
)
{
unsigned
char
tmp
;
if
(
on
)
{
/*
* Turn off screen and disable sequencer.
*/
tmp
=
VGArSEQ
(
0x01
);
vgaHWSeqReset
(
1
);
/* start synchronous reset */
VGAwSEQ
(
0x01
,
tmp
|
0x20
);
/* disable the display */
VGAenablePalette
();
}
else
{
/*
* Reenable sequencer, then turn on screen.
*/
tmp
=
VGArSEQ
(
0x01
);
VGAwSEQ
(
0x01
,
tmp
&
~
0x20
);
/* reenable display */
vgaHWSeqReset
(
0
);
/* clear synchronousreset */
VGAdisablePalette
();
}
}
static
void
vgaHWRestore
(
const
struct
fb_info
*
info
,
const
struct
neofb_par
*
par
)
{
int
i
;
VGAwMISC
(
par
->
MiscOutReg
);
for
(
i
=
1
;
i
<
5
;
i
++
)
VGAwSEQ
(
i
,
par
->
Sequencer
[
i
]);
/* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 or CRTC[17] */
VGAwCR
(
17
,
par
->
CRTC
[
17
]
&
~
0x80
);
for
(
i
=
0
;
i
<
25
;
i
++
)
VGAwCR
(
i
,
par
->
CRTC
[
i
]);
for
(
i
=
0
;
i
<
9
;
i
++
)
VGAwGR
(
i
,
par
->
Graphics
[
i
]);
VGAenablePalette
();
for
(
i
=
0
;
i
<
21
;
i
++
)
VGAwATTR
(
i
,
par
->
Attribute
[
i
]);
VGAdisablePalette
();
}
/* -------------------- Hardware specific routines ------------------------- */
/*
* Hardware Acceleration for Neo2200+
*/
static
inline
void
neo2200_wait_idle
(
struct
neofb_par
*
par
)
{
int
waitcycles
;
while
(
par
->
neo2200
->
bltStat
&
1
)
waitcycles
++
;
}
static
inline
void
neo2200_wait_fifo
(
struct
neofb_par
*
par
,
int
requested_fifo_space
)
{
// ndev->neo.waitfifo_calls++;
// ndev->neo.waitfifo_sum += requested_fifo_space;
/* FIXME: does not work
if (neo_fifo_space < requested_fifo_space)
{
neo_fifo_waitcycles++;
while (1)
{
neo_fifo_space = (neo2200->bltStat >> 8);
if (neo_fifo_space >= requested_fifo_space)
break;
}
}
else
{
neo_fifo_cache_hits++;
}
neo_fifo_space -= requested_fifo_space;
*/
neo2200_wait_idle
(
par
);
}
static
inline
void
neo2200_accel_init
(
struct
fb_info
*
fb
,
struct
fb_var_screeninfo
*
var
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
fb
->
par
;
Neo2200
*
neo2200
=
par
->
neo2200
;
u32
bltMod
,
pitch
;
neo2200_wait_idle
(
par
);
switch
(
var
->
bits_per_pixel
)
{
case
8
:
bltMod
=
NEO_MODE1_DEPTH8
;
pitch
=
var
->
xres_virtual
;
break
;
case
15
:
case
16
:
bltMod
=
NEO_MODE1_DEPTH16
;
pitch
=
var
->
xres_virtual
*
2
;
break
;
default:
printk
(
KERN_ERR
"neofb: neo2200_accel_init: unexpected bits per pixel!
\n
"
);
return
;
}
return
0
;
neo2200
->
bltStat
=
bltMod
<<
16
;
neo2200
->
pitch
=
(
pitch
<<
16
)
|
pitch
;
}
static
int
neofb_decode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
neofb_info
*
info
,
struct
neofb_par
*
par
)
/* --------------------------------------------------------------------- */
static
int
neofb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
unsigned
int
pixclock
=
var
->
pixclock
;
struct
xtimings
timings
;
int
lcd_stretch
;
int
hoffset
,
voffset
;
int
memlen
,
vramlen
;
int
mode_ok
=
0
;
unsigned
int
pixclock
=
var
->
pixclock
;
DBG
(
"neofb_decode
_var"
);
DBG
(
"neofb_check
_var"
);
if
(
!
pixclock
)
pixclock
=
10000
;
/* 10ns = 100MHz */
if
(
!
pixclock
)
pixclock
=
10000
;
/* 10ns = 100MHz */
timings
.
pixclock
=
1000000000
/
pixclock
;
if
(
timings
.
pixclock
<
1
)
timings
.
pixclock
=
1
;
if
(
timings
.
pixclock
<
1
)
timings
.
pixclock
=
1
;
if
(
timings
.
pixclock
>
par
->
maxClock
)
return
-
EINVAL
;
timings
.
dblscan
=
var
->
vmode
&
FB_VMODE_DOUBLE
;
timings
.
interlaced
=
var
->
vmode
&
FB_VMODE_INTERLACED
;
timings
.
HDisplay
=
var
->
xres
;
...
...
@@ -1032,24 +550,18 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
timings
.
VTotal
=
timings
.
VSyncEnd
+
var
->
upper_margin
;
timings
.
sync
=
var
->
sync
;
if
(
timings
.
pixclock
>
info
->
maxClock
)
return
-
EINVAL
;
/* Is the mode larger than the LCD panel? */
if
((
var
->
xres
>
info
->
NeoPanelWidth
)
||
(
var
->
yres
>
info
->
NeoPanelHeight
))
{
printk
(
KERN_INFO
"Mode (%dx%d) larger than the LCD panel (%dx%d)
\n
"
,
var
->
xres
,
var
->
yres
,
info
->
NeoPanelWidth
,
info
->
NeoPanelHeight
);
if
((
var
->
xres
>
par
->
NeoPanelWidth
)
||
(
var
->
yres
>
par
->
NeoPanelHeight
))
{
printk
(
KERN_INFO
"Mode (%dx%d) larger than the LCD panel (%dx%d)
\n
"
,
var
->
xres
,
var
->
yres
,
par
->
NeoPanelWidth
,
par
->
NeoPanelHeight
);
return
-
EINVAL
;
}
/* Is the mode one of the acceptable sizes? */
switch
(
var
->
xres
)
{
switch
(
var
->
xres
)
{
case
1280
:
if
(
var
->
yres
==
1024
)
mode_ok
=
1
;
...
...
@@ -1068,58 +580,87 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
break
;
}
if
(
!
mode_ok
)
{
printk
(
KERN_INFO
"Mode (%dx%d) won't display properly on LCD
\n
"
,
if
(
!
mode_ok
)
{
printk
(
KERN_INFO
"Mode (%dx%d) won't display properly on LCD
\n
"
,
var
->
xres
,
var
->
yres
);
return
-
EINVAL
;
}
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
switch
(
var
->
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
switch
(
var
->
bits_per_pixel
)
{
case
8
:
/* PSEUDOCOLOUR, 256 */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
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
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
case
16
:
/* DIRECTCOLOUR, 64k */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
var
->
red
.
offset
=
11
;
var
->
red
.
length
=
5
;
var
->
green
.
offset
=
5
;
var
->
green
.
length
=
6
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
5
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
case
24
:
/* TRUECOLOUR, 16m */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
var
->
red
.
offset
=
16
;
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
break
;
#endif
#ifdef NO_32BIT_SUPPORT_YET
# ifdef FBCON_HAS_CFB32
case
32
:
case
32
:
/* TRUECOLOUR, 16m */
var
->
transp
.
offset
=
24
;
var
->
transp
.
length
=
8
;
var
->
red
.
offset
=
16
;
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
8
;
break
;
# endif
#endif
default:
printk
(
KERN_WARNING
"neofb: no support for %dbpp
\n
"
,
var
->
bits_per_pixel
);
return
-
EINVAL
;
}
par
->
depth
=
var
->
bits_per_pixel
;
vramlen
=
info
->
video
.
len
;
if
(
vramlen
>
4
*
1024
*
1024
)
vramlen
=
4
*
1024
*
1024
;
vramlen
=
info
->
fix
.
smem_len
;
if
(
vramlen
>
4
*
1024
*
1024
)
vramlen
=
4
*
1024
*
1024
;
if
(
var
->
yres_virtual
<
var
->
yres
)
var
->
yres_virtual
=
var
->
yres
;
if
(
var
->
xres_virtual
<
var
->
xres
)
var
->
xres_virtual
=
var
->
xres
;
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
if
(
memlen
>
vramlen
)
{
var
->
yres_virtual
=
vramlen
*
8
/
(
var
->
xres_virtual
*
var
->
bits_per_pixel
);
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
if
(
memlen
>
vramlen
)
{
var
->
yres_virtual
=
vramlen
*
8
/
(
var
->
xres_virtual
*
var
->
bits_per_pixel
);
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
}
/* we must round yres/xres down, we already rounded y/xres_virtual up
...
...
@@ -1133,13 +674,48 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
if
(
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
)
var
->
yoffset
=
var
->
yres_virtual
-
var
->
yres
;
if
(
var
->
bits_per_pixel
>=
24
||
!
par
->
neo2200
)
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
return
0
;
}
static
int
neofb_set_par
(
struct
fb_info
*
info
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
struct
xtimings
timings
;
unsigned
char
temp
;
int
i
,
clock_hi
=
0
;
int
lcd_stretch
;
int
hoffset
,
voffset
;
DBG
(
"neofb_set_par"
);
neoUnlock
();
vgaHWProtect
(
1
);
/* Blank the screen */
timings
.
dblscan
=
info
->
var
.
vmode
&
FB_VMODE_DOUBLE
;
timings
.
interlaced
=
info
->
var
.
vmode
&
FB_VMODE_INTERLACED
;
timings
.
HDisplay
=
info
->
var
.
xres
;
timings
.
HSyncStart
=
timings
.
HDisplay
+
info
->
var
.
right_margin
;
timings
.
HSyncEnd
=
timings
.
HSyncStart
+
info
->
var
.
hsync_len
;
timings
.
HTotal
=
timings
.
HSyncEnd
+
info
->
var
.
left_margin
;
timings
.
VDisplay
=
info
->
var
.
yres
;
timings
.
VSyncStart
=
timings
.
VDisplay
+
info
->
var
.
lower_margin
;
timings
.
VSyncEnd
=
timings
.
VSyncStart
+
info
->
var
.
vsync_len
;
timings
.
VTotal
=
timings
.
VSyncEnd
+
info
->
var
.
upper_margin
;
timings
.
sync
=
info
->
var
.
sync
;
timings
.
pixclock
=
PICOS2KHZ
(
info
->
var
.
pixclock
);
if
(
timings
.
pixclock
<
1
)
timings
.
pixclock
=
1
;
/*
* This will allocate the datastructure and initialize all of the
* generic VGA registers.
*/
if
(
vgaHWInit
(
var
,
info
,
par
,
&
timings
))
if
(
vgaHWInit
(
&
info
->
var
,
info
,
par
,
&
timings
))
return
-
EINVAL
;
/*
...
...
@@ -1148,27 +724,26 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
*/
par
->
Attribute
[
16
]
=
0x01
;
switch
(
var
->
bits_per_pixel
)
{
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
3
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
11
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
3
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
11
;
par
->
ExtColorModeSelect
=
0x11
;
break
;
case
16
:
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
2
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
10
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
2
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
10
;
par
->
ExtColorModeSelect
=
0x13
;
break
;
case
24
:
par
->
CRTC
[
0x13
]
=
(
var
->
xres_virtual
*
3
)
>>
3
;
par
->
ExtCRTOffset
=
(
var
->
xres_virtual
*
3
)
>>
11
;
par
->
CRTC
[
0x13
]
=
(
info
->
var
.
xres_virtual
*
3
)
>>
3
;
par
->
ExtCRTOffset
=
(
info
->
var
.
xres_virtual
*
3
)
>>
11
;
par
->
ExtColorModeSelect
=
0x14
;
break
;
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
/* FIXME: guessed values */
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
1
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
9
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
1
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
9
;
par
->
ExtColorModeSelect
=
0x15
;
break
;
#endif
...
...
@@ -1179,13 +754,13 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
ExtCRTDispAddr
=
0x10
;
/* Vertical Extension */
par
->
VerticalExt
=
(((
timings
.
VTotal
-
2
)
&
0x400
)
>>
10
)
|
(((
timings
.
VDisplay
-
1
)
&
0x400
)
>>
9
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
8
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
7
);
par
->
VerticalExt
=
(((
timings
.
VTotal
-
2
)
&
0x400
)
>>
10
)
|
(((
timings
.
VDisplay
-
1
)
&
0x400
)
>>
9
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
8
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
7
);
/* Fast write bursts on unless disabled. */
if
(
info
->
pci_burst
)
if
(
par
->
pci_burst
)
par
->
SysIfaceCntl1
=
0x30
;
else
par
->
SysIfaceCntl1
=
0x00
;
...
...
@@ -1194,9 +769,9 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
/* Enable any user specified display devices. */
par
->
PanelDispCntlReg1
=
0x00
;
if
(
info
->
internal_display
)
if
(
par
->
internal_display
)
par
->
PanelDispCntlReg1
|=
0x02
;
if
(
info
->
external_display
)
if
(
par
->
external_display
)
par
->
PanelDispCntlReg1
|=
0x01
;
/* If the user did not specify any display devices, then... */
...
...
@@ -1206,8 +781,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
}
/* If we are using a fixed mode, then tell the chip we are. */
switch
(
var
->
xres
)
{
switch
(
info
->
var
.
xres
)
{
case
1280
:
par
->
PanelDispCntlReg1
|=
0x60
;
break
;
...
...
@@ -1223,8 +797,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
}
/* Setup shadow register locking. */
switch
(
par
->
PanelDispCntlReg1
&
0x03
)
{
switch
(
par
->
PanelDispCntlReg1
&
0x03
)
{
case
0x01
:
/* External CRT only mode: */
par
->
GeneralLockReg
=
0x00
;
/* We need to program the VCLK for external display only mode. */
...
...
@@ -1247,12 +820,9 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
PanelDispCntlReg2
=
0x00
;
par
->
PanelDispCntlReg3
=
0x00
;
if
(
info
->
lcd_stretch
&&
(
par
->
PanelDispCntlReg1
==
0x02
)
&&
/* LCD only */
(
var
->
xres
!=
info
->
NeoPanelWidth
))
{
switch
(
var
->
xres
)
{
if
(
par
->
lcd_stretch
&&
(
par
->
PanelDispCntlReg1
==
0x02
)
&&
/* LCD only */
(
info
->
var
.
xres
!=
par
->
NeoPanelWidth
))
{
switch
(
info
->
var
.
xres
)
{
case
320
:
/* Needs testing. KEM -- 24 May 98 */
case
400
:
/* Needs testing. KEM -- 24 May 98 */
case
640
:
...
...
@@ -1265,8 +835,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
lcd_stretch
=
0
;
/* No stretching in these modes. */
}
}
else
}
else
lcd_stretch
=
0
;
/*
...
...
@@ -1285,35 +854,31 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
PanelHorizCenterReg5
=
0x00
;
if
(
par
->
PanelDispCntlReg1
&
0x02
)
{
if
(
var
->
xres
==
info
->
NeoPanelWidth
)
{
if
(
par
->
PanelDispCntlReg1
&
0x02
)
{
if
(
info
->
var
.
xres
==
par
->
NeoPanelWidth
)
{
/*
* No centering required when the requested display width
* equals the panel width.
*/
}
else
{
}
else
{
par
->
PanelDispCntlReg2
|=
0x01
;
par
->
PanelDispCntlReg3
|=
0x10
;
/* Calculate the horizontal and vertical offsets. */
if
(
!
lcd_stretch
)
{
hoffset
=
((
info
->
NeoPanelWidth
-
var
->
xres
)
>>
4
)
-
1
;
voffset
=
((
info
->
NeoPanelHeight
-
var
->
yres
)
>>
1
)
-
2
;
}
else
{
if
(
!
lcd_stretch
)
{
hoffset
=
((
par
->
NeoPanelWidth
-
info
->
var
.
xres
)
>>
4
)
-
1
;
voffset
=
((
par
->
NeoPanelHeight
-
info
->
var
.
yres
)
>>
1
)
-
2
;
}
else
{
/* Stretched modes cannot be centered. */
hoffset
=
0
;
voffset
=
0
;
}
switch
(
var
->
xres
)
{
switch
(
info
->
var
.
xres
)
{
case
320
:
/* Needs testing. KEM -- 24 May 98 */
par
->
PanelHorizCenterReg3
=
hoffset
;
par
->
PanelVertCenterReg2
=
voffset
;
...
...
@@ -1342,210 +907,268 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
}
}
par
->
biosMode
=
neoFindMode
(
var
->
xres
,
var
->
yres
,
var
->
bits_per_pixel
);
par
->
biosMode
=
neoFindMode
(
info
->
var
.
xres
,
info
->
var
.
yres
,
info
->
var
.
bits_per_pixel
);
/*
* Calculate the VCLK that most closely matches the requested dot
* clock.
*/
neoCalcVCLK
(
info
,
par
,
timings
.
pixclock
);
neoCalcVCLK
(
info
,
par
,
timings
.
pixclock
);
/* Since we program the clocks ourselves, always use VCLK3. */
par
->
MiscOutReg
|=
0x0C
;
return
0
;
}
/* linear colormap for non palettized modes */
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
/* PseudoColor, 256 */
info
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
break
;
case
16
:
/* DirectColor, 64k */
info
->
fix
.
visual
=
FB_VISUAL_DIRECTCOLOR
;
static
int
neofb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
struct
display
*
display
;
struct
neofb_par
par
;
int
err
,
chgvar
=
0
;
for
(
i
=
0
;
i
<
64
;
i
++
)
{
outb
(
i
,
0x3c8
);
outb
(
i
<<
1
,
0x3c9
);
outb
(
i
,
0x3c9
);
outb
(
i
<<
1
,
0x3c9
);
}
break
;
case
24
:
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
#endif
/* TrueColor, 16m */
info
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
DBG
(
"neofb_set_var"
);
for
(
i
=
0
;
i
<
256
;
i
++
)
{
outb
(
i
,
0x3c8
);
err
=
neofb_decode_var
(
var
,
info
,
&
par
);
if
(
err
)
return
err
;
outb
(
i
,
0x3c9
);
outb
(
i
,
0x3c9
);
outb
(
i
,
0x3c9
);
}
break
;
}
/* alread unlocked above */
/* BOGUS VGAwGR (0x09, 0x26); */
/* don't know what this is, but it's 0 from bootup anyway */
VGAwGR
(
0x15
,
0x00
);
/* was set to 0x01 by my bios in text and vesa modes */
VGAwGR
(
0x0A
,
par
->
GeneralLockReg
);
/*
* The color mode needs to be set before calling vgaHWRestore
* to ensure the DAC is initialized properly.
*
* NOTE: Make sure we don't change bits make sure we don't change
* any reserved bits.
*/
temp
=
VGArGR
(
0x90
);
switch
(
info
->
fix
.
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
temp
&=
0xF0
;
/* Save bits 7:4 */
temp
|=
(
par
->
ExtColorModeSelect
&
~
0xF0
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
case
FB_ACCEL_NEOMAGIC_NM2093
:
case
FB_ACCEL_NEOMAGIC_NM2097
:
case
FB_ACCEL_NEOMAGIC_NM2160
:
case
FB_ACCEL_NEOMAGIC_NM2200
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
temp
&=
0x70
;
/* Save bits 6:4 */
temp
|=
(
par
->
ExtColorModeSelect
&
~
0x70
);
break
;
}
VGAwGR
(
0x90
,
temp
);
/*
* In some rare cases a lockup might occur if we don't delay
* here. (Reported by Miles Lane)
*/
//mdelay(200);
/*
* Disable horizontal and vertical graphics and text expansions so
* that vgaHWRestore works properly.
*/
temp
=
VGArGR
(
0x25
);
temp
&=
0x39
;
VGAwGR
(
0x25
,
temp
);
/*
* Sleep for 200ms to make sure that the two operations above have
* had time to take effect.
*/
mdelay
(
200
);
/*
* This function handles restoring the generic VGA registers. */
vgaHWRestore
(
info
,
par
);
VGAwGR
(
0x0E
,
par
->
ExtCRTDispAddr
);
VGAwGR
(
0x0F
,
par
->
ExtCRTOffset
);
temp
=
VGArGR
(
0x10
);
temp
&=
0x0F
;
/* Save bits 3:0 */
temp
|=
(
par
->
SysIfaceCntl1
&
~
0x0F
);
/* VESA Bios sets bit 1! */
VGAwGR
(
0x10
,
temp
);
VGAwGR
(
0x11
,
par
->
SysIfaceCntl2
);
VGAwGR
(
0x15
,
0
/*par->SingleAddrPage */
);
VGAwGR
(
0x16
,
0
/*par->DualAddrPage */
);
temp
=
VGArGR
(
0x20
);
switch
(
info
->
fix
.
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
temp
&=
0xFC
;
/* Save bits 7:2 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0xFC
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
case
FB_ACCEL_NEOMAGIC_NM2093
:
case
FB_ACCEL_NEOMAGIC_NM2097
:
case
FB_ACCEL_NEOMAGIC_NM2160
:
temp
&=
0xDC
;
/* Save bits 7:6,4:2 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0xDC
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2200
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
temp
&=
0x98
;
/* Save bits 7,4:3 */
temp
|=
(
par
->
PanelDispCntlReg1
&
~
0x98
);
break
;
}
VGAwGR
(
0x20
,
temp
);
temp
=
VGArGR
(
0x25
);
temp
&=
0x38
;
/* Save bits 5:3 */
temp
|=
(
par
->
PanelDispCntlReg2
&
~
0x38
);
VGAwGR
(
0x25
,
temp
);
if
(
info
->
fix
.
accel
!=
FB_ACCEL_NEOMAGIC_NM2070
)
{
temp
=
VGArGR
(
0x30
);
temp
&=
0xEF
;
/* Save bits 7:5 and bits 3:0 */
temp
|=
(
par
->
PanelDispCntlReg3
&
~
0xEF
);
VGAwGR
(
0x30
,
temp
);
}
if
(
var
->
activate
&
FB_ACTIVATE_TEST
)
return
0
;
VGAwGR
(
0x28
,
par
->
PanelVertCenterReg1
);
VGAwGR
(
0x29
,
par
->
PanelVertCenterReg2
);
VGAwGR
(
0x2a
,
par
->
PanelVertCenterReg3
);
if
(
con
<
0
)
{
display
=
fb
->
disp
;
chgvar
=
0
;
}
else
{
display
=
fb_display
+
con
;
if
(
fb
->
var
.
xres
!=
var
->
xres
)
chgvar
=
1
;
if
(
fb
->
var
.
yres
!=
var
->
yres
)
chgvar
=
1
;
if
(
fb
->
var
.
xres_virtual
!=
var
->
xres_virtual
)
chgvar
=
1
;
if
(
fb
->
var
.
yres_virtual
!=
var
->
yres_virtual
)
chgvar
=
1
;
if
(
fb
->
var
.
bits_per_pixel
!=
var
->
bits_per_pixel
)
chgvar
=
1
;
if
(
info
->
fix
.
accel
!=
FB_ACCEL_NEOMAGIC_NM2070
)
{
VGAwGR
(
0x32
,
par
->
PanelVertCenterReg4
);
VGAwGR
(
0x33
,
par
->
PanelHorizCenterReg1
);
VGAwGR
(
0x34
,
par
->
PanelHorizCenterReg2
);
VGAwGR
(
0x35
,
par
->
PanelHorizCenterReg3
);
}
if
(
!
info
->
neo2200
)
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2160
)
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
switch
(
var
->
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
/* PSEUDOCOLOUR, 256 */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
var
->
red
.
offset
=
0
;
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
0
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
8
;
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
VGAwGR
(
0x37
,
par
->
PanelVertCenterReg5
);
VGAwGR
(
0x38
,
par
->
PanelHorizCenterReg5
);
fb
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
info
->
dispsw
=
&
fbcon_cfb8
;
display
->
dispsw_data
=
NULL
;
display
->
next_line
=
var
->
xres_virtual
;
break
;
#endif
clock_hi
=
1
;
}
#ifdef FBCON_HAS_CFB16
case
16
:
/* DIRECTCOLOUR, 64k */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
var
->
red
.
offset
=
11
;
var
->
red
.
length
=
5
;
var
->
green
.
offset
=
5
;
var
->
green
.
length
=
6
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
5
;
/* Program VCLK3 if needed. */
if
(
par
->
ProgramVCLK
&&
((
VGArGR
(
0x9B
)
!=
par
->
VCLK3NumeratorLow
)
||
(
VGArGR
(
0x9F
)
!=
par
->
VCLK3Denominator
)
||
(
clock_hi
&&
((
VGArGR
(
0x8F
)
&
~
0x0f
)
!=
(
par
->
VCLK3NumeratorHigh
&
~
0x0F
)))))
{
VGAwGR
(
0x9B
,
par
->
VCLK3NumeratorLow
);
if
(
clock_hi
)
{
temp
=
VGArGR
(
0x8F
);
temp
&=
0x0F
;
/* Save bits 3:0 */
temp
|=
(
par
->
VCLK3NumeratorHigh
&
~
0x0F
);
VGAwGR
(
0x8F
,
temp
);
}
VGAwGR
(
0x9F
,
par
->
VCLK3Denominator
);
}
fb
->
fix
.
visual
=
FB_VISUAL_DIRECTCOLOR
;
info
->
dispsw
=
&
fbcon_cfb16
;
display
->
dispsw_data
=
fb
->
pseudo_palette
;
display
->
next_line
=
var
->
xres_virtual
*
2
;
break
;
#endif
if
(
par
->
biosMode
)
VGAwCR
(
0x23
,
par
->
biosMode
);
#ifdef FBCON_HAS_CFB24
case
24
:
/* TRUECOLOUR, 16m */
var
->
transp
.
offset
=
0
;
var
->
transp
.
length
=
0
;
var
->
red
.
offset
=
16
;
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
8
;
VGAwGR
(
0x93
,
0xc0
);
/* Gives 5x faster framebuffer writes !!! */
fb
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
info
->
dispsw
=
&
fbcon_cfb24
;
display
->
dispsw_data
=
fb
->
pseudo_palette
;
display
->
next_line
=
var
->
xres_virtual
*
3
;
/* Program vertical extension register */
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
VGAwCR
(
0x70
,
par
->
VerticalExt
);
}
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
break
;
#endif
#ifdef NO_32BIT_SUPPORT_YET
# ifdef FBCON_HAS_CFB32
case
32
:
/* TRUECOLOUR, 16m */
var
->
transp
.
offset
=
24
;
var
->
transp
.
length
=
8
;
var
->
red
.
offset
=
16
;
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
8
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
8
;
vgaHWProtect
(
0
);
/* Turn on screen */
fb
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
info
->
dispsw
=
&
fbcon_cfb32
;
display
->
dispsw_data
=
fb
->
pseudo_palette
;
display
->
next_line
=
var
->
xres_virtual
*
4
;
/* Calling this also locks offset registers required in update_start */
neoLock
();
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
break
;
# endif
#endif
info
->
fix
.
line_length
=
info
->
var
.
xres_virtual
*
(
info
->
var
.
bits_per_pixel
>>
3
);
default:
printk
(
KERN_WARNING
"neofb: no support for %dbpp
\n
"
,
var
->
bits_per_pixel
);
info
->
dispsw
=
&
fbcon_dummy
;
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
break
;
}
if
(
info
->
var
.
accel_flags
&
FB_ACCELF_TEXT
)
neo2200_accel_init
(
info
,
&
info
->
var
);
return
0
;
}
if
(
var
->
accel_flags
&
FB_ACCELF_TEXT
)
display
->
dispsw
=
&
fbcon_neo2200_accel
;
else
display
->
dispsw
=
info
->
dispsw
;
static
void
neofb_update_start
(
struct
fb_info
*
info
,
struct
fb_var_screeninfo
*
var
)
{
int
oldExtCRTDispAddr
;
int
Base
;
fb
->
fix
.
line_length
=
display
->
next_line
;
DBG
(
"neofb_update_start"
)
;
display
->
line_length
=
fb
->
fix
.
line_length
;
display
->
visual
=
fb
->
fix
.
visual
;
display
->
type
=
fb
->
fix
.
type
;
display
->
type_aux
=
fb
->
fix
.
type_aux
;
display
->
ypanstep
=
fb
->
fix
.
ypanstep
;
display
->
ywrapstep
=
fb
->
fix
.
ywrapstep
;
display
->
can_soft_blank
=
1
;
display
->
inverse
=
0
;
Base
=
(
var
->
yoffset
*
var
->
xres_virtual
+
var
->
xoffset
)
>>
2
;
Base
*=
(
var
->
bits_per_pixel
+
7
)
/
8
;
fb
->
var
=
*
var
;
fb
->
var
.
activate
&=
~
FB_ACTIVATE_ALL
;
neoUnlock
();
/*
* Update the old var. The fbcon drivers still use this.
* Once they are using cfb->fb.var, this can be dropped.
* --rmk
* These are the generic starting address registers.
*/
display
->
var
=
fb
->
var
;
VGAwCR
(
0x0C
,
(
Base
&
0x00FF00
)
>>
8
);
VGAwCR
(
0x0D
,
(
Base
&
0x00FF
));
/*
* If we are setting all the virtual consoles, also set the
* defaults used to create new consoles.
* Make sure we don't clobber some other bits that might already
* have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
* be needed.
*/
if
(
var
->
activate
&
FB_ACTIVATE_ALL
)
fb
->
disp
->
var
=
fb
->
var
;
if
(
chgvar
&&
fb
&&
fb
->
changevar
)
fb
->
changevar
(
con
);
if
(
con
==
info
->
fb
.
currcon
)
{
if
(
chgvar
||
con
<
0
)
neofb_set_par
(
info
,
&
par
);
neofb_update_start
(
info
,
var
);
fb_set_cmap
(
&
fb
->
cmap
,
1
,
fb
);
if
(
var
->
accel_flags
&
FB_ACCELF_TEXT
)
neo2200_accel_init
(
info
,
var
);
}
oldExtCRTDispAddr
=
VGArGR
(
0x0E
);
VGAwGR
(
0x0E
,
(((
Base
>>
16
)
&
0x0f
)
|
(
oldExtCRTDispAddr
&
0xf0
)));
return
0
;
neoLock
()
;
}
/*
* Pan or Wrap the Display
*/
static
int
neofb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
static
int
neofb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
struct
fb_info
*
info
=
(
struct
fb_info
*
)
fb
;
u_int
y_bottom
;
y_bottom
=
var
->
yoffset
;
...
...
@@ -1558,7 +1181,7 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
if
(
y_bottom
>
fb
->
var
.
yres_virtual
)
return
-
EINVAL
;
neofb_update_start
(
info
,
var
);
neofb_update_start
(
info
,
var
);
fb
->
var
.
xoffset
=
var
->
xoffset
;
fb
->
var
.
yoffset
=
var
->
yoffset
;
...
...
@@ -1571,71 +1194,54 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
return
0
;
}
/*
* Update the `var' structure (called by fbcon.c)
*
* This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'.
* Since it's called by a kernel driver, no range checking is done.
*/
static
int
neofb_updatevar
(
int
con
,
struct
fb_info
*
fb
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
neofb_update_start
(
info
,
&
fb_display
[
con
].
var
);
return
0
;
}
static
int
neofb_switch
(
int
con
,
struct
fb_info
*
fb
)
static
int
neofb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
fb
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
struct
display
*
disp
;
struct
fb_cmap
*
cmap
;
if
(
regno
>=
NR_PALETTE
)
return
-
EINVAL
;
if
(
info
->
fb
.
currcon
>=
0
)
{
disp
=
fb_display
+
info
->
fb
.
currcon
;
switch
(
fb
->
var
.
bits_per_pixel
)
{
case
8
:
outb
(
regno
,
0x3c8
)
;
/*
* Save the old colormap and video mode.
*/
disp
->
var
=
fb
->
var
;
if
(
disp
->
cmap
.
len
)
fb_copy_cmap
(
&
fb
->
cmap
,
&
disp
->
cmap
,
0
);
outb
(
red
>>
10
,
0x3c9
);
outb
(
green
>>
10
,
0x3c9
);
outb
(
blue
>>
10
,
0x3c9
);
break
;
case
16
:
if
(
regno
<
16
)
((
u16
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
red
&
0xf800
))
|
((
green
&
0xfc00
)
>>
5
)
|
((
blue
&
0xf800
)
>>
11
);
break
;
case
24
:
if
(
regno
<
16
)
((
u32
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
red
&
0xff00
)
<<
8
)
|
((
green
&
0xff00
))
|
((
blue
&
0xff00
)
>>
8
);
break
;
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
if
(
regno
<
16
)
((
u32
*
)
fb
->
pseudo_palette
)[
regno
]
=
((
transp
&
0xff00
)
<<
16
)
|
((
red
&
0xff00
)
<<
8
)
|
((
green
&
0xff00
))
|
((
blue
&
0xff00
)
>>
8
);
break
;
#endif
default:
return
1
;
}
info
->
fb
.
currcon
=
con
;
disp
=
fb_display
+
con
;
/*
* Install the new colormap and change the video mode. By default,
* fbcon sets all the colormaps and video modes to the default
* values at bootup.
*
* Really, we want to set the colourmap size depending on the
* depth of the new video mode. For now, we leave it at its
* default 256 entry.
*/
if
(
disp
->
cmap
.
len
)
cmap
=
&
disp
->
cmap
;
else
cmap
=
fb_default_cmap
(
1
<<
disp
->
var
.
bits_per_pixel
);
fb_copy_cmap
(
cmap
,
&
fb
->
cmap
,
0
);
disp
->
var
.
activate
=
FB_ACTIVATE_NOW
;
neofb_set_var
(
&
disp
->
var
,
con
,
fb
);
return
0
;
}
/*
* (Un)Blank the display.
*/
static
int
neofb_blank
(
int
blank
,
struct
fb_info
*
fb
)
static
int
neofb_blank
(
int
blank
,
struct
fb_info
*
fb
)
{
// struct neofb_info *info = (struct neo
fb_info *)fb;
// struct fb_info *info = (struct
fb_info *)fb;
/*
* Blank the screen if blank_mode != 0, else unblank. If
...
...
@@ -1653,8 +1259,7 @@ static int neofb_blank (int blank, struct fb_info *fb)
* run "setterm -powersave powerdown" to take advantage
*/
switch
(
blank
)
{
switch
(
blank
)
{
case
4
:
/* powerdown - both sync lines down */
break
;
case
3
:
/* hsync off */
...
...
@@ -1669,16 +1274,132 @@ static int neofb_blank (int blank, struct fb_info *fb)
return
0
;
}
static
void
neo2200fb_fillrect
(
struct
fb_info
*
info
,
struct
fb_fillrect
*
rect
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
u_long
dst
,
rop
;
dst
=
rect
->
dx
+
rect
->
dy
*
info
->
var
.
xres_virtual
;
rop
=
rect
->
rop
?
0x060000
:
0x0c0000
;
neo2200_wait_fifo
(
par
,
4
);
/* set blt control */
par
->
neo2200
->
bltCntl
=
NEO_BC3_FIFO_EN
|
NEO_BC0_SRC_IS_FG
|
NEO_BC3_SKIP_MAPPING
|
// NEO_BC3_DST_XY_ADDR |
// NEO_BC3_SRC_XY_ADDR |
rop
;
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
par
->
neo2200
->
fgColor
=
rect
->
color
;
break
;
case
16
:
par
->
neo2200
->
fgColor
=
((
u16
*
)
(
info
->
pseudo_palette
))[
rect
->
color
];
break
;
}
par
->
neo2200
->
dstStart
=
dst
*
((
info
->
var
.
bits_per_pixel
+
7
)
/
8
);
par
->
neo2200
->
xyExt
=
(
rect
->
height
<<
16
)
|
(
rect
->
width
&
0xffff
);
}
static
void
neo2200fb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
u_long
src
,
dst
,
bltCntl
;
bltCntl
=
NEO_BC3_FIFO_EN
|
NEO_BC3_SKIP_MAPPING
|
0x0C0000
;
if
(
area
->
sy
<
area
->
dy
)
{
area
->
sy
+=
(
area
->
height
-
1
);
area
->
dy
+=
(
area
->
height
-
1
);
bltCntl
|=
NEO_BC0_DST_Y_DEC
|
NEO_BC0_SRC_Y_DEC
;
}
if
(
area
->
sx
<
area
->
dx
)
{
area
->
sx
+=
(
area
->
width
-
1
);
area
->
dx
+=
(
area
->
width
-
1
);
bltCntl
|=
NEO_BC0_X_DEC
;
}
src
=
area
->
sx
*
(
info
->
var
.
bits_per_pixel
>>
3
)
+
area
->
sy
*
info
->
fix
.
line_length
;
dst
=
area
->
dx
*
(
info
->
var
.
bits_per_pixel
>>
3
)
+
area
->
dy
*
info
->
fix
.
line_length
;
neo2200_wait_fifo
(
par
,
4
);
/* set blt control */
par
->
neo2200
->
bltCntl
=
bltCntl
;
par
->
neo2200
->
srcStart
=
src
;
par
->
neo2200
->
dstStart
=
dst
;
par
->
neo2200
->
xyExt
=
(
area
->
height
<<
16
)
|
(
area
->
width
&
0xffff
);
}
static
void
neo2200fb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
image
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
neo2200_wait_idle
(
par
);
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
par
->
neo2200
->
fgColor
=
image
->
fg_color
;
par
->
neo2200
->
bgColor
=
image
->
bg_color
;
break
;
case
16
:
par
->
neo2200
->
fgColor
=
((
u16
*
)
(
info
->
pseudo_palette
))[
image
->
fg_color
];
par
->
neo2200
->
bgColor
=
((
u16
*
)
(
info
->
pseudo_palette
))[
image
->
bg_color
];
break
;
}
par
->
neo2200
->
bltCntl
=
NEO_BC0_SYS_TO_VID
|
NEO_BC0_SRC_MONO
|
NEO_BC3_SKIP_MAPPING
|
// NEO_BC3_DST_XY_ADDR |
0x0c0000
;
par
->
neo2200
->
srcStart
=
0
;
// par->neo2200->dstStart = (image->dy << 16) | (image->dx & 0xffff);
par
->
neo2200
->
dstStart
=
((
image
->
dx
&
0xffff
)
*
(
info
->
var
.
bits_per_pixel
>>
3
)
+
image
->
dy
*
info
->
fix
.
line_length
);
par
->
neo2200
->
xyExt
=
(
image
->
height
<<
16
)
|
(
image
->
width
&
0xffff
);
memcpy
(
par
->
mmio_vbase
+
0x100000
,
image
->
data
,
(
image
->
width
*
image
->
height
)
>>
3
);
}
static
struct
fb_ops
neofb_ops
=
{
owner:
THIS_MODULE
,
fb_set_var:
neofb_set_var
,
fb_check_var:
neofb_check_var
,
fb_set_par:
neofb_set_par
,
fb_set_var:
gen_set_var
,
fb_get_fix:
gen_get_fix
,
fb_get_var:
gen_get_var
,
fb_get_cmap:
gen_get_cmap
,
fb_set_cmap:
gen_set_cmap
,
fb_setcolreg:
neofb_setcolreg
,
fb_pan_display:
neofb_pan_display
,
fb_blank:
neofb_blank
,
fb_get_fix:
gen_get_fix
,
fb_get_var:
gen_get_var
,
fb_get_cmap:
gen_get_cmap
,
fb_fillrect:
cfb_fillrect
,
fb_copyarea:
cfb_copyarea
,
fb_imageblit:
cfb_imageblit
,
};
/* --------------------------------------------------------------------- */
...
...
@@ -1697,7 +1418,6 @@ static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
lower_margin:
10
,
hsync_len:
96
,
vsync_len:
2
,
sync:
0
,
vmode:
FB_VMODE_NONINTERLACED
};
...
...
@@ -1759,106 +1479,110 @@ static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
static
struct
fb_var_screeninfo
*
neofb_var
=
NULL
;
static
int
__devinit
neo_map_mmio
(
struct
neofb_info
*
info
)
static
int
__devinit
neo_map_mmio
(
struct
fb_info
*
info
,
struct
pci_dev
*
dev
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
DBG
(
"neo_map_mmio"
);
info
->
mmio
.
pbase
=
pci_resource_start
(
info
->
pci
dev
,
1
);
info
->
mmio
.
len
=
MMIO_SIZE
;
info
->
fix
.
mmio_start
=
pci_resource_start
(
dev
,
1
);
info
->
fix
.
mmio_len
=
MMIO_SIZE
;
if
(
!
request_mem_region
(
info
->
mmio
.
pbase
,
MMIO_SIZE
,
"memory mapped I/O"
))
{
printk
(
"neofb: memory mapped IO in use
\n
"
);
if
(
!
request_mem_region
(
info
->
fix
.
mmio_start
,
MMIO_SIZE
,
"memory mapped I/O"
))
{
printk
(
"neofb: memory mapped IO in use
\n
"
);
return
-
EBUSY
;
}
info
->
mmio
.
vbase
=
ioremap
(
info
->
mmio
.
pbase
,
MMIO_SIZE
);
if
(
!
info
->
mmio
.
vbase
)
{
printk
(
"neofb: unable to map memory mapped IO
\n
"
);
release_mem_region
(
info
->
mmio
.
pbase
,
info
->
mmio
.
len
);
par
->
mmio_vbase
=
ioremap
(
info
->
fix
.
mmio_start
,
MMIO_SIZE
);
if
(
!
par
->
mmio_vbase
)
{
printk
(
"neofb: unable to map memory mapped IO
\n
"
);
release_mem_region
(
info
->
fix
.
mmio_start
,
info
->
fix
.
mmio_
len
);
return
-
ENOMEM
;
}
else
printk
(
KERN_INFO
"neofb: mapped io at %p
\n
"
,
info
->
mmio
.
vbase
);
info
->
fb
.
fix
.
mmio_start
=
info
->
mmio
.
pbase
;
info
->
fb
.
fix
.
mmio_len
=
info
->
mmio
.
len
;
}
else
printk
(
KERN_INFO
"neofb: mapped io at %p
\n
"
,
par
->
mmio_vbase
);
return
0
;
}
static
void
__devinit
neo_unmap_mmio
(
struct
neo
fb_info
*
info
)
static
void
__devinit
neo_unmap_mmio
(
struct
fb_info
*
info
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
DBG
(
"neo_unmap_mmio"
);
if
(
info
->
mmio
.
vbase
)
{
iounmap
(
info
->
mmio
.
vbase
);
info
->
mmio
.
vbase
=
NULL
;
if
(
par
->
mmio_vbase
)
{
iounmap
(
par
->
mmio_vbase
);
par
->
mmio_vbase
=
NULL
;
release_mem_region
(
info
->
mmio
.
pbase
,
info
->
mmio
.
len
);
release_mem_region
(
info
->
fix
.
mmio_start
,
info
->
fix
.
mmio_len
);
}
}
static
int
__devinit
neo_map_video
(
struct
neofb_info
*
info
,
int
video_len
)
static
int
__devinit
neo_map_video
(
struct
fb_info
*
info
,
struct
pci_dev
*
dev
,
int
video_len
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
DBG
(
"neo_map_video"
);
info
->
video
.
pbase
=
pci_resource_start
(
info
->
pci
dev
,
0
);
info
->
video
.
len
=
video_len
;
info
->
fix
.
smem_start
=
pci_resource_start
(
dev
,
0
);
info
->
fix
.
smem_len
=
video_len
;
if
(
!
request_mem_region
(
info
->
video
.
pbase
,
info
->
video
.
len
,
"frame buffer"
))
{
printk
(
"neofb: frame buffer in use
\n
"
);
if
(
!
request_mem_region
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
,
"frame buffer"
))
{
printk
(
"neofb: frame buffer in use
\n
"
);
return
-
EBUSY
;
}
info
->
video
.
vbase
=
ioremap
(
info
->
video
.
pbase
,
info
->
video
.
len
);
if
(
!
info
->
video
.
vbase
)
{
printk
(
"neofb: unable to map screen memory
\n
"
);
release_mem_region
(
info
->
video
.
pbase
,
info
->
video
.
len
);
info
->
screen_base
=
ioremap
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
printk
(
"neofb: unable to map screen memory
\n
"
);
release_mem_region
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
return
-
ENOMEM
;
}
else
printk
(
KERN_INFO
"neofb: mapped framebuffer at %p
\n
"
,
info
->
video
.
vbase
);
info
->
fb
.
fix
.
smem_start
=
info
->
video
.
pbase
;
info
->
fb
.
fix
.
smem_len
=
info
->
video
.
len
;
info
->
fb
.
screen_base
=
info
->
video
.
vbase
;
}
else
printk
(
KERN_INFO
"neofb: mapped framebuffer at %p
\n
"
,
info
->
screen_base
);
#ifdef CONFIG_MTRR
info
->
video
.
mtrr
=
mtrr_add
(
info
->
video
.
pbase
,
pci_resource_len
(
info
->
pcidev
,
0
),
MTRR_TYPE_WRCOMB
,
1
);
par
->
mtrr
=
mtrr_add
(
info
->
fix
.
smem_start
,
pci_resource_len
(
dev
,
0
),
MTRR_TYPE_WRCOMB
,
1
);
#endif
/* Clear framebuffer, it's all white in memory after boot */
memset
(
info
->
video
.
vbase
,
0
,
info
->
video
.
len
);
memset
(
info
->
screen_base
,
0
,
info
->
fix
.
smem_len
);
return
0
;
}
static
void
__devinit
neo_unmap_video
(
struct
neo
fb_info
*
info
)
static
void
__devinit
neo_unmap_video
(
struct
fb_info
*
info
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
DBG
(
"neo_unmap_video"
);
if
(
info
->
video
.
vbase
)
{
if
(
info
->
screen_base
)
{
#ifdef CONFIG_MTRR
mtrr_del
(
info
->
video
.
mtrr
,
info
->
video
.
pbase
,
info
->
video
.
len
);
mtrr_del
(
par
->
mtrr
,
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
#endif
iounmap
(
info
->
video
.
vbase
);
info
->
video
.
vbase
=
NULL
;
info
->
fb
.
screen_base
=
NULL
;
iounmap
(
info
->
screen_base
);
info
->
screen_base
=
NULL
;
release_mem_region
(
info
->
video
.
pbase
,
info
->
video
.
len
);
release_mem_region
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
}
}
static
int
__devinit
neo_init_hw
(
struct
neo
fb_info
*
info
)
static
int
__devinit
neo_init_hw
(
struct
fb_info
*
info
)
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
int
videoRam
=
896
;
int
maxClock
=
65000
;
int
CursorMem
=
1024
;
...
...
@@ -1874,64 +1598,65 @@ static int __devinit neo_init_hw (struct neofb_info *info)
neoUnlock
();
#if 0
printk (KERN_DEBUG "--- Neo extended register dump ---\n");
for (w=0; w<0x85; w++)
printk (KERN_DEBUG "CR %p: %p\n", (void*)w, (void*)VGArCR (w));
for (w=0; w<0xC7; w++)
printk (KERN_DEBUG "GR %p: %p\n", (void*)w, (void*)VGArGR (w));
printk(KERN_DEBUG "--- Neo extended register dump ---\n");
for (w = 0; w < 0x85; w++)
printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
(void *) VGArCR(w));
for (w = 0; w < 0xC7; w++)
printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
(void *) VGArGR(w));
#endif
/* Determine the panel type */
VGAwGR
(
0x09
,
0x26
);
VGAwGR
(
0x09
,
0x26
);
type
=
VGArGR
(
0x21
);
display
=
VGArGR
(
0x20
);
/* Determine panel width -- used in NeoValidMode. */
w
=
VGArGR
(
0x20
);
VGAwGR
(
0x09
,
0x00
);
switch
((
w
&
0x18
)
>>
3
)
{
VGAwGR
(
0x09
,
0x00
);
switch
((
w
&
0x18
)
>>
3
)
{
case
0x00
:
info
->
NeoPanelWidth
=
640
;
info
->
NeoPanelHeight
=
480
;
par
->
NeoPanelWidth
=
640
;
par
->
NeoPanelHeight
=
480
;
neofb_var
=
&
neofb_var640x480x8
;
break
;
case
0x01
:
info
->
NeoPanelWidth
=
800
;
info
->
NeoPanelHeight
=
600
;
par
->
NeoPanelWidth
=
800
;
par
->
NeoPanelHeight
=
600
;
neofb_var
=
&
neofb_var800x600x8
;
break
;
case
0x02
:
info
->
NeoPanelWidth
=
1024
;
info
->
NeoPanelHeight
=
768
;
par
->
NeoPanelWidth
=
1024
;
par
->
NeoPanelHeight
=
768
;
neofb_var
=
&
neofb_var1024x768x8
;
break
;
case
0x03
:
/* 1280x1024 panel support needs to be added */
#ifdef NOT_DONE
info
->
NeoPanelWidth
=
1280
;
info
->
NeoPanelHeight
=
1024
;
par
->
NeoPanelWidth
=
1280
;
par
->
NeoPanelHeight
=
1024
;
neofb_var
=
&
neofb_var1280x1024x8
;
break
;
#else
printk
(
KERN_ERR
"neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported
\n
"
);
printk
(
KERN_ERR
"neofb: Only 640x480, 800x600 and 1024x768 panels are currently supported
\n
"
);
return
-
1
;
#endif
default:
info
->
NeoPanelWidth
=
640
;
info
->
NeoPanelHeight
=
480
;
par
->
NeoPanelWidth
=
640
;
par
->
NeoPanelHeight
=
480
;
neofb_var
=
&
neofb_var640x480x8
;
break
;
}
printk
(
KERN_INFO
"Panel is a %dx%d %s %s display
\n
"
,
info
->
NeoPanelWidth
,
info
->
NeoPanelHeight
,
printk
(
KERN_INFO
"Panel is a %dx%d %s %s display
\n
"
,
par
->
NeoPanelWidth
,
par
->
NeoPanelHeight
,
(
type
&
0x02
)
?
"color"
:
"monochrome"
,
(
type
&
0x10
)
?
"TFT"
:
"dual scan"
);
switch
(
info
->
accel
)
{
switch
(
info
->
fix
.
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
videoRam
=
896
;
maxClock
=
65000
;
...
...
@@ -1978,7 +1703,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2230
:
videoRam
=
3008
;
...
...
@@ -1989,7 +1714,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2360
:
videoRam
=
4096
;
...
...
@@ -2000,7 +1725,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2380
:
videoRam
=
6144
;
...
...
@@ -2011,155 +1736,154 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
}
info
->
maxClock
=
maxClock
;
par
->
maxClock
=
maxClock
;
return
videoRam
*
1024
;
}
static
struct
neofb_info
*
__devinit
neo_alloc_fb_info
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
static
struct
fb_info
*
__devinit
neo_alloc_fb_info
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
{
struct
neofb_info
*
info
;
struct
fb_info
*
info
;
struct
neofb_par
*
par
;
info
=
kmalloc
(
sizeof
(
struct
neo
fb_info
)
+
sizeof
(
struct
display
)
+
info
=
kmalloc
(
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
16
,
GFP_KERNEL
);
if
(
!
info
)
return
NULL
;
memset
(
info
,
0
,
sizeof
(
struct
neo
fb_info
)
+
sizeof
(
struct
display
));
memset
(
info
,
0
,
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
));
info
->
fb
.
currcon
=
-
1
;
info
->
pcidev
=
dev
;
info
->
accel
=
id
->
driver_data
;
par
=
&
default_par
;
memset
(
par
,
0
,
sizeof
(
struct
neofb_par
));
info
->
pci_burst
=
!
nopciburst
;
info
->
lcd_stretch
=
!
nostretch
;
info
->
currcon
=
-
1
;
info
->
fix
.
accel
=
id
->
driver_data
;
if
(
!
internal
&&
!
external
)
{
info
->
internal_display
=
1
;
info
->
external_display
=
0
;
}
else
{
info
->
internal_display
=
internal
;
info
->
external_display
=
external
;
par
->
pci_burst
=
!
nopciburst
;
par
->
lcd_stretch
=
!
nostretch
;
if
(
!
internal
&&
!
external
)
{
par
->
internal_display
=
1
;
par
->
external_display
=
0
;
}
else
{
par
->
internal_display
=
internal
;
par
->
external_display
=
external
;
}
switch
(
info
->
accel
)
{
switch
(
info
->
fix
.
accel
)
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128V"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128V"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2093
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128ZV"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128ZV"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2097
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128ZV+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128ZV+"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2160
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128XD"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128XD"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2200
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256AV"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256AV"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2230
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256AV+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256AV+"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2360
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256ZX"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256ZX"
);
break
;
case
FB_ACCEL_NEOMAGIC_NM2380
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256XL+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256XL+"
);
break
;
}
info
->
fb
.
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fb
.
fix
.
type_aux
=
0
;
info
->
fb
.
fix
.
xpanstep
=
0
;
info
->
fb
.
fix
.
ypanstep
=
4
;
info
->
fb
.
fix
.
ywrapstep
=
0
;
info
->
fb
.
fix
.
accel
=
id
->
driver_data
;
info
->
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fix
.
type_aux
=
0
;
info
->
fix
.
xpanstep
=
0
;
info
->
fix
.
ypanstep
=
4
;
info
->
fix
.
ywrapstep
=
0
;
info
->
fix
.
accel
=
id
->
driver_data
;
info
->
fb
.
var
.
nonstd
=
0
;
info
->
fb
.
var
.
activate
=
FB_ACTIVATE_NOW
;
info
->
fb
.
var
.
height
=
-
1
;
info
->
fb
.
var
.
width
=
-
1
;
info
->
fb
.
var
.
accel_flags
=
0
;
info
->
var
.
nonstd
=
0
;
info
->
var
.
activate
=
FB_ACTIVATE_NOW
;
info
->
var
.
height
=
-
1
;
info
->
var
.
width
=
-
1
;
info
->
var
.
accel_flags
=
0
;
strcpy
(
info
->
fb
.
modename
,
info
->
fb
.
fix
.
id
);
strcpy
(
info
->
modename
,
info
->
fix
.
id
);
info
->
fb
.
fbops
=
&
neofb_ops
;
info
->
fb
.
changevar
=
NULL
;
info
->
fb
.
switch_con
=
neofb_switch
;
info
->
fb
.
updatevar
=
neofb_updatevar
;
info
->
fb
.
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
fb
.
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
fb
.
pseudo_palette
=
(
void
*
)(
info
->
fb
.
disp
+
1
);
info
->
fbops
=
&
neofb_ops
;
info
->
changevar
=
NULL
;
info
->
switch_con
=
gen_switch
;
info
->
updatevar
=
gen_update_var
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
par
=
par
;
info
->
disp
=
(
struct
display
*
)
(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)
(
info
->
disp
+
1
);
fb_alloc_cmap
(
&
info
->
fb
.
cmap
,
NR_PALETTE
,
0
);
fb_alloc_cmap
(
&
info
->
cmap
,
NR_PALETTE
,
0
);
return
info
;
}
static
void
__devinit
neo_free_fb_info
(
struct
neo
fb_info
*
info
)
static
void
__devinit
neo_free_fb_info
(
struct
fb_info
*
info
)
{
if
(
info
)
{
if
(
info
)
{
/*
* Free the colourmap
*/
fb_alloc_cmap
(
&
info
->
fb
.
cmap
,
0
,
0
);
fb_alloc_cmap
(
&
info
->
cmap
,
0
,
0
);
kfree
(
info
);
kfree
(
info
);
}
}
/* --------------------------------------------------------------------- */
static
int
__devinit
neofb_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
static
int
__devinit
neofb_probe
(
struct
pci_dev
*
dev
,
const
struct
pci_device_id
*
id
)
{
struct
neo
fb_info
*
info
;
struct
fb_info
*
info
;
u_int
h_sync
,
v_sync
;
int
err
;
int
video_len
;
DBG
(
"neofb_probe"
);
err
=
pci_enable_device
(
dev
);
err
=
pci_enable_device
(
dev
);
if
(
err
)
return
err
;
err
=
-
ENOMEM
;
info
=
neo_alloc_fb_info
(
dev
,
id
);
info
=
neo_alloc_fb_info
(
dev
,
id
);
if
(
!
info
)
goto
failed
;
err
=
neo_map_mmio
(
info
);
err
=
neo_map_mmio
(
info
,
dev
);
if
(
err
)
goto
failed
;
video_len
=
neo_init_hw
(
info
);
if
(
video_len
<
0
)
{
video_len
=
neo_init_hw
(
info
);
if
(
video_len
<
0
)
{
err
=
video_len
;
goto
failed
;
}
err
=
neo_map_video
(
info
,
video_len
);
err
=
neo_map_video
(
info
,
dev
,
video_len
);
if
(
err
)
goto
failed
;
neofb_set_var
(
neofb_var
,
-
1
,
&
info
->
fb
);
gen_set_var
(
neofb_var
,
-
1
,
info
);
/*
* Calculate the hsync and vsync frequencies. Note that
...
...
@@ -2167,24 +1891,26 @@ static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_i
* the precision and fit the results into 32-bit registers.
* (1953125000 * 512 = 1e12)
*/
h_sync
=
1953125000
/
info
->
fb
.
var
.
pixclock
;
h_sync
=
h_sync
*
512
/
(
info
->
fb
.
var
.
xres
+
info
->
fb
.
var
.
left_margin
+
info
->
fb
.
var
.
right_margin
+
info
->
fb
.
var
.
hsync_len
);
v_sync
=
h_sync
/
(
info
->
fb
.
var
.
yres
+
info
->
fb
.
var
.
upper_margin
+
info
->
fb
.
var
.
lower_margin
+
info
->
fb
.
var
.
vsync_len
);
h_sync
=
1953125000
/
info
->
var
.
pixclock
;
h_sync
=
h_sync
*
512
/
(
info
->
var
.
xres
+
info
->
var
.
left_margin
+
info
->
var
.
right_margin
+
info
->
var
.
hsync_len
);
v_sync
=
h_sync
/
(
info
->
var
.
yres
+
info
->
var
.
upper_margin
+
info
->
var
.
lower_margin
+
info
->
var
.
vsync_len
);
printk
(
KERN_INFO
"neofb v"
NEOFB_VERSION
": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz
\n
"
,
info
->
fb
.
fix
.
smem_len
>>
10
,
info
->
fb
.
var
.
xres
,
info
->
fb
.
var
.
y
res
,
h_sync
/
1000
,
h_sync
%
1000
,
v_sync
);
printk
(
KERN_INFO
"neofb v"
NEOFB_VERSION
": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz
\n
"
,
info
->
fix
.
smem_len
>>
10
,
info
->
var
.
x
res
,
info
->
var
.
yres
,
h_sync
/
1000
,
h_sync
%
1000
,
v_sync
);
err
=
register_framebuffer
(
&
info
->
fb
);
err
=
register_framebuffer
(
info
);
if
(
err
<
0
)
goto
failed
;
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
GET_FB_IDX
(
info
->
fb
.
node
),
info
->
fb
.
modename
);
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
GET_FB_IDX
(
info
->
node
),
info
->
modename
);
/*
* Our driver data
...
...
@@ -2193,33 +1919,33 @@ static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_i
return
0
;
failed:
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
failed:
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
return
err
;
}
static
void
__devexit
neofb_remove
(
struct
pci_dev
*
dev
)
static
void
__devexit
neofb_remove
(
struct
pci_dev
*
dev
)
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
dev
->
driver_data
;
struct
fb_info
*
info
=
(
struct
fb_info
*
)
dev
->
driver_data
;
DBG
(
"neofb_remove"
);
if
(
info
)
{
if
(
info
)
{
/*
* If unregister_framebuffer fails, then
* we will be leaving hooks that could cause
* oopsen laying around.
*/
if
(
unregister_framebuffer
(
&
info
->
fb
))
printk
(
KERN_WARNING
"neofb: danger danger! Oopsen imminent!
\n
"
);
if
(
unregister_framebuffer
(
info
))
printk
(
KERN_WARNING
"neofb: danger danger! Oopsen imminent!
\n
"
);
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
/*
* Ensure that the driver data is no longer
...
...
@@ -2271,18 +1997,18 @@ static struct pci_driver neofb_driver = {
/* **************************** init-time only **************************** */
static
void
__init
neo_init
(
void
)
static
void
__init
neo_init
(
void
)
{
DBG
(
"neo_init"
);
pci_register_driver
(
&
neofb_driver
);
pci_register_driver
(
&
neofb_driver
);
}
/* **************************** exit-time only **************************** */
static
void
__exit
neo_done
(
void
)
static
void
__exit
neo_done
(
void
)
{
DBG
(
"neo_done"
);
pci_unregister_driver
(
&
neofb_driver
);
pci_unregister_driver
(
&
neofb_driver
);
}
...
...
@@ -2290,7 +2016,7 @@ static void __exit neo_done (void)
/* ************************* init in-kernel code ************************** */
int
__init
neofb_setup
(
char
*
options
)
int
__init
neofb_setup
(
char
*
options
)
{
char
*
this_opt
;
...
...
@@ -2299,9 +2025,9 @@ int __init neofb_setup (char *options)
if
(
!
options
||
!*
options
)
return
0
;
while
((
this_opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
{
if
(
!*
this_opt
)
continue
;
while
((
this_opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
{
if
(
!*
this_opt
)
continue
;
if
(
!
strncmp
(
this_opt
,
"disabled"
,
8
))
disabled
=
1
;
...
...
@@ -2327,8 +2053,7 @@ int __init neofb_init(void)
if
(
disabled
)
return
-
ENXIO
;
if
(
!
initialized
)
{
if
(
!
initialized
)
{
initialized
=
1
;
neo_init
();
}
...
...
drivers/video/tdfxfb.c
View file @
34dfe0cd
...
...
@@ -76,15 +76,6 @@
#include <linux/timer.h>
#include <linux/spinlock.h>
#include <linux/kd.h>
#include <linux/console.h>
#include <linux/selection.h>
#include <linux/vt_kern.h>
#ifdef CONFIG_MTRR
#include <asm/mtrr.h>
#endif
#include <video/tdfx.h>
#include <video/fbcon.h>
...
...
@@ -92,17 +83,7 @@
#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
#endif
#define TDFXF_HSYNC_ACT_HIGH 0x01
#define TDFXF_HSYNC_ACT_LOW 0x02
#define TDFXF_VSYNC_ACT_HIGH 0x04
#define TDFXF_VSYNC_ACT_LOW 0x08
#define TDFXF_LINE_DOUBLE 0x10
#define TDFXF_VIDEO_ENABLE 0x20
#define TDFXF_HSYNC_MASK 0x03
#define TDFXF_VSYNC_MASK 0x0c
//#define TDFXFB_DEBUG
#undef TDFXFB_DEBUG
#ifdef TDFXFB_DEBUG
#define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
#else
...
...
@@ -113,230 +94,115 @@
#define VOODOO3_MAX_PIXCLOCK 300000.0
#define VOODOO5_MAX_PIXCLOCK 350000.0
struct
tdfxfb_par
{
u32
pixclock
;
u32
baseline
;
u32
width
;
u32
height
;
u32
width_virt
;
u32
height_virt
;
u32
lpitch
;
/* line pitch, in bytes */
u32
ppitch
;
/* pixel pitch, in bits */
u32
bpp
;
u32
hdispend
;
u32
hsyncsta
;
u32
hsyncend
;
u32
htotal
;
u32
vdispend
;
u32
vsyncsta
;
u32
vsyncend
;
u32
vtotal
;
u32
video
;
u32
accel_flags
;
u32
cmap_len
;
static
struct
fb_fix_screeninfo
tdfx_fix
__initdata
=
{
id:
"3Dfx"
,
type:
FB_TYPE_PACKED_PIXELS
,
visual:
FB_VISUAL_PSEUDOCOLOR
,
ypanstep:
1
,
ywrapstep:
1
,
accel:
FB_ACCEL_3DFX_BANSHEE
};
struct
fb_info_tdfx
{
struct
fb_info
fb_info
;
u16
dev
;
u32
max_pixclock
;
unsigned
long
regbase_phys
;
void
*
regbase_virt
;
unsigned
long
regbase_size
;
unsigned
long
bufbase_phys
;
void
*
bufbase_virt
;
unsigned
long
bufbase_size
;
unsigned
long
iobase
;
struct
{
unsigned
red
,
green
,
blue
,
pad
;
}
palette
[
256
];
struct
tdfxfb_par
default_par
;
struct
tdfxfb_par
current_par
;
struct
display
disp
;
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
union
{
#ifdef FBCON_HAS_CFB16
u16
cfb16
[
16
];
#endif
#ifdef FBCON_HAS_CFB24
u32
cfb24
[
16
];
#endif
#ifdef FBCON_HAS_CFB32
u32
cfb32
[
16
];
#endif
}
fbcon_cmap
;
#endif
struct
{
int
type
;
int
state
;
int
w
,
u
,
d
;
int
x
,
y
,
redraw
;
unsigned
long
enable
,
disable
;
unsigned
long
cursorimage
;
struct
timer_list
timer
;
}
cursor
;
spinlock_t
DAClock
;
#ifdef CONFIG_MTRR
int
mtrr_idx
;
#endif
static
struct
fb_var_screeninfo
tdfx_var
__initdata
=
{
/* "640x480, 8 bpp @ 60 Hz */
xres:
640
,
yres:
480
,
xres_virtual:
640
,
yres_virtual:
1024
,
bits_per_pixel:
8
,
red:
{
0
,
8
,
0
},
blue:
{
0
,
8
,
0
},
green:
{
0
,
8
,
0
},
activate:
FB_ACTIVATE_NOW
,
height:
-
1
,
width:
-
1
,
accel_flags:
FB_ACCELF_TEXT
,
pixclock:
39722
,
left_margin:
40
,
right_margin:
24
,
upper_margin:
32
,
lower_margin:
11
,
hsync_len:
96
,
vsync_len:
2
,
vmode:
FB_VMODE_NONINTERLACED
};
/*
* Frame buffer device API
*/
static
int
tdfxfb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
fb
);
static
int
tdfxfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_get_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
);
static
int
tdfxfb_set_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
);
/*
* Interface to the low level console driver
*/
static
int
tdfxfb_switch_con
(
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_updatevar
(
int
con
,
struct
fb_info
*
fb
);
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
fb
);
/*
* Internal routines
*/
static
void
tdfxfb_set_par
(
const
struct
tdfxfb_par
*
par
,
struct
fb_info_tdfx
*
info
);
static
int
tdfxfb_decode_var
(
const
struct
fb_var_screeninfo
*
var
,
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
);
static
int
tdfxfb_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
);
static
int
tdfxfb_encode_fix
(
struct
fb_fix_screeninfo
*
fix
,
const
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
);
static
void
tdfxfb_set_dispsw
(
struct
display
*
disp
,
struct
fb_info_tdfx
*
info
,
int
bpp
,
int
accel
);
static
int
tdfxfb_getcolreg
(
u_int
regno
,
u_int
*
red
,
u_int
*
green
,
u_int
*
blue
,
u_int
*
transp
,
struct
fb_info
*
fb
);
static
void
tdfxfb_hwcursor_init
(
void
);
static
void
tdfxfb_createcursorshape
(
struct
display
*
p
);
static
void
tdfxfb_createcursor
(
struct
display
*
p
);
/*
* do_xxx: Hardware-specific functions
*/
static
void
do_pan_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info_tdfx
*
i
);
static
void
do_flashcursor
(
unsigned
long
ptr
);
static
void
do_bitblt
(
u32
curx
,
u32
cury
,
u32
dstx
,
u32
dsty
,
u32
width
,
u32
height
,
u32
stride
,
u32
bpp
);
static
void
do_fillrect
(
u32
x
,
u32
y
,
u32
w
,
u32
h
,
u32
color
,
u32
stride
,
u32
bpp
,
u32
rop
);
static
void
do_putc
(
u32
fgx
,
u32
bgx
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
);
static
void
do_putcs
(
u32
fgx
,
u32
bgx
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
);
static
u32
do_calc_pll
(
int
freq
,
int
*
freq_out
);
static
void
do_write_regs
(
struct
banshee_reg
*
reg
);
static
unsigned
long
do_lfb_size
(
void
);
/*
* Interface used by the world
*/
int
tdfxfb_init
(
void
);
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
);
/*
* PCI driver prototypes
*/
static
int
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
);
static
int
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
);
static
void
tdfxfb_remove
(
struct
pci_dev
*
pdev
);
static
struct
fb_ops
tdfxfb_ops
=
{
owner:
THIS_MODULE
,
fb_get_fix:
tdfxfb_get_fix
,
fb_get_var:
tdfxfb_get_var
,
fb_set_var:
tdfxfb_set_var
,
fb_get_cmap:
tdfxfb_get_cmap
,
fb_set_cmap:
tdfxfb_set_cmap
,
fb_setcolreg:
tdfxfb_setcolreg
,
fb_pan_display:
tdfxfb_pan_display
,
fb_blank:
tdfxfb_blank
,
};
static
struct
pci_device_id
tdfxfb_id_table
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_BANSHEE
,
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_BANSHEE
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO3
,
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO3
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO5
,
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO5
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
{
0
,
}
0xff0000
,
0
},
{
0
,
}
};
static
struct
pci_driver
tdfxfb_driver
=
{
name:
"tdfxfb"
,
id_table:
tdfxfb_id_table
,
probe:
tdfxfb_probe
,
remove:
__devexit_p
(
tdfxfb_remove
)
,
name:
"tdfxfb"
,
id_table:
tdfxfb_id_table
,
probe:
tdfxfb_probe
,
remove:
tdfxfb_remove
,
};
MODULE_DEVICE_TABLE
(
pci
,
tdfxfb_id_table
);
struct
mode
{
char
*
name
;
struct
fb_var_screeninfo
var
;
}
mode
;
/* 2.3.x kernels have a fb mode database, so supply only one backup default */
struct
mode
default_mode
[]
=
{
{
"640x480-8@60"
,
/* @ 60 Hz */
{
640
,
480
,
640
,
1024
,
0
,
0
,
8
,
0
,
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
0
,
0
},
0
,
FB_ACTIVATE_NOW
,
-
1
,
-
1
,
FB_ACCELF_TEXT
,
39722
,
40
,
24
,
32
,
11
,
96
,
2
,
0
,
FB_VMODE_NONINTERLACED
}
}
/*
* Frame buffer device API
*/
int
tdfxfb_init
(
void
);
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
);
static
int
tdfxfb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fb
);
static
int
tdfxfb_set_par
(
struct
fb_info
*
info
);
static
int
tdfxfb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
);
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
info
);
static
int
tdfxfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
);
static
void
tdfxfb_fillrect
(
struct
fb_info
*
info
,
struct
fb_fillrect
*
rect
);
static
void
tdfxfb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
);
static
void
tdfxfb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
image
);
static
struct
fb_ops
tdfxfb_ops
=
{
owner:
THIS_MODULE
,
fb_get_fix:
gen_get_fix
,
fb_get_var:
gen_get_var
,
fb_set_var:
gen_set_var
,
fb_get_cmap:
gen_get_cmap
,
fb_set_cmap:
gen_set_cmap
,
fb_check_var:
tdfxfb_check_var
,
fb_set_par:
tdfxfb_set_par
,
fb_setcolreg:
tdfxfb_setcolreg
,
fb_blank:
tdfxfb_blank
,
fb_pan_display:
tdfxfb_pan_display
,
fb_fillrect:
tdfxfb_fillrect
,
fb_copyarea:
tdfxfb_copyarea
,
fb_imageblit:
tdfxfb_imageblit
,
};
static
struct
fb_info_tdfx
fb_info
;
/*
* do_xxx: Hardware-specific functions
*/
static
u32
do_calc_pll
(
int
freq
,
int
*
freq_out
);
static
void
do_write_regs
(
struct
banshee_reg
*
reg
);
static
unsigned
long
do_lfb_size
(
unsigned
short
);
/*
* Driver data
*/
static
struct
tdfx_par
default_par
;
static
int
noaccel
=
0
;
static
int
nopan
=
0
;
static
int
nowrap
=
1
;
// not implemented (yet)
static
int
inverse
=
0
;
#ifdef CONFIG_MTRR
static
int
nomtrr
=
0
;
#endif
static
int
nohwcursor
=
0
;
static
char
__initdata
fontname
[
40
]
=
{
0
};
static
char
*
mode_option
__initdata
=
NULL
;
/* -------------------------------------------------------------------------
...
...
@@ -344,98 +210,62 @@ static char *mode_option __initdata = NULL;
* ------------------------------------------------------------------------- */
#ifdef VGA_REG_IO
static
inline
u8
vga_inb
(
u32
reg
)
{
return
inb
(
reg
);
}
static
inline
u16
vga_inw
(
u32
reg
)
{
return
inw
(
reg
);
}
static
inline
u16
vga_inl
(
u32
reg
)
{
return
inl
(
reg
);
}
static
inline
u8
vga_inb
(
u32
reg
)
{
return
inb
(
reg
);
}
static
inline
u16
vga_inw
(
u32
reg
)
{
return
inw
(
reg
);
}
static
inline
u16
vga_inl
(
u32
reg
)
{
return
inl
(
reg
);
}
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
outb
(
val
,
reg
);
}
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
outw
(
val
,
reg
);
}
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
outl
(
val
,
reg
);
}
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
outb
(
val
,
reg
);
}
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
outw
(
val
,
reg
);
}
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
outl
(
val
,
reg
);
}
#else
static
inline
u8
vga_inb
(
u32
reg
)
{
return
inb
(
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
u8
vga_inb
(
u32
reg
)
{
return
inb
(
default_par
.
iobase
+
reg
-
0x300
);
}
static
inline
u16
vga_inw
(
u32
reg
)
{
return
inw
(
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
u16
vga_inw
(
u32
reg
)
{
return
inw
(
default_par
.
iobase
+
reg
-
0x300
);
}
static
inline
u16
vga_inl
(
u32
reg
)
{
return
inl
(
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
u16
vga_inl
(
u32
reg
)
{
return
inl
(
default_par
.
iobase
+
reg
-
0x300
);
}
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
outb
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
outb
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
}
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
outw
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
outw
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
}
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
outl
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
outl
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
}
#endif
static
inline
void
gra_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
GRA_I
,
idx
);
vga_outb
(
GRA_D
,
val
);
static
inline
void
gra_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
GRA_I
,
idx
);
vga_outb
(
GRA_D
,
val
);
}
static
inline
u8
gra_inb
(
u32
idx
)
{
vga_outb
(
GRA_I
,
idx
);
return
vga_inb
(
GRA_D
);
static
inline
u8
gra_inb
(
u32
idx
)
{
vga_outb
(
GRA_I
,
idx
);
return
vga_inb
(
GRA_D
);
}
static
inline
void
seq_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
SEQ_I
,
idx
);
vga_outb
(
SEQ_D
,
val
);
static
inline
void
seq_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
SEQ_I
,
idx
);
vga_outb
(
SEQ_D
,
val
);
}
static
inline
u8
seq_inb
(
u32
idx
)
{
vga_outb
(
SEQ_I
,
idx
);
return
vga_inb
(
SEQ_D
);
static
inline
u8
seq_inb
(
u32
idx
)
{
vga_outb
(
SEQ_I
,
idx
);
return
vga_inb
(
SEQ_D
);
}
static
inline
void
crt_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
CRT_I
,
idx
);
vga_outb
(
CRT_D
,
val
);
static
inline
void
crt_outb
(
u32
idx
,
u8
val
)
{
vga_outb
(
CRT_I
,
idx
);
vga_outb
(
CRT_D
,
val
);
}
static
inline
u8
crt_inb
(
u32
idx
)
{
vga_outb
(
CRT_I
,
idx
);
return
vga_inb
(
CRT_D
);
static
inline
u8
crt_inb
(
u32
idx
)
{
vga_outb
(
CRT_I
,
idx
);
return
vga_inb
(
CRT_D
);
}
static
inline
void
att_outb
(
u32
idx
,
u8
val
)
{
unsigned
char
tmp
;
tmp
=
vga_inb
(
IS1_R
);
vga_outb
(
ATT_IW
,
idx
);
vga_outb
(
ATT_IW
,
val
);
...
...
@@ -444,6 +274,7 @@ static inline void att_outb(u32 idx, u8 val)
static
inline
u8
att_inb
(
u32
idx
)
{
unsigned
char
tmp
;
tmp
=
vga_inb
(
IS1_R
);
vga_outb
(
ATT_IW
,
idx
);
return
vga_inb
(
ATT_IW
);
...
...
@@ -452,6 +283,7 @@ static inline u8 att_inb(u32 idx)
static
inline
void
vga_disable_video
(
void
)
{
unsigned
char
s
;
s
=
seq_inb
(
0x01
)
|
0x20
;
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x01
,
s
);
...
...
@@ -461,6 +293,7 @@ static inline void vga_disable_video(void)
static
inline
void
vga_enable_video
(
void
)
{
unsigned
char
s
;
s
=
seq_inb
(
0x01
)
&
0xdf
;
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x01
,
s
);
...
...
@@ -481,17 +314,17 @@ static inline void vga_enable_palette(void)
static
inline
u32
tdfx_inl
(
unsigned
int
reg
)
{
return
readl
(
fb_info
.
regbase_virt
+
reg
);
return
readl
(
default_par
.
regbase_virt
+
reg
);
}
static
inline
void
tdfx_outl
(
unsigned
int
reg
,
u32
val
)
{
writel
(
val
,
fb_info
.
regbase_virt
+
reg
);
writel
(
val
,
default_par
.
regbase_virt
+
reg
);
}
static
inline
void
banshee_make_room
(
int
size
)
{
while
((
tdfx_inl
(
STATUS
)
&
0x1f
)
<
size
);
while
((
tdfx_inl
(
STATUS
)
&
0x1f
)
<
size
);
}
static
inline
void
banshee_wait_idle
(
void
)
...
...
@@ -501,10 +334,9 @@ static inline void banshee_wait_idle(void)
banshee_make_room
(
1
);
tdfx_outl
(
COMMAND_3D
,
COMMAND_3D_NOP
);
while
(
1
)
{
while
(
1
)
{
i
=
(
tdfx_inl
(
STATUS
)
&
STATUS_BUSY
)
?
0
:
i
+
1
;
if
(
i
==
3
)
break
;
if
(
i
==
3
)
break
;
}
}
...
...
@@ -518,239 +350,7 @@ static inline void do_setpalentry(unsigned regno, u32 c)
tdfx_outl
(
DACDATA
,
c
);
}
/*
* Set the starting position of the visible screen to var->yoffset
*/
static
void
do_pan_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info_tdfx
*
i
)
{
u32
addr
;
addr
=
var
->
yoffset
*
i
->
current_par
.
lpitch
;
banshee_make_room
(
1
);
tdfx_outl
(
VIDDESKSTART
,
addr
);
}
/*
* Invert the hardware cursor image (timerfunc)
*/
static
void
do_flashcursor
(
unsigned
long
ptr
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
ptr
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
i
->
DAClock
,
flags
);
banshee_make_room
(
1
);
tdfx_outl
(
VIDPROCCFG
,
tdfx_inl
(
VIDPROCCFG
)
^
VIDCFG_HWCURSOR_ENABLE
);
i
->
cursor
.
timer
.
expires
=
jiffies
+
HZ
/
2
;
add_timer
(
&
i
->
cursor
.
timer
);
spin_unlock_irqrestore
(
&
i
->
DAClock
,
flags
);
}
/*
* FillRect 2D command (solidfill or invert (via ROP_XOR))
*/
static
void
do_fillrect
(
u32
x
,
u32
y
,
u32
w
,
u32
h
,
u32
color
,
u32
stride
,
u32
bpp
,
u32
rop
)
{
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
banshee_make_room
(
5
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
COLORFORE
,
color
);
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_FILLRECT
|
(
rop
<<
24
));
tdfx_outl
(
DSTSIZE
,
w
|
(
h
<<
16
));
tdfx_outl
(
LAUNCH_2D
,
x
|
(
y
<<
16
));
banshee_wait_idle
();
}
/*
* Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
*/
static
void
do_bitblt
(
u32
curx
,
u32
cury
,
u32
dstx
,
u32
dsty
,
u32
width
,
u32
height
,
u32
stride
,
u32
bpp
)
{
u32
blitcmd
=
COMMAND_2D_S2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
);
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
if
(
curx
<=
dstx
)
{
//-X
blitcmd
|=
BIT
(
14
);
curx
+=
width
-
1
;
dstx
+=
width
-
1
;
}
if
(
cury
<=
dsty
)
{
//-Y
blitcmd
|=
BIT
(
15
);
cury
+=
height
-
1
;
dsty
+=
height
-
1
;
}
banshee_make_room
(
6
);
tdfx_outl
(
SRCFORMAT
,
fmt
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
COMMAND_2D
,
blitcmd
);
tdfx_outl
(
DSTSIZE
,
width
|
(
height
<<
16
));
tdfx_outl
(
DSTXY
,
dstx
|
(
dsty
<<
16
));
tdfx_outl
(
LAUNCH_2D
,
curx
|
(
cury
<<
16
));
banshee_wait_idle
();
}
static
void
do_putc
(
u32
fgx
,
u32
bgx
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
int
i
;
int
stride
=
fb_info
.
current_par
.
lpitch
;
u32
bpp
=
fb_info
.
current_par
.
bpp
;
int
fw
=
(
fontwidth
(
p
)
+
7
)
>>
3
;
u8
*
chardata
=
p
->
fontdata
+
(
c
&
p
->
charmask
)
*
fontheight
(
p
)
*
fw
;
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
xx
*=
fontwidth
(
p
);
yy
*=
fontheight
(
p
);
banshee_make_room
(
8
+
((
fontheight
(
p
)
*
fw
+
3
)
>>
2
));
tdfx_outl
(
COLORFORE
,
fgx
);
tdfx_outl
(
COLORBACK
,
bgx
);
tdfx_outl
(
SRCXY
,
0
);
tdfx_outl
(
DSTXY
,
xx
|
(
yy
<<
16
));
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_H2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
));
tdfx_outl
(
SRCFORMAT
,
0x400000
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
DSTSIZE
,
fontwidth
(
p
)
|
(
fontheight
(
p
)
<<
16
));
i
=
fontheight
(
p
);
switch
(
fw
)
{
case
1
:
while
(
i
>=
4
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
i
-=
4
;
}
switch
(
i
)
{
case
0
:
break
;
case
1
:
tdfx_outl
(
LAUNCH_2D
,
*
chardata
);
break
;
case
2
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
);
break
;
case
3
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
|
((
chardata
[
3
])
<<
24
));
break
;
}
break
;
case
2
:
while
(
i
>=
2
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
i
-=
2
;
}
if
(
i
)
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
);
break
;
default:
// Is there a font with width more that 16 pixels ?
for
(
i
=
fontheight
(
p
);
i
>
0
;
i
--
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
}
break
;
}
banshee_wait_idle
();
}
static
void
do_putcs
(
u32
fgx
,
u32
bgx
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
int
i
;
int
stride
=
fb_info
.
current_par
.
lpitch
;
u32
bpp
=
fb_info
.
current_par
.
bpp
;
int
fw
=
(
fontwidth
(
p
)
+
7
)
>>
3
;
int
w
=
fontwidth
(
p
);
int
h
=
fontheight
(
p
);
int
regsneed
=
1
+
((
h
*
fw
+
3
)
>>
2
);
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
xx
*=
w
;
yy
=
(
yy
*
h
)
<<
16
;
banshee_make_room
(
8
);
tdfx_outl
(
COMMAND_3D
,
COMMAND_3D_NOP
);
tdfx_outl
(
COLORFORE
,
fgx
);
tdfx_outl
(
COLORBACK
,
bgx
);
tdfx_outl
(
SRCFORMAT
,
0x400000
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
DSTSIZE
,
w
|
(
h
<<
16
));
tdfx_outl
(
SRCXY
,
0
);
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_H2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
));
while
(
count
--
)
{
u8
*
chardata
=
p
->
fontdata
+
(
scr_readw
(
s
++
)
&
p
->
charmask
)
*
h
*
fw
;
banshee_make_room
(
regsneed
);
tdfx_outl
(
DSTXY
,
xx
|
yy
);
xx
+=
w
;
i
=
h
;
switch
(
fw
)
{
case
1
:
while
(
i
>=
4
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
i
-=
4
;
}
switch
(
i
)
{
case
0
:
break
;
case
1
:
tdfx_outl
(
LAUNCH_2D
,
*
chardata
);
break
;
case
2
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
);
break
;
case
3
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
|
((
chardata
[
3
])
<<
24
));
break
;
}
break
;
case
2
:
while
(
i
>=
2
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
i
-=
2
;
}
if
(
i
)
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
);
break
;
default:
// Is there a font with width more that 16 pixels ?
for
(;
i
>
0
;
i
--
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
}
break
;
}
}
banshee_wait_idle
();
}
static
u32
do_calc_pll
(
int
freq
,
int
*
freq_out
)
static
u32
do_calc_pll
(
int
freq
,
int
*
freq_out
)
{
int
m
,
n
,
k
,
best_m
,
best_n
,
best_k
,
f_cur
,
best_error
;
int
fref
=
14318
;
...
...
@@ -762,10 +362,9 @@ static u32 do_calc_pll(int freq, int *freq_out)
for
(
n
=
1
;
n
<
256
;
n
++
)
{
for
(
m
=
1
;
m
<
64
;
m
++
)
{
for
(
k
=
0
;
k
<
4
;
k
++
)
{
f_cur
=
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
f_cur
=
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
if
(
abs
(
f_cur
-
freq
)
<
best_error
)
{
best_error
=
abs
(
f_cur
-
freq
);
best_error
=
abs
(
f_cur
-
freq
);
best_n
=
n
;
best_m
=
m
;
best_k
=
k
;
...
...
@@ -776,12 +375,11 @@ static u32 do_calc_pll(int freq, int *freq_out)
n
=
best_n
;
m
=
best_m
;
k
=
best_k
;
*
freq_out
=
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
*
freq_out
=
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
return
(
n
<<
8
)
|
(
m
<<
2
)
|
k
;
}
static
void
do_write_regs
(
struct
banshee_reg
*
reg
)
static
void
do_write_regs
(
struct
banshee_reg
*
reg
)
{
int
i
;
...
...
@@ -824,16 +422,9 @@ static void do_write_regs(struct banshee_reg *reg)
tdfx_outl
(
VGAINIT0
,
reg
->
vgainit0
);
tdfx_outl
(
DACMODE
,
reg
->
dacmode
);
tdfx_outl
(
VIDDESKSTRIDE
,
reg
->
stride
);
if
(
nohwcursor
)
{
tdfx_outl
(
HWCURPATADDR
,
0
);
}
else
{
tdfx_outl
(
HWCURPATADDR
,
reg
->
curspataddr
);
tdfx_outl
(
HWCURC0
,
reg
->
cursc0
);
tdfx_outl
(
HWCURC1
,
reg
->
cursc1
);
tdfx_outl
(
HWCURLOC
,
reg
->
cursloc
);
}
tdfx_outl
(
VIDSCREENSIZE
,
reg
->
screensize
);
tdfx_outl
(
VIDSCREENSIZE
,
reg
->
screensize
);
tdfx_outl
(
VIDDESKSTART
,
reg
->
startaddr
);
tdfx_outl
(
VIDPROCCFG
,
reg
->
vidcfg
);
tdfx_outl
(
VGAINIT1
,
reg
->
vgainit1
);
...
...
@@ -852,7 +443,7 @@ static void do_write_regs(struct banshee_reg *reg)
banshee_wait_idle
();
}
static
unsigned
long
do_lfb_size
(
void
)
static
unsigned
long
do_lfb_size
(
unsigned
short
dev_id
)
{
u32
draminit0
=
0
;
u32
draminit1
=
0
;
...
...
@@ -863,14 +454,14 @@ static unsigned long do_lfb_size(void)
draminit0
=
tdfx_inl
(
DRAMINIT0
);
draminit1
=
tdfx_inl
(
DRAMINIT1
);
if
((
fb_info
.
dev
==
PCI_DEVICE_ID_3DFX_BANSHEE
)
||
(
fb_info
.
dev
==
PCI_DEVICE_ID_3DFX_VOODOO3
))
{
if
((
dev_id
==
PCI_DEVICE_ID_3DFX_BANSHEE
)
||
(
dev_id
==
PCI_DEVICE_ID_3DFX_VOODOO3
))
{
sgram_p
=
(
draminit1
&
DRAMINIT1_MEM_SDRAM
)
?
0
:
1
;
lfbsize
=
sgram_p
?
(((
draminit0
&
DRAMINIT0_SGRAM_NUM
)
?
2
:
1
)
*
((
draminit0
&
DRAMINIT0_SGRAM_TYPE
)
?
8
:
4
)
*
1024
*
1024
)
:
16
*
1024
*
1024
;
((
draminit0
&
DRAMINIT0_SGRAM_TYPE
)
?
8
:
4
)
*
1024
*
1024
)
:
16
*
1024
*
1024
;
}
else
{
/* Voodoo4/5 */
u32
chips
,
psize
,
banks
;
...
...
@@ -881,7 +472,6 @@ static unsigned long do_lfb_size(void)
lfbsize
=
chips
*
psize
*
banks
;
lfbsize
<<=
20
;
}
/* disable block writes for SDRAM (why?) */
miscinit1
=
tdfx_inl
(
MISCINIT1
);
miscinit1
|=
sgram_p
?
0
:
MISCINIT1_2DBLOCK_DIS
;
...
...
@@ -889,306 +479,155 @@ static unsigned long do_lfb_size(void)
banshee_make_room
(
1
);
tdfx_outl
(
MISCINIT1
,
miscinit1
);
return
lfbsize
;
}
/* -------------------------------------------------------------------------
* Hardware independent part, interface to the world
* ------------------------------------------------------------------------- */
#define tdfx_cfb24_putc tdfx_cfb32_putc
#define tdfx_cfb24_putcs tdfx_cfb32_putcs
#define tdfx_cfb24_clear tdfx_cfb32_clear
/* ------------------------------------------------------------------------- */
static
void
tdfx_cfbX_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
static
int
tdfxfb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
unsigned
int
cw
=
fontwidth
(
p
);
unsigned
int
ch
=
fontheight
(
p
);
unsigned
int
rw
=
p
->
var
.
xres
%
cw
;
// it be in a non-standard mode or not?
unsigned
int
bh
=
p
->
var
.
yres
%
ch
;
unsigned
int
rs
=
p
->
var
.
xres
-
rw
;
unsigned
int
bs
=
p
->
var
.
yres
-
bh
;
if
(
!
bottom_only
&&
rw
)
{
do_fillrect
(
p
->
var
.
xoffset
+
rs
,
0
,
rw
,
p
->
var
.
yres_virtual
,
0
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
}
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
u32
lpitch
;
if
(
bh
)
{
do_fillrect
(
p
->
var
.
xoffset
,
p
->
var
.
yoffset
+
bs
,
rs
,
bh
,
0
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
if
(
var
->
bits_per_pixel
!=
8
&&
var
->
bits_per_pixel
!=
16
&&
var
->
bits_per_pixel
!=
24
&&
var
->
bits_per_pixel
!=
32
)
{
DPRINTK
(
"depth not supported: %u
\n
"
,
var
->
bits_per_pixel
);
return
-
EINVAL
;
}
}
static
void
tdfx_cfbX_bmove
(
struct
display
*
p
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
{
do_bitblt
(
fontwidth
(
p
)
*
sx
,
fontheight
(
p
)
*
sy
,
fontwidth
(
p
)
*
dx
,
fontheight
(
p
)
*
dy
,
fontwidth
(
p
)
*
width
,
fontheight
(
p
)
*
height
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
);
}
static
void
tdfx_cfb8_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
u32
fgx
,
bgx
;
fgx
=
attr_fgcol
(
p
,
c
);
bgx
=
attr_bgcol
(
p
,
c
);
do_putc
(
fgx
,
bgx
,
p
,
c
,
yy
,
xx
);
}
static
void
tdfx_cfb16_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
u32
fgx
,
bgx
;
fgx
=
((
u16
*
)
p
->
dispsw_data
)[
attr_fgcol
(
p
,
c
)];
bgx
=
((
u16
*
)
p
->
dispsw_data
)[
attr_bgcol
(
p
,
c
)];
do_putc
(
fgx
,
bgx
,
p
,
c
,
yy
,
xx
);
}
if
(
var
->
xres
!=
var
->
xres_virtual
)
{
DPRINTK
(
"virtual x resolution != physical x resolution not supported
\n
"
);
return
-
EINVAL
;
}
static
void
tdfx_cfb32_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
u32
fgx
,
bgx
;
fgx
=
((
u32
*
)
p
->
dispsw_data
)[
attr_fgcol
(
p
,
c
)];
bgx
=
((
u32
*
)
p
->
dispsw_data
)[
attr_bgcol
(
p
,
c
)];
do_putc
(
fgx
,
bgx
,
p
,
c
,
yy
,
xx
);
}
static
void
tdfx_cfb8_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
u16
c
=
scr_readw
(
s
);
u32
fgx
=
attr_fgcol
(
p
,
c
);
u32
bgx
=
attr_bgcol
(
p
,
c
);
do_putcs
(
fgx
,
bgx
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
tdfx_cfb16_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
u16
c
=
scr_readw
(
s
);
u32
fgx
=
((
u16
*
)
p
->
dispsw_data
)[
attr_fgcol
(
p
,
c
)];
u32
bgx
=
((
u16
*
)
p
->
dispsw_data
)[
attr_bgcol
(
p
,
c
)];
do_putcs
(
fgx
,
bgx
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
tdfx_cfb32_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
u16
c
=
scr_readw
(
s
);
u32
fgx
=
((
u32
*
)
p
->
dispsw_data
)[
attr_fgcol
(
p
,
c
)];
u32
bgx
=
((
u32
*
)
p
->
dispsw_data
)[
attr_bgcol
(
p
,
c
)];
do_putcs
(
fgx
,
bgx
,
p
,
s
,
count
,
yy
,
xx
);
}
if
(
var
->
yres
>
var
->
yres_virtual
)
{
DPRINTK
(
"virtual y resolution < physical y resolution not possible
\n
"
);
return
-
EINVAL
;
}
static
void
tdfx_cfb8_clear
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
sy
,
int
sx
,
int
height
,
int
width
)
{
u32
bg
;
bg
=
attr_bgcol_ec
(
p
,
conp
);
do_fillrect
(
fontwidth
(
p
)
*
sx
,
fontheight
(
p
)
*
sy
,
fontwidth
(
p
)
*
width
,
fontheight
(
p
)
*
height
,
bg
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
}
if
(
var
->
xoffset
)
{
DPRINTK
(
"xoffset not supported
\n
"
);
return
-
EINVAL
;
}
static
void
tdfx_cfb16_clear
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
sy
,
int
sx
,
int
height
,
int
width
)
{
u32
bg
;
bg
=
((
u16
*
)
p
->
dispsw_data
)[
attr_bgcol_ec
(
p
,
conp
)];
do_fillrect
(
fontwidth
(
p
)
*
sx
,
fontheight
(
p
)
*
sy
,
fontwidth
(
p
)
*
width
,
fontheight
(
p
)
*
height
,
bg
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
}
/* fixme: does Voodoo3 support interlace? Banshee doesn't */
if
((
var
->
vmode
&
FB_VMODE_MASK
)
==
FB_VMODE_INTERLACED
)
{
DPRINTK
(
"interlace not supported
\n
"
);
return
-
EINVAL
;
}
static
void
tdfx_cfb32_clear
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
sy
,
int
sx
,
int
height
,
int
width
)
{
u32
bg
;
bg
=
((
u32
*
)
p
->
dispsw_data
)[
attr_bgcol_ec
(
p
,
conp
)];
do_fillrect
(
fontwidth
(
p
)
*
sx
,
fontheight
(
p
)
*
sy
,
fontwidth
(
p
)
*
width
,
fontheight
(
p
)
*
height
,
bg
,
fb_info
.
current_par
.
lpitch
,
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
}
static
void
tdfx_cfbX_revc
(
struct
display
*
p
,
int
xx
,
int
yy
)
{
int
bpp
=
fb_info
.
current_par
.
bpp
;
var
->
xres
=
(
var
->
xres
+
15
)
&
~
15
;
/* could sometimes be 8 */
lpitch
=
var
->
xres
*
((
var
->
bits_per_pixel
+
7
)
>>
3
);
do_fillrect
(
xx
*
fontwidth
(
p
),
yy
*
fontheight
(
p
),
fontwidth
(
p
),
fontheight
(
p
),
(
bpp
==
8
)
?
0x0f
:
0xffffffff
,
fb_info
.
current_par
.
lpitch
,
bpp
,
TDFX_ROP_XOR
);
if
(
var
->
xres
<
320
||
var
->
xres
>
2048
)
{
DPRINTK
(
"width not supported: %u
\n
"
,
var
->
xres
);
return
-
EINVAL
;
}
}
static
void
tdfx_cfbX_cursor
(
struct
display
*
p
,
int
mode
,
int
x
,
int
y
)
{
unsigned
long
flags
;
int
tip
;
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
p
->
fb_info
;
tip
=
p
->
conp
->
vc_cursor_type
&
CUR_HWMASK
;
if
(
mode
==
CM_ERASE
)
{
if
(
info
->
cursor
.
state
!=
CM_ERASE
)
{
spin_lock_irqsave
(
&
info
->
DAClock
,
flags
);
info
->
cursor
.
state
=
CM_ERASE
;
del_timer
(
&
(
info
->
cursor
.
timer
));
tdfx_outl
(
VIDPROCCFG
,
info
->
cursor
.
disable
);
spin_unlock_irqrestore
(
&
info
->
DAClock
,
flags
);
if
(
var
->
yres
<
200
||
var
->
yres
>
2048
)
{
DPRINTK
(
"height not supported: %u
\n
"
,
var
->
yres
);
return
-
EINVAL
;
}
return
;
if
(
lpitch
*
var
->
yres_virtual
>
info
->
fix
.
smem_len
)
{
DPRINTK
(
"no memory for screen (%ux%ux%u)
\n
"
,
var
->
xres
,
var
->
yres_virtual
,
var
->
bits_per_pixel
);
return
-
EINVAL
;
}
if
((
p
->
conp
->
vc_cursor_type
&
CUR_HWMASK
)
!=
info
->
cursor
.
type
)
tdfxfb_createcursor
(
p
);
x
*=
fontwidth
(
p
);
y
*=
fontheight
(
p
);
y
-=
p
->
var
.
yoffset
;
spin_lock_irqsave
(
&
info
->
DAClock
,
flags
);
if
((
x
!=
info
->
cursor
.
x
)
||
(
y
!=
info
->
cursor
.
y
)
||
(
info
->
cursor
.
redraw
))
{
info
->
cursor
.
x
=
x
;
info
->
cursor
.
y
=
y
;
info
->
cursor
.
redraw
=
0
;
x
+=
63
;
y
+=
63
;
banshee_make_room
(
2
);
tdfx_outl
(
VIDPROCCFG
,
info
->
cursor
.
disable
);
tdfx_outl
(
HWCURLOC
,
(
y
<<
16
)
+
x
);
/* fix cursor color - XFree86 forgets to restore it properly */
tdfx_outl
(
HWCURC0
,
0
);
tdfx_outl
(
HWCURC1
,
0xffffff
);
if
(
PICOS2KHZ
(
var
->
pixclock
)
>
par
->
max_pixclock
)
{
DPRINTK
(
"pixclock too high (%ldKHz)
\n
"
,
PICOS2KHZ
(
var
->
pixclock
));
return
-
EINVAL
;
}
info
->
cursor
.
state
=
CM_DRAW
;
mod_timer
(
&
info
->
cursor
.
timer
,
jiffies
+
HZ
/
2
);
banshee_make_room
(
1
);
tdfx_outl
(
VIDPROCCFG
,
info
->
cursor
.
enable
);
spin_unlock_irqrestore
(
&
info
->
DAClock
,
flags
);
return
;
}
#ifdef FBCON_HAS_CFB8
static
struct
display_switch
fbcon_banshee8
=
{
setup:
fbcon_cfb8_setup
,
bmove:
tdfx_cfbX_bmove
,
clear:
tdfx_cfb8_clear
,
putc:
tdfx_cfb8_putc
,
putcs:
tdfx_cfb8_putcs
,
revc:
tdfx_cfbX_revc
,
cursor:
tdfx_cfbX_cursor
,
clear_margins:
tdfx_cfbX_clear_margins
,
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
};
#endif
#ifdef FBCON_HAS_CFB16
static
struct
display_switch
fbcon_banshee16
=
{
setup:
fbcon_cfb16_setup
,
bmove:
tdfx_cfbX_bmove
,
clear:
tdfx_cfb16_clear
,
putc:
tdfx_cfb16_putc
,
putcs:
tdfx_cfb16_putcs
,
revc:
tdfx_cfbX_revc
,
cursor:
tdfx_cfbX_cursor
,
clear_margins:
tdfx_cfbX_clear_margins
,
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
};
#endif
#ifdef FBCON_HAS_CFB24
static
struct
display_switch
fbcon_banshee24
=
{
setup:
fbcon_cfb24_setup
,
bmove:
tdfx_cfbX_bmove
,
clear:
tdfx_cfb24_clear
,
putc:
tdfx_cfb24_putc
,
putcs:
tdfx_cfb24_putcs
,
revc:
tdfx_cfbX_revc
,
cursor:
tdfx_cfbX_cursor
,
clear_margins:
tdfx_cfbX_clear_margins
,
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
};
#endif
#ifdef FBCON_HAS_CFB32
static
struct
display_switch
fbcon_banshee32
=
{
setup:
fbcon_cfb32_setup
,
bmove:
tdfx_cfbX_bmove
,
clear:
tdfx_cfb32_clear
,
putc:
tdfx_cfb32_putc
,
putcs:
tdfx_cfb32_putcs
,
revc:
tdfx_cfbX_revc
,
cursor:
tdfx_cfbX_cursor
,
clear_margins:
tdfx_cfbX_clear_margins
,
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
};
#endif
switch
(
var
->
bits_per_pixel
)
{
case
8
:
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
break
;
case
16
:
var
->
red
.
offset
=
11
;
var
->
red
.
length
=
5
;
var
->
green
.
offset
=
5
;
var
->
green
.
length
=
6
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
5
;
break
;
case
24
:
var
->
red
.
offset
=
16
;
var
->
green
.
offset
=
8
;
var
->
blue
.
offset
=
0
;
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
case
32
:
var
->
red
.
offset
=
16
;
var
->
green
.
offset
=
8
;
var
->
blue
.
offset
=
0
;
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
break
;
}
var
->
height
=
var
->
width
=
-
1
;
/* ------------------------------------------------------------------------- */
var
->
accel_flags
=
FB_ACCELF_TEXT
;
DPRINTK
(
"Checking graphics mode at %dx%d depth %d
\n
"
,
var
->
xres
,
var
->
yres
,
var
->
bits_per_pixel
);
return
0
;
}
static
void
tdfxfb_set_par
(
const
struct
tdfxfb_par
*
par
,
struct
fb_info_tdfx
*
info
)
static
int
tdfxfb_set_par
(
struct
fb_info
*
info
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
info
;
struct
banshee_reg
reg
;
u32
cpp
;
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
u32
hdispend
,
hsyncsta
,
hsyncend
,
htotal
;
u32
hd
,
hs
,
he
,
ht
,
hbs
,
hbe
;
u32
vd
,
vs
,
ve
,
vt
,
vbs
,
vbe
;
u32
wd
;
int
fout
;
int
freq
;
struct
banshee_reg
reg
;
int
fout
,
freq
;
u32
wd
,
cpp
;
info
->
cmap
.
len
=
(
info
->
var
.
bits_per_pixel
==
8
)
?
256
:
16
;
par
->
baseline
=
0
;
memset
(
&
reg
,
0
,
sizeof
(
reg
));
cpp
=
(
info
->
var
.
bits_per_pixel
+
7
)
/
8
;
reg
.
vidcfg
=
VIDCFG_VIDPROC_ENABLE
|
VIDCFG_DESK_ENABLE
|
VIDCFG_CURS_X11
|
((
cpp
-
1
)
<<
VIDCFG_PIXFMT_SHIFT
)
|
(
cpp
!=
1
?
VIDCFG_CLUT_BYPASS
:
0
);
cpp
=
(
par
->
bpp
+
7
)
/
8
;
/* PLL settings */
freq
=
PICOS2KHZ
(
info
->
var
.
pixclock
);
reg
.
dacmode
=
0
;
reg
.
vidcfg
&=
~
VIDCFG_2X
;
wd
=
(
par
->
hdispend
>>
3
)
-
1
;
hdispend
=
info
->
var
.
xres
;
hsyncsta
=
hdispend
+
info
->
var
.
right_margin
;
hsyncend
=
hsyncsta
+
info
->
var
.
hsync_len
;
htotal
=
hsyncend
+
info
->
var
.
left_margin
;
if
(
freq
>
par
->
max_pixclock
/
2
)
{
freq
=
freq
>
par
->
max_pixclock
?
par
->
max_pixclock
:
freq
;
reg
.
dacmode
|=
DACMODE_2X
;
reg
.
vidcfg
|=
VIDCFG_2X
;
hdispend
>>=
1
;
hsyncsta
>>=
1
;
hsyncend
>>=
1
;
htotal
>>=
1
;
}
hd
=
(
par
->
hdispend
>>
3
)
-
1
;
hs
=
(
par
->
hsyncsta
>>
3
)
-
1
;
he
=
(
par
->
hsyncend
>>
3
)
-
1
;
ht
=
(
par
->
htotal
>>
3
)
-
1
;
hd
=
wd
=
(
hdispend
>>
3
)
-
1
;
hs
=
(
hsyncsta
>>
3
)
-
1
;
he
=
(
hsyncend
>>
3
)
-
1
;
ht
=
(
htotal
>>
3
)
-
1
;
hbs
=
hd
;
hbe
=
ht
;
vd
=
par
->
vdispend
-
1
;
vs
=
par
->
vsyncsta
-
1
;
ve
=
par
->
vsyncend
-
1
;
vt
=
par
->
vtotal
-
2
;
vbs
=
vd
;
vbe
=
vt
;
vbs
=
vd
=
info
->
var
.
yres
-
1
;
vs
=
vd
+
info
->
var
.
lower_margin
;
ve
=
vs
+
info
->
var
.
vsync_len
;
vbe
=
vt
=
ve
+
info
->
var
.
upper_margin
-
1
;
/* this is all pretty standard VGA register stuffing */
reg
.
misc
[
0x00
]
=
0x0f
|
(
par
->
hdispend
<
400
?
0xa0
:
par
->
hdispend
<
480
?
0x60
:
par
->
hdispend
<
768
?
0xe0
:
0x20
);
reg
.
misc
[
0x00
]
=
0x0f
|
(
info
->
var
.
xres
<
400
?
0xa0
:
info
->
var
.
xres
<
480
?
0x60
:
info
->
var
.
xres
<
768
?
0xe0
:
0x20
);
reg
.
gra
[
0x00
]
=
0x00
;
reg
.
gra
[
0x01
]
=
0x00
;
...
...
@@ -1235,14 +674,13 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg
.
crt
[
0x04
]
=
hs
;
reg
.
crt
[
0x05
]
=
((
hbe
&
0x20
)
<<
2
)
|
(
he
&
0x1f
);
reg
.
crt
[
0x06
]
=
vt
;
reg
.
crt
[
0x07
]
=
((
vs
&
0x200
)
>>
2
)
|
reg
.
crt
[
0x07
]
=
((
vs
&
0x200
)
>>
2
)
|
((
vd
&
0x200
)
>>
3
)
|
((
vt
&
0x200
)
>>
4
)
|
0x10
|
((
vt
&
0x200
)
>>
4
)
|
0x10
|
((
vbs
&
0x100
)
>>
5
)
|
((
vs
&
0x100
)
>>
6
)
|
((
vd
&
0x100
)
>>
7
)
|
((
vt
&
0x100
)
>>
8
);
((
vd
&
0x100
)
>>
7
)
|
((
vt
&
0x100
)
>>
8
);
reg
.
crt
[
0x08
]
=
0x00
;
reg
.
crt
[
0x09
]
=
0x40
|
((
vbs
&
0x200
)
>>
4
);
reg
.
crt
[
0x0a
]
=
0x00
;
...
...
@@ -1266,47 +704,37 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
((
hd
&
0x100
)
>>
6
)
|
((
hbs
&
0x100
)
>>
4
)
|
((
hbe
&
0x40
)
>>
1
)
|
((
hs
&
0x100
)
>>
2
)
|
((
he
&
0x20
)
<<
2
));
((
hs
&
0x100
)
>>
2
)
|
((
he
&
0x20
)
<<
2
));
reg
.
ext
[
0x01
]
=
(((
vt
&
0x400
)
>>
10
)
|
((
vd
&
0x400
)
>>
8
)
|
((
vbs
&
0x400
)
>>
6
)
|
((
vbe
&
0x400
)
>>
4
));
((
vbs
&
0x400
)
>>
6
)
|
((
vbe
&
0x400
)
>>
4
));
reg
.
vgainit0
=
VGAINIT0_8BIT_DAC
|
reg
.
vgainit0
=
VGAINIT0_8BIT_DAC
|
VGAINIT0_EXT_ENABLE
|
VGAINIT0_WAKEUP_3C3
|
VGAINIT0_ALT_READBACK
|
VGAINIT0_EXTSHIFTOUT
;
VGAINIT0_ALT_READBACK
|
VGAINIT0_EXTSHIFTOUT
;
reg
.
vgainit1
=
tdfx_inl
(
VGAINIT1
)
&
0x1fffff
;
reg
.
vidcfg
=
VIDCFG_VIDPROC_ENABLE
|
VIDCFG_DESK_ENABLE
|
VIDCFG_CURS_X11
|
((
cpp
-
1
)
<<
VIDCFG_PIXFMT_SHIFT
)
|
(
cpp
!=
1
?
VIDCFG_CLUT_BYPASS
:
0
);
fb_info
.
cursor
.
enable
=
reg
.
vidcfg
|
VIDCFG_HWCURSOR_ENABLE
;
fb_info
.
cursor
.
disable
=
reg
.
vidcfg
;
reg
.
stride
=
par
->
width
*
cpp
;
reg
.
cursloc
=
0
;
reg
.
cursc0
=
0
;
reg
.
cursc1
=
0xffffff
;
reg
.
curspataddr
=
fb_info
.
cursor
.
cursorimage
;
reg
.
stride
=
info
->
var
.
xres
*
cpp
;
reg
.
startaddr
=
par
->
baseline
*
reg
.
stride
;
reg
.
srcbase
=
reg
.
startaddr
;
reg
.
dstbase
=
reg
.
startaddr
;
/* PLL settings */
freq
=
par
->
pixclock
;
freq
=
PICOS2KHZ
(
info
->
var
.
pixclock
)
;
reg
.
dacmode
&=
~
DACMODE_2X
;
reg
.
vidcfg
&=
~
VIDCFG_2X
;
if
(
freq
>
i
->
max_pixclock
/
2
)
{
freq
=
freq
>
i
->
max_pixclock
?
i
->
max_pixclock
:
freq
;
if
(
freq
>
par
->
max_pixclock
/
2
)
{
freq
=
freq
>
par
->
max_pixclock
?
par
->
max_pixclock
:
freq
;
reg
.
dacmode
|=
DACMODE_2X
;
reg
.
vidcfg
|=
VIDCFG_2X
;
}
...
...
@@ -1316,13 +744,12 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.gfxpll = do_calc_pll(..., &fout);
#endif
reg
.
screensize
=
par
->
width
|
(
par
->
height
<<
12
);
reg
.
screensize
=
info
->
var
.
xres
|
(
info
->
var
.
yres
<<
12
);
reg
.
vidcfg
&=
~
VIDCFG_HALF_MODE
;
reg
.
miscinit0
=
tdfx_inl
(
MISCINIT0
);
#if defined(__BIG_ENDIAN)
switch
(
par
->
bpp
)
{
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
reg
.
miscinit0
&=
~
(
1
<<
30
);
reg
.
miscinit0
&=
~
(
1
<<
31
);
...
...
@@ -1338,431 +765,211 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
break
;
}
#endif
do_write_regs
(
&
reg
);
i
->
current_par
=
*
par
;
/* Now change fb_fix_screeninfo according to changes in par */
info
->
fix
.
line_length
=
info
->
var
.
xres
*
((
info
->
var
.
bits_per_pixel
+
7
)
>>
3
);
info
->
fix
.
visual
=
(
info
->
var
.
bits_per_pixel
==
8
)
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_TRUECOLOR
;
DPRINTK
(
"Graphics mode is now set at %dx%d depth %d
\n
"
,
info
->
var
.
xres
,
info
->
var
.
yres
,
info
->
var
.
bits_per_pixel
);
return
0
;
}
static
int
tdfxfb_decode_var
(
const
struct
fb_var_screeninfo
*
var
,
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
)
static
int
tdfxfb_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
info
;
if
(
var
->
bits_per_pixel
!=
8
&&
var
->
bits_per_pixel
!=
16
&&
var
->
bits_per_pixel
!=
24
&&
var
->
bits_per_pixel
!=
32
)
{
DPRINTK
(
"depth not supported: %u
\n
"
,
var
->
bits_per_pixel
);
return
-
EINVAL
;
}
if
((
var
->
vmode
&
FB_VMODE_MASK
)
==
FB_VMODE_INTERLACED
)
{
DPRINTK
(
"interlace not supported
\n
"
);
return
-
EINVAL
;
}
if
(
var
->
xoffset
)
{
DPRINTK
(
"xoffset not supported
\n
"
);
return
-
EINVAL
;
}
if
(
var
->
xres
!=
var
->
xres_virtual
)
{
DPRINTK
(
"virtual x resolution != physical x resolution not supported
\n
"
);
return
-
EINVAL
;
}
if
(
var
->
yres
>
var
->
yres_virtual
)
{
DPRINTK
(
"virtual y resolution < physical y resolution not possible
\n
"
);
return
-
EINVAL
;
}
/* fixme: does Voodoo3 support interlace? Banshee doesn't */
if
((
var
->
vmode
&
FB_VMODE_MASK
)
==
FB_VMODE_INTERLACED
)
{
DPRINTK
(
"interlace not supported
\n
"
);
return
-
EINVAL
;
}
memset
(
par
,
0
,
sizeof
(
struct
tdfxfb_par
));
switch
(
i
->
dev
)
{
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
par
->
width
=
(
var
->
xres
+
15
)
&
~
15
;
/* could sometimes be 8 */
par
->
width_virt
=
par
->
width
;
par
->
height
=
var
->
yres
;
par
->
height_virt
=
var
->
yres_virtual
;
par
->
bpp
=
var
->
bits_per_pixel
;
par
->
ppitch
=
var
->
bits_per_pixel
;
par
->
lpitch
=
par
->
width
*
((
par
->
ppitch
+
7
)
>>
3
);
par
->
cmap_len
=
(
par
->
bpp
==
8
)
?
256
:
16
;
par
->
baseline
=
0
;
if
(
par
->
width
<
320
||
par
->
width
>
2048
)
{
DPRINTK
(
"width not supported: %u
\n
"
,
par
->
width
);
return
-
EINVAL
;
}
if
(
par
->
height
<
200
||
par
->
height
>
2048
)
{
DPRINTK
(
"height not supported: %u
\n
"
,
par
->
height
);
return
-
EINVAL
;
}
if
(
par
->
lpitch
*
par
->
height_virt
>
i
->
bufbase_size
)
{
DPRINTK
(
"no memory for screen (%ux%ux%u)
\n
"
,
par
->
width
,
par
->
height_virt
,
par
->
bpp
);
return
-
EINVAL
;
}
par
->
pixclock
=
PICOS2KHZ
(
var
->
pixclock
);
if
(
par
->
pixclock
>
i
->
max_pixclock
)
{
DPRINTK
(
"pixclock too high (%uKHz)
\n
"
,
par
->
pixclock
);
return
-
EINVAL
;
}
par
->
hdispend
=
var
->
xres
;
par
->
hsyncsta
=
par
->
hdispend
+
var
->
right_margin
;
par
->
hsyncend
=
par
->
hsyncsta
+
var
->
hsync_len
;
par
->
htotal
=
par
->
hsyncend
+
var
->
left_margin
;
par
->
vdispend
=
var
->
yres
;
par
->
vsyncsta
=
par
->
vdispend
+
var
->
lower_margin
;
par
->
vsyncend
=
par
->
vsyncsta
+
var
->
vsync_len
;
par
->
vtotal
=
par
->
vsyncend
+
var
->
upper_margin
;
if
(
var
->
sync
&
FB_SYNC_HOR_HIGH_ACT
)
par
->
video
|=
TDFXF_HSYNC_ACT_HIGH
;
else
par
->
video
|=
TDFXF_HSYNC_ACT_LOW
;
if
(
var
->
sync
&
FB_SYNC_VERT_HIGH_ACT
)
par
->
video
|=
TDFXF_VSYNC_ACT_HIGH
;
else
par
->
video
|=
TDFXF_VSYNC_ACT_LOW
;
if
((
var
->
vmode
&
FB_VMODE_MASK
)
==
FB_VMODE_DOUBLE
)
par
->
video
|=
TDFXF_LINE_DOUBLE
;
if
(
var
->
activate
==
FB_ACTIVATE_NOW
)
par
->
video
|=
TDFXF_VIDEO_ENABLE
;
}
if
(
var
->
accel_flags
&
FB_ACCELF_TEXT
)
par
->
accel_flags
=
FB_ACCELF_TEXT
;
else
par
->
accel_flags
=
0
;
u32
rgbcol
;
return
0
;
}
if
(
regno
>=
info
->
cmap
.
len
)
return
1
;
static
int
tdfxfb_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
)
{
struct
fb_var_screeninfo
v
;
memset
(
&
v
,
0
,
sizeof
(
struct
fb_var_screeninfo
));
v
.
xres_virtual
=
par
->
width_virt
;
v
.
yres_virtual
=
par
->
height_virt
;
v
.
xres
=
par
->
width
;
v
.
yres
=
par
->
height
;
v
.
right_margin
=
par
->
hsyncsta
-
par
->
hdispend
;
v
.
hsync_len
=
par
->
hsyncend
-
par
->
hsyncsta
;
v
.
left_margin
=
par
->
htotal
-
par
->
hsyncend
;
v
.
lower_margin
=
par
->
vsyncsta
-
par
->
vdispend
;
v
.
vsync_len
=
par
->
vsyncend
-
par
->
vsyncsta
;
v
.
upper_margin
=
par
->
vtotal
-
par
->
vsyncend
;
v
.
bits_per_pixel
=
par
->
bpp
;
switch
(
par
->
bpp
)
{
case
8
:
v
.
red
.
length
=
v
.
green
.
length
=
v
.
blue
.
length
=
8
;
switch
(
info
->
fix
.
visual
)
{
case
FB_VISUAL_PSEUDOCOLOR
:
rgbcol
=
(((
u32
)
red
&
0xff00
)
<<
8
)
|
(((
u32
)
green
&
0xff00
)
<<
0
)
|
(((
u32
)
blue
&
0xff00
)
>>
8
);
do_setpalentry
(
regno
,
rgbcol
);
break
;
case
16
:
v
.
red
.
offset
=
11
;
v
.
red
.
length
=
5
;
v
.
green
.
offset
=
5
;
v
.
green
.
length
=
6
;
v
.
blue
.
offset
=
0
;
v
.
blue
.
length
=
5
;
/* Truecolor has no hardware color palettes. */
case
FB_VISUAL_TRUECOLOR
:
rgbcol
=
(
red
<<
info
->
var
.
red
.
offset
)
|
(
green
<<
info
->
var
.
green
.
offset
)
|
(
blue
<<
info
->
var
.
blue
.
offset
)
|
(
transp
<<
info
->
var
.
transp
.
offset
);
if
(
info
->
var
.
bits_per_pixel
<=
16
)
((
u16
*
)(
info
->
pseudo_palette
))[
regno
]
=
rgbcol
;
else
((
u32
*
)(
info
->
pseudo_palette
))[
regno
]
=
rgbcol
;
break
;
case
24
:
v
.
red
.
offset
=
16
;
v
.
green
.
offset
=
8
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
v
.
green
.
length
=
v
.
blue
.
length
=
8
;
case
32
:
v
.
red
.
offset
=
16
;
v
.
green
.
offset
=
8
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
v
.
green
.
length
=
v
.
blue
.
length
=
8
;
default:
DPRINTK
(
"bad depth %u
\n
"
,
info
->
var
.
bits_per_pixel
);
break
;
}
v
.
height
=
v
.
width
=
-
1
;
v
.
pixclock
=
KHZ2PICOS
(
par
->
pixclock
);
if
((
par
->
video
&
TDFXF_HSYNC_MASK
)
==
TDFXF_HSYNC_ACT_HIGH
)
v
.
sync
|=
FB_SYNC_HOR_HIGH_ACT
;
if
((
par
->
video
&
TDFXF_VSYNC_MASK
)
==
TDFXF_VSYNC_ACT_HIGH
)
v
.
sync
|=
FB_SYNC_VERT_HIGH_ACT
;
if
(
par
->
video
&
TDFXF_LINE_DOUBLE
)
v
.
vmode
=
FB_VMODE_DOUBLE
;
*
var
=
v
;
return
0
;
}
static
int
tdfxfb_encode_fix
(
struct
fb_fix_screeninfo
*
fix
,
const
struct
tdfxfb_par
*
par
,
const
struct
fb_info_tdfx
*
info
)
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
info
)
{
memset
(
fix
,
0
,
sizeof
(
struct
fb_fix_screeninfo
))
;
u32
dacmode
,
state
=
0
,
vgablank
=
0
;
switch
(
info
->
dev
)
{
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
strcpy
(
fix
->
id
,
"3Dfx Banshee"
);
dacmode
=
tdfx_inl
(
DACMODE
);
switch
(
blank
)
{
case
0
:
/* Screen: On; HSync: On, VSync: On */
state
=
0
;
vgablank
=
0
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
strcpy
(
fix
->
id
,
"3Dfx Voodoo3"
);
case
1
:
/* Screen: Off; HSync: On, VSync: On */
state
=
0
;
vgablank
=
1
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
strcpy
(
fix
->
id
,
"3Dfx Voodoo5"
);
case
2
:
/* Screen: Off; HSync: On, VSync: Off */
state
=
BIT
(
3
);
vgablank
=
1
;
break
;
case
3
:
/* Screen: Off; HSync: Off, VSync: On */
state
=
BIT
(
1
);
vgablank
=
1
;
break
;
case
4
:
/* Screen: Off; HSync: Off, VSync: Off */
state
=
BIT
(
1
)
|
BIT
(
3
);
vgablank
=
1
;
break
;
default:
return
-
EINVAL
;
}
fix
->
smem_start
=
info
->
bufbase_phys
;
fix
->
smem_len
=
info
->
bufbase_size
;
fix
->
mmio_start
=
info
->
regbase_phys
;
fix
->
mmio_len
=
info
->
regbase_size
;
fix
->
accel
=
FB_ACCEL_3DFX_BANSHEE
;
fix
->
type
=
FB_TYPE_PACKED_PIXELS
;
fix
->
type_aux
=
0
;
fix
->
line_length
=
par
->
lpitch
;
fix
->
visual
=
(
par
->
bpp
==
8
)
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_DIRECTCOLOR
;
fix
->
xpanstep
=
0
;
fix
->
ypanstep
=
nopan
?
0
:
1
;
fix
->
ywrapstep
=
nowrap
?
0
:
1
;
dacmode
&=
~
(
BIT
(
1
)
|
BIT
(
3
));
dacmode
|=
state
;
banshee_make_room
(
1
);
tdfx_outl
(
DACMODE
,
dacmode
);
if
(
vgablank
)
vga_disable_video
();
else
vga_enable_video
();
return
0
;
}
static
int
tdfxfb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
fb
)
/*
* Set the starting position of the visible screen to var->yoffset
*/
static
int
tdfxfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
const
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
fb
;
struct
tdfxfb_par
par
;
u32
addr
;
if
(
con
==
-
1
)
par
=
info
->
default_par
;
else
tdfxfb_decode_var
(
&
fb_display
[
con
].
var
,
&
par
,
info
);
tdfxfb_encode_fix
(
fix
,
&
par
,
info
);
return
0
;
}
if
(
nopan
||
var
->
xoffset
||
(
var
->
yoffset
>
var
->
yres_virtual
))
return
-
EINVAL
;
if
((
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
&&
nowrap
))
return
-
EINVAL
;
static
int
tdfxfb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
const
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
fb
;
addr
=
var
->
yoffset
*
info
->
fix
.
line_length
;
banshee_make_room
(
1
);
tdfx_outl
(
VIDDESKSTART
,
addr
);
if
(
con
==
-
1
)
tdfxfb_encode_var
(
var
,
&
info
->
default_par
,
info
);
else
*
var
=
fb_display
[
con
].
var
;
info
->
var
.
xoffset
=
var
->
xoffset
;
info
->
var
.
yoffset
=
var
->
yoffset
;
return
0
;
}
static
void
tdfxfb_set_dispsw
(
struct
display
*
disp
,
struct
fb_info_tdfx
*
info
,
int
bpp
,
int
accel
)
/*
* FillRect 2D command (solidfill or invert (via ROP_XOR))
*/
static
void
tdfxfb_fillrect
(
struct
fb_info
*
info
,
struct
fb_fillrect
*
rect
)
{
u32
bpp
=
info
->
var
.
bits_per_pixel
;
u32
stride
=
info
->
fix
.
line_length
;
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
int
tdfx_rop
;
if
(
disp
->
dispsw
&&
disp
->
conp
)
fb_con
.
con_cursor
(
disp
->
conp
,
CM_ERASE
);
switch
(
bpp
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
disp
->
dispsw
=
noaccel
?
&
fbcon_cfb8
:
&
fbcon_banshee8
;
if
(
nohwcursor
)
fbcon_banshee8
.
cursor
=
NULL
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
disp
->
dispsw
=
noaccel
?
&
fbcon_cfb16
:
&
fbcon_banshee16
;
disp
->
dispsw_data
=
info
->
fbcon_cmap
.
cfb16
;
if
(
nohwcursor
)
fbcon_banshee16
.
cursor
=
NULL
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
disp
->
dispsw
=
noaccel
?
&
fbcon_cfb24
:
&
fbcon_banshee24
;
disp
->
dispsw_data
=
info
->
fbcon_cmap
.
cfb24
;
if
(
nohwcursor
)
fbcon_banshee24
.
cursor
=
NULL
;
break
;
#endif
#ifdef FBCON_HAS_CFB32
case
32
:
disp
->
dispsw
=
noaccel
?
&
fbcon_cfb32
:
&
fbcon_banshee32
;
disp
->
dispsw_data
=
info
->
fbcon_cmap
.
cfb32
;
if
(
nohwcursor
)
fbcon_banshee32
.
cursor
=
NULL
;
break
;
#endif
default:
disp
->
dispsw
=
&
fbcon_dummy
;
}
if
(
rect
->
rop
==
ROP_COPY
)
tdfx_rop
=
TDFX_ROP_COPY
;
else
tdfx_rop
=
TDFX_ROP_XOR
;
banshee_make_room
(
5
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
COLORFORE
,
rect
->
color
);
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_FILLRECT
|
(
tdfx_rop
<<
24
));
tdfx_outl
(
DSTSIZE
,
rect
->
width
|
(
rect
->
height
<<
16
));
tdfx_outl
(
LAUNCH_2D
,
rect
->
dx
|
(
rect
->
dy
<<
16
));
banshee_wait_idle
();
}
static
int
tdfxfb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
/*
* Screen-to-Screen BitBlt 2D command (for the bmove fb op.)
*/
static
void
tdfxfb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
)
{
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
fb
;
struct
tdfxfb_par
par
;
struct
display
*
display
;
int
oldxres
,
oldyres
,
oldvxres
,
oldvyres
,
oldbpp
,
oldaccel
,
accel
,
err
;
int
activate
=
var
->
activate
;
int
j
,
k
;
if
(
con
>=
0
)
display
=
&
fb_display
[
con
];
else
display
=
fb
->
disp
;
/* used during initialization */
if
((
err
=
tdfxfb_decode_var
(
var
,
&
par
,
info
)))
return
err
;
tdfxfb_encode_var
(
var
,
&
par
,
info
);
if
((
activate
&
FB_ACTIVATE_MASK
)
==
FB_ACTIVATE_NOW
)
{
oldxres
=
display
->
var
.
xres
;
oldyres
=
display
->
var
.
yres
;
oldvxres
=
display
->
var
.
xres_virtual
;
oldvyres
=
display
->
var
.
yres_virtual
;
oldbpp
=
display
->
var
.
bits_per_pixel
;
oldaccel
=
display
->
var
.
accel_flags
;
display
->
var
=
*
var
;
if
(
con
<
0
||
oldxres
!=
var
->
xres
||
oldyres
!=
var
->
yres
||
oldvxres
!=
var
->
xres_virtual
||
oldvyres
!=
var
->
yres_virtual
||
oldbpp
!=
var
->
bits_per_pixel
||
oldaccel
!=
var
->
accel_flags
)
{
struct
fb_fix_screeninfo
fix
;
tdfxfb_encode_fix
(
&
fix
,
&
par
,
info
);
display
->
visual
=
fix
.
visual
;
display
->
type
=
fix
.
type
;
display
->
type_aux
=
fix
.
type_aux
;
display
->
ypanstep
=
fix
.
ypanstep
;
display
->
ywrapstep
=
fix
.
ywrapstep
;
display
->
line_length
=
fix
.
line_length
;
display
->
next_line
=
fix
.
line_length
;
display
->
can_soft_blank
=
1
;
display
->
inverse
=
inverse
;
accel
=
var
->
accel_flags
&
FB_ACCELF_TEXT
;
tdfxfb_set_dispsw
(
display
,
info
,
par
.
bpp
,
accel
);
if
(
nopan
)
display
->
scrollmode
=
SCROLL_YREDRAW
;
if
(
info
->
fb_info
.
changevar
)
(
*
info
->
fb_info
.
changevar
)
(
con
);
}
if
(
var
->
bits_per_pixel
==
8
)
for
(
j
=
0
;
j
<
16
;
j
++
)
{
k
=
color_table
[
j
];
fb_info
.
palette
[
j
].
red
=
default_red
[
k
];
fb_info
.
palette
[
j
].
green
=
default_grn
[
k
];
fb_info
.
palette
[
j
].
blue
=
default_blu
[
k
];
}
u32
bpp
=
info
->
var
.
bits_per_pixel
;
u32
stride
=
info
->
fix
.
line_length
;
u32
blitcmd
=
COMMAND_2D_S2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
);
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
del_timer
(
&
(
info
->
cursor
.
timer
));
fb_info
.
cursor
.
state
=
CM_ERASE
;
if
(
!
info
->
fb_info
.
display_fg
||
info
->
fb_info
.
display_fg
->
vc_num
==
con
||
con
<
0
)
tdfxfb_set_par
(
&
par
,
info
);
if
(
!
nohwcursor
)
if
(
display
&&
display
->
conp
)
tdfxfb_createcursor
(
display
);
info
->
cursor
.
redraw
=
1
;
if
(
oldbpp
!=
var
->
bits_per_pixel
||
con
<
0
)
{
if
((
err
=
fb_alloc_cmap
(
&
display
->
cmap
,
0
,
0
)))
return
err
;
do_install_cmap
(
con
,
&
(
info
->
fb_info
));
if
(
area
->
sx
<=
area
->
dx
)
{
//-X
blitcmd
|=
BIT
(
14
);
area
->
sx
+=
area
->
width
-
1
;
area
->
dx
+=
area
->
width
-
1
;
}
if
(
area
->
sy
<=
area
->
dy
)
{
//-Y
blitcmd
|=
BIT
(
15
);
area
->
sy
+=
area
->
height
-
1
;
area
->
dy
+=
area
->
height
-
1
;
}
return
0
;
}
static
int
tdfxfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
fb
;
if
(
nopan
)
return
-
EINVAL
;
if
(
var
->
xoffset
)
return
-
EINVAL
;
if
(
var
->
yoffset
>
var
->
yres_virtual
)
return
-
EINVAL
;
if
(
nowrap
&&
(
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
))
return
-
EINVAL
;
if
(
con
==
fb
->
currcon
)
do_pan_var
(
var
,
i
);
banshee_make_room
(
6
);
fb_display
[
con
].
var
.
xoffset
=
var
->
xoffset
;
fb_display
[
con
].
var
.
yoffset
=
var
->
yoffset
;
return
0
;
tdfx_outl
(
SRCFORMAT
,
fmt
);
tdfx_outl
(
DSTFORMAT
,
fmt
);
tdfx_outl
(
COMMAND_2D
,
blitcmd
);
tdfx_outl
(
DSTSIZE
,
area
->
width
|
(
area
->
height
<<
16
));
tdfx_outl
(
DSTXY
,
area
->
dx
|
(
area
->
dy
<<
16
));
tdfx_outl
(
LAUNCH_2D
,
area
->
sx
|
(
area
->
sy
<<
16
));
banshee_wait_idle
();
}
static
int
tdfxfb_get_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
fb
)
static
void
tdfxfb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
pixmap
)
{
int
size
=
pixmap
->
height
*
((
pixmap
->
width
*
pixmap
->
depth
+
7
)
>>
3
);
int
i
,
stride
=
info
->
fix
.
line_length
;
u32
bpp
=
info
->
var
.
bits_per_pixel
;
u32
dstfmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
u8
*
chardata
=
(
u8
*
)
pixmap
->
data
;
u32
srcfmt
;
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
fb
;
struct
display
*
d
=
(
con
<
0
)
?
fb
->
disp
:
fb_display
+
con
;
if
(
con
==
fb
->
currcon
)
{
/* current console? */
return
fb_get_cmap
(
cmap
,
kspc
,
tdfxfb_getcolreg
,
fb
);
}
else
if
(
d
->
cmap
.
len
)
{
/* non default colormap? */
fb_copy_cmap
(
&
d
->
cmap
,
cmap
,
kspc
?
0
:
2
);
if
(
pixmap
->
depth
==
1
)
{
banshee_make_room
(
8
+
((
size
+
3
)
>>
2
));
tdfx_outl
(
COLORFORE
,
pixmap
->
fg_color
);
tdfx_outl
(
COLORBACK
,
pixmap
->
bg_color
);
srcfmt
=
0x400000
;
}
else
{
fb_copy_cmap
(
fb_default_cmap
(
i
->
current_par
.
cmap_len
),
cmap
,
kspc
?
0
:
2
)
;
banshee_make_room
(
6
+
((
size
+
3
)
>>
2
));
srcfmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
)
|
0x400000
;
}
return
0
;
}
static
int
tdfxfb_set_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
fb
)
{
struct
display
*
d
=
(
con
<
0
)
?
fb
->
disp
:
fb_display
+
con
;
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
fb
;
int
cmap_len
=
(
i
->
current_par
.
bpp
==
8
)
?
256
:
16
;
if
(
d
->
cmap
.
len
!=
cmap_len
)
{
int
err
;
if
((
err
=
fb_alloc_cmap
(
&
d
->
cmap
,
cmap_len
,
0
)))
return
err
;
tdfx_outl
(
SRCXY
,
0
);
tdfx_outl
(
DSTXY
,
pixmap
->
dx
|
(
pixmap
->
dy
<<
16
));
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_H2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
));
tdfx_outl
(
SRCFORMAT
,
srcfmt
);
tdfx_outl
(
DSTFORMAT
,
dstfmt
);
tdfx_outl
(
DSTSIZE
,
pixmap
->
width
|
(
pixmap
->
height
<<
16
));
/* Send four bytes at a time of data */
for
(
i
=
(
size
>>
2
)
;
i
>
0
;
i
--
)
{
tdfx_outl
(
LAUNCH_2D
,
*
(
u32
*
)
chardata
);
chardata
+=
4
;
}
if
(
con
==
fb
->
currcon
)
{
/* current console? */
return
fb_set_cmap
(
cmap
,
kspc
,
fb
);
}
else
{
fb_copy_cmap
(
cmap
,
&
d
->
cmap
,
kspc
?
0
:
1
);
/* Send the leftovers now */
i
=
size
%
4
;
switch
(
i
)
{
case
0
:
break
;
case
1
:
tdfx_outl
(
LAUNCH_2D
,
*
chardata
);
break
;
case
2
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
);
break
;
case
3
:
tdfx_outl
(
LAUNCH_2D
,
*
(
u16
*
)
chardata
|
((
chardata
[
3
])
<<
24
));
break
;
}
return
0
;
banshee_wait_idle
()
;
}
/**
...
...
@@ -1777,143 +984,132 @@ static int tdfxfb_set_cmap(struct fb_cmap *cmap,
static
int
__devinit
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
{
struct
fb_var_screeninfo
var
;
char
*
name
=
NULL
;
struct
fb_info
*
info
;
int
size
,
err
;
if
((
err
=
pci_enable_device
(
pdev
)))
{
printk
(
KERN_WARNING
"tdfxfb: Can't enable pdev: %d
\n
"
,
err
);
return
err
;
}
info
=
kmalloc
(
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
16
,
GFP_KERNEL
);
if
(
!
info
)
return
-
ENXIO
;
fb_info
.
dev
=
pdev
->
device
;
memset
(
info
,
0
,
sizeof
(
info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
16
)
;
/* Configure the default fb_fix_screeninfo first */
switch
(
pdev
->
device
)
{
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
fb_info
.
max_pixclock
=
BANSHEE_MAX_PIXCLOCK
;
name
=
"Banshee"
;
strcat
(
tdfx_fix
.
id
,
" Banshee"
)
;
default_par
.
max_pixclock
=
BANSHEE_MAX_PIXCLOCK
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
fb_info
.
max_pixclock
=
VOODOO3_MAX_PIXCLOCK
;
name
=
"Voodoo3"
;
strcat
(
tdfx_fix
.
id
,
" Voodoo3"
)
;
default_par
.
max_pixclock
=
VOODOO3_MAX_PIXCLOCK
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
fb_info
.
max_pixclock
=
VOODOO5_MAX_PIXCLOCK
;
name
=
"Voodoo5"
;
strcat
(
tdfx_fix
.
id
,
" Voodoo5"
)
;
default_par
.
max_pixclock
=
VOODOO5_MAX_PIXCLOCK
;
break
;
}
fb_info
.
regbase_phys
=
pci_resource_start
(
pdev
,
0
);
fb_info
.
regbase_size
=
1
<<
24
;
fb_info
.
regbase_virt
=
ioremap_nocache
(
fb_info
.
regbase_phys
,
1
<<
24
);
if
(
!
fb_info
.
regbase_virt
)
{
printk
(
KERN_WARNING
"fb: Can't remap %s register area.
\n
"
,
name
);
tdfx_fix
.
mmio_start
=
pci_resource_start
(
pdev
,
0
);
tdfx_fix
.
mmio_len
=
1
<<
24
;
default_par
.
regbase_virt
=
ioremap_nocache
(
tdfx_fix
.
mmio_start
,
1
<<
24
);
if
(
!
default_par
.
regbase_virt
)
{
printk
(
"fb: Can't remap %s register area.
\n
"
,
tdfx_fix
.
id
);
return
-
ENXIO
;
}
fb_info
.
bufbase_phys
=
pci_resource_start
(
pdev
,
1
);
if
(
!
(
fb_info
.
bufbase_size
=
do_lfb_size
()))
{
iounmap
(
fb_info
.
regbase_virt
);
printk
(
KERN_WARNING
"fb: Can't count %s memory.
\n
"
,
name
);
if
(
!
request_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
),
"tdfx regbase"
))
{
printk
(
KERN_WARNING
"tdfxfb: Can't reserve regbase
\n
"
);
iounmap
(
default_par
.
regbase_virt
);
return
-
ENXIO
;
}
fb_info
.
bufbase_virt
=
ioremap_nocache
(
fb_info
.
bufbase_phys
,
fb_info
.
bufbase_size
);
tdfx_fix
.
smem_start
=
pci_resource_start
(
pdev
,
1
);
if
(
!
(
tdfx_fix
.
smem_len
=
do_lfb_size
(
pdev
->
device
)))
{
iounmap
(
default_par
.
regbase_virt
);
printk
(
"fb: Can't count %s memory.
\n
"
,
tdfx_fix
.
id
);
return
-
ENXIO
;
}
if
(
!
fb_info
.
regbase_virt
)
{
printk
(
KERN_WARNING
"fb: Can't remap %s framebuffer.
\n
"
,
name
);
iounmap
(
fb_info
.
regbase_virt
);
if
(
!
request_mem_region
(
pci_resource_start
(
pdev
,
1
),
pci_resource_len
(
pdev
,
1
),
"tdfx smem"
))
{
printk
(
KERN_WARNING
"tdfxfb: Can't reserve smem
\n
"
);
release_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
));
iounmap
(
default_par
.
regbase_virt
);
return
-
ENXIO
;
}
fb_info
.
iobase
=
pci_resource_start
(
pdev
,
2
);
info
->
screen_base
=
ioremap_nocache
(
tdfx_fix
.
smem_start
,
tdfx_fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
printk
(
"fb: Can't remap %s framebuffer.
\n
"
,
tdfx_fix
.
id
);
iounmap
(
default_par
.
regbase_virt
);
return
-
ENXIO
;
}
printk
(
"fb: %s memory = %ldK
\n
"
,
name
,
fb_info
.
bufbase_size
>>
10
);
default_par
.
iobase
=
pci_resource_start
(
pdev
,
2
);
#ifdef CONFIG_MTRR
if
(
!
nomtrr
)
{
fb_info
.
mtrr_idx
=
mtrr_add
(
fb_info
.
bufbase_phys
,
fb_info
.
bufbase_size
,
MTRR_TYPE_WRCOMB
,
1
);
printk
(
KERN_INFO
"fb: MTRR's turned on
\n
"
);
if
(
!
request_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
),
"tdfx iobase"
))
{
printk
(
KERN_WARNING
"tdfxfb: Can't reserve iobase
\n
"
);
release_mem_region
(
pci_resource_start
(
pdev
,
1
),
pci_resource_len
(
pdev
,
1
));
release_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
));
iounmap
(
default_par
.
regbase_virt
);
iounmap
(
info
->
screen_base
);
return
-
ENXIO
;
}
#endif
printk
(
"fb: %s memory = %dK
\n
"
,
tdfx_fix
.
id
,
tdfx_fix
.
smem_len
>>
10
);
/* clear framebuffer memory */
memset_io
(
fb_info
.
bufbase_virt
,
0
,
fb_info
.
bufbase_size
);
fb_info
.
fb_info
.
currcon
=
-
1
;
if
(
!
nohwcursor
)
tdfxfb_hwcursor_init
();
init_timer
(
&
fb_info
.
cursor
.
timer
);
fb_info
.
cursor
.
timer
.
function
=
do_flashcursor
;
fb_info
.
cursor
.
timer
.
data
=
(
unsigned
long
)
(
&
fb_info
);
fb_info
.
cursor
.
state
=
CM_ERASE
;
spin_lock_init
(
&
fb_info
.
DAClock
);
strcpy
(
fb_info
.
fb_info
.
modename
,
"3Dfx "
);
strcat
(
fb_info
.
fb_info
.
modename
,
name
);
fb_info
.
fb_info
.
changevar
=
NULL
;
fb_info
.
fb_info
.
node
=
NODEV
;
fb_info
.
fb_info
.
fbops
=
&
tdfxfb_ops
;
fb_info
.
fb_info
.
disp
=
&
fb_info
.
disp
;
fb_info
.
fb_info
.
currcon
=
-
1
;
strcpy
(
fb_info
.
fb_info
.
fontname
,
fontname
);
fb_info
.
fb_info
.
switch_con
=
&
tdfxfb_switch_con
;
fb_info
.
fb_info
.
updatevar
=
&
tdfxfb_updatevar
;
fb_info
.
fb_info
.
flags
=
FBINFO_FLAG_DEFAULT
;
memset
(
&
var
,
0
,
sizeof
(
var
));
if
(
!
mode_option
||
!
fb_find_mode
(
&
var
,
&
fb_info
.
fb_info
,
mode_option
,
NULL
,
0
,
NULL
,
8
))
var
=
default_mode
[
0
].
var
;
noaccel
?
(
var
.
accel_flags
&=
~
FB_ACCELF_TEXT
)
:
(
var
.
accel_flags
|=
FB_ACCELF_TEXT
);
if
(
tdfxfb_decode_var
(
&
var
,
&
fb_info
.
default_par
,
&
fb_info
))
{
/*
* ugh -- can't use the mode from the mode db. (or command
* line), so try the default
*/
memset_io
(
info
->
screen_base
,
0
,
tdfx_fix
.
smem_len
);
printk
(
KERN_NOTICE
"tdfxfb: can't decode the supplied video mode, using default
\n
"
)
;
tdfx_fix
.
ypanstep
=
nopan
?
0
:
1
;
tdfx_fix
.
ywrapstep
=
nowrap
?
0
:
1
;
var
=
default_mode
[
0
].
var
;
info
->
node
=
NODEV
;
info
->
fbops
=
&
tdfxfb_ops
;
info
->
fix
=
tdfx_fix
;
info
->
par
=
&
default_par
;
info
->
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)(
info
->
disp
+
1
);
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
noaccel
?
(
var
.
accel_flags
&=
~
FB_ACCELF_TEXT
)
:
(
var
.
accel_flags
|=
FB_ACCELF_TEXT
);
/* The below feilds will go away !!!! */
strcpy
(
info
->
modename
,
info
->
fix
.
id
);
info
->
currcon
=
-
1
;
info
->
switch_con
=
gen_switch
;
info
->
updatevar
=
gen_update_var
;
if
(
tdfxfb_decode_var
(
&
var
,
&
fb_info
.
default_par
,
&
fb_info
))
{
/* this is getting really bad!... */
printk
(
KERN_WARNING
"tdfxfb: can't decode default video mode
\n
"
);
return
-
ENXIO
;
}
}
if
(
!
mode_option
)
mode_option
=
"640x480@60"
;
fb_info
.
fb_info
.
screen_base
=
fb_info
.
bufbase_virt
;
fb_info
.
disp
.
var
=
var
;
err
=
fb_find_mode
(
&
info
->
var
,
info
,
mode_option
,
NULL
,
0
,
NULL
,
8
);
if
(
!
err
||
err
==
4
)
info
->
var
=
tdfx_var
;
if
(
tdfxfb_set_var
(
&
var
,
-
1
,
&
fb_info
.
fb_info
))
{
printk
(
KERN_WARNING
"tdfxfb: can't set default video mode
\n
"
);
return
-
ENXIO
;
}
size
=
(
info
->
var
.
bits_per_pixel
==
8
)
?
256
:
16
;
fb_alloc_cmap
(
&
info
->
cmap
,
size
,
0
);
gen_set_var
(
&
info
->
var
,
-
1
,
info
);
if
(
register_framebuffer
(
&
fb_info
.
fb_info
)
<
0
)
{
printk
(
KERN_WARNING
"tdfxfb: can't register framebuffer
\n
"
);
if
(
register_framebuffer
(
info
)
<
0
)
{
printk
(
"tdfxfb: can't register framebuffer
\n
"
);
return
-
ENXIO
;
}
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
GET_FB_IDX
(
fb_info
.
fb_info
.
node
),
fb_info
.
fb_info
.
modename
);
/*
* Our driver data
*/
pdev
->
driver_data
=
info
;
return
0
;
}
...
...
@@ -1928,19 +1124,20 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
*/
static
void
__devexit
tdfxfb_remove
(
struct
pci_dev
*
pdev
)
{
unregister_framebuffer
(
&
fb_info
.
fb_info
);
del_timer_sync
(
&
fb_info
.
cursor
.
timer
);
#ifdef CONFIG_MTRR
if
(
!
nomtrr
)
{
mtrr_del
(
fb_info
.
mtrr_idx
,
fb_info
.
bufbase_phys
,
fb_info
.
bufbase_size
);
printk
(
"fb: MTRR's turned off
\n
"
);
}
#endif
struct
fb_info
*
info
=
(
struct
fb_info
*
)
pdev
->
driver_data
;
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
iounmap
(
fb_info
.
regbase_virt
);
iounmap
(
fb_info
.
bufbase_virt
);
unregister_framebuffer
(
info
);
iounmap
(
par
->
regbase_virt
);
iounmap
(
info
->
screen_base
);
/* Clean up after reserved regions */
release_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
));
release_mem_region
(
pci_resource_start
(
pdev
,
1
),
pci_resource_len
(
pdev
,
1
));
release_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
));
}
int
__init
tdfxfb_init
(
void
)
...
...
@@ -1956,7 +1153,8 @@ static void __exit tdfxfb_exit(void)
MODULE_AUTHOR
(
"Hannu Mallat <hmallat@cc.hut.fi>"
);
MODULE_DESCRIPTION
(
"3Dfx framebuffer device driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
noaccel
,
"i"
);
MODULE_PARM_DESC
(
noaccel
,
"Disable hardware acceleration (1 = disabled), enabled by default."
);
#ifdef MODULE
module_init
(
tdfxfb_init
);
...
...
@@ -1967,7 +1165,7 @@ module_exit(tdfxfb_exit);
#ifndef MODULE
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
)
{
char
*
this_opt
;
char
*
this_opt
;
if
(
!
options
||
!*
options
)
return
;
...
...
@@ -1978,20 +1176,10 @@ void tdfxfb_setup(char *options, int *ints)
if
(
!
strcmp
(
this_opt
,
"inverse"
))
{
inverse
=
1
;
fb_invert_cmaps
();
}
else
if
(
!
strcmp
(
this_opt
,
"noaccel"
))
{
noaccel
=
nopan
=
nowrap
=
nohwcursor
=
1
;
}
else
if
(
!
strcmp
(
this_opt
,
"nopan"
))
{
}
else
if
(
!
strcmp
(
this_opt
,
"nopan"
))
{
nopan
=
1
;
}
else
if
(
!
strcmp
(
this_opt
,
"nowrap"
))
{
}
else
if
(
!
strcmp
(
this_opt
,
"nowrap"
))
{
nowrap
=
1
;
}
else
if
(
!
strcmp
(
this_opt
,
"nohwcursor"
))
{
nohwcursor
=
1
;
#ifdef CONFIG_MTRR
}
else
if
(
!
strcmp
(
this_opt
,
"nomtrr"
))
{
nomtrr
=
1
;
#endif
}
else
if
(
!
strncmp
(
this_opt
,
"font:"
,
5
))
{
strncpy
(
fontname
,
this_opt
+
5
,
40
);
}
else
{
mode_option
=
this_opt
;
}
...
...
@@ -1999,267 +1187,3 @@ void tdfxfb_setup(char *options, int *ints)
}
#endif
static
int
tdfxfb_switch_con
(
int
con
,
struct
fb_info
*
fb
)
{
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
fb
;
struct
tdfxfb_par
par
;
int
old_con
=
fb
->
currcon
;
int
set_par
=
1
;
/* Do we have to save the colormap? */
if
(
fb
->
currcon
>=
0
)
if
(
fb_display
[
fb
->
currcon
].
cmap
.
len
)
fb_get_cmap
(
&
fb_display
[
fb
->
currcon
].
cmap
,
1
,
tdfxfb_getcolreg
,
fb
);
fb
->
currcon
=
con
;
fb_display
[
fb
->
currcon
].
var
.
activate
=
FB_ACTIVATE_NOW
;
tdfxfb_decode_var
(
&
fb_display
[
con
].
var
,
&
par
,
info
);
if
(
old_con
>=
0
&&
vt_cons
[
old_con
]
->
vc_mode
!=
KD_GRAPHICS
)
{
/* check if we have to change video registers */
struct
tdfxfb_par
old_par
;
tdfxfb_decode_var
(
&
fb_display
[
old_con
].
var
,
&
old_par
,
info
);
if
(
!
memcmp
(
&
par
,
&
old_par
,
sizeof
(
par
)))
set_par
=
0
;
/* avoid flicker */
}
if
(
set_par
)
tdfxfb_set_par
(
&
par
,
info
);
if
(
fb_display
[
con
].
dispsw
&&
fb_display
[
con
].
conp
)
fb_con
.
con_cursor
(
fb_display
[
con
].
conp
,
CM_ERASE
);
del_timer
(
&
(
info
->
cursor
.
timer
));
fb_info
.
cursor
.
state
=
CM_ERASE
;
if
(
!
nohwcursor
)
if
(
fb_display
[
con
].
conp
)
tdfxfb_createcursor
(
&
fb_display
[
con
]);
info
->
cursor
.
redraw
=
1
;
tdfxfb_set_dispsw
(
&
fb_display
[
con
],
info
,
par
.
bpp
,
par
.
accel_flags
&
FB_ACCELF_TEXT
);
do_install_cmap
(
con
,
fb
);
tdfxfb_updatevar
(
con
,
fb
);
return
1
;
}
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
fb
)
{
u32
dacmode
,
state
=
0
,
vgablank
=
0
;
dacmode
=
tdfx_inl
(
DACMODE
);
switch
(
blank
)
{
case
0
:
/* Screen: On; HSync: On, VSync: On */
state
=
0
;
vgablank
=
0
;
break
;
case
1
:
/* Screen: Off; HSync: On, VSync: On */
state
=
0
;
vgablank
=
1
;
break
;
case
2
:
/* Screen: Off; HSync: On, VSync: Off */
state
=
BIT
(
3
);
vgablank
=
1
;
break
;
case
3
:
/* Screen: Off; HSync: Off, VSync: On */
state
=
BIT
(
1
);
vgablank
=
1
;
break
;
case
4
:
/* Screen: Off; HSync: Off, VSync: Off */
state
=
BIT
(
1
)
|
BIT
(
3
);
vgablank
=
1
;
break
;
}
dacmode
&=
~
(
BIT
(
1
)
|
BIT
(
3
));
dacmode
|=
state
;
banshee_make_room
(
1
);
tdfx_outl
(
DACMODE
,
dacmode
);
if
(
vgablank
)
vga_disable_video
();
else
vga_enable_video
();
return
0
;
}
static
int
tdfxfb_updatevar
(
int
con
,
struct
fb_info
*
fb
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
fb
;
if
((
con
==
fb
->
currcon
)
&&
(
!
nopan
))
do_pan_var
(
&
fb_display
[
con
].
var
,
i
);
return
0
;
}
static
int
tdfxfb_getcolreg
(
unsigned
regno
,
unsigned
*
red
,
unsigned
*
green
,
unsigned
*
blue
,
unsigned
*
transp
,
struct
fb_info
*
fb
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
fb
;
if
(
regno
>
i
->
current_par
.
cmap_len
)
return
1
;
*
red
=
i
->
palette
[
regno
].
red
;
*
green
=
i
->
palette
[
regno
].
green
;
*
blue
=
i
->
palette
[
regno
].
blue
;
*
transp
=
0
;
return
0
;
}
static
int
tdfxfb_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
info
;
#ifdef FBCON_HAS_CFB8
u32
rgbcol
;
#endif
if
(
regno
>=
i
->
current_par
.
cmap_len
)
return
1
;
i
->
palette
[
regno
].
red
=
red
;
i
->
palette
[
regno
].
green
=
green
;
i
->
palette
[
regno
].
blue
=
blue
;
switch
(
i
->
current_par
.
bpp
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
rgbcol
=
(((
u32
)
red
&
0xff00
)
<<
8
)
|
(((
u32
)
green
&
0xff00
)
<<
0
)
|
(((
u32
)
blue
&
0xff00
)
>>
8
);
do_setpalentry
(
regno
,
rgbcol
);
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
i
->
fbcon_cmap
.
cfb16
[
regno
]
=
(((
u32
)
red
&
0xf800
)
>>
0
)
|
(((
u32
)
green
&
0xfc00
)
>>
5
)
|
(((
u32
)
blue
&
0xf800
)
>>
11
);
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
i
->
fbcon_cmap
.
cfb24
[
regno
]
=
(((
u32
)
red
&
0xff00
)
<<
8
)
|
(((
u32
)
green
&
0xff00
)
<<
0
)
|
(((
u32
)
blue
&
0xff00
)
>>
8
);
break
;
#endif
#ifdef FBCON_HAS_CFB32
case
32
:
i
->
fbcon_cmap
.
cfb32
[
regno
]
=
(((
u32
)
red
&
0xff00
)
<<
8
)
|
(((
u32
)
green
&
0xff00
)
<<
0
)
|
(((
u32
)
blue
&
0xff00
)
>>
8
);
break
;
#endif
default:
DPRINTK
(
"bad depth %u
\n
"
,
i
->
current_par
.
bpp
);
break
;
}
return
0
;
}
static
void
tdfxfb_createcursorshape
(
struct
display
*
p
)
{
unsigned
int
h
,
cu
,
cd
;
h
=
fontheight
(
p
);
cd
=
h
;
if
(
cd
>=
10
)
cd
--
;
fb_info
.
cursor
.
type
=
p
->
conp
->
vc_cursor_type
&
CUR_HWMASK
;
switch
(
fb_info
.
cursor
.
type
)
{
case
CUR_NONE
:
cu
=
cd
;
break
;
case
CUR_UNDERLINE
:
cu
=
cd
-
2
;
break
;
case
CUR_LOWER_THIRD
:
cu
=
(
h
*
2
)
/
3
;
break
;
case
CUR_LOWER_HALF
:
cu
=
h
/
2
;
break
;
case
CUR_TWO_THIRDS
:
cu
=
h
/
3
;
break
;
case
CUR_BLOCK
:
default:
cu
=
0
;
cd
=
h
;
break
;
}
fb_info
.
cursor
.
w
=
fontwidth
(
p
);
fb_info
.
cursor
.
u
=
cu
;
fb_info
.
cursor
.
d
=
cd
;
}
static
void
tdfxfb_createcursor
(
struct
display
*
p
)
{
u8
*
cursorbase
;
u32
xline
;
unsigned
int
i
;
unsigned
int
h
,
to
;
tdfxfb_createcursorshape
(
p
);
xline
=
~
((
1
<<
(
32
-
fb_info
.
cursor
.
w
))
-
1
);
#ifdef __LITTLE_ENDIAN
xline
=
swab32
(
xline
);
#endif
cursorbase
=
(
u8
*
)
fb_info
.
bufbase_virt
;
h
=
fb_info
.
cursor
.
cursorimage
;
to
=
fb_info
.
cursor
.
u
;
for
(
i
=
0
;
i
<
to
;
i
++
)
{
writel
(
0
,
cursorbase
+
h
);
writel
(
0
,
cursorbase
+
h
+
4
);
writel
(
~
0
,
cursorbase
+
h
+
8
);
writel
(
~
0
,
cursorbase
+
h
+
12
);
h
+=
16
;
}
to
=
fb_info
.
cursor
.
d
;
for
(;
i
<
to
;
i
++
)
{
writel
(
xline
,
cursorbase
+
h
);
writel
(
0
,
cursorbase
+
h
+
4
);
writel
(
~
0
,
cursorbase
+
h
+
8
);
writel
(
~
0
,
cursorbase
+
h
+
12
);
h
+=
16
;
}
for
(;
i
<
64
;
i
++
)
{
writel
(
0
,
cursorbase
+
h
);
writel
(
0
,
cursorbase
+
h
+
4
);
writel
(
~
0
,
cursorbase
+
h
+
8
);
writel
(
~
0
,
cursorbase
+
h
+
12
);
h
+=
16
;
}
}
static
void
tdfxfb_hwcursor_init
(
void
)
{
unsigned
int
start
;
start
=
(
fb_info
.
bufbase_size
-
1024
)
&
PAGE_MASK
;
fb_info
.
bufbase_size
=
start
;
fb_info
.
cursor
.
cursorimage
=
fb_info
.
bufbase_size
;
printk
(
"tdfxfb: reserving 1024 bytes for the hwcursor at %p
\n
"
,
fb_info
.
regbase_virt
+
fb_info
.
cursor
.
cursorimage
);
}
drivers/video/neofb
.h
→
include/video/neomagic
.h
View file @
34dfe0cd
/*
* linux/
drivers/video/neofb
.h -- NeoMagic Framebuffer Driver
* linux/
include/video/neo_reg
.h -- NeoMagic Framebuffer Driver
*
* Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
*
...
...
@@ -8,6 +8,54 @@
* archive for more details.
*/
#define NEO_BS0_BLT_BUSY 0x00000001
#define NEO_BS0_FIFO_AVAIL 0x00000002
#define NEO_BS0_FIFO_PEND 0x00000004
#define NEO_BC0_DST_Y_DEC 0x00000001
#define NEO_BC0_X_DEC 0x00000002
#define NEO_BC0_SRC_TRANS 0x00000004
#define NEO_BC0_SRC_IS_FG 0x00000008
#define NEO_BC0_SRC_Y_DEC 0x00000010
#define NEO_BC0_FILL_PAT 0x00000020
#define NEO_BC0_SRC_MONO 0x00000040
#define NEO_BC0_SYS_TO_VID 0x00000080
#define NEO_BC1_DEPTH8 0x00000100
#define NEO_BC1_DEPTH16 0x00000200
#define NEO_BC1_X_320 0x00000400
#define NEO_BC1_X_640 0x00000800
#define NEO_BC1_X_800 0x00000c00
#define NEO_BC1_X_1024 0x00001000
#define NEO_BC1_X_1152 0x00001400
#define NEO_BC1_X_1280 0x00001800
#define NEO_BC1_X_1600 0x00001c00
#define NEO_BC1_DST_TRANS 0x00002000
#define NEO_BC1_MSTR_BLT 0x00004000
#define NEO_BC1_FILTER_Z 0x00008000
#define NEO_BC2_WR_TR_DST 0x00800000
#define NEO_BC3_SRC_XY_ADDR 0x01000000
#define NEO_BC3_DST_XY_ADDR 0x02000000
#define NEO_BC3_CLIP_ON 0x04000000
#define NEO_BC3_FIFO_EN 0x08000000
#define NEO_BC3_BLT_ON_ADDR 0x10000000
#define NEO_BC3_SKIP_MAPPING 0x80000000
#define NEO_MODE1_DEPTH8 0x0100
#define NEO_MODE1_DEPTH16 0x0200
#define NEO_MODE1_DEPTH24 0x0300
#define NEO_MODE1_X_320 0x0400
#define NEO_MODE1_X_640 0x0800
#define NEO_MODE1_X_800 0x0c00
#define NEO_MODE1_X_1024 0x1000
#define NEO_MODE1_X_1152 0x1400
#define NEO_MODE1_X_1280 0x1800
#define NEO_MODE1_X_1600 0x1c00
#define NEO_MODE1_BLT_ON_ADDR 0x2000
#ifdef __KERNEL__
#ifdef NEOFB_DEBUG
# define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x));
...
...
@@ -15,7 +63,6 @@
# define DBG(x)
#endif
#define PCI_CHIP_NM2070 0x0001
#define PCI_CHIP_NM2090 0x0002
#define PCI_CHIP_NM2093 0x0003
...
...
@@ -78,8 +125,6 @@ typedef volatile struct {
struct
neofb_par
{
int
depth
;
unsigned
char
MiscOutReg
;
/* Misc */
unsigned
char
CRTC
[
25
];
/* Crtc Controller */
unsigned
char
Sequencer
[
5
];
/* Video Sequencer */
...
...
@@ -113,31 +158,11 @@ struct neofb_par {
unsigned
char
VCLK3NumeratorHigh
;
unsigned
char
VCLK3Denominator
;
unsigned
char
VerticalExt
;
};
struct
neofb_info
{
struct
fb_info
fb
;
struct
display_switch
*
dispsw
;
struct
pci_dev
*
pcidev
;
int
accel
;
char
*
name
;
struct
{
u8
*
vbase
;
u32
pbase
;
u32
len
;
#ifdef CONFIG_MTRR
int
mtrr
;
#endif
}
video
;
struct
{
u8
*
vbase
;
u32
pbase
;
u32
len
;
}
mmio
;
u8
*
mmio_vbase
;
Neo2200
*
neo2200
;
...
...
@@ -151,20 +176,14 @@ struct neofb_info {
int
lcd_stretch
;
int
internal_display
;
int
external_display
;
struct
{
u16
red
,
green
,
blue
,
transp
;
}
palette
[
NR_PALETTE
];
};
typedef
struct
{
int
x_res
;
int
y_res
;
int
mode
;
}
biosMode
;
/* vga IO functions */
static
inline
u8
VGArCR
(
u8
index
)
{
...
...
@@ -241,51 +260,5 @@ static inline void VGAwMISC (u8 value)
{
outb
(
value
,
0x3c2
);
}
#endif
#define NEO_BS0_BLT_BUSY 0x00000001
#define NEO_BS0_FIFO_AVAIL 0x00000002
#define NEO_BS0_FIFO_PEND 0x00000004
#define NEO_BC0_DST_Y_DEC 0x00000001
#define NEO_BC0_X_DEC 0x00000002
#define NEO_BC0_SRC_TRANS 0x00000004
#define NEO_BC0_SRC_IS_FG 0x00000008
#define NEO_BC0_SRC_Y_DEC 0x00000010
#define NEO_BC0_FILL_PAT 0x00000020
#define NEO_BC0_SRC_MONO 0x00000040
#define NEO_BC0_SYS_TO_VID 0x00000080
#define NEO_BC1_DEPTH8 0x00000100
#define NEO_BC1_DEPTH16 0x00000200
#define NEO_BC1_X_320 0x00000400
#define NEO_BC1_X_640 0x00000800
#define NEO_BC1_X_800 0x00000c00
#define NEO_BC1_X_1024 0x00001000
#define NEO_BC1_X_1152 0x00001400
#define NEO_BC1_X_1280 0x00001800
#define NEO_BC1_X_1600 0x00001c00
#define NEO_BC1_DST_TRANS 0x00002000
#define NEO_BC1_MSTR_BLT 0x00004000
#define NEO_BC1_FILTER_Z 0x00008000
#define NEO_BC2_WR_TR_DST 0x00800000
#define NEO_BC3_SRC_XY_ADDR 0x01000000
#define NEO_BC3_DST_XY_ADDR 0x02000000
#define NEO_BC3_CLIP_ON 0x04000000
#define NEO_BC3_FIFO_EN 0x08000000
#define NEO_BC3_BLT_ON_ADDR 0x10000000
#define NEO_BC3_SKIP_MAPPING 0x80000000
#define NEO_MODE1_DEPTH8 0x0100
#define NEO_MODE1_DEPTH16 0x0200
#define NEO_MODE1_DEPTH24 0x0300
#define NEO_MODE1_X_320 0x0400
#define NEO_MODE1_X_640 0x0800
#define NEO_MODE1_X_800 0x0c00
#define NEO_MODE1_X_1024 0x1000
#define NEO_MODE1_X_1152 0x1400
#define NEO_MODE1_X_1280 0x1800
#define NEO_MODE1_X_1600 0x1c00
#define NEO_MODE1_BLT_ON_ADDR 0x2000
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