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
Kirill Smelkov
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
...
@@ -262,7 +262,7 @@ if [ "$CONFIG_FB" = "y" ]; then
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
if [ "$CONFIG_FB_ACORN" = "y" -o "$CONFIG_FB_ATARI" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_ATY" = "y" -o "$CONFIG_FB_MAC" = "y" -o \
"$CONFIG_FB_OF" = "y" -o "$CONFIG_FB_TGA" = "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_TCX" = "y" -o "$CONFIG_FB_CGTHREE" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
"$CONFIG_FB_CGFOURTEEN" = "y" -o "$CONFIG_FB_TRIDENT" = "y" -o \
...
@@ -275,13 +275,13 @@ if [ "$CONFIG_FB" = "y" ]; then
...
@@ -275,13 +275,13 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SGIVW" = "y" -o "$CONFIG_FB_CYBER2000" = "y" -o \
"$CONFIG_FB_SA1100" = "y" -o "$CONFIG_FB_SIS" = "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_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
define_tristate CONFIG_FBCON_CFB8 y
else
else
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
if [ "$CONFIG_FB_ACORN" = "m" -o "$CONFIG_FB_ATARI" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_ATY" = "m" -o "$CONFIG_FB_MAC" = "m" -o \
"$CONFIG_FB_OF" = "m" -o "$CONFIG_FB_TGA" = "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_TCX" = "m" -o "$CONFIG_FB_CGTHREE" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
"$CONFIG_FB_CGFOURTEEN" = "m" -o "$CONFIG_FB_TRIDENT" = "m" -o \
...
@@ -294,12 +294,12 @@ if [ "$CONFIG_FB" = "y" ]; then
...
@@ -294,12 +294,12 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_SGIVW" = "m" -o "$CONFIG_FB_CYBER2000" = "m" -o \
"$CONFIG_FB_PMAG_BA" = "m" -o "$CONFIG_FB_PMAGB_B" = "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_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
define_tristate CONFIG_FBCON_CFB8 m
fi
fi
fi
fi
if [ "$CONFIG_FB_ATARI" = "y" -o "$CONFIG_FB_ATY" = "y" -o \
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_TRIDENT" = "y" -o "$CONFIG_FB_TBOX" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_VOODOO1" = "y" -o "$CONFIG_FB_RADEON" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
"$CONFIG_FB_CONTROL" = "y" -o "$CONFIG_FB_CLGEN" = "y" -o \
...
@@ -309,12 +309,11 @@ if [ "$CONFIG_FB" = "y" ]; then
...
@@ -309,12 +309,11 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_PM2" = "y" -o "$CONFIG_FB_SGIVW" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_RIVA" = "y" -o "$CONFIG_FB_ATY128" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_CYBER2000" = "y" -o "$CONFIG_FB_PM3" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" -o \
"$CONFIG_FB_SIS" = "y" -o "$CONFIG_FB_SA1100" = "y" ]; then
"$CONFIG_FB_PVR2" = "y" ]; then
define_tristate CONFIG_FBCON_CFB16 y
define_tristate CONFIG_FBCON_CFB16 y
else
else
if [ "$CONFIG_FB_ATARI" = "m" -o "$CONFIG_FB_ATY" = "m" -o \
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_TRIDENT" = "m" -o "$CONFIG_FB_TBOX" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_VOODOO1" = "m" -o "$CONFIG_FB_PM3" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
"$CONFIG_FB_CONTROL" = "m" -o "$CONFIG_FB_CLGEN" = "m" -o \
...
@@ -324,8 +323,7 @@ if [ "$CONFIG_FB" = "y" ]; then
...
@@ -324,8 +323,7 @@ if [ "$CONFIG_FB" = "y" ]; then
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
"$CONFIG_FB_PM2" = "m" -o "$CONFIG_FB_SGIVW" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_RIVA" = "m" -o "$CONFIG_FB_ATY128" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_CYBER2000" = "m" -o "$CONFIG_FB_SIS" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" -o \
"$CONFIG_FB_SA1100" = "m" -o "$CONFIG_FB_RADEON" = "m" ]; then
"$CONFIG_FB_PVR2" = "m" ]; then
define_tristate CONFIG_FBCON_CFB16 m
define_tristate CONFIG_FBCON_CFB16 m
fi
fi
fi
fi
...
...
drivers/video/Makefile
View file @
34dfe0cd
...
@@ -48,13 +48,13 @@ obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgb
...
@@ -48,13 +48,13 @@ obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgb
obj-$(CONFIG_FB_ATARI)
+=
atafb.o
obj-$(CONFIG_FB_ATARI)
+=
atafb.o
obj-$(CONFIG_FB_ATY128)
+=
aty128fb.o
obj-$(CONFIG_FB_ATY128)
+=
aty128fb.o
obj-$(CONFIG_FB_RADEON)
+=
radeonfb.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_IGA)
+=
igafb.o
obj-$(CONFIG_FB_CONTROL)
+=
controlfb.o
obj-$(CONFIG_FB_CONTROL)
+=
controlfb.o
obj-$(CONFIG_FB_PLATINUM)
+=
platinumfb.o
obj-$(CONFIG_FB_PLATINUM)
+=
platinumfb.o
obj-$(CONFIG_FB_VALKYRIE)
+=
valkyriefb.o
obj-$(CONFIG_FB_VALKYRIE)
+=
valkyriefb.o
obj-$(CONFIG_FB_CT65550)
+=
chipsfb.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_CLPS711X)
+=
clps711xfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_CYBER)
+=
cyberfb.o
obj-$(CONFIG_FB_CYBER)
+=
cyberfb.o
obj-$(CONFIG_FB_CYBER2000)
+=
cyber2000fb.o
obj-$(CONFIG_FB_CYBER2000)
+=
cyber2000fb.o
...
...
drivers/video/anakinfb.c
View file @
34dfe0cd
...
@@ -21,7 +21,6 @@
...
@@ -21,7 +21,6 @@
#include <asm/io.h>
#include <asm/io.h>
#include <video/fbcon.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb16.h>
static
u32
colreg
[
16
];
static
u32
colreg
[
16
];
static
struct
fb_info
fb_info
;
static
struct
fb_info
fb_info
;
...
...
drivers/video/clps711xfb.c
View file @
34dfe0cd
...
@@ -203,6 +203,9 @@ static struct fb_ops clps7111fb_ops = {
...
@@ -203,6 +203,9 @@ static struct fb_ops clps7111fb_ops = {
fb_get_cmap:
gen_get_cmap
,
fb_get_cmap:
gen_get_cmap
,
fb_setcolreg:
clps7111fb_setcolreg
,
fb_setcolreg:
clps7111fb_setcolreg
,
fb_blank:
clps7111fb_blank
,
fb_blank:
clps7111fb_blank
,
fb_fillrect:
cfb_fillrect
,
fb_copyarea:
cfb_copyarea
,
fb_imageblit:
cfb_imageblit
,
};
};
static
int
static
int
...
...
drivers/video/cyber2000fb.c
View file @
34dfe0cd
...
@@ -1729,8 +1729,9 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
...
@@ -1729,8 +1729,9 @@ static int cyberpro_pci_resume(struct pci_dev *dev)
}
}
static
struct
pci_device_id
cyberpro_pci_table
[]
__devinitdata
=
{
static
struct
pci_device_id
cyberpro_pci_table
[]
__devinitdata
=
{
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_1682
,
// Not yet
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
ID_IGA_1682
},
// { 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_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_2000
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
ID_CYBERPRO_2000
},
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
ID_CYBERPRO_2000
},
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_2010
,
{
PCI_VENDOR_ID_INTERG
,
PCI_DEVICE_ID_INTERG_2010
,
...
...
drivers/video/neofb.c
View file @
34dfe0cd
...
@@ -11,6 +11,8 @@
...
@@ -11,6 +11,8 @@
* Public License. See the file COPYING in the main directory of this
* Public License. See the file COPYING in the main directory of this
* archive for more details.
* archive for more details.
*
*
* 0.3.3
* - Porting over to new fbdev api. (jsimmons)
*
*
* 0.3.2
* 0.3.2
* - got rid of all floating point (dok)
* - got rid of all floating point (dok)
...
@@ -66,768 +68,117 @@
...
@@ -66,768 +68,117 @@
#endif
#endif
#include <video/fbcon.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb8.h>
#include <video/neomagic.h>
#include <video/fbcon-cfb16.h>
#include <video/fbcon-cfb24.h>
#include <video/fbcon-cfb32.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. */
static
int
disabled
=
0
;
if
(
par
->
ProgramVCLK
static
int
internal
=
0
;
&&
((
VGArGR
(
0x9B
)
!=
par
->
VCLK3NumeratorLow
)
static
int
external
=
0
;
||
(
VGArGR
(
0x9F
)
!=
par
->
VCLK3Denominator
)
static
int
nostretch
=
0
;
||
(
clock_hi
&&
((
VGArGR
(
0x8F
)
&
~
0x0f
)
static
int
nopciburst
=
0
;
!=
(
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
);
}
if
(
par
->
biosMode
)
VGAwCR
(
0x23
,
par
->
biosMode
);
VGAwGR
(
0x93
,
0xc0
);
/* Gives 5x faster framebuffer writes !!! */
#ifdef MODULE
/* Program vertical extension register */
MODULE_AUTHOR
(
"(c) 2001-2002 Denis Oliver Kropp <dok@convergence.de>"
);
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
MODULE_LICENSE
(
"GPL"
);
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
MODULE_DESCRIPTION
(
"FBDev driver for NeoMagic PCI Chips"
);
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
MODULE_PARM
(
disabled
,
"i"
);
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
MODULE_PARM_DESC
(
disabled
,
"Disable this driver's initialization."
);
{
MODULE_PARM
(
internal
,
"i"
);
VGAwCR
(
0x70
,
par
->
VerticalExt
);
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
)
static
biosMode
bios8
[]
=
{
{
{
320
,
240
,
0x40
},
int
oldExtCRTDispAddr
;
{
300
,
400
,
0x42
},
int
Base
;
{
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
;
static
biosMode
bios24
[]
=
{
Base
*=
(
var
->
bits_per_pixel
+
7
)
/
8
;
{
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
/*
static
int
neoFindMode
(
int
xres
,
int
yres
,
int
depth
)
* These are the generic starting address registers.
{
*/
int
xres_s
;
VGAwCR
(
0x0C
,
(
Base
&
0x00FF00
)
>>
8
)
;
int
i
,
size
;
VGAwCR
(
0x0D
,
(
Base
&
0x00FF
))
;
biosMode
*
mode
;
/*
switch
(
depth
)
{
* Make sure we don't clobber some other bits that might already
case
8
:
* have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
size
=
sizeof
(
bios8
)
/
sizeof
(
biosMode
);
* be needed.
mode
=
bios8
;
*/
break
;
oldExtCRTDispAddr
=
VGArGR
(
0x0E
);
case
16
:
VGAwGR
(
0x0E
,(((
Base
>>
16
)
&
0x0f
)
|
(
oldExtCRTDispAddr
&
0xf0
)));
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
...
@@ -840,7 +191,8 @@ static void neofb_update_start (struct neofb_info *info, struct fb_var_screeninf
#define MAX_D 31
#define MAX_D 31
#define MAX_F 1
#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
,
d
,
f
;
int
n_best
=
0
,
d_best
=
0
,
f_best
=
0
;
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
...
@@ -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
(
f
=
0
;
f
<=
MAX_F
;
f
++
)
for
(
n
=
0
;
n
<=
MAX_N
;
n
++
)
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_out
;
/* 20.12 */
long
f_diff
;
/* 20.12 */
long
f_diff
;
/* 20.12 */
f_out
=
((((
n
+
1
)
<<
12
)
/
((
d
+
1
)
*
(
1
<<
f
)))
>>
12
)
*
REF_FREQ
;
f_out
=
f_diff
=
abs
(
f_out
-
f_target
);
((((
n
+
1
)
<<
12
)
/
((
d
+
if
(
f_diff
<
f_best_diff
)
1
)
*
{
(
1
<<
f
)))
>>
12
)
*
REF_FREQ
;
f_diff
=
abs
(
f_out
-
f_target
);
if
(
f_diff
<
f_best_diff
)
{
f_best_diff
=
f_diff
;
f_best_diff
=
f_diff
;
n_best
=
n
;
n_best
=
n
;
d_best
=
d
;
d_best
=
d
;
...
@@ -865,28 +219,25 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
...
@@ -865,28 +219,25 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
}
}
}
}
if
(
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
info
->
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
{
/* NOT_DONE: We are trying the full range of the 2200 clock.
/* NOT_DONE: We are trying the full range of the 2200 clock.
We should be able to try n up to 2047 */
We should be able to try n up to 2047 */
par
->
VCLK3NumeratorLow
=
n_best
;
par
->
VCLK3NumeratorLow
=
n_best
;
par
->
VCLK3NumeratorHigh
=
(
f_best
<<
7
);
par
->
VCLK3NumeratorHigh
=
(
f_best
<<
7
);
}
}
else
else
par
->
VCLK3NumeratorLow
=
n_best
|
(
f_best
<<
7
);
par
->
VCLK3NumeratorLow
=
n_best
|
(
f_best
<<
7
);
par
->
VCLK3Denominator
=
d_best
;
par
->
VCLK3Denominator
=
d_best
;
#ifdef NEOFB_DEBUG
#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
,
f_target
>>
12
,
par
->
VCLK3NumeratorLow
,
par
->
VCLK3NumeratorLow
,
par
->
VCLK3NumeratorHigh
,
par
->
VCLK3NumeratorHigh
,
par
->
VCLK3Denominator
,
par
->
VCLK3Denominator
,
f_best_diff
>>
12
);
f_best_diff
>>
12
);
#endif
#endif
}
}
...
@@ -896,10 +247,9 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
...
@@ -896,10 +247,9 @@ static void neoCalcVCLK (const struct neofb_info *info, struct neofb_par *par, l
* Return FALSE on failure.
* Return FALSE on failure.
*/
*/
static
int
vgaHWInit
(
const
struct
fb_var_screeninfo
*
var
,
static
int
vgaHWInit
(
const
struct
fb_var_screeninfo
*
var
,
const
struct
neofb_info
*
info
,
const
struct
fb_info
*
info
,
struct
neofb_par
*
par
,
struct
neofb_par
*
par
,
struct
xtimings
*
timings
)
struct
xtimings
*
timings
)
{
{
par
->
MiscOutReg
=
0x23
;
par
->
MiscOutReg
=
0x23
;
...
@@ -933,8 +283,7 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
...
@@ -933,8 +283,7 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
7
)
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
7
)
|
((
timings
->
VSyncStart
&
0x100
)
>>
6
)
|
((
timings
->
VSyncStart
&
0x100
)
>>
6
)
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
5
)
|
(((
timings
->
VDisplay
-
1
)
&
0x100
)
>>
5
)
|
0x10
|
0x10
|
(((
timings
->
VTotal
-
2
)
&
0x200
)
>>
4
)
|
(((
timings
->
VTotal
-
2
)
&
0x200
)
>>
4
)
|
(((
timings
->
VDisplay
-
1
)
&
0x200
)
>>
3
)
|
(((
timings
->
VDisplay
-
1
)
&
0x200
)
>>
3
)
|
((
timings
->
VSyncStart
&
0x200
)
>>
2
);
|
((
timings
->
VSyncStart
&
0x200
)
>>
2
);
par
->
CRTC
[
8
]
=
0x00
;
par
->
CRTC
[
8
]
=
0x00
;
...
@@ -979,47 +328,216 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
...
@@ -979,47 +328,216 @@ static int vgaHWInit (const struct fb_var_screeninfo *var,
par
->
Graphics
[
8
]
=
0xFF
;
par
->
Graphics
[
8
]
=
0xFF
;
par
->
Attribute
[
0
]
=
0x00
;
/* standard colormap translation */
par
->
Attribute
[
0
]
=
0x00
;
/* standard colormap translation */
par
->
Attribute
[
1
]
=
0x01
;
par
->
Attribute
[
1
]
=
0x01
;
par
->
Attribute
[
2
]
=
0x02
;
par
->
Attribute
[
2
]
=
0x02
;
par
->
Attribute
[
3
]
=
0x03
;
par
->
Attribute
[
3
]
=
0x03
;
par
->
Attribute
[
4
]
=
0x04
;
par
->
Attribute
[
4
]
=
0x04
;
par
->
Attribute
[
5
]
=
0x05
;
par
->
Attribute
[
5
]
=
0x05
;
par
->
Attribute
[
6
]
=
0x06
;
par
->
Attribute
[
6
]
=
0x06
;
par
->
Attribute
[
7
]
=
0x07
;
par
->
Attribute
[
7
]
=
0x07
;
par
->
Attribute
[
8
]
=
0x08
;
par
->
Attribute
[
8
]
=
0x08
;
par
->
Attribute
[
9
]
=
0x09
;
par
->
Attribute
[
9
]
=
0x09
;
par
->
Attribute
[
10
]
=
0x0A
;
par
->
Attribute
[
10
]
=
0x0A
;
par
->
Attribute
[
11
]
=
0x0B
;
par
->
Attribute
[
11
]
=
0x0B
;
par
->
Attribute
[
12
]
=
0x0C
;
par
->
Attribute
[
12
]
=
0x0C
;
par
->
Attribute
[
13
]
=
0x0D
;
par
->
Attribute
[
13
]
=
0x0D
;
par
->
Attribute
[
14
]
=
0x0E
;
par
->
Attribute
[
14
]
=
0x0E
;
par
->
Attribute
[
15
]
=
0x0F
;
par
->
Attribute
[
15
]
=
0x0F
;
par
->
Attribute
[
16
]
=
0x41
;
par
->
Attribute
[
16
]
=
0x41
;
par
->
Attribute
[
17
]
=
0xFF
;
par
->
Attribute
[
17
]
=
0xFF
;
par
->
Attribute
[
18
]
=
0x0F
;
par
->
Attribute
[
18
]
=
0x0F
;
par
->
Attribute
[
19
]
=
0x00
;
par
->
Attribute
[
19
]
=
0x00
;
par
->
Attribute
[
20
]
=
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
;
struct
xtimings
timings
;
int
lcd_stretch
;
int
hoffset
,
voffset
;
int
memlen
,
vramlen
;
int
memlen
,
vramlen
;
int
mode_ok
=
0
;
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
;
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
.
dblscan
=
var
->
vmode
&
FB_VMODE_DOUBLE
;
timings
.
interlaced
=
var
->
vmode
&
FB_VMODE_INTERLACED
;
timings
.
interlaced
=
var
->
vmode
&
FB_VMODE_INTERLACED
;
timings
.
HDisplay
=
var
->
xres
;
timings
.
HDisplay
=
var
->
xres
;
...
@@ -1032,24 +550,18 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1032,24 +550,18 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
timings
.
VTotal
=
timings
.
VSyncEnd
+
var
->
upper_margin
;
timings
.
VTotal
=
timings
.
VSyncEnd
+
var
->
upper_margin
;
timings
.
sync
=
var
->
sync
;
timings
.
sync
=
var
->
sync
;
if
(
timings
.
pixclock
>
info
->
maxClock
)
return
-
EINVAL
;
/* Is the mode larger than the LCD panel? */
/* Is the mode larger than the LCD panel? */
if
((
var
->
xres
>
info
->
NeoPanelWidth
)
||
if
((
var
->
xres
>
par
->
NeoPanelWidth
)
||
(
var
->
yres
>
info
->
NeoPanelHeight
))
(
var
->
yres
>
par
->
NeoPanelHeight
))
{
{
printk
(
KERN_INFO
printk
(
KERN_INFO
"Mode (%dx%d) larger than the LCD panel (%dx%d)
\n
"
,
"Mode (%dx%d) larger than the LCD panel (%dx%d)
\n
"
,
var
->
xres
,
var
->
xres
,
var
->
yres
,
par
->
NeoPanelWidth
,
var
->
yres
,
par
->
NeoPanelHeight
);
info
->
NeoPanelWidth
,
info
->
NeoPanelHeight
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* Is the mode one of the acceptable sizes? */
/* Is the mode one of the acceptable sizes? */
switch
(
var
->
xres
)
switch
(
var
->
xres
)
{
{
case
1280
:
case
1280
:
if
(
var
->
yres
==
1024
)
if
(
var
->
yres
==
1024
)
mode_ok
=
1
;
mode_ok
=
1
;
...
@@ -1068,58 +580,87 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1068,58 +580,87 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
break
;
break
;
}
}
if
(
!
mode_ok
)
if
(
!
mode_ok
)
{
{
printk
(
KERN_INFO
printk
(
KERN_INFO
"Mode (%dx%d) won't display properly on LCD
\n
"
,
"Mode (%dx%d) won't display properly on LCD
\n
"
,
var
->
xres
,
var
->
yres
);
var
->
xres
,
var
->
yres
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
switch
(
var
->
bits_per_pixel
)
switch
(
var
->
bits_per_pixel
)
{
{
case
8
:
/* PSEUDOCOLOUR, 256 */
#ifdef FBCON_HAS_CFB8
var
->
transp
.
offset
=
0
;
case
8
:
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
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
/* DIRECTCOLOUR, 64k */
case
16
:
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
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
/* TRUECOLOUR, 16m */
case
24
:
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
;
break
;
#endif
#ifdef NO_32BIT_SUPPORT_YET
#ifdef NO_32BIT_SUPPORT_YET
# ifdef FBCON_HAS_CFB32
case
32
:
/* TRUECOLOUR, 16m */
case
32
:
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
;
break
;
# endif
#endif
#endif
default:
default:
printk
(
KERN_WARNING
"neofb: no support for %dbpp
\n
"
,
var
->
bits_per_pixel
);
return
-
EINVAL
;
return
-
EINVAL
;
}
}
par
->
depth
=
var
->
bits_per_pixel
;
vramlen
=
info
->
fix
.
smem_len
;
if
(
vramlen
>
4
*
1024
*
1024
)
vramlen
=
info
->
video
.
len
;
vramlen
=
4
*
1024
*
1024
;
if
(
vramlen
>
4
*
1024
*
1024
)
vramlen
=
4
*
1024
*
1024
;
if
(
var
->
yres_virtual
<
var
->
yres
)
if
(
var
->
yres_virtual
<
var
->
yres
)
var
->
yres_virtual
=
var
->
yres
;
var
->
yres_virtual
=
var
->
yres
;
if
(
var
->
xres_virtual
<
var
->
xres
)
if
(
var
->
xres_virtual
<
var
->
xres
)
var
->
xres_virtual
=
var
->
xres
;
var
->
xres_virtual
=
var
->
xres
;
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
memlen
=
if
(
memlen
>
vramlen
)
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
{
8
;
var
->
yres_virtual
=
vramlen
*
8
/
(
var
->
xres_virtual
*
var
->
bits_per_pixel
);
if
(
memlen
>
vramlen
)
{
memlen
=
var
->
xres_virtual
*
var
->
bits_per_pixel
*
var
->
yres_virtual
/
8
;
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
/* 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,
...
@@ -1133,13 +674,48 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
if
(
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
)
if
(
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
)
var
->
yoffset
=
var
->
yres_virtual
-
var
->
yres
;
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
* This will allocate the datastructure and initialize all of the
* generic VGA registers.
* generic VGA registers.
*/
*/
if
(
vgaHWInit
(
var
,
info
,
par
,
&
timings
))
if
(
vgaHWInit
(
&
info
->
var
,
info
,
par
,
&
timings
))
return
-
EINVAL
;
return
-
EINVAL
;
/*
/*
...
@@ -1148,27 +724,26 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1148,27 +724,26 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
*/
*/
par
->
Attribute
[
16
]
=
0x01
;
par
->
Attribute
[
16
]
=
0x01
;
switch
(
var
->
bits_per_pixel
)
switch
(
info
->
var
.
bits_per_pixel
)
{
{
case
8
:
case
8
:
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
3
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
3
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
11
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
11
;
par
->
ExtColorModeSelect
=
0x11
;
par
->
ExtColorModeSelect
=
0x11
;
break
;
break
;
case
16
:
case
16
:
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
2
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
2
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
10
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
10
;
par
->
ExtColorModeSelect
=
0x13
;
par
->
ExtColorModeSelect
=
0x13
;
break
;
break
;
case
24
:
case
24
:
par
->
CRTC
[
0x13
]
=
(
var
->
xres_virtual
*
3
)
>>
3
;
par
->
CRTC
[
0x13
]
=
(
info
->
var
.
xres_virtual
*
3
)
>>
3
;
par
->
ExtCRTOffset
=
(
var
->
xres_virtual
*
3
)
>>
11
;
par
->
ExtCRTOffset
=
(
info
->
var
.
xres_virtual
*
3
)
>>
11
;
par
->
ExtColorModeSelect
=
0x14
;
par
->
ExtColorModeSelect
=
0x14
;
break
;
break
;
#ifdef NO_32BIT_SUPPORT_YET
#ifdef NO_32BIT_SUPPORT_YET
case
32
:
/* FIXME: guessed values */
case
32
:
/* FIXME: guessed values */
par
->
CRTC
[
0x13
]
=
var
->
xres_virtual
>>
1
;
par
->
CRTC
[
0x13
]
=
info
->
var
.
xres_virtual
>>
1
;
par
->
ExtCRTOffset
=
var
->
xres_virtual
>>
9
;
par
->
ExtCRTOffset
=
info
->
var
.
xres_virtual
>>
9
;
par
->
ExtColorModeSelect
=
0x15
;
par
->
ExtColorModeSelect
=
0x15
;
break
;
break
;
#endif
#endif
...
@@ -1179,13 +754,13 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1179,13 +754,13 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
ExtCRTDispAddr
=
0x10
;
par
->
ExtCRTDispAddr
=
0x10
;
/* Vertical Extension */
/* Vertical Extension */
par
->
VerticalExt
=
(((
timings
.
VTotal
-
2
)
&
0x400
)
>>
10
)
par
->
VerticalExt
=
(((
timings
.
VTotal
-
2
)
&
0x400
)
>>
10
)
|
(((
timings
.
VDisplay
-
1
)
&
0x400
)
>>
9
)
|
(((
timings
.
VDisplay
-
1
)
&
0x400
)
>>
9
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
8
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
8
)
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
7
);
|
(((
timings
.
VSyncStart
)
&
0x400
)
>>
7
);
/* Fast write bursts on unless disabled. */
/* Fast write bursts on unless disabled. */
if
(
info
->
pci_burst
)
if
(
par
->
pci_burst
)
par
->
SysIfaceCntl1
=
0x30
;
par
->
SysIfaceCntl1
=
0x30
;
else
else
par
->
SysIfaceCntl1
=
0x00
;
par
->
SysIfaceCntl1
=
0x00
;
...
@@ -1194,9 +769,9 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1194,9 +769,9 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
/* Enable any user specified display devices. */
/* Enable any user specified display devices. */
par
->
PanelDispCntlReg1
=
0x00
;
par
->
PanelDispCntlReg1
=
0x00
;
if
(
info
->
internal_display
)
if
(
par
->
internal_display
)
par
->
PanelDispCntlReg1
|=
0x02
;
par
->
PanelDispCntlReg1
|=
0x02
;
if
(
info
->
external_display
)
if
(
par
->
external_display
)
par
->
PanelDispCntlReg1
|=
0x01
;
par
->
PanelDispCntlReg1
|=
0x01
;
/* If the user did not specify any display devices, then... */
/* If the user did not specify any display devices, then... */
...
@@ -1206,8 +781,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -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. */
/* If we are using a fixed mode, then tell the chip we are. */
switch
(
var
->
xres
)
switch
(
info
->
var
.
xres
)
{
{
case
1280
:
case
1280
:
par
->
PanelDispCntlReg1
|=
0x60
;
par
->
PanelDispCntlReg1
|=
0x60
;
break
;
break
;
...
@@ -1223,8 +797,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1223,8 +797,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
}
}
/* Setup shadow register locking. */
/* Setup shadow register locking. */
switch
(
par
->
PanelDispCntlReg1
&
0x03
)
switch
(
par
->
PanelDispCntlReg1
&
0x03
)
{
{
case
0x01
:
/* External CRT only mode: */
case
0x01
:
/* External CRT only mode: */
par
->
GeneralLockReg
=
0x00
;
par
->
GeneralLockReg
=
0x00
;
/* We need to program the VCLK for external display only mode. */
/* 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,
...
@@ -1247,12 +820,9 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
PanelDispCntlReg2
=
0x00
;
par
->
PanelDispCntlReg2
=
0x00
;
par
->
PanelDispCntlReg3
=
0x00
;
par
->
PanelDispCntlReg3
=
0x00
;
if
(
info
->
lcd_stretch
&&
if
(
par
->
lcd_stretch
&&
(
par
->
PanelDispCntlReg1
==
0x02
)
&&
/* LCD only */
(
par
->
PanelDispCntlReg1
==
0x02
)
&&
/* LCD only */
(
info
->
var
.
xres
!=
par
->
NeoPanelWidth
))
{
(
var
->
xres
!=
info
->
NeoPanelWidth
))
switch
(
info
->
var
.
xres
)
{
{
switch
(
var
->
xres
)
{
case
320
:
/* Needs testing. KEM -- 24 May 98 */
case
320
:
/* Needs testing. KEM -- 24 May 98 */
case
400
:
/* Needs testing. KEM -- 24 May 98 */
case
400
:
/* Needs testing. KEM -- 24 May 98 */
case
640
:
case
640
:
...
@@ -1265,8 +835,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1265,8 +835,7 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
lcd_stretch
=
0
;
lcd_stretch
=
0
;
/* No stretching in these modes. */
/* No stretching in these modes. */
}
}
}
}
else
else
lcd_stretch
=
0
;
lcd_stretch
=
0
;
/*
/*
...
@@ -1285,35 +854,31 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -1285,35 +854,31 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
par
->
PanelHorizCenterReg5
=
0x00
;
par
->
PanelHorizCenterReg5
=
0x00
;
if
(
par
->
PanelDispCntlReg1
&
0x02
)
if
(
par
->
PanelDispCntlReg1
&
0x02
)
{
{
if
(
info
->
var
.
xres
==
par
->
NeoPanelWidth
)
{
if
(
var
->
xres
==
info
->
NeoPanelWidth
)
{
/*
/*
* No centering required when the requested display width
* No centering required when the requested display width
* equals the panel width.
* equals the panel width.
*/
*/
}
}
else
{
else
{
par
->
PanelDispCntlReg2
|=
0x01
;
par
->
PanelDispCntlReg2
|=
0x01
;
par
->
PanelDispCntlReg3
|=
0x10
;
par
->
PanelDispCntlReg3
|=
0x10
;
/* Calculate the horizontal and vertical offsets. */
/* Calculate the horizontal and vertical offsets. */
if
(
!
lcd_stretch
)
if
(
!
lcd_stretch
)
{
{
hoffset
=
hoffset
=
((
info
->
NeoPanelWidth
-
var
->
xres
)
>>
4
)
-
1
;
((
par
->
NeoPanelWidth
-
voffset
=
((
info
->
NeoPanelHeight
-
var
->
yres
)
>>
1
)
-
2
;
info
->
var
.
xres
)
>>
4
)
-
1
;
}
voffset
=
else
((
par
->
NeoPanelHeight
-
{
info
->
var
.
yres
)
>>
1
)
-
2
;
}
else
{
/* Stretched modes cannot be centered. */
/* Stretched modes cannot be centered. */
hoffset
=
0
;
hoffset
=
0
;
voffset
=
0
;
voffset
=
0
;
}
}
switch
(
var
->
xres
)
switch
(
info
->
var
.
xres
)
{
{
case
320
:
/* Needs testing. KEM -- 24 May 98 */
case
320
:
/* Needs testing. KEM -- 24 May 98 */
par
->
PanelHorizCenterReg3
=
hoffset
;
par
->
PanelHorizCenterReg3
=
hoffset
;
par
->
PanelVertCenterReg2
=
voffset
;
par
->
PanelVertCenterReg2
=
voffset
;
...
@@ -1342,210 +907,268 @@ static int neofb_decode_var (struct fb_var_screeninfo *var,
...
@@ -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
* Calculate the VCLK that most closely matches the requested dot
* clock.
* clock.
*/
*/
neoCalcVCLK
(
info
,
par
,
timings
.
pixclock
);
neoCalcVCLK
(
info
,
par
,
timings
.
pixclock
);
/* Since we program the clocks ourselves, always use VCLK3. */
/* Since we program the clocks ourselves, always use VCLK3. */
par
->
MiscOutReg
|=
0x0C
;
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
,
for
(
i
=
0
;
i
<
64
;
i
++
)
{
struct
fb_info
*
fb
)
outb
(
i
,
0x3c8
);
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
outb
(
i
<<
1
,
0x3c9
);
struct
display
*
display
;
outb
(
i
,
0x3c9
);
struct
neofb_par
par
;
outb
(
i
<<
1
,
0x3c9
);
int
err
,
chgvar
=
0
;
}
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
);
outb
(
i
,
0x3c9
);
if
(
err
)
outb
(
i
,
0x3c9
);
return
err
;
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
)
VGAwGR
(
0x28
,
par
->
PanelVertCenterReg1
);
return
0
;
VGAwGR
(
0x29
,
par
->
PanelVertCenterReg2
);
VGAwGR
(
0x2a
,
par
->
PanelVertCenterReg3
);
if
(
con
<
0
)
if
(
info
->
fix
.
accel
!=
FB_ACCEL_NEOMAGIC_NM2070
)
{
{
VGAwGR
(
0x32
,
par
->
PanelVertCenterReg4
);
display
=
fb
->
disp
;
VGAwGR
(
0x33
,
par
->
PanelHorizCenterReg1
);
chgvar
=
0
;
VGAwGR
(
0x34
,
par
->
PanelHorizCenterReg2
);
}
VGAwGR
(
0x35
,
par
->
PanelHorizCenterReg3
);
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
->
neo2200
)
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2160
)
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
switch
(
var
->
bits_per_pixel
)
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
{
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
#ifdef FBCON_HAS_CFB8
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2360
||
case
8
:
/* PSEUDOCOLOUR, 256 */
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2380
)
{
var
->
transp
.
offset
=
0
;
VGAwGR
(
0x36
,
par
->
PanelHorizCenterReg4
);
var
->
transp
.
length
=
0
;
VGAwGR
(
0x37
,
par
->
PanelVertCenterReg5
);
var
->
red
.
offset
=
0
;
VGAwGR
(
0x38
,
par
->
PanelHorizCenterReg5
);
var
->
red
.
length
=
8
;
var
->
green
.
offset
=
0
;
var
->
green
.
length
=
8
;
var
->
blue
.
offset
=
0
;
var
->
blue
.
length
=
8
;
fb
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
clock_hi
=
1
;
info
->
dispsw
=
&
fbcon_cfb8
;
}
display
->
dispsw_data
=
NULL
;
display
->
next_line
=
var
->
xres_virtual
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
/* Program VCLK3 if needed. */
case
16
:
/* DIRECTCOLOUR, 64k */
if
(
par
->
ProgramVCLK
&&
((
VGArGR
(
0x9B
)
!=
par
->
VCLK3NumeratorLow
)
var
->
transp
.
offset
=
0
;
||
(
VGArGR
(
0x9F
)
!=
par
->
VCLK3Denominator
)
var
->
transp
.
length
=
0
;
||
(
clock_hi
&&
((
VGArGR
(
0x8F
)
&
~
0x0f
)
var
->
red
.
offset
=
11
;
!=
(
par
->
var
->
red
.
length
=
5
;
VCLK3NumeratorHigh
&
var
->
green
.
offset
=
5
;
~
0x0F
)))))
{
var
->
green
.
length
=
6
;
VGAwGR
(
0x9B
,
par
->
VCLK3NumeratorLow
);
var
->
blue
.
offset
=
0
;
if
(
clock_hi
)
{
var
->
blue
.
length
=
5
;
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
;
if
(
par
->
biosMode
)
info
->
dispsw
=
&
fbcon_cfb16
;
VGAwCR
(
0x23
,
par
->
biosMode
);
display
->
dispsw_data
=
fb
->
pseudo_palette
;
display
->
next_line
=
var
->
xres_virtual
*
2
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
VGAwGR
(
0x93
,
0xc0
);
/* Gives 5x faster framebuffer writes !!! */
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
;
fb
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
/* Program vertical extension register */
info
->
dispsw
=
&
fbcon_cfb24
;
if
(
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2200
||
display
->
dispsw_data
=
fb
->
pseudo_palette
;
info
->
fix
.
accel
==
FB_ACCEL_NEOMAGIC_NM2230
||
display
->
next_line
=
var
->
xres_virtual
*
3
;
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
vgaHWProtect
(
0
);
/* Turn on screen */
# 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
;
fb
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
/* Calling this also locks offset registers required in update_start */
info
->
dispsw
=
&
fbcon_cfb32
;
neoLock
();
display
->
dispsw_data
=
fb
->
pseudo_palette
;
display
->
next_line
=
var
->
xres_virtual
*
4
;
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
info
->
fix
.
line_length
=
break
;
info
->
var
.
xres_virtual
*
(
info
->
var
.
bits_per_pixel
>>
3
);
# endif
#endif
default:
if
(
info
->
var
.
accel_flags
&
FB_ACCELF_TEXT
)
printk
(
KERN_WARNING
"neofb: no support for %dbpp
\n
"
,
var
->
bits_per_pixel
);
neo2200_accel_init
(
info
,
&
info
->
var
);
info
->
dispsw
=
&
fbcon_dummy
;
return
0
;
var
->
accel_flags
&=
~
FB_ACCELF_TEXT
;
}
break
;
}
if
(
var
->
accel_flags
&
FB_ACCELF_TEXT
)
static
void
neofb_update_start
(
struct
fb_info
*
info
,
display
->
dispsw
=
&
fbcon_neo2200_accel
;
struct
fb_var_screeninfo
*
var
)
else
{
display
->
dispsw
=
info
->
dispsw
;
int
oldExtCRTDispAddr
;
int
Base
;
fb
->
fix
.
line_length
=
display
->
next_line
;
DBG
(
"neofb_update_start"
)
;
display
->
line_length
=
fb
->
fix
.
line_length
;
Base
=
(
var
->
yoffset
*
var
->
xres_virtual
+
var
->
xoffset
)
>>
2
;
display
->
visual
=
fb
->
fix
.
visual
;
Base
*=
(
var
->
bits_per_pixel
+
7
)
/
8
;
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
;
fb
->
var
=
*
var
;
neoUnlock
();
fb
->
var
.
activate
&=
~
FB_ACTIVATE_ALL
;
/*
/*
* Update the old var. The fbcon drivers still use this.
* These are the generic starting address registers.
* Once they are using cfb->fb.var, this can be dropped.
* --rmk
*/
*/
display
->
var
=
fb
->
var
;
VGAwCR
(
0x0C
,
(
Base
&
0x00FF00
)
>>
8
);
VGAwCR
(
0x0D
,
(
Base
&
0x00FF
));
/*
/*
* If we are setting all the virtual consoles, also set the
* Make sure we don't clobber some other bits that might already
* defaults used to create new consoles.
* have been set. NOTE: NM2200 has a writable bit 3, but it shouldn't
* be needed.
*/
*/
if
(
var
->
activate
&
FB_ACTIVATE_ALL
)
oldExtCRTDispAddr
=
VGArGR
(
0x0E
);
fb
->
disp
->
var
=
fb
->
var
;
VGAwGR
(
0x0E
,
(((
Base
>>
16
)
&
0x0f
)
|
(
oldExtCRTDispAddr
&
0xf0
)));
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
);
}
return
0
;
neoLock
()
;
}
}
/*
/*
* Pan or Wrap the Display
* 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
fb_info
*
fb
)
{
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
struct
fb_info
*
info
=
(
struct
fb_info
*
)
fb
;
u_int
y_bottom
;
u_int
y_bottom
;
y_bottom
=
var
->
yoffset
;
y_bottom
=
var
->
yoffset
;
...
@@ -1558,7 +1181,7 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
...
@@ -1558,7 +1181,7 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
if
(
y_bottom
>
fb
->
var
.
yres_virtual
)
if
(
y_bottom
>
fb
->
var
.
yres_virtual
)
return
-
EINVAL
;
return
-
EINVAL
;
neofb_update_start
(
info
,
var
);
neofb_update_start
(
info
,
var
);
fb
->
var
.
xoffset
=
var
->
xoffset
;
fb
->
var
.
xoffset
=
var
->
xoffset
;
fb
->
var
.
yoffset
=
var
->
yoffset
;
fb
->
var
.
yoffset
=
var
->
yoffset
;
...
@@ -1571,71 +1194,54 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
...
@@ -1571,71 +1194,54 @@ static int neofb_pan_display (struct fb_var_screeninfo *var, int con,
return
0
;
return
0
;
}
}
static
int
neofb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
/*
u_int
transp
,
struct
fb_info
*
fb
)
* 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
)
{
{
struct
neofb_info
*
info
=
(
struct
neofb_info
*
)
fb
;
if
(
regno
>=
NR_PALETTE
)
struct
display
*
disp
;
return
-
EINVAL
;
struct
fb_cmap
*
cmap
;
if
(
info
->
fb
.
currcon
>=
0
)
switch
(
fb
->
var
.
bits_per_pixel
)
{
{
case
8
:
disp
=
fb_display
+
info
->
fb
.
currcon
;
outb
(
regno
,
0x3c8
)
;
/*
outb
(
red
>>
10
,
0x3c9
);
* Save the old colormap and video mode.
outb
(
green
>>
10
,
0x3c9
);
*/
outb
(
blue
>>
10
,
0x3c9
);
disp
->
var
=
fb
->
var
;
break
;
if
(
disp
->
cmap
.
len
)
case
16
:
fb_copy_cmap
(
&
fb
->
cmap
,
&
disp
->
cmap
,
0
);
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
;
return
0
;
}
}
/*
/*
* (Un)Blank the display.
* (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
* Blank the screen if blank_mode != 0, else unblank. If
...
@@ -1653,8 +1259,7 @@ static int neofb_blank (int blank, struct fb_info *fb)
...
@@ -1653,8 +1259,7 @@ static int neofb_blank (int blank, struct fb_info *fb)
* run "setterm -powersave powerdown" to take advantage
* run "setterm -powersave powerdown" to take advantage
*/
*/
switch
(
blank
)
switch
(
blank
)
{
{
case
4
:
/* powerdown - both sync lines down */
case
4
:
/* powerdown - both sync lines down */
break
;
break
;
case
3
:
/* hsync off */
case
3
:
/* hsync off */
...
@@ -1669,16 +1274,132 @@ static int neofb_blank (int blank, struct fb_info *fb)
...
@@ -1669,16 +1274,132 @@ static int neofb_blank (int blank, struct fb_info *fb)
return
0
;
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
=
{
static
struct
fb_ops
neofb_ops
=
{
owner:
THIS_MODULE
,
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_set_cmap:
gen_set_cmap
,
fb_setcolreg:
neofb_setcolreg
,
fb_setcolreg:
neofb_setcolreg
,
fb_pan_display:
neofb_pan_display
,
fb_pan_display:
neofb_pan_display
,
fb_blank:
neofb_blank
,
fb_blank:
neofb_blank
,
fb_get_fix:
gen_get_fix
,
fb_fillrect:
cfb_fillrect
,
fb_get_var:
gen_get_var
,
fb_copyarea:
cfb_copyarea
,
fb_get_cmap:
gen_get_cmap
,
fb_imageblit:
cfb_imageblit
,
};
};
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
...
@@ -1697,7 +1418,6 @@ static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
...
@@ -1697,7 +1418,6 @@ static struct fb_var_screeninfo __devinitdata neofb_var640x480x8 = {
lower_margin:
10
,
lower_margin:
10
,
hsync_len:
96
,
hsync_len:
96
,
vsync_len:
2
,
vsync_len:
2
,
sync:
0
,
vmode:
FB_VMODE_NONINTERLACED
vmode:
FB_VMODE_NONINTERLACED
};
};
...
@@ -1759,106 +1479,110 @@ static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
...
@@ -1759,106 +1479,110 @@ static struct fb_var_screeninfo __devinitdata neofb_var1280x1024x8 = {
static
struct
fb_var_screeninfo
*
neofb_var
=
NULL
;
static
struct
fb_var_screeninfo
*
neofb_var
=
NULL
;
static
int
__devinit
neo_map_mmio
(
struct
fb_info
*
info
,
static
int
__devinit
neo_map_mmio
(
struct
neofb_info
*
info
)
struct
pci_dev
*
dev
)
{
{
struct
neofb_par
*
par
=
(
struct
neofb_par
*
)
info
->
par
;
DBG
(
"neo_map_mmio"
);
DBG
(
"neo_map_mmio"
);
info
->
mmio
.
pbase
=
pci_resource_start
(
info
->
pci
dev
,
1
);
info
->
fix
.
mmio_start
=
pci_resource_start
(
dev
,
1
);
info
->
mmio
.
len
=
MMIO_SIZE
;
info
->
fix
.
mmio_len
=
MMIO_SIZE
;
if
(
!
request_mem_region
(
info
->
mmio
.
pbase
,
MMIO_SIZE
,
"memory mapped I/O"
))
if
(
!
request_mem_region
{
(
info
->
fix
.
mmio_start
,
MMIO_SIZE
,
"memory mapped I/O"
))
{
printk
(
"neofb: memory mapped IO in use
\n
"
);
printk
(
"neofb: memory mapped IO in use
\n
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
info
->
mmio
.
vbase
=
ioremap
(
info
->
mmio
.
pbase
,
MMIO_SIZE
);
par
->
mmio_vbase
=
ioremap
(
info
->
fix
.
mmio_start
,
MMIO_SIZE
);
if
(
!
info
->
mmio
.
vbase
)
if
(
!
par
->
mmio_vbase
)
{
{
printk
(
"neofb: unable to map memory mapped IO
\n
"
);
printk
(
"neofb: unable to map memory mapped IO
\n
"
);
release_mem_region
(
info
->
fix
.
mmio_start
,
release_mem_region
(
info
->
mmio
.
pbase
,
info
->
mmio
.
len
);
info
->
fix
.
mmio_
len
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
else
else
printk
(
KERN_INFO
"neofb: mapped io at %p
\n
"
,
printk
(
KERN_INFO
"neofb: mapped io at %p
\n
"
,
info
->
mmio
.
vbase
);
par
->
mmio_vbase
);
info
->
fb
.
fix
.
mmio_start
=
info
->
mmio
.
pbase
;
info
->
fb
.
fix
.
mmio_len
=
info
->
mmio
.
len
;
return
0
;
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"
);
DBG
(
"neo_unmap_mmio"
);
if
(
info
->
mmio
.
vbase
)
if
(
par
->
mmio_vbase
)
{
{
iounmap
(
par
->
mmio_vbase
);
iounmap
(
info
->
mmio
.
vbase
);
par
->
mmio_vbase
=
NULL
;
info
->
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"
);
DBG
(
"neo_map_video"
);
info
->
video
.
pbase
=
pci_resource_start
(
info
->
pci
dev
,
0
);
info
->
fix
.
smem_start
=
pci_resource_start
(
dev
,
0
);
info
->
video
.
len
=
video_len
;
info
->
fix
.
smem_len
=
video_len
;
if
(
!
request_mem_region
(
info
->
video
.
pbase
,
info
->
video
.
len
,
"frame buffer"
))
if
(
!
request_mem_region
{
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
,
"frame buffer"
))
{
printk
(
"neofb: frame buffer in use
\n
"
);
printk
(
"neofb: frame buffer in use
\n
"
);
return
-
EBUSY
;
return
-
EBUSY
;
}
}
info
->
video
.
vbase
=
ioremap
(
info
->
video
.
pbase
,
info
->
video
.
len
);
info
->
screen_base
=
if
(
!
info
->
video
.
vbase
)
ioremap
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
{
if
(
!
info
->
screen_base
)
{
printk
(
"neofb: unable to map screen memory
\n
"
);
printk
(
"neofb: unable to map screen memory
\n
"
);
release_mem_region
(
info
->
video
.
pbase
,
info
->
video
.
len
);
release_mem_region
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
return
-
ENOMEM
;
return
-
ENOMEM
;
}
}
else
else
printk
(
KERN_INFO
"neofb: mapped framebuffer at %p
\n
"
,
printk
(
KERN_INFO
"neofb: mapped framebuffer at %p
\n
"
,
info
->
video
.
vbase
);
info
->
screen_base
);
info
->
fb
.
fix
.
smem_start
=
info
->
video
.
pbase
;
info
->
fb
.
fix
.
smem_len
=
info
->
video
.
len
;
info
->
fb
.
screen_base
=
info
->
video
.
vbase
;
#ifdef CONFIG_MTRR
#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
#endif
/* Clear framebuffer, it's all white in memory after boot */
/* 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
;
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"
);
DBG
(
"neo_unmap_video"
);
if
(
info
->
video
.
vbase
)
if
(
info
->
screen_base
)
{
{
#ifdef CONFIG_MTRR
#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
#endif
iounmap
(
info
->
video
.
vbase
);
iounmap
(
info
->
screen_base
);
info
->
video
.
vbase
=
NULL
;
info
->
screen_base
=
NULL
;
info
->
fb
.
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
videoRam
=
896
;
int
maxClock
=
65000
;
int
maxClock
=
65000
;
int
CursorMem
=
1024
;
int
CursorMem
=
1024
;
...
@@ -1874,64 +1598,65 @@ static int __devinit neo_init_hw (struct neofb_info *info)
...
@@ -1874,64 +1598,65 @@ static int __devinit neo_init_hw (struct neofb_info *info)
neoUnlock
();
neoUnlock
();
#if 0
#if 0
printk (KERN_DEBUG "--- Neo extended register dump ---\n");
printk(KERN_DEBUG "--- Neo extended register dump ---\n");
for (w=0; w<0x85; w++)
for (w = 0; w < 0x85; w++)
printk (KERN_DEBUG "CR %p: %p\n", (void*)w, (void*)VGArCR (w));
printk(KERN_DEBUG "CR %p: %p\n", (void *) w,
for (w=0; w<0xC7; w++)
(void *) VGArCR(w));
printk (KERN_DEBUG "GR %p: %p\n", (void*)w, (void*)VGArGR (w));
for (w = 0; w < 0xC7; w++)
printk(KERN_DEBUG "GR %p: %p\n", (void *) w,
(void *) VGArGR(w));
#endif
#endif
/* Determine the panel type */
/* Determine the panel type */
VGAwGR
(
0x09
,
0x26
);
VGAwGR
(
0x09
,
0x26
);
type
=
VGArGR
(
0x21
);
type
=
VGArGR
(
0x21
);
display
=
VGArGR
(
0x20
);
display
=
VGArGR
(
0x20
);
/* Determine panel width -- used in NeoValidMode. */
/* Determine panel width -- used in NeoValidMode. */
w
=
VGArGR
(
0x20
);
w
=
VGArGR
(
0x20
);
VGAwGR
(
0x09
,
0x00
);
VGAwGR
(
0x09
,
0x00
);
switch
((
w
&
0x18
)
>>
3
)
switch
((
w
&
0x18
)
>>
3
)
{
{
case
0x00
:
case
0x00
:
info
->
NeoPanelWidth
=
640
;
par
->
NeoPanelWidth
=
640
;
info
->
NeoPanelHeight
=
480
;
par
->
NeoPanelHeight
=
480
;
neofb_var
=
&
neofb_var640x480x8
;
neofb_var
=
&
neofb_var640x480x8
;
break
;
break
;
case
0x01
:
case
0x01
:
info
->
NeoPanelWidth
=
800
;
par
->
NeoPanelWidth
=
800
;
info
->
NeoPanelHeight
=
600
;
par
->
NeoPanelHeight
=
600
;
neofb_var
=
&
neofb_var800x600x8
;
neofb_var
=
&
neofb_var800x600x8
;
break
;
break
;
case
0x02
:
case
0x02
:
info
->
NeoPanelWidth
=
1024
;
par
->
NeoPanelWidth
=
1024
;
info
->
NeoPanelHeight
=
768
;
par
->
NeoPanelHeight
=
768
;
neofb_var
=
&
neofb_var1024x768x8
;
neofb_var
=
&
neofb_var1024x768x8
;
break
;
break
;
case
0x03
:
case
0x03
:
/* 1280x1024 panel support needs to be added */
/* 1280x1024 panel support needs to be added */
#ifdef NOT_DONE
#ifdef NOT_DONE
info
->
NeoPanelWidth
=
1280
;
par
->
NeoPanelWidth
=
1280
;
info
->
NeoPanelHeight
=
1024
;
par
->
NeoPanelHeight
=
1024
;
neofb_var
=
&
neofb_var1280x1024x8
;
neofb_var
=
&
neofb_var1280x1024x8
;
break
;
break
;
#else
#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
;
return
-
1
;
#endif
#endif
default:
default:
info
->
NeoPanelWidth
=
640
;
par
->
NeoPanelWidth
=
640
;
info
->
NeoPanelHeight
=
480
;
par
->
NeoPanelHeight
=
480
;
neofb_var
=
&
neofb_var640x480x8
;
neofb_var
=
&
neofb_var640x480x8
;
break
;
break
;
}
}
printk
(
KERN_INFO
"Panel is a %dx%d %s %s display
\n
"
,
printk
(
KERN_INFO
"Panel is a %dx%d %s %s display
\n
"
,
info
->
NeoPanelWidth
,
par
->
NeoPanelWidth
,
info
->
NeoPanelHeight
,
par
->
NeoPanelHeight
,
(
type
&
0x02
)
?
"color"
:
"monochrome"
,
(
type
&
0x02
)
?
"color"
:
"monochrome"
,
(
type
&
0x10
)
?
"TFT"
:
"dual scan"
);
(
type
&
0x10
)
?
"TFT"
:
"dual scan"
);
switch
(
info
->
accel
)
switch
(
info
->
fix
.
accel
)
{
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
case
FB_ACCEL_NEOMAGIC_NM2070
:
videoRam
=
896
;
videoRam
=
896
;
maxClock
=
65000
;
maxClock
=
65000
;
...
@@ -1978,7 +1703,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
...
@@ -1978,7 +1703,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
videoRam
=
3008
;
videoRam
=
3008
;
...
@@ -1989,7 +1714,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
...
@@ -1989,7 +1714,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
videoRam
=
4096
;
videoRam
=
4096
;
...
@@ -2000,7 +1725,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
...
@@ -2000,7 +1725,7 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2380
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
videoRam
=
6144
;
videoRam
=
6144
;
...
@@ -2011,155 +1736,154 @@ static int __devinit neo_init_hw (struct neofb_info *info)
...
@@ -2011,155 +1736,154 @@ static int __devinit neo_init_hw (struct neofb_info *info)
maxWidth
=
1280
;
maxWidth
=
1280
;
maxHeight
=
1024
;
/* ???? */
maxHeight
=
1024
;
/* ???? */
info
->
neo2200
=
(
Neo2200
*
)
info
->
mmio
.
vbase
;
par
->
neo2200
=
(
Neo2200
*
)
par
->
mmio_
vbase
;
break
;
break
;
}
}
info
->
maxClock
=
maxClock
;
par
->
maxClock
=
maxClock
;
return
videoRam
*
1024
;
return
videoRam
*
1024
;
}
}
static
struct
neofb_info
*
__devinit
neo_alloc_fb_info
(
struct
pci_dev
*
dev
,
static
struct
fb_info
*
__devinit
neo_alloc_fb_info
(
struct
pci_dev
*
dev
,
const
struct
const
struct
pci_device_id
*
id
)
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
);
sizeof
(
u32
)
*
16
,
GFP_KERNEL
);
if
(
!
info
)
if
(
!
info
)
return
NULL
;
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
;
par
=
&
default_par
;
info
->
pcidev
=
dev
;
memset
(
par
,
0
,
sizeof
(
struct
neofb_par
));
info
->
accel
=
id
->
driver_data
;
info
->
pci_burst
=
!
nopciburst
;
info
->
currcon
=
-
1
;
info
->
lcd_stretch
=
!
nostretch
;
info
->
fix
.
accel
=
id
->
driver_data
;
if
(
!
internal
&&
!
external
)
par
->
pci_burst
=
!
nopciburst
;
{
par
->
lcd_stretch
=
!
nostretch
;
info
->
internal_display
=
1
;
info
->
external_display
=
0
;
if
(
!
internal
&&
!
external
)
{
}
par
->
internal_display
=
1
;
else
par
->
external_display
=
0
;
{
}
else
{
info
->
internal_display
=
internal
;
par
->
internal_display
=
internal
;
info
->
external_display
=
external
;
par
->
external_display
=
external
;
}
}
switch
(
info
->
accel
)
switch
(
info
->
fix
.
accel
)
{
{
case
FB_ACCEL_NEOMAGIC_NM2070
:
case
FB_ACCEL_NEOMAGIC_NM2070
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2090
:
case
FB_ACCEL_NEOMAGIC_NM2090
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128V"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128V"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2093
:
case
FB_ACCEL_NEOMAGIC_NM2093
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128ZV"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128ZV"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2097
:
case
FB_ACCEL_NEOMAGIC_NM2097
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128ZV+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128ZV+"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2160
:
case
FB_ACCEL_NEOMAGIC_NM2160
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 128XD"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 128XD"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2200
:
case
FB_ACCEL_NEOMAGIC_NM2200
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256AV"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256AV"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2230
:
case
FB_ACCEL_NEOMAGIC_NM2230
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256AV+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256AV+"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2360
:
case
FB_ACCEL_NEOMAGIC_NM2360
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256ZX"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256ZX"
);
break
;
break
;
case
FB_ACCEL_NEOMAGIC_NM2380
:
case
FB_ACCEL_NEOMAGIC_NM2380
:
sprintf
(
info
->
fb
.
fix
.
id
,
"MagicGraph 256XL+"
);
sprintf
(
info
->
fix
.
id
,
"MagicGraph 256XL+"
);
break
;
break
;
}
}
info
->
fb
.
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fb
.
fix
.
type_aux
=
0
;
info
->
fix
.
type_aux
=
0
;
info
->
fb
.
fix
.
xpanstep
=
0
;
info
->
fix
.
xpanstep
=
0
;
info
->
fb
.
fix
.
ypanstep
=
4
;
info
->
fix
.
ypanstep
=
4
;
info
->
fb
.
fix
.
ywrapstep
=
0
;
info
->
fix
.
ywrapstep
=
0
;
info
->
fb
.
fix
.
accel
=
id
->
driver_data
;
info
->
fix
.
accel
=
id
->
driver_data
;
info
->
fb
.
var
.
nonstd
=
0
;
info
->
var
.
nonstd
=
0
;
info
->
fb
.
var
.
activate
=
FB_ACTIVATE_NOW
;
info
->
var
.
activate
=
FB_ACTIVATE_NOW
;
info
->
fb
.
var
.
height
=
-
1
;
info
->
var
.
height
=
-
1
;
info
->
fb
.
var
.
width
=
-
1
;
info
->
var
.
width
=
-
1
;
info
->
fb
.
var
.
accel_flags
=
0
;
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
->
fbops
=
&
neofb_ops
;
info
->
fb
.
changevar
=
NULL
;
info
->
changevar
=
NULL
;
info
->
fb
.
switch_con
=
neofb_switch
;
info
->
switch_con
=
gen_switch
;
info
->
fb
.
updatevar
=
neofb_updatevar
;
info
->
updatevar
=
gen_update_var
;
info
->
fb
.
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
fb
.
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
par
=
par
;
info
->
fb
.
pseudo_palette
=
(
void
*
)(
info
->
fb
.
disp
+
1
);
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
;
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
* 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
;
u_int
h_sync
,
v_sync
;
int
err
;
int
err
;
int
video_len
;
int
video_len
;
DBG
(
"neofb_probe"
);
DBG
(
"neofb_probe"
);
err
=
pci_enable_device
(
dev
);
err
=
pci_enable_device
(
dev
);
if
(
err
)
if
(
err
)
return
err
;
return
err
;
err
=
-
ENOMEM
;
err
=
-
ENOMEM
;
info
=
neo_alloc_fb_info
(
dev
,
id
);
info
=
neo_alloc_fb_info
(
dev
,
id
);
if
(
!
info
)
if
(
!
info
)
goto
failed
;
goto
failed
;
err
=
neo_map_mmio
(
info
);
err
=
neo_map_mmio
(
info
,
dev
);
if
(
err
)
if
(
err
)
goto
failed
;
goto
failed
;
video_len
=
neo_init_hw
(
info
);
video_len
=
neo_init_hw
(
info
);
if
(
video_len
<
0
)
if
(
video_len
<
0
)
{
{
err
=
video_len
;
err
=
video_len
;
goto
failed
;
goto
failed
;
}
}
err
=
neo_map_video
(
info
,
video_len
);
err
=
neo_map_video
(
info
,
dev
,
video_len
);
if
(
err
)
if
(
err
)
goto
failed
;
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
* 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
...
@@ -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.
* the precision and fit the results into 32-bit registers.
* (1953125000 * 512 = 1e12)
* (1953125000 * 512 = 1e12)
*/
*/
h_sync
=
1953125000
/
info
->
fb
.
var
.
pixclock
;
h_sync
=
1953125000
/
info
->
var
.
pixclock
;
h_sync
=
h_sync
*
512
/
(
info
->
fb
.
var
.
xres
+
info
->
fb
.
var
.
left_margin
+
h_sync
=
info
->
fb
.
var
.
right_margin
+
info
->
fb
.
var
.
hsync_len
);
h_sync
*
512
/
(
info
->
var
.
xres
+
info
->
var
.
left_margin
+
v_sync
=
h_sync
/
(
info
->
fb
.
var
.
yres
+
info
->
fb
.
var
.
upper_margin
+
info
->
var
.
right_margin
+
info
->
var
.
hsync_len
);
info
->
fb
.
var
.
lower_margin
+
info
->
fb
.
var
.
vsync_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
"
,
printk
(
KERN_INFO
"neofb v"
NEOFB_VERSION
info
->
fb
.
fix
.
smem_len
>>
10
,
": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz
\n
"
,
info
->
fb
.
var
.
xres
,
info
->
fb
.
var
.
y
res
,
info
->
fix
.
smem_len
>>
10
,
info
->
var
.
x
res
,
h_sync
/
1000
,
h_sync
%
1000
,
v_sync
);
info
->
var
.
yres
,
h_sync
/
1000
,
h_sync
%
1000
,
v_sync
);
err
=
register_framebuffer
(
&
info
->
fb
);
err
=
register_framebuffer
(
info
);
if
(
err
<
0
)
if
(
err
<
0
)
goto
failed
;
goto
failed
;
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
GET_FB_IDX
(
info
->
fb
.
node
),
info
->
fb
.
modename
);
GET_FB_IDX
(
info
->
node
),
info
->
modename
);
/*
/*
* Our driver data
* Our driver data
...
@@ -2193,33 +1919,33 @@ static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_i
...
@@ -2193,33 +1919,33 @@ static int __devinit neofb_probe (struct pci_dev* dev, const struct pci_device_i
return
0
;
return
0
;
failed:
failed:
neo_unmap_video
(
info
);
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
neo_free_fb_info
(
info
);
return
err
;
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"
);
DBG
(
"neofb_remove"
);
if
(
info
)
if
(
info
)
{
{
/*
/*
* If unregister_framebuffer fails, then
* If unregister_framebuffer fails, then
* we will be leaving hooks that could cause
* we will be leaving hooks that could cause
* oopsen laying around.
* oopsen laying around.
*/
*/
if
(
unregister_framebuffer
(
&
info
->
fb
))
if
(
unregister_framebuffer
(
info
))
printk
(
KERN_WARNING
"neofb: danger danger! Oopsen imminent!
\n
"
);
printk
(
KERN_WARNING
"neofb: danger danger! Oopsen imminent!
\n
"
);
neo_unmap_video
(
info
);
neo_unmap_video
(
info
);
neo_unmap_mmio
(
info
);
neo_unmap_mmio
(
info
);
neo_free_fb_info
(
info
);
neo_free_fb_info
(
info
);
/*
/*
* Ensure that the driver data is no longer
* Ensure that the driver data is no longer
...
@@ -2271,18 +1997,18 @@ static struct pci_driver neofb_driver = {
...
@@ -2271,18 +1997,18 @@ static struct pci_driver neofb_driver = {
/* **************************** init-time only **************************** */
/* **************************** init-time only **************************** */
static
void
__init
neo_init
(
void
)
static
void
__init
neo_init
(
void
)
{
{
DBG
(
"neo_init"
);
DBG
(
"neo_init"
);
pci_register_driver
(
&
neofb_driver
);
pci_register_driver
(
&
neofb_driver
);
}
}
/* **************************** exit-time only **************************** */
/* **************************** exit-time only **************************** */
static
void
__exit
neo_done
(
void
)
static
void
__exit
neo_done
(
void
)
{
{
DBG
(
"neo_done"
);
DBG
(
"neo_done"
);
pci_unregister_driver
(
&
neofb_driver
);
pci_unregister_driver
(
&
neofb_driver
);
}
}
...
@@ -2290,7 +2016,7 @@ static void __exit neo_done (void)
...
@@ -2290,7 +2016,7 @@ static void __exit neo_done (void)
/* ************************* init in-kernel code ************************** */
/* ************************* init in-kernel code ************************** */
int
__init
neofb_setup
(
char
*
options
)
int
__init
neofb_setup
(
char
*
options
)
{
{
char
*
this_opt
;
char
*
this_opt
;
...
@@ -2299,9 +2025,9 @@ int __init neofb_setup (char *options)
...
@@ -2299,9 +2025,9 @@ int __init neofb_setup (char *options)
if
(
!
options
||
!*
options
)
if
(
!
options
||
!*
options
)
return
0
;
return
0
;
while
((
this_opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
while
((
this_opt
=
strsep
(
&
options
,
","
))
!=
NULL
)
{
{
if
(
!*
this_opt
)
if
(
!*
this_opt
)
continue
;
continue
;
if
(
!
strncmp
(
this_opt
,
"disabled"
,
8
))
if
(
!
strncmp
(
this_opt
,
"disabled"
,
8
))
disabled
=
1
;
disabled
=
1
;
...
@@ -2327,8 +2053,7 @@ int __init neofb_init(void)
...
@@ -2327,8 +2053,7 @@ int __init neofb_init(void)
if
(
disabled
)
if
(
disabled
)
return
-
ENXIO
;
return
-
ENXIO
;
if
(
!
initialized
)
if
(
!
initialized
)
{
{
initialized
=
1
;
initialized
=
1
;
neo_init
();
neo_init
();
}
}
...
...
drivers/video/tdfxfb.c
View file @
34dfe0cd
...
@@ -76,15 +76,6 @@
...
@@ -76,15 +76,6 @@
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/spinlock.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/tdfx.h>
#include <video/fbcon.h>
#include <video/fbcon.h>
...
@@ -92,17 +83,7 @@
...
@@ -92,17 +83,7 @@
#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
#define PCI_DEVICE_ID_3DFX_VOODOO5 0x0009
#endif
#endif
#define TDFXF_HSYNC_ACT_HIGH 0x01
#undef TDFXFB_DEBUG
#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
#ifdef TDFXFB_DEBUG
#ifdef TDFXFB_DEBUG
#define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
#define DPRINTK(a,b...) printk(KERN_DEBUG "fb: %s: " a, __FUNCTION__ , ## b)
#else
#else
...
@@ -113,230 +94,115 @@
...
@@ -113,230 +94,115 @@
#define VOODOO3_MAX_PIXCLOCK 300000.0
#define VOODOO3_MAX_PIXCLOCK 300000.0
#define VOODOO5_MAX_PIXCLOCK 350000.0
#define VOODOO5_MAX_PIXCLOCK 350000.0
struct
tdfxfb_par
{
static
struct
fb_fix_screeninfo
tdfx_fix
__initdata
=
{
u32
pixclock
;
id:
"3Dfx"
,
type:
FB_TYPE_PACKED_PIXELS
,
u32
baseline
;
visual:
FB_VISUAL_PSEUDOCOLOR
,
ypanstep:
1
,
u32
width
;
ywrapstep:
1
,
u32
height
;
accel:
FB_ACCEL_3DFX_BANSHEE
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
;
};
};
struct
fb_info_tdfx
{
static
struct
fb_var_screeninfo
tdfx_var
__initdata
=
{
struct
fb_info
fb_info
;
/* "640x480, 8 bpp @ 60 Hz */
xres:
640
,
u16
dev
;
yres:
480
,
u32
max_pixclock
;
xres_virtual:
640
,
yres_virtual:
1024
,
unsigned
long
regbase_phys
;
bits_per_pixel:
8
,
void
*
regbase_virt
;
red:
{
0
,
8
,
0
},
unsigned
long
regbase_size
;
blue:
{
0
,
8
,
0
},
unsigned
long
bufbase_phys
;
green:
{
0
,
8
,
0
},
void
*
bufbase_virt
;
activate:
FB_ACTIVATE_NOW
,
unsigned
long
bufbase_size
;
height:
-
1
,
unsigned
long
iobase
;
width:
-
1
,
accel_flags:
FB_ACCELF_TEXT
,
struct
{
pixclock:
39722
,
unsigned
red
,
green
,
blue
,
pad
;
left_margin:
40
,
}
palette
[
256
];
right_margin:
24
,
struct
tdfxfb_par
default_par
;
upper_margin:
32
,
struct
tdfxfb_par
current_par
;
lower_margin:
11
,
struct
display
disp
;
hsync_len:
96
,
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)
vsync_len:
2
,
union
{
vmode:
FB_VMODE_NONINTERLACED
#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
};
};
/*
* 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
* PCI driver prototypes
*/
*/
static
int
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
static
int
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
);
const
struct
pci_device_id
*
id
);
static
void
tdfxfb_remove
(
struct
pci_dev
*
pdev
);
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
=
{
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
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO3
,
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO3
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
0xff0000
,
0
},
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO5
,
{
PCI_VENDOR_ID_3DFX
,
PCI_DEVICE_ID_3DFX_VOODOO5
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
PCI_ANY_ID
,
PCI_ANY_ID
,
PCI_BASE_CLASS_DISPLAY
<<
16
,
0xff0000
,
0
},
0xff0000
,
0
},
{
0
,
}
{
0
,
}
};
};
static
struct
pci_driver
tdfxfb_driver
=
{
static
struct
pci_driver
tdfxfb_driver
=
{
name:
"tdfxfb"
,
name:
"tdfxfb"
,
id_table:
tdfxfb_id_table
,
id_table:
tdfxfb_id_table
,
probe:
tdfxfb_probe
,
probe:
tdfxfb_probe
,
remove:
__devexit_p
(
tdfxfb_remove
)
,
remove:
tdfxfb_remove
,
};
};
MODULE_DEVICE_TABLE
(
pci
,
tdfxfb_id_table
);
MODULE_DEVICE_TABLE
(
pci
,
tdfxfb_id_table
);
struct
mode
{
/*
char
*
name
;
* Frame buffer device API
struct
fb_var_screeninfo
var
;
*/
}
mode
;
int
tdfxfb_init
(
void
);
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
);
/* 2.3.x kernels have a fb mode database, so supply only one backup default */
struct
mode
default_mode
[]
=
{
static
int
tdfxfb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
fb
);
{
"640x480-8@60"
,
/* @ 60 Hz */
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
,
640
,
480
,
640
,
1024
,
0
,
0
,
8
,
0
,
u_int
transp
,
struct
fb_info
*
info
);
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
0
,
0
},
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
info
);
0
,
FB_ACTIVATE_NOW
,
-
1
,
-
1
,
FB_ACCELF_TEXT
,
static
int
tdfxfb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
);
39722
,
40
,
24
,
32
,
11
,
96
,
2
,
static
void
tdfxfb_fillrect
(
struct
fb_info
*
info
,
struct
fb_fillrect
*
rect
);
0
,
FB_VMODE_NONINTERLACED
}
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
nopan
=
0
;
static
int
nowrap
=
1
;
// not implemented (yet)
static
int
nowrap
=
1
;
// not implemented (yet)
static
int
inverse
=
0
;
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
;
static
char
*
mode_option
__initdata
=
NULL
;
/* -------------------------------------------------------------------------
/* -------------------------------------------------------------------------
...
@@ -344,98 +210,62 @@ static char *mode_option __initdata = NULL;
...
@@ -344,98 +210,62 @@ static char *mode_option __initdata = NULL;
* ------------------------------------------------------------------------- */
* ------------------------------------------------------------------------- */
#ifdef VGA_REG_IO
#ifdef VGA_REG_IO
static
inline
u8
vga_inb
(
u32
reg
)
static
inline
u8
vga_inb
(
u32
reg
)
{
return
inb
(
reg
);
}
{
static
inline
u16
vga_inw
(
u32
reg
)
{
return
inw
(
reg
);
}
return
inb
(
reg
);
static
inline
u16
vga_inl
(
u32
reg
)
{
return
inl
(
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
)
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
outb
(
val
,
reg
);
}
{
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
outw
(
val
,
reg
);
}
outb
(
val
,
reg
);
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
outl
(
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
#else
static
inline
u8
vga_inb
(
u32
reg
)
static
inline
u8
vga_inb
(
u32
reg
)
{
{
return
inb
(
default_par
.
iobase
+
reg
-
0x300
);
return
inb
(
fb_info
.
iobase
+
reg
-
0x300
);
}
}
static
inline
u16
vga_inw
(
u32
reg
)
static
inline
u16
vga_inw
(
u32
reg
)
{
{
return
inw
(
default_par
.
iobase
+
reg
-
0x300
);
return
inw
(
fb_info
.
iobase
+
reg
-
0x300
);
}
}
static
inline
u16
vga_inl
(
u32
reg
)
static
inline
u16
vga_inl
(
u32
reg
)
{
{
return
inl
(
default_par
.
iobase
+
reg
-
0x300
);
return
inl
(
fb_info
.
iobase
+
reg
-
0x300
);
}
}
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
{
static
inline
void
vga_outb
(
u32
reg
,
u8
val
)
outb
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
{
outb
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
}
}
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
static
inline
void
vga_outw
(
u32
reg
,
u16
val
)
{
{
outw
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
outw
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
}
}
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
static
inline
void
vga_outl
(
u32
reg
,
u32
val
)
{
{
outl
(
val
,
default_par
.
iobase
+
reg
-
0x300
);
outl
(
val
,
fb_info
.
iobase
+
reg
-
0x300
);
}
}
#endif
#endif
static
inline
void
gra_outb
(
u32
idx
,
u8
val
)
static
inline
void
gra_outb
(
u32
idx
,
u8
val
)
{
{
vga_outb
(
GRA_I
,
idx
);
vga_outb
(
GRA_D
,
val
);
vga_outb
(
GRA_I
,
idx
);
vga_outb
(
GRA_D
,
val
);
}
}
static
inline
u8
gra_inb
(
u32
idx
)
static
inline
u8
gra_inb
(
u32
idx
)
{
{
vga_outb
(
GRA_I
,
idx
);
return
vga_inb
(
GRA_D
);
vga_outb
(
GRA_I
,
idx
);
return
vga_inb
(
GRA_D
);
}
}
static
inline
void
seq_outb
(
u32
idx
,
u8
val
)
static
inline
void
seq_outb
(
u32
idx
,
u8
val
)
{
{
vga_outb
(
SEQ_I
,
idx
);
vga_outb
(
SEQ_D
,
val
);
vga_outb
(
SEQ_I
,
idx
);
vga_outb
(
SEQ_D
,
val
);
}
}
static
inline
u8
seq_inb
(
u32
idx
)
static
inline
u8
seq_inb
(
u32
idx
)
{
{
vga_outb
(
SEQ_I
,
idx
);
return
vga_inb
(
SEQ_D
);
vga_outb
(
SEQ_I
,
idx
);
return
vga_inb
(
SEQ_D
);
}
}
static
inline
void
crt_outb
(
u32
idx
,
u8
val
)
static
inline
void
crt_outb
(
u32
idx
,
u8
val
)
{
{
vga_outb
(
CRT_I
,
idx
);
vga_outb
(
CRT_D
,
val
);
vga_outb
(
CRT_I
,
idx
);
vga_outb
(
CRT_D
,
val
);
}
}
static
inline
u8
crt_inb
(
u32
idx
)
static
inline
u8
crt_inb
(
u32
idx
)
{
{
vga_outb
(
CRT_I
,
idx
);
return
vga_inb
(
CRT_D
);
vga_outb
(
CRT_I
,
idx
);
return
vga_inb
(
CRT_D
);
}
}
static
inline
void
att_outb
(
u32
idx
,
u8
val
)
static
inline
void
att_outb
(
u32
idx
,
u8
val
)
{
{
unsigned
char
tmp
;
unsigned
char
tmp
;
tmp
=
vga_inb
(
IS1_R
);
tmp
=
vga_inb
(
IS1_R
);
vga_outb
(
ATT_IW
,
idx
);
vga_outb
(
ATT_IW
,
idx
);
vga_outb
(
ATT_IW
,
val
);
vga_outb
(
ATT_IW
,
val
);
...
@@ -444,6 +274,7 @@ static inline void att_outb(u32 idx, u8 val)
...
@@ -444,6 +274,7 @@ static inline void att_outb(u32 idx, u8 val)
static
inline
u8
att_inb
(
u32
idx
)
static
inline
u8
att_inb
(
u32
idx
)
{
{
unsigned
char
tmp
;
unsigned
char
tmp
;
tmp
=
vga_inb
(
IS1_R
);
tmp
=
vga_inb
(
IS1_R
);
vga_outb
(
ATT_IW
,
idx
);
vga_outb
(
ATT_IW
,
idx
);
return
vga_inb
(
ATT_IW
);
return
vga_inb
(
ATT_IW
);
...
@@ -452,6 +283,7 @@ static inline u8 att_inb(u32 idx)
...
@@ -452,6 +283,7 @@ static inline u8 att_inb(u32 idx)
static
inline
void
vga_disable_video
(
void
)
static
inline
void
vga_disable_video
(
void
)
{
{
unsigned
char
s
;
unsigned
char
s
;
s
=
seq_inb
(
0x01
)
|
0x20
;
s
=
seq_inb
(
0x01
)
|
0x20
;
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x01
,
s
);
seq_outb
(
0x01
,
s
);
...
@@ -461,6 +293,7 @@ static inline void vga_disable_video(void)
...
@@ -461,6 +293,7 @@ static inline void vga_disable_video(void)
static
inline
void
vga_enable_video
(
void
)
static
inline
void
vga_enable_video
(
void
)
{
{
unsigned
char
s
;
unsigned
char
s
;
s
=
seq_inb
(
0x01
)
&
0xdf
;
s
=
seq_inb
(
0x01
)
&
0xdf
;
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x00
,
0x01
);
seq_outb
(
0x01
,
s
);
seq_outb
(
0x01
,
s
);
...
@@ -481,17 +314,17 @@ static inline void vga_enable_palette(void)
...
@@ -481,17 +314,17 @@ static inline void vga_enable_palette(void)
static
inline
u32
tdfx_inl
(
unsigned
int
reg
)
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
)
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
)
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
)
static
inline
void
banshee_wait_idle
(
void
)
...
@@ -501,10 +334,9 @@ static inline void banshee_wait_idle(void)
...
@@ -501,10 +334,9 @@ static inline void banshee_wait_idle(void)
banshee_make_room
(
1
);
banshee_make_room
(
1
);
tdfx_outl
(
COMMAND_3D
,
COMMAND_3D_NOP
);
tdfx_outl
(
COMMAND_3D
,
COMMAND_3D_NOP
);
while
(
1
)
{
while
(
1
)
{
i
=
(
tdfx_inl
(
STATUS
)
&
STATUS_BUSY
)
?
0
:
i
+
1
;
i
=
(
tdfx_inl
(
STATUS
)
&
STATUS_BUSY
)
?
0
:
i
+
1
;
if
(
i
==
3
)
if
(
i
==
3
)
break
;
break
;
}
}
}
}
...
@@ -518,239 +350,7 @@ static inline void do_setpalentry(unsigned regno, u32 c)
...
@@ -518,239 +350,7 @@ static inline void do_setpalentry(unsigned regno, u32 c)
tdfx_outl
(
DACDATA
,
c
);
tdfx_outl
(
DACDATA
,
c
);
}
}
/*
static
u32
do_calc_pll
(
int
freq
,
int
*
freq_out
)
* 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
)
{
{
int
m
,
n
,
k
,
best_m
,
best_n
,
best_k
,
f_cur
,
best_error
;
int
m
,
n
,
k
,
best_m
,
best_n
,
best_k
,
f_cur
,
best_error
;
int
fref
=
14318
;
int
fref
=
14318
;
...
@@ -762,10 +362,9 @@ static u32 do_calc_pll(int freq, int *freq_out)
...
@@ -762,10 +362,9 @@ static u32 do_calc_pll(int freq, int *freq_out)
for
(
n
=
1
;
n
<
256
;
n
++
)
{
for
(
n
=
1
;
n
<
256
;
n
++
)
{
for
(
m
=
1
;
m
<
64
;
m
++
)
{
for
(
m
=
1
;
m
<
64
;
m
++
)
{
for
(
k
=
0
;
k
<
4
;
k
++
)
{
for
(
k
=
0
;
k
<
4
;
k
++
)
{
f_cur
=
f_cur
=
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
fref
*
(
n
+
2
)
/
(
m
+
2
)
/
(
1
<<
k
);
if
(
abs
(
f_cur
-
freq
)
<
best_error
)
{
if
(
abs
(
f_cur
-
freq
)
<
best_error
)
{
best_error
=
abs
(
f_cur
-
freq
);
best_error
=
abs
(
f_cur
-
freq
);
best_n
=
n
;
best_n
=
n
;
best_m
=
m
;
best_m
=
m
;
best_k
=
k
;
best_k
=
k
;
...
@@ -776,12 +375,11 @@ static u32 do_calc_pll(int freq, int *freq_out)
...
@@ -776,12 +375,11 @@ static u32 do_calc_pll(int freq, int *freq_out)
n
=
best_n
;
n
=
best_n
;
m
=
best_m
;
m
=
best_m
;
k
=
best_k
;
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
;
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
;
int
i
;
...
@@ -824,16 +422,9 @@ static void do_write_regs(struct banshee_reg *reg)
...
@@ -824,16 +422,9 @@ static void do_write_regs(struct banshee_reg *reg)
tdfx_outl
(
VGAINIT0
,
reg
->
vgainit0
);
tdfx_outl
(
VGAINIT0
,
reg
->
vgainit0
);
tdfx_outl
(
DACMODE
,
reg
->
dacmode
);
tdfx_outl
(
DACMODE
,
reg
->
dacmode
);
tdfx_outl
(
VIDDESKSTRIDE
,
reg
->
stride
);
tdfx_outl
(
VIDDESKSTRIDE
,
reg
->
stride
);
if
(
nohwcursor
)
{
tdfx_outl
(
HWCURPATADDR
,
0
);
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
(
VIDDESKSTART
,
reg
->
startaddr
);
tdfx_outl
(
VIDPROCCFG
,
reg
->
vidcfg
);
tdfx_outl
(
VIDPROCCFG
,
reg
->
vidcfg
);
tdfx_outl
(
VGAINIT1
,
reg
->
vgainit1
);
tdfx_outl
(
VGAINIT1
,
reg
->
vgainit1
);
...
@@ -852,7 +443,7 @@ static void do_write_regs(struct banshee_reg *reg)
...
@@ -852,7 +443,7 @@ static void do_write_regs(struct banshee_reg *reg)
banshee_wait_idle
();
banshee_wait_idle
();
}
}
static
unsigned
long
do_lfb_size
(
void
)
static
unsigned
long
do_lfb_size
(
unsigned
short
dev_id
)
{
{
u32
draminit0
=
0
;
u32
draminit0
=
0
;
u32
draminit1
=
0
;
u32
draminit1
=
0
;
...
@@ -863,14 +454,14 @@ static unsigned long do_lfb_size(void)
...
@@ -863,14 +454,14 @@ static unsigned long do_lfb_size(void)
draminit0
=
tdfx_inl
(
DRAMINIT0
);
draminit0
=
tdfx_inl
(
DRAMINIT0
);
draminit1
=
tdfx_inl
(
DRAMINIT1
);
draminit1
=
tdfx_inl
(
DRAMINIT1
);
if
((
fb_info
.
dev
==
PCI_DEVICE_ID_3DFX_BANSHEE
)
||
if
((
dev_id
==
PCI_DEVICE_ID_3DFX_BANSHEE
)
||
(
fb_info
.
dev
==
PCI_DEVICE_ID_3DFX_VOODOO3
))
{
(
dev_id
==
PCI_DEVICE_ID_3DFX_VOODOO3
))
{
sgram_p
=
(
draminit1
&
DRAMINIT1_MEM_SDRAM
)
?
0
:
1
;
sgram_p
=
(
draminit1
&
DRAMINIT1_MEM_SDRAM
)
?
0
:
1
;
lfbsize
=
sgram_p
?
lfbsize
=
sgram_p
?
(((
draminit0
&
DRAMINIT0_SGRAM_NUM
)
?
2
:
1
)
*
(((
draminit0
&
DRAMINIT0_SGRAM_NUM
)
?
2
:
1
)
*
((
draminit0
&
DRAMINIT0_SGRAM_TYPE
)
?
8
:
4
)
*
1024
*
((
draminit0
&
DRAMINIT0_SGRAM_TYPE
)
?
8
:
4
)
*
1024
*
1024
)
:
1024
)
:
16
*
1024
*
1024
;
16
*
1024
*
1024
;
}
else
{
}
else
{
/* Voodoo4/5 */
/* Voodoo4/5 */
u32
chips
,
psize
,
banks
;
u32
chips
,
psize
,
banks
;
...
@@ -881,7 +472,6 @@ static unsigned long do_lfb_size(void)
...
@@ -881,7 +472,6 @@ static unsigned long do_lfb_size(void)
lfbsize
=
chips
*
psize
*
banks
;
lfbsize
=
chips
*
psize
*
banks
;
lfbsize
<<=
20
;
lfbsize
<<=
20
;
}
}
/* disable block writes for SDRAM (why?) */
/* disable block writes for SDRAM (why?) */
miscinit1
=
tdfx_inl
(
MISCINIT1
);
miscinit1
=
tdfx_inl
(
MISCINIT1
);
miscinit1
|=
sgram_p
?
0
:
MISCINIT1_2DBLOCK_DIS
;
miscinit1
|=
sgram_p
?
0
:
MISCINIT1_2DBLOCK_DIS
;
...
@@ -889,306 +479,155 @@ static unsigned long do_lfb_size(void)
...
@@ -889,306 +479,155 @@ static unsigned long do_lfb_size(void)
banshee_make_room
(
1
);
banshee_make_room
(
1
);
tdfx_outl
(
MISCINIT1
,
miscinit1
);
tdfx_outl
(
MISCINIT1
,
miscinit1
);
return
lfbsize
;
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
,
static
int
tdfxfb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
struct
display
*
p
,
int
bottom_only
)
{
{
unsigned
int
cw
=
fontwidth
(
p
);
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
unsigned
int
ch
=
fontheight
(
p
);
u32
lpitch
;
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
);
}
if
(
bh
)
{
if
(
var
->
bits_per_pixel
!=
8
&&
var
->
bits_per_pixel
!=
16
&&
do_fillrect
(
p
->
var
.
xoffset
,
p
->
var
.
yoffset
+
bs
,
var
->
bits_per_pixel
!=
24
&&
var
->
bits_per_pixel
!=
32
)
{
rs
,
bh
,
0
,
DPRINTK
(
"depth not supported: %u
\n
"
,
var
->
bits_per_pixel
);
fb_info
.
current_par
.
lpitch
,
return
-
EINVAL
;
fb_info
.
current_par
.
bpp
,
TDFX_ROP_COPY
);
}
}
}
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
,
if
(
var
->
xres
!=
var
->
xres_virtual
)
{
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
DPRINTK
(
"virtual x resolution != physical x resolution not supported
\n
"
);
{
return
-
EINVAL
;
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
);
}
static
void
tdfx_cfb32_putc
(
struct
vc_data
*
conp
,
if
(
var
->
yres
>
var
->
yres_virtual
)
{
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
DPRINTK
(
"virtual y resolution < physical y resolution not possible
\n
"
);
{
return
-
EINVAL
;
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
);
}
static
void
tdfx_cfb8_clear
(
struct
vc_data
*
conp
,
if
(
var
->
xoffset
)
{
struct
display
*
p
,
DPRINTK
(
"xoffset not supported
\n
"
);
int
sy
,
int
sx
,
int
height
,
int
width
)
return
-
EINVAL
;
{
}
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
);
}
static
void
tdfx_cfb16_clear
(
struct
vc_data
*
conp
,
/* fixme: does Voodoo3 support interlace? Banshee doesn't */
struct
display
*
p
,
if
((
var
->
vmode
&
FB_VMODE_MASK
)
==
FB_VMODE_INTERLACED
)
{
int
sy
,
int
sx
,
int
height
,
int
width
)
DPRINTK
(
"interlace not supported
\n
"
);
{
return
-
EINVAL
;
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
);
}
static
void
tdfx_cfb32_clear
(
struct
vc_data
*
conp
,
var
->
xres
=
(
var
->
xres
+
15
)
&
~
15
;
/* could sometimes be 8 */
struct
display
*
p
,
lpitch
=
var
->
xres
*
((
var
->
bits_per_pixel
+
7
)
>>
3
);
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
;
do_fillrect
(
xx
*
fontwidth
(
p
),
yy
*
fontheight
(
p
),
if
(
var
->
xres
<
320
||
var
->
xres
>
2048
)
{
fontwidth
(
p
),
fontheight
(
p
),
DPRINTK
(
"width not supported: %u
\n
"
,
var
->
xres
);
(
bpp
==
8
)
?
0x0f
:
0xffffffff
,
return
-
EINVAL
;
fb_info
.
current_par
.
lpitch
,
bpp
,
TDFX_ROP_XOR
);
}
}
if
(
var
->
yres
<
200
||
var
->
yres
>
2048
)
{
static
void
tdfx_cfbX_cursor
(
struct
display
*
p
,
int
mode
,
int
x
,
int
y
)
DPRINTK
(
"height not supported: %u
\n
"
,
var
->
yres
);
{
return
-
EINVAL
;
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
);
}
}
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
);
if
(
PICOS2KHZ
(
var
->
pixclock
)
>
par
->
max_pixclock
)
{
x
*=
fontwidth
(
p
);
DPRINTK
(
"pixclock too high (%ldKHz)
\n
"
,
PICOS2KHZ
(
var
->
pixclock
));
y
*=
fontheight
(
p
);
return
-
EINVAL
;
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
);
}
}
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
switch
(
var
->
bits_per_pixel
)
{
static
struct
display_switch
fbcon_banshee8
=
{
case
8
:
setup:
fbcon_cfb8_setup
,
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
bmove:
tdfx_cfbX_bmove
,
break
;
clear:
tdfx_cfb8_clear
,
case
16
:
putc:
tdfx_cfb8_putc
,
var
->
red
.
offset
=
11
;
putcs:
tdfx_cfb8_putcs
,
var
->
red
.
length
=
5
;
revc:
tdfx_cfbX_revc
,
var
->
green
.
offset
=
5
;
cursor:
tdfx_cfbX_cursor
,
var
->
green
.
length
=
6
;
clear_margins:
tdfx_cfbX_clear_margins
,
var
->
blue
.
offset
=
0
;
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
var
->
blue
.
length
=
5
;
};
break
;
#endif
case
24
:
#ifdef FBCON_HAS_CFB16
var
->
red
.
offset
=
16
;
static
struct
display_switch
fbcon_banshee16
=
{
var
->
green
.
offset
=
8
;
setup:
fbcon_cfb16_setup
,
var
->
blue
.
offset
=
0
;
bmove:
tdfx_cfbX_bmove
,
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
clear:
tdfx_cfb16_clear
,
case
32
:
putc:
tdfx_cfb16_putc
,
var
->
red
.
offset
=
16
;
putcs:
tdfx_cfb16_putcs
,
var
->
green
.
offset
=
8
;
revc:
tdfx_cfbX_revc
,
var
->
blue
.
offset
=
0
;
cursor:
tdfx_cfbX_cursor
,
var
->
red
.
length
=
var
->
green
.
length
=
var
->
blue
.
length
=
8
;
clear_margins:
tdfx_cfbX_clear_margins
,
break
;
fontwidthmask:
FONTWIDTHRANGE
(
8
,
12
)
}
};
var
->
height
=
var
->
width
=
-
1
;
#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
/* ------------------------------------------------------------------------- */
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
,
static
int
tdfxfb_set_par
(
struct
fb_info
*
info
)
struct
fb_info_tdfx
*
info
)
{
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
info
;
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
struct
banshee_reg
reg
;
u32
hdispend
,
hsyncsta
,
hsyncend
,
htotal
;
u32
cpp
;
u32
hd
,
hs
,
he
,
ht
,
hbs
,
hbe
;
u32
hd
,
hs
,
he
,
ht
,
hbs
,
hbe
;
u32
vd
,
vs
,
ve
,
vt
,
vbs
,
vbe
;
u32
vd
,
vs
,
ve
,
vt
,
vbs
,
vbe
;
u32
wd
;
struct
banshee_reg
reg
;
int
fout
;
int
fout
,
freq
;
int
freq
;
u32
wd
,
cpp
;
info
->
cmap
.
len
=
(
info
->
var
.
bits_per_pixel
==
8
)
?
256
:
16
;
par
->
baseline
=
0
;
memset
(
&
reg
,
0
,
sizeof
(
reg
));
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
;
hd
=
wd
=
(
hdispend
>>
3
)
-
1
;
hs
=
(
par
->
hsyncsta
>>
3
)
-
1
;
hs
=
(
hsyncsta
>>
3
)
-
1
;
he
=
(
par
->
hsyncend
>>
3
)
-
1
;
he
=
(
hsyncend
>>
3
)
-
1
;
ht
=
(
par
->
htotal
>>
3
)
-
1
;
ht
=
(
htotal
>>
3
)
-
1
;
hbs
=
hd
;
hbs
=
hd
;
hbe
=
ht
;
hbe
=
ht
;
vd
=
par
->
vdispend
-
1
;
vbs
=
vd
=
info
->
var
.
yres
-
1
;
vs
=
par
->
vsyncsta
-
1
;
vs
=
vd
+
info
->
var
.
lower_margin
;
ve
=
par
->
vsyncend
-
1
;
ve
=
vs
+
info
->
var
.
vsync_len
;
vt
=
par
->
vtotal
-
2
;
vbe
=
vt
=
ve
+
info
->
var
.
upper_margin
-
1
;
vbs
=
vd
;
vbe
=
vt
;
/* this is all pretty standard VGA register stuffing */
/* this is all pretty standard VGA register stuffing */
reg
.
misc
[
0x00
]
=
reg
.
misc
[
0x00
]
=
0x0f
|
0x0f
|
(
info
->
var
.
xres
<
400
?
0xa0
:
(
par
->
hdispend
<
400
?
0xa0
:
info
->
var
.
xres
<
480
?
0x60
:
par
->
hdispend
<
480
?
0x60
:
info
->
var
.
xres
<
768
?
0xe0
:
0x20
);
par
->
hdispend
<
768
?
0xe0
:
0x20
);
reg
.
gra
[
0x00
]
=
0x00
;
reg
.
gra
[
0x00
]
=
0x00
;
reg
.
gra
[
0x01
]
=
0x00
;
reg
.
gra
[
0x01
]
=
0x00
;
...
@@ -1235,14 +674,13 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
...
@@ -1235,14 +674,13 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg
.
crt
[
0x04
]
=
hs
;
reg
.
crt
[
0x04
]
=
hs
;
reg
.
crt
[
0x05
]
=
((
hbe
&
0x20
)
<<
2
)
|
(
he
&
0x1f
);
reg
.
crt
[
0x05
]
=
((
hbe
&
0x20
)
<<
2
)
|
(
he
&
0x1f
);
reg
.
crt
[
0x06
]
=
vt
;
reg
.
crt
[
0x06
]
=
vt
;
reg
.
crt
[
0x07
]
=
reg
.
crt
[
0x07
]
=
((
vs
&
0x200
)
>>
2
)
|
((
vs
&
0x200
)
>>
2
)
|
((
vd
&
0x200
)
>>
3
)
|
((
vd
&
0x200
)
>>
3
)
|
((
vt
&
0x200
)
>>
4
)
|
((
vt
&
0x200
)
>>
4
)
|
0x10
|
0x10
|
((
vbs
&
0x100
)
>>
5
)
|
((
vbs
&
0x100
)
>>
5
)
|
((
vs
&
0x100
)
>>
6
)
|
((
vs
&
0x100
)
>>
6
)
|
((
vd
&
0x100
)
>>
7
)
|
((
vt
&
0x100
)
>>
8
);
((
vd
&
0x100
)
>>
7
)
|
((
vt
&
0x100
)
>>
8
);
reg
.
crt
[
0x08
]
=
0x00
;
reg
.
crt
[
0x08
]
=
0x00
;
reg
.
crt
[
0x09
]
=
0x40
|
((
vbs
&
0x200
)
>>
4
);
reg
.
crt
[
0x09
]
=
0x40
|
((
vbs
&
0x200
)
>>
4
);
reg
.
crt
[
0x0a
]
=
0x00
;
reg
.
crt
[
0x0a
]
=
0x00
;
...
@@ -1266,47 +704,37 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
...
@@ -1266,47 +704,37 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
((
hd
&
0x100
)
>>
6
)
|
((
hd
&
0x100
)
>>
6
)
|
((
hbs
&
0x100
)
>>
4
)
|
((
hbs
&
0x100
)
>>
4
)
|
((
hbe
&
0x40
)
>>
1
)
|
((
hbe
&
0x40
)
>>
1
)
|
((
hs
&
0x100
)
>>
2
)
|
((
he
&
0x20
)
<<
2
));
((
hs
&
0x100
)
>>
2
)
|
((
he
&
0x20
)
<<
2
));
reg
.
ext
[
0x01
]
=
(((
vt
&
0x400
)
>>
10
)
|
reg
.
ext
[
0x01
]
=
(((
vt
&
0x400
)
>>
10
)
|
((
vd
&
0x400
)
>>
8
)
|
((
vd
&
0x400
)
>>
8
)
|
((
vbs
&
0x400
)
>>
6
)
|
((
vbe
&
0x400
)
>>
4
));
((
vbs
&
0x400
)
>>
6
)
|
((
vbe
&
0x400
)
>>
4
));
reg
.
vgainit0
=
reg
.
vgainit0
=
VGAINIT0_8BIT_DAC
|
VGAINIT0_8BIT_DAC
|
VGAINIT0_EXT_ENABLE
|
VGAINIT0_EXT_ENABLE
|
VGAINIT0_WAKEUP_3C3
|
VGAINIT0_WAKEUP_3C3
|
VGAINIT0_ALT_READBACK
|
VGAINIT0_EXTSHIFTOUT
;
VGAINIT0_ALT_READBACK
|
VGAINIT0_EXTSHIFTOUT
;
reg
.
vgainit1
=
tdfx_inl
(
VGAINIT1
)
&
0x1fffff
;
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
.
cursloc
=
0
;
reg
.
cursc0
=
0
;
reg
.
cursc0
=
0
;
reg
.
cursc1
=
0xffffff
;
reg
.
cursc1
=
0xffffff
;
reg
.
curspataddr
=
fb_info
.
cursor
.
cursorimage
;
reg
.
stride
=
info
->
var
.
xres
*
cpp
;
reg
.
startaddr
=
par
->
baseline
*
reg
.
stride
;
reg
.
startaddr
=
par
->
baseline
*
reg
.
stride
;
reg
.
srcbase
=
reg
.
startaddr
;
reg
.
srcbase
=
reg
.
startaddr
;
reg
.
dstbase
=
reg
.
startaddr
;
reg
.
dstbase
=
reg
.
startaddr
;
/* PLL settings */
/* PLL settings */
freq
=
par
->
pixclock
;
freq
=
PICOS2KHZ
(
info
->
var
.
pixclock
)
;
reg
.
dacmode
&=
~
DACMODE_2X
;
reg
.
dacmode
&=
~
DACMODE_2X
;
reg
.
vidcfg
&=
~
VIDCFG_2X
;
reg
.
vidcfg
&=
~
VIDCFG_2X
;
if
(
freq
>
i
->
max_pixclock
/
2
)
{
if
(
freq
>
par
->
max_pixclock
/
2
)
{
freq
=
freq
>
i
->
max_pixclock
?
i
->
max_pixclock
:
freq
;
freq
=
freq
>
par
->
max_pixclock
?
par
->
max_pixclock
:
freq
;
reg
.
dacmode
|=
DACMODE_2X
;
reg
.
dacmode
|=
DACMODE_2X
;
reg
.
vidcfg
|=
VIDCFG_2X
;
reg
.
vidcfg
|=
VIDCFG_2X
;
}
}
...
@@ -1316,13 +744,12 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
...
@@ -1316,13 +744,12 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
reg.gfxpll = do_calc_pll(..., &fout);
reg.gfxpll = do_calc_pll(..., &fout);
#endif
#endif
reg
.
screensize
=
par
->
width
|
(
par
->
height
<<
12
);
reg
.
screensize
=
info
->
var
.
xres
|
(
info
->
var
.
yres
<<
12
);
reg
.
vidcfg
&=
~
VIDCFG_HALF_MODE
;
reg
.
vidcfg
&=
~
VIDCFG_HALF_MODE
;
reg
.
miscinit0
=
tdfx_inl
(
MISCINIT0
);
reg
.
miscinit0
=
tdfx_inl
(
MISCINIT0
);
#if defined(__BIG_ENDIAN)
#if defined(__BIG_ENDIAN)
switch
(
par
->
bpp
)
{
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
case
8
:
reg
.
miscinit0
&=
~
(
1
<<
30
);
reg
.
miscinit0
&=
~
(
1
<<
30
);
reg
.
miscinit0
&=
~
(
1
<<
31
);
reg
.
miscinit0
&=
~
(
1
<<
31
);
...
@@ -1338,431 +765,211 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
...
@@ -1338,431 +765,211 @@ static void tdfxfb_set_par(const struct tdfxfb_par *par,
break
;
break
;
}
}
#endif
#endif
do_write_regs
(
&
reg
);
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
,
static
int
tdfxfb_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
struct
tdfxfb_par
*
par
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
const
struct
fb_info_tdfx
*
info
)
{
{
struct
fb_info_tdfx
*
i
=
(
struct
fb_info_tdfx
*
)
info
;
u32
rgbcol
;
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
;
return
0
;
if
(
regno
>=
info
->
cmap
.
len
)
return
1
;
}
static
int
tdfxfb_encode_var
(
struct
fb_var_screeninfo
*
var
,
switch
(
info
->
fix
.
visual
)
{
const
struct
tdfxfb_par
*
par
,
case
FB_VISUAL_PSEUDOCOLOR
:
const
struct
fb_info_tdfx
*
info
)
rgbcol
=
(((
u32
)
red
&
0xff00
)
<<
8
)
|
{
(((
u32
)
green
&
0xff00
)
<<
0
)
|
struct
fb_var_screeninfo
v
;
(((
u32
)
blue
&
0xff00
)
>>
8
);
do_setpalentry
(
regno
,
rgbcol
);
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
;
break
;
break
;
case
16
:
/* Truecolor has no hardware color palettes. */
v
.
red
.
offset
=
11
;
case
FB_VISUAL_TRUECOLOR
:
v
.
red
.
length
=
5
;
rgbcol
=
(
red
<<
info
->
var
.
red
.
offset
)
|
v
.
green
.
offset
=
5
;
(
green
<<
info
->
var
.
green
.
offset
)
|
v
.
green
.
length
=
6
;
(
blue
<<
info
->
var
.
blue
.
offset
)
|
v
.
blue
.
offset
=
0
;
(
transp
<<
info
->
var
.
transp
.
offset
);
v
.
blue
.
length
=
5
;
if
(
info
->
var
.
bits_per_pixel
<=
16
)
((
u16
*
)(
info
->
pseudo_palette
))[
regno
]
=
rgbcol
;
else
((
u32
*
)(
info
->
pseudo_palette
))[
regno
]
=
rgbcol
;
break
;
break
;
case
24
:
default:
v
.
red
.
offset
=
16
;
DPRINTK
(
"bad depth %u
\n
"
,
info
->
var
.
bits_per_pixel
);
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
;
break
;
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
;
return
0
;
}
}
static
int
tdfxfb_encode_fix
(
struct
fb_fix_screeninfo
*
fix
,
/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */
const
struct
tdfxfb_par
*
par
,
static
int
tdfxfb_blank
(
int
blank
,
struct
fb_info
*
info
)
const
struct
fb_info_tdfx
*
info
)
{
{
memset
(
fix
,
0
,
sizeof
(
struct
fb_fix_screeninfo
))
;
u32
dacmode
,
state
=
0
,
vgablank
=
0
;
switch
(
info
->
dev
)
{
dacmode
=
tdfx_inl
(
DACMODE
);
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
strcpy
(
fix
->
id
,
"3Dfx Banshee"
);
switch
(
blank
)
{
case
0
:
/* Screen: On; HSync: On, VSync: On */
state
=
0
;
vgablank
=
0
;
break
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
case
1
:
/* Screen: Off; HSync: On, VSync: On */
strcpy
(
fix
->
id
,
"3Dfx Voodoo3"
);
state
=
0
;
vgablank
=
1
;
break
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
case
2
:
/* Screen: Off; HSync: On, VSync: Off */
strcpy
(
fix
->
id
,
"3Dfx Voodoo5"
);
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
;
break
;
default:
return
-
EINVAL
;
}
}
fix
->
smem_start
=
info
->
bufbase_phys
;
dacmode
&=
~
(
BIT
(
1
)
|
BIT
(
3
));
fix
->
smem_len
=
info
->
bufbase_size
;
dacmode
|=
state
;
fix
->
mmio_start
=
info
->
regbase_phys
;
banshee_make_room
(
1
);
fix
->
mmio_len
=
info
->
regbase_size
;
tdfx_outl
(
DACMODE
,
dacmode
);
fix
->
accel
=
FB_ACCEL_3DFX_BANSHEE
;
if
(
vgablank
)
fix
->
type
=
FB_TYPE_PACKED_PIXELS
;
vga_disable_video
();
fix
->
type_aux
=
0
;
else
fix
->
line_length
=
par
->
lpitch
;
vga_enable_video
();
fix
->
visual
=
(
par
->
bpp
==
8
)
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_DIRECTCOLOR
;
fix
->
xpanstep
=
0
;
fix
->
ypanstep
=
nopan
?
0
:
1
;
fix
->
ywrapstep
=
nowrap
?
0
:
1
;
return
0
;
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
;
u32
addr
;
struct
tdfxfb_par
par
;
if
(
con
==
-
1
)
if
(
nopan
||
var
->
xoffset
||
(
var
->
yoffset
>
var
->
yres_virtual
))
par
=
info
->
default_par
;
return
-
EINVAL
;
else
if
((
var
->
yoffset
+
var
->
yres
>
var
->
yres_virtual
&&
nowrap
))
tdfxfb_decode_var
(
&
fb_display
[
con
].
var
,
&
par
,
info
);
return
-
EINVAL
;
tdfxfb_encode_fix
(
fix
,
&
par
,
info
);
return
0
;
}
static
int
tdfxfb_get_var
(
struct
fb_var_screeninfo
*
var
,
addr
=
var
->
yoffset
*
info
->
fix
.
line_length
;
int
con
,
struct
fb_info
*
fb
)
banshee_make_room
(
1
);
{
tdfx_outl
(
VIDDESKSTART
,
addr
);
const
struct
fb_info_tdfx
*
info
=
(
struct
fb_info_tdfx
*
)
fb
;
if
(
con
==
-
1
)
info
->
var
.
xoffset
=
var
->
xoffset
;
tdfxfb_encode_var
(
var
,
&
info
->
default_par
,
info
);
info
->
var
.
yoffset
=
var
->
yoffset
;
else
*
var
=
fb_display
[
con
].
var
;
return
0
;
return
0
;
}
}
static
void
tdfxfb_set_dispsw
(
struct
display
*
disp
,
/*
struct
fb_info_tdfx
*
info
,
* FillRect 2D command (solidfill or invert (via ROP_XOR))
int
bpp
,
int
accel
)
*/
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
)
if
(
rect
->
rop
==
ROP_COPY
)
fb_con
.
con_cursor
(
disp
->
conp
,
CM_ERASE
);
tdfx_rop
=
TDFX_ROP_COPY
;
switch
(
bpp
)
{
else
#ifdef FBCON_HAS_CFB8
tdfx_rop
=
TDFX_ROP_XOR
;
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
;
}
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
;
u32
bpp
=
info
->
var
.
bits_per_pixel
;
struct
tdfxfb_par
par
;
u32
stride
=
info
->
fix
.
line_length
;
struct
display
*
display
;
u32
blitcmd
=
COMMAND_2D_S2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
);
int
oldxres
,
oldyres
,
oldvxres
,
oldvyres
,
oldbpp
,
oldaccel
,
accel
,
u32
fmt
=
stride
|
((
bpp
+
((
bpp
==
8
)
?
0
:
8
))
<<
13
);
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
];
}
del_timer
(
&
(
info
->
cursor
.
timer
));
if
(
area
->
sx
<=
area
->
dx
)
{
fb_info
.
cursor
.
state
=
CM_ERASE
;
//-X
if
(
!
info
->
fb_info
.
display_fg
||
blitcmd
|=
BIT
(
14
);
info
->
fb_info
.
display_fg
->
vc_num
==
con
||
con
<
0
)
area
->
sx
+=
area
->
width
-
1
;
tdfxfb_set_par
(
&
par
,
info
);
area
->
dx
+=
area
->
width
-
1
;
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
->
sy
<=
area
->
dy
)
{
//-Y
blitcmd
|=
BIT
(
15
);
area
->
sy
+=
area
->
height
-
1
;
area
->
dy
+=
area
->
height
-
1
;
}
}
return
0
;
banshee_make_room
(
6
);
}
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
);
fb_display
[
con
].
var
.
xoffset
=
var
->
xoffset
;
tdfx_outl
(
SRCFORMAT
,
fmt
);
fb_display
[
con
].
var
.
yoffset
=
var
->
yoffset
;
tdfx_outl
(
DSTFORMAT
,
fmt
);
return
0
;
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
,
static
void
tdfxfb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
pixmap
)
int
kspc
,
int
con
,
struct
fb_info
*
fb
)
{
{
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
;
if
(
pixmap
->
depth
==
1
)
{
struct
display
*
d
=
(
con
<
0
)
?
fb
->
disp
:
fb_display
+
con
;
banshee_make_room
(
8
+
((
size
+
3
)
>>
2
));
tdfx_outl
(
COLORFORE
,
pixmap
->
fg_color
);
if
(
con
==
fb
->
currcon
)
{
tdfx_outl
(
COLORBACK
,
pixmap
->
bg_color
);
/* current console? */
srcfmt
=
0x400000
;
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
);
}
else
{
}
else
{
fb_copy_cmap
(
fb_default_cmap
(
i
->
current_par
.
cmap_len
),
banshee_make_room
(
6
+
((
size
+
3
)
>>
2
));
cmap
,
kspc
?
0
:
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
;
tdfx_outl
(
SRCXY
,
0
);
if
(
d
->
cmap
.
len
!=
cmap_len
)
{
tdfx_outl
(
DSTXY
,
pixmap
->
dx
|
(
pixmap
->
dy
<<
16
));
int
err
;
tdfx_outl
(
COMMAND_2D
,
COMMAND_2D_H2S_BITBLT
|
(
TDFX_ROP_COPY
<<
24
));
if
((
err
=
fb_alloc_cmap
(
&
d
->
cmap
,
cmap_len
,
0
)))
tdfx_outl
(
SRCFORMAT
,
srcfmt
);
return
err
;
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? */
/* Send the leftovers now */
return
fb_set_cmap
(
cmap
,
kspc
,
fb
);
i
=
size
%
4
;
}
else
{
switch
(
i
)
{
fb_copy_cmap
(
cmap
,
&
d
->
cmap
,
kspc
?
0
:
1
);
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,
...
@@ -1777,143 +984,132 @@ static int tdfxfb_set_cmap(struct fb_cmap *cmap,
static
int
__devinit
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
static
int
__devinit
tdfxfb_probe
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
id
)
const
struct
pci_device_id
*
id
)
{
{
struct
fb_var_screeninfo
var
;
struct
fb_info
*
info
;
char
*
name
=
NULL
;
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
)
{
switch
(
pdev
->
device
)
{
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
case
PCI_DEVICE_ID_3DFX_BANSHEE
:
fb_info
.
max_pixclock
=
BANSHEE_MAX_PIXCLOCK
;
strcat
(
tdfx_fix
.
id
,
" Banshee"
)
;
name
=
"Banshee"
;
default_par
.
max_pixclock
=
BANSHEE_MAX_PIXCLOCK
;
break
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
case
PCI_DEVICE_ID_3DFX_VOODOO3
:
fb_info
.
max_pixclock
=
VOODOO3_MAX_PIXCLOCK
;
strcat
(
tdfx_fix
.
id
,
" Voodoo3"
)
;
name
=
"Voodoo3"
;
default_par
.
max_pixclock
=
VOODOO3_MAX_PIXCLOCK
;
break
;
break
;
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
case
PCI_DEVICE_ID_3DFX_VOODOO5
:
fb_info
.
max_pixclock
=
VOODOO5_MAX_PIXCLOCK
;
strcat
(
tdfx_fix
.
id
,
" Voodoo5"
)
;
name
=
"Voodoo5"
;
default_par
.
max_pixclock
=
VOODOO5_MAX_PIXCLOCK
;
break
;
break
;
}
}
fb_info
.
regbase_phys
=
pci_resource_start
(
pdev
,
0
);
tdfx_fix
.
mmio_start
=
pci_resource_start
(
pdev
,
0
);
fb_info
.
regbase_size
=
1
<<
24
;
tdfx_fix
.
mmio_len
=
1
<<
24
;
fb_info
.
regbase_virt
=
default_par
.
regbase_virt
=
ioremap_nocache
(
tdfx_fix
.
mmio_start
,
1
<<
24
);
ioremap_nocache
(
fb_info
.
regbase_phys
,
1
<<
24
);
if
(
!
default_par
.
regbase_virt
)
{
printk
(
"fb: Can't remap %s register area.
\n
"
,
tdfx_fix
.
id
);
if
(
!
fb_info
.
regbase_virt
)
{
printk
(
KERN_WARNING
"fb: Can't remap %s register area.
\n
"
,
name
);
return
-
ENXIO
;
return
-
ENXIO
;
}
}
fb_info
.
bufbase_phys
=
pci_resource_start
(
pdev
,
1
);
if
(
!
request_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
),
"tdfx regbase"
))
{
if
(
!
(
fb_info
.
bufbase_size
=
do_lfb_size
()))
{
printk
(
KERN_WARNING
"tdfxfb: Can't reserve regbase
\n
"
);
iounmap
(
fb_info
.
regbase_virt
);
iounmap
(
default_par
.
regbase_virt
);
printk
(
KERN_WARNING
"fb: Can't count %s memory.
\n
"
,
name
);
return
-
ENXIO
;
return
-
ENXIO
;
}
}
fb_info
.
bufbase_virt
=
ioremap_nocache
(
fb_info
.
bufbase_phys
,
tdfx_fix
.
smem_start
=
pci_resource_start
(
pdev
,
1
);
fb_info
.
bufbase_size
);
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
)
{
if
(
!
request_mem_region
(
pci_resource_start
(
pdev
,
1
),
printk
(
KERN_WARNING
"fb: Can't remap %s framebuffer.
\n
"
,
pci_resource_len
(
pdev
,
1
),
"tdfx smem"
))
{
name
);
printk
(
KERN_WARNING
"tdfxfb: Can't reserve smem
\n
"
);
iounmap
(
fb_info
.
regbase_virt
);
release_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
));
iounmap
(
default_par
.
regbase_virt
);
return
-
ENXIO
;
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
(
!
request_region
(
pci_resource_start
(
pdev
,
2
),
if
(
!
nomtrr
)
{
pci_resource_len
(
pdev
,
2
),
"tdfx iobase"
))
{
fb_info
.
mtrr_idx
=
mtrr_add
(
fb_info
.
bufbase_phys
,
printk
(
KERN_WARNING
"tdfxfb: Can't reserve iobase
\n
"
);
fb_info
.
bufbase_size
,
release_mem_region
(
pci_resource_start
(
pdev
,
1
),
MTRR_TYPE_WRCOMB
,
1
);
pci_resource_len
(
pdev
,
1
));
printk
(
KERN_INFO
"fb: MTRR's turned on
\n
"
);
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 */
/* clear framebuffer memory */
memset_io
(
fb_info
.
bufbase_virt
,
0
,
fb_info
.
bufbase_size
);
memset_io
(
info
->
screen_base
,
0
,
tdfx_fix
.
smem_len
);
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
*/
printk
(
KERN_NOTICE
tdfx_fix
.
ypanstep
=
nopan
?
0
:
1
;
"tdfxfb: can't decode the supplied video mode, using default
\n
"
)
;
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
)
:
/* The below feilds will go away !!!! */
(
var
.
accel_flags
|=
FB_ACCELF_TEXT
);
strcpy
(
info
->
modename
,
info
->
fix
.
id
);
info
->
currcon
=
-
1
;
info
->
switch_con
=
gen_switch
;
info
->
updatevar
=
gen_update_var
;
if
(
tdfxfb_decode_var
if
(
!
mode_option
)
(
&
var
,
&
fb_info
.
default_par
,
&
fb_info
))
{
mode_option
=
"640x480@60"
;
/* this is getting really bad!... */
printk
(
KERN_WARNING
"tdfxfb: can't decode default video mode
\n
"
);
return
-
ENXIO
;
}
}
fb_info
.
fb_info
.
screen_base
=
fb_info
.
bufbase_virt
;
err
=
fb_find_mode
(
&
info
->
var
,
info
,
mode_option
,
NULL
,
0
,
NULL
,
8
);
fb_info
.
disp
.
var
=
var
;
if
(
!
err
||
err
==
4
)
info
->
var
=
tdfx_var
;
if
(
tdfxfb_set_var
(
&
var
,
-
1
,
&
fb_info
.
fb_info
))
{
size
=
(
info
->
var
.
bits_per_pixel
==
8
)
?
256
:
16
;
printk
(
KERN_WARNING
fb_alloc_cmap
(
&
info
->
cmap
,
size
,
0
);
"tdfxfb: can't set default video mode
\n
"
);
return
-
ENXIO
;
gen_set_var
(
&
info
->
var
,
-
1
,
info
);
}
if
(
register_framebuffer
(
&
fb_info
.
fb_info
)
<
0
)
{
if
(
register_framebuffer
(
info
)
<
0
)
{
printk
(
KERN_WARNING
printk
(
"tdfxfb: can't register framebuffer
\n
"
);
"tdfxfb: can't register framebuffer
\n
"
);
return
-
ENXIO
;
return
-
ENXIO
;
}
}
/*
printk
(
KERN_INFO
"fb%d: %s frame buffer device
\n
"
,
* Our driver data
GET_FB_IDX
(
fb_info
.
fb_info
.
node
),
fb_info
.
fb_info
.
modename
);
*/
pdev
->
driver_data
=
info
;
return
0
;
return
0
;
}
}
...
@@ -1928,19 +1124,20 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
...
@@ -1928,19 +1124,20 @@ static int __devinit tdfxfb_probe(struct pci_dev *pdev,
*/
*/
static
void
__devexit
tdfxfb_remove
(
struct
pci_dev
*
pdev
)
static
void
__devexit
tdfxfb_remove
(
struct
pci_dev
*
pdev
)
{
{
unregister_framebuffer
(
&
fb_info
.
fb_info
);
struct
fb_info
*
info
=
(
struct
fb_info
*
)
pdev
->
driver_data
;
del_timer_sync
(
&
fb_info
.
cursor
.
timer
);
struct
tdfx_par
*
par
=
(
struct
tdfx_par
*
)
info
->
par
;
#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
iounmap
(
fb_info
.
regbase_virt
);
unregister_framebuffer
(
info
);
iounmap
(
fb_info
.
bufbase_virt
);
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
)
int
__init
tdfxfb_init
(
void
)
...
@@ -1956,7 +1153,8 @@ static void __exit tdfxfb_exit(void)
...
@@ -1956,7 +1153,8 @@ static void __exit tdfxfb_exit(void)
MODULE_AUTHOR
(
"Hannu Mallat <hmallat@cc.hut.fi>"
);
MODULE_AUTHOR
(
"Hannu Mallat <hmallat@cc.hut.fi>"
);
MODULE_DESCRIPTION
(
"3Dfx framebuffer device driver"
);
MODULE_DESCRIPTION
(
"3Dfx framebuffer device driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
noaccel
,
"i"
);
MODULE_PARM_DESC
(
noaccel
,
"Disable hardware acceleration (1 = disabled), enabled by default."
);
#ifdef MODULE
#ifdef MODULE
module_init
(
tdfxfb_init
);
module_init
(
tdfxfb_init
);
...
@@ -1967,7 +1165,7 @@ module_exit(tdfxfb_exit);
...
@@ -1967,7 +1165,7 @@ module_exit(tdfxfb_exit);
#ifndef MODULE
#ifndef MODULE
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
)
void
tdfxfb_setup
(
char
*
options
,
int
*
ints
)
{
{
char
*
this_opt
;
char
*
this_opt
;
if
(
!
options
||
!*
options
)
if
(
!
options
||
!*
options
)
return
;
return
;
...
@@ -1978,20 +1176,10 @@ void tdfxfb_setup(char *options, int *ints)
...
@@ -1978,20 +1176,10 @@ void tdfxfb_setup(char *options, int *ints)
if
(
!
strcmp
(
this_opt
,
"inverse"
))
{
if
(
!
strcmp
(
this_opt
,
"inverse"
))
{
inverse
=
1
;
inverse
=
1
;
fb_invert_cmaps
();
fb_invert_cmaps
();
}
else
if
(
!
strcmp
(
this_opt
,
"noaccel"
))
{
}
else
if
(
!
strcmp
(
this_opt
,
"nopan"
))
{
noaccel
=
nopan
=
nowrap
=
nohwcursor
=
1
;
}
else
if
(
!
strcmp
(
this_opt
,
"nopan"
))
{
nopan
=
1
;
nopan
=
1
;
}
else
if
(
!
strcmp
(
this_opt
,
"nowrap"
))
{
}
else
if
(
!
strcmp
(
this_opt
,
"nowrap"
))
{
nowrap
=
1
;
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
{
}
else
{
mode_option
=
this_opt
;
mode_option
=
this_opt
;
}
}
...
@@ -1999,267 +1187,3 @@ void tdfxfb_setup(char *options, int *ints)
...
@@ -1999,267 +1187,3 @@ void tdfxfb_setup(char *options, int *ints)
}
}
#endif
#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>
* Copyright (c) 2001 Denis Oliver Kropp <dok@convergence.de>
*
*
...
@@ -8,6 +8,54 @@
...
@@ -8,6 +8,54 @@
* archive for more details.
* 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
#ifdef NEOFB_DEBUG
# define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x));
# define DBG(x) printk (KERN_DEBUG "neofb: %s\n", (x));
...
@@ -15,7 +63,6 @@
...
@@ -15,7 +63,6 @@
# define DBG(x)
# define DBG(x)
#endif
#endif
#define PCI_CHIP_NM2070 0x0001
#define PCI_CHIP_NM2070 0x0001
#define PCI_CHIP_NM2090 0x0002
#define PCI_CHIP_NM2090 0x0002
#define PCI_CHIP_NM2093 0x0003
#define PCI_CHIP_NM2093 0x0003
...
@@ -78,8 +125,6 @@ typedef volatile struct {
...
@@ -78,8 +125,6 @@ typedef volatile struct {
struct
neofb_par
{
struct
neofb_par
{
int
depth
;
unsigned
char
MiscOutReg
;
/* Misc */
unsigned
char
MiscOutReg
;
/* Misc */
unsigned
char
CRTC
[
25
];
/* Crtc Controller */
unsigned
char
CRTC
[
25
];
/* Crtc Controller */
unsigned
char
Sequencer
[
5
];
/* Video Sequencer */
unsigned
char
Sequencer
[
5
];
/* Video Sequencer */
...
@@ -113,31 +158,11 @@ struct neofb_par {
...
@@ -113,31 +158,11 @@ struct neofb_par {
unsigned
char
VCLK3NumeratorHigh
;
unsigned
char
VCLK3NumeratorHigh
;
unsigned
char
VCLK3Denominator
;
unsigned
char
VCLK3Denominator
;
unsigned
char
VerticalExt
;
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
#ifdef CONFIG_MTRR
int
mtrr
;
int
mtrr
;
#endif
#endif
}
video
;
u8
*
mmio_vbase
;
struct
{
u8
*
vbase
;
u32
pbase
;
u32
len
;
}
mmio
;
Neo2200
*
neo2200
;
Neo2200
*
neo2200
;
...
@@ -151,20 +176,14 @@ struct neofb_info {
...
@@ -151,20 +176,14 @@ struct neofb_info {
int
lcd_stretch
;
int
lcd_stretch
;
int
internal_display
;
int
internal_display
;
int
external_display
;
int
external_display
;
struct
{
u16
red
,
green
,
blue
,
transp
;
}
palette
[
NR_PALETTE
];
};
};
typedef
struct
{
typedef
struct
{
int
x_res
;
int
x_res
;
int
y_res
;
int
y_res
;
int
mode
;
int
mode
;
}
biosMode
;
}
biosMode
;
/* vga IO functions */
/* vga IO functions */
static
inline
u8
VGArCR
(
u8
index
)
static
inline
u8
VGArCR
(
u8
index
)
{
{
...
@@ -241,51 +260,5 @@ static inline void VGAwMISC (u8 value)
...
@@ -241,51 +260,5 @@ static inline void VGAwMISC (u8 value)
{
{
outb
(
value
,
0x3c2
);
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