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