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
2eaf7c63
Commit
2eaf7c63
authored
Jul 07, 2002
by
James Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Port step some changes at authors request.
parent
8ef1bf6d
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
3329 additions
and
2257 deletions
+3329
-2257
drivers/video/aty128fb.c
drivers/video/aty128fb.c
+1783
-1334
drivers/video/riva/fbdev.c
drivers/video/riva/fbdev.c
+951
-578
drivers/video/riva/riva_hw.c
drivers/video/riva/riva_hw.c
+9
-29
drivers/video/riva/riva_hw.h
drivers/video/riva/riva_hw.h
+0
-2
drivers/video/riva/rivafb.h
drivers/video/riva/rivafb.h
+41
-19
drivers/video/sa1100fb.c
drivers/video/sa1100fb.c
+535
-288
drivers/video/sa1100fb.h
drivers/video/sa1100fb.h
+10
-7
No files found.
drivers/video/aty128fb.c
View file @
2eaf7c63
This source diff could not be displayed because it is too large. You can
view the blob
instead.
drivers/video/riva/fbdev.c
View file @
2eaf7c63
/*
* linux/drivers/video/riva/fbdev
ar->
c - nVidia RIVA 128/TNT/TNT2 fb driver
* linux/drivers/video/riva/fbdev
.
c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Maintained by Ani Joshi <ajoshi@shell.unixbox.com>
*
...
...
@@ -25,6 +25,7 @@
* Known bugs and issues:
* restoring text mode fails
* doublescan modes are broken
* option 'noaccel' has no effect
*/
#include <linux/config.h>
...
...
@@ -51,10 +52,12 @@
#error This driver requires PCI support.
#endif
#include "../fbcon-accel.h"
/* version number of this driver */
#define RIVAFB_VERSION "0.9.3"
#define RIVAFB_VERSION "0.9.2a"
/* ------------------------------------------------------------------------- *
*
...
...
@@ -88,8 +91,8 @@
#define Set8Bits(value) ((value)&0xff)
/* HW cursor parameters */
#define DEFAULT_CURSOR_BLINK_RATE (
2
0)
#define CURSOR_HIDE_DELAY (
1
0)
#define DEFAULT_CURSOR_BLINK_RATE (
4
0)
#define CURSOR_HIDE_DELAY (
2
0)
#define CURSOR_SHOW_DELAY (3)
#define CURSOR_COLOR 0x7fff
...
...
@@ -97,6 +100,7 @@
#define MAX_CURS 32
/* ------------------------------------------------------------------------- *
*
* prototypes
...
...
@@ -105,6 +109,11 @@
static
int
rivafb_blank
(
int
blank
,
struct
fb_info
*
info
);
extern
void
riva_setup_accel
(
struct
rivafb_info
*
rinfo
);
extern
inline
void
wait_for_idle
(
struct
rivafb_info
*
rinfo
);
/* ------------------------------------------------------------------------- *
*
* card identification
...
...
@@ -127,11 +136,6 @@ enum riva_chips {
CH_GEFORCE2_GTS
,
CH_GEFORCE2_ULTRA
,
CH_QUADRO2_PRO
,
CH_GEFORCE2_GO
,
CH_GEFORCE3
,
CH_GEFORCE3_1
,
CH_GEFORCE3_2
,
CH_QUADRO_DDC
};
/* directly indexed by riva_chips enum, above */
...
...
@@ -154,11 +158,6 @@ static struct riva_chip_info {
{
"GeForce2-GTS"
,
NV_ARCH_10
},
{
"GeForce2-ULTRA"
,
NV_ARCH_10
},
{
"Quadro2-PRO"
,
NV_ARCH_10
},
{
"GeForce2-Go"
,
NV_ARCH_10
},
{
"GeForce3"
,
NV_ARCH_20
},
{
"GeForce3 Ti 200"
,
NV_ARCH_20
},
{
"GeForce3 Ti 500"
,
NV_ARCH_20
},
{
"Quadro DDC"
,
NV_ARCH_20
}
};
static
struct
pci_device_id
rivafb_pci_tbl
[]
__devinitdata
=
{
...
...
@@ -196,30 +195,64 @@ static struct pci_device_id rivafb_pci_tbl[] __devinitdata = {
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_GEFORCE2_ULTRA
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_QUADRO2_PRO
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_QUADRO2_PRO
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_GEFORCE2_GO
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_GEFORCE2_GO
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_GEFORCE3
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_GEFORCE3
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_GEFORCE3_1
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_GEFORCE3_1
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_GEFORCE3_2
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_GEFORCE3_2
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_QUADRO_DDC
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
CH_QUADRO_DDC
},
{
0
,
}
/* terminate list */
};
MODULE_DEVICE_TABLE
(
pci
,
rivafb_pci_tbl
);
/* ------------------------------------------------------------------------- *
*
* framebuffer related structures
*
* ------------------------------------------------------------------------- */
#ifdef FBCON_HAS_CFB8
extern
struct
display_switch
fbcon_riva8
;
#endif
#ifdef FBCON_HAS_CFB16
extern
struct
display_switch
fbcon_riva16
;
#endif
#ifdef FBCON_HAS_CFB32
extern
struct
display_switch
fbcon_riva32
;
#endif
#if 0
/* describes the state of a Riva board */
struct rivafb_par {
struct riva_regs state; /* state of hw board */
__u32 visual; /* FB_VISUAL_xxx */
unsigned depth; /* bpp of current mode */
};
#endif
struct
riva_cursor
{
int
enable
;
int
on
;
int
vbl_cnt
;
int
last_move_delay
;
int
blink_rate
;
struct
{
u16
x
,
y
;
}
pos
,
size
;
unsigned
short
image
[
MAX_CURS
*
MAX_CURS
];
struct
timer_list
*
timer
;
};
/* ------------------------------------------------------------------------- *
*
* global variables
*
* ------------------------------------------------------------------------- */
struct
fb_info
*
riva_boards
=
NULL
;
struct
riva
fb_info
*
riva_boards
=
NULL
;
/* command line data, set in rivafb_setup() */
static
char
fontname
[
40
]
__initdata
=
{
0
};
static
char
noaccel
__initdata
=
0
;
static
char
nomove
=
0
;
static
char
nohwcursor
__initdata
=
0
;
static
char
noblink
=
0
;
#ifdef CONFIG_MTRR
...
...
@@ -232,26 +265,24 @@ static char *mode_option __initdata = NULL;
static
char
*
font
=
NULL
;
#endif
static
struct
fb_fix_screeninfo
rivafb_fix
=
{
id:
"nVidia"
,
type:
FB_TYPE_PACKED_PIXELS
,
xpanstep:
1
,
ypanstep:
1
,
};
static
struct
fb_var_screeninfo
rivafb_default_var
=
{
xres:
640
,
yres:
480
,
xres_virtual:
640
,
yres_virtual:
480
,
xoffset:
0
,
yoffset:
0
,
bits_per_pixel:
8
,
grayscale:
0
,
red:
{
0
,
6
,
0
},
green:
{
0
,
6
,
0
},
blue:
{
0
,
6
,
0
},
activate:
FB_ACTIVATE_NOW
,
transp:
{
0
,
0
,
0
},
nonstd:
0
,
activate:
0
,
height:
-
1
,
width:
-
1
,
accel_flags:
FB_ACCELF_TEXT
,
accel_flags:
0
,
pixclock:
39721
,
left_margin:
40
,
right_margin:
24
,
...
...
@@ -259,28 +290,10 @@ static struct fb_var_screeninfo rivafb_default_var = {
lower_margin:
11
,
hsync_len:
96
,
vsync_len:
2
,
sync:
0
,
vmode:
FB_VMODE_NONINTERLACED
};
static
u8
byte_rev
[
256
]
=
{
0x00
,
0x80
,
0x40
,
0xc0
,
0x20
,
0xa0
,
0x60
,
0xe0
,
0x10
,
0x90
,
0x50
,
0xd0
,
0x30
,
0xb0
,
0x70
,
0xf0
,
0x08
,
0x88
,
0x48
,
0xc8
,
0x28
,
0xa8
,
0x68
,
0xe8
,
0x18
,
0x98
,
0x58
,
0xd8
,
0x38
,
0xb8
,
0x78
,
0xf8
,
0x04
,
0x84
,
0x44
,
0xc4
,
0x24
,
0xa4
,
0x64
,
0xe4
,
0x14
,
0x94
,
0x54
,
0xd4
,
0x34
,
0xb4
,
0x74
,
0xf4
,
0x0c
,
0x8c
,
0x4c
,
0xcc
,
0x2c
,
0xac
,
0x6c
,
0xec
,
0x1c
,
0x9c
,
0x5c
,
0xdc
,
0x3c
,
0xbc
,
0x7c
,
0xfc
,
0x02
,
0x82
,
0x42
,
0xc2
,
0x22
,
0xa2
,
0x62
,
0xe2
,
0x12
,
0x92
,
0x52
,
0xd2
,
0x32
,
0xb2
,
0x72
,
0xf2
,
0x0a
,
0x8a
,
0x4a
,
0xca
,
0x2a
,
0xaa
,
0x6a
,
0xea
,
0x1a
,
0x9a
,
0x5a
,
0xda
,
0x3a
,
0xba
,
0x7a
,
0xfa
,
0x06
,
0x86
,
0x46
,
0xc6
,
0x26
,
0xa6
,
0x66
,
0xe6
,
0x16
,
0x96
,
0x56
,
0xd6
,
0x36
,
0xb6
,
0x76
,
0xf6
,
0x0e
,
0x8e
,
0x4e
,
0xce
,
0x2e
,
0xae
,
0x6e
,
0xee
,
0x1e
,
0x9e
,
0x5e
,
0xde
,
0x3e
,
0xbe
,
0x7e
,
0xfe
,
0x01
,
0x81
,
0x41
,
0xc1
,
0x21
,
0xa1
,
0x61
,
0xe1
,
0x11
,
0x91
,
0x51
,
0xd1
,
0x31
,
0xb1
,
0x71
,
0xf1
,
0x09
,
0x89
,
0x49
,
0xc9
,
0x29
,
0xa9
,
0x69
,
0xe9
,
0x19
,
0x99
,
0x59
,
0xd9
,
0x39
,
0xb9
,
0x79
,
0xf9
,
0x05
,
0x85
,
0x45
,
0xc5
,
0x25
,
0xa5
,
0x65
,
0xe5
,
0x15
,
0x95
,
0x55
,
0xd5
,
0x35
,
0xb5
,
0x75
,
0xf5
,
0x0d
,
0x8d
,
0x4d
,
0xcd
,
0x2d
,
0xad
,
0x6d
,
0xed
,
0x1d
,
0x9d
,
0x5d
,
0xdd
,
0x3d
,
0xbd
,
0x7d
,
0xfd
,
0x03
,
0x83
,
0x43
,
0xc3
,
0x23
,
0xa3
,
0x63
,
0xe3
,
0x13
,
0x93
,
0x53
,
0xd3
,
0x33
,
0xb3
,
0x73
,
0xf3
,
0x0b
,
0x8b
,
0x4b
,
0xcb
,
0x2b
,
0xab
,
0x6b
,
0xeb
,
0x1b
,
0x9b
,
0x5b
,
0xdb
,
0x3b
,
0xbb
,
0x7b
,
0xfb
,
0x07
,
0x87
,
0x47
,
0xc7
,
0x27
,
0xa7
,
0x67
,
0xe7
,
0x17
,
0x97
,
0x57
,
0xd7
,
0x37
,
0xb7
,
0x77
,
0xf7
,
0x0f
,
0x8f
,
0x4f
,
0xcf
,
0x2f
,
0xaf
,
0x6f
,
0xef
,
0x1f
,
0x9f
,
0x5f
,
0xdf
,
0x3f
,
0xbf
,
0x7f
,
0xff
,
};
/* from GGI */
static
const
struct
riva_regs
reg_template
=
{
{
0x00
,
0x01
,
0x02
,
0x03
,
0x04
,
0x05
,
0x06
,
0x07
,
/* ATTR */
...
...
@@ -302,76 +315,78 @@ static const struct riva_regs reg_template = {
0xEB
/* MISC */
};
/* ------------------------------------------------------------------------- *
*
* MMIO access macros
*
* ------------------------------------------------------------------------- */
static
inline
void
CRTCout
(
struct
riva
_par
*
par
,
unsigned
char
index
,
static
inline
void
CRTCout
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
,
unsigned
char
val
)
{
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3d4
,
index
);
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3d5
,
val
);
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3d4
,
index
);
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3d5
,
val
);
}
static
inline
unsigned
char
CRTCin
(
struct
riva
_par
*
par
,
static
inline
unsigned
char
CRTCin
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
)
{
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3d4
,
index
);
return
(
VGA_RD08
(
par
->
riva
.
PCIO
,
0x3d5
));
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3d4
,
index
);
return
(
VGA_RD08
(
rinfo
->
riva
.
PCIO
,
0x3d5
));
}
static
inline
void
GRAout
(
struct
riva
_par
*
par
,
unsigned
char
index
,
static
inline
void
GRAout
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
,
unsigned
char
val
)
{
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3ce
,
index
);
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3cf
,
val
);
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3ce
,
index
);
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3cf
,
val
);
}
static
inline
unsigned
char
GRAin
(
struct
riva
_par
*
par
,
static
inline
unsigned
char
GRAin
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
)
{
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3ce
,
index
);
return
(
VGA_RD08
(
par
->
riva
.
PVIO
,
0x3cf
));
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3ce
,
index
);
return
(
VGA_RD08
(
rinfo
->
riva
.
PVIO
,
0x3cf
));
}
static
inline
void
SEQout
(
struct
riva
_par
*
par
,
unsigned
char
index
,
static
inline
void
SEQout
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
,
unsigned
char
val
)
{
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3c4
,
index
);
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3c5
,
val
);
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3c4
,
index
);
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3c5
,
val
);
}
static
inline
unsigned
char
SEQin
(
struct
riva
_par
*
par
,
static
inline
unsigned
char
SEQin
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
)
{
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3c4
,
index
);
return
(
VGA_RD08
(
par
->
riva
.
PVIO
,
0x3c5
));
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3c4
,
index
);
return
(
VGA_RD08
(
rinfo
->
riva
.
PVIO
,
0x3c5
));
}
static
inline
void
ATTRout
(
struct
riva
_par
*
par
,
unsigned
char
index
,
static
inline
void
ATTRout
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
,
unsigned
char
val
)
{
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3c0
,
index
);
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3c0
,
val
);
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3c0
,
index
);
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3c0
,
val
);
}
static
inline
unsigned
char
ATTRin
(
struct
riva
_par
*
par
,
static
inline
unsigned
char
ATTRin
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
index
)
{
VGA_WR08
(
par
->
riva
.
PCIO
,
0x3c0
,
index
);
return
(
VGA_RD08
(
par
->
riva
.
PCIO
,
0x3c1
));
VGA_WR08
(
rinfo
->
riva
.
PCIO
,
0x3c0
,
index
);
return
(
VGA_RD08
(
rinfo
->
riva
.
PCIO
,
0x3c1
));
}
static
inline
void
MISCout
(
struct
riva
_par
*
par
,
unsigned
char
val
)
static
inline
void
MISCout
(
struct
riva
fb_info
*
rinfo
,
unsigned
char
val
)
{
VGA_WR08
(
par
->
riva
.
PVIO
,
0x3c2
,
val
);
VGA_WR08
(
rinfo
->
riva
.
PVIO
,
0x3c2
,
val
);
}
static
inline
unsigned
char
MISCin
(
struct
riva
_par
*
par
)
static
inline
unsigned
char
MISCin
(
struct
riva
fb_info
*
rinfo
)
{
return
(
VGA_RD08
(
par
->
riva
.
PVIO
,
0x3cc
));
return
(
VGA_RD08
(
rinfo
->
riva
.
PVIO
,
0x3cc
));
}
...
...
@@ -384,40 +399,39 @@ static inline unsigned char MISCin(struct riva_par *par)
/**
* riva_cursor_timer_handler - blink timer
* @dev_addr: pointer to fb_info object containing info for current riva board
* @dev_addr: pointer to
riva
fb_info object containing info for current riva board
*
* DESCRIPTION:
* Cursor blink timer.
*/
static
void
riva_cursor_timer_handler
(
unsigned
long
dev_addr
)
{
struct
fb_info
*
info
=
(
struct
fb_info
*
)
dev_addr
;
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
rivafb_info
*
rinfo
=
(
struct
rivafb_info
*
)
dev_addr
;
if
(
!
par
->
cursor
)
return
;
if
(
!
rinfo
->
cursor
)
return
;
if
(
!
par
->
cursor
->
enable
)
goto
out
;
if
(
!
rinfo
->
cursor
->
enable
)
goto
out
;
par
->
cursor
->
prev_slice_moves
=
par
->
cursor
->
last_slice_moves
;
par
->
cursor
->
last_slice_moves
=
0
;
if
(
rinfo
->
cursor
->
last_move_delay
<
1000
)
rinfo
->
cursor
->
last_move_delay
++
;
if
(
par
->
cursor
->
vbl_cnt
&&
--
par
->
cursor
->
vbl_cnt
==
0
)
{
par
->
cursor
->
on
^=
1
;
if
(
par
->
cursor
->
on
)
*
(
par
->
riva
.
CURSORPOS
)
=
(
par
->
cursor
->
pos
.
x
&
0xFFFF
)
|
(
par
->
cursor
->
pos
.
y
<<
16
);
par
->
riva
.
ShowHideCursor
(
&
par
->
riva
,
par
->
cursor
->
on
);
if
(
rinfo
->
cursor
->
vbl_cnt
&&
--
rinfo
->
cursor
->
vbl_cnt
==
0
)
{
rinfo
->
cursor
->
on
^=
1
;
if
(
rinfo
->
cursor
->
on
)
*
(
rinfo
->
riva
.
CURSORPOS
)
=
(
rinfo
->
cursor
->
pos
.
x
&
0xFFFF
)
|
(
rinfo
->
cursor
->
pos
.
y
<<
16
);
rinfo
->
riva
.
ShowHideCursor
(
&
rinfo
->
riva
,
rinfo
->
cursor
->
on
);
if
(
!
noblink
)
par
->
cursor
->
vbl_cnt
=
par
->
cursor
->
blink_rate
;
rinfo
->
cursor
->
vbl_cnt
=
rinfo
->
cursor
->
blink_rate
;
}
out:
par
->
cursor
->
timer
->
expires
=
jiffies
+
(
HZ
/
5
0
);
add_timer
(
par
->
cursor
->
timer
);
rinfo
->
cursor
->
timer
->
expires
=
jiffies
+
(
HZ
/
10
0
);
add_timer
(
rinfo
->
cursor
->
timer
);
}
/**
* rivafb_init_cursor - allocates cursor structure and starts blink timer
* @
info: pointer to
fb_info object containing info for current riva board
* @
rinfo: pointer to riva
fb_info object containing info for current riva board
*
* DESCRIPTION:
* Allocates cursor structure and starts blink timer.
...
...
@@ -428,7 +442,7 @@ static void riva_cursor_timer_handler(unsigned long dev_addr)
* CALLED FROM:
* rivafb_init_one()
*/
static
struct
riva_cursor
*
__init
rivafb_init_cursor
(
struct
fb_info
*
info
)
static
struct
riva_cursor
*
__init
rivafb_init_cursor
(
struct
rivafb_info
*
r
info
)
{
struct
riva_cursor
*
cursor
;
...
...
@@ -446,8 +460,8 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
cursor
->
blink_rate
=
DEFAULT_CURSOR_BLINK_RATE
;
init_timer
(
cursor
->
timer
);
cursor
->
timer
->
expires
=
jiffies
+
(
HZ
/
5
0
);
cursor
->
timer
->
data
=
(
unsigned
long
)
info
;
cursor
->
timer
->
expires
=
jiffies
+
(
HZ
/
10
0
);
cursor
->
timer
->
data
=
(
unsigned
long
)
r
info
;
cursor
->
timer
->
function
=
riva_cursor_timer_handler
;
add_timer
(
cursor
->
timer
);
...
...
@@ -456,7 +470,7 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
/**
* rivafb_exit_cursor - stops blink timer and releases cursor structure
* @
par: pointer to riva_par
object containing info for current riva board
* @
rinfo: pointer to rivafb_info
object containing info for current riva board
*
* DESCRIPTION:
* Stops blink timer and releases cursor structure.
...
...
@@ -465,9 +479,9 @@ static struct riva_cursor * __init rivafb_init_cursor(struct fb_info *info)
* rivafb_init_one()
* rivafb_remove_one()
*/
static
void
rivafb_exit_cursor
(
struct
riva
_par
*
par
)
static
void
rivafb_exit_cursor
(
struct
riva
fb_info
*
rinfo
)
{
struct
riva_cursor
*
cursor
=
par
->
cursor
;
struct
riva_cursor
*
cursor
=
rinfo
->
cursor
;
if
(
cursor
)
{
if
(
cursor
->
timer
)
{
...
...
@@ -475,13 +489,13 @@ static void rivafb_exit_cursor(struct riva_par *par)
kfree
(
cursor
->
timer
);
}
kfree
(
cursor
);
par
->
cursor
=
NULL
;
rinfo
->
cursor
=
0
;
}
}
/**
* rivafb_download_cursor - writes cursor shape into card registers
* @
par: pointer to riva_par
object containing info for current riva board
* @
rinfo: pointer to rivafb_info
object containing info for current riva board
*
* DESCRIPTION:
* Writes cursor shape into card registers.
...
...
@@ -489,24 +503,24 @@ static void rivafb_exit_cursor(struct riva_par *par)
* CALLED FROM:
* riva_load_video_mode()
*/
static
void
rivafb_download_cursor
(
struct
riva
_par
*
par
)
static
void
rivafb_download_cursor
(
struct
riva
fb_info
*
rinfo
)
{
int
i
,
save
;
int
*
image
;
if
(
!
par
->
cursor
)
return
;
if
(
!
rinfo
->
cursor
)
return
;
image
=
(
int
*
)
par
->
cursor
->
image
;
save
=
par
->
riva
.
ShowHideCursor
(
&
par
->
riva
,
0
);
image
=
(
int
*
)
rinfo
->
cursor
->
image
;
save
=
rinfo
->
riva
.
ShowHideCursor
(
&
rinfo
->
riva
,
0
);
for
(
i
=
0
;
i
<
(
MAX_CURS
*
MAX_CURS
*
2
)
/
sizeof
(
int
);
i
++
)
writel
(
image
[
i
],
par
->
riva
.
CURSOR
+
i
);
writel
(
image
[
i
],
rinfo
->
riva
.
CURSOR
+
i
);
par
->
riva
.
ShowHideCursor
(
&
par
->
riva
,
save
);
rinfo
->
riva
.
ShowHideCursor
(
&
rinfo
->
riva
,
save
);
}
/**
* rivafb_create_cursor - sets rectangular cursor
* @
par: pointer to riva_par
object containing info for current riva board
* @
rinfo: pointer to rivafb_info
object containing info for current riva board
* @width: cursor width in pixels
* @height: cursor height in pixels
*
...
...
@@ -515,11 +529,11 @@ static void rivafb_download_cursor(struct riva_par *par)
*
* CALLED FROM:
* rivafb_set_font()
* rivafb_set_
p
ar()
* rivafb_set_
v
ar()
*/
static
void
rivafb_create_cursor
(
struct
riva
_par
*
par
,
int
width
,
int
height
)
static
void
rivafb_create_cursor
(
struct
riva
fb_info
*
rinfo
,
int
width
,
int
height
)
{
struct
riva_cursor
*
c
=
par
->
cursor
;
struct
riva_cursor
*
c
=
rinfo
->
cursor
;
int
i
,
j
,
idx
;
if
(
c
)
{
...
...
@@ -561,10 +575,9 @@ static void rivafb_create_cursor(struct riva_par *par, int width, int height)
*/
static
int
rivafb_set_font
(
struct
display
*
p
,
int
width
,
int
height
)
{
struct
fb_info
*
fb
=
p
->
fb_info
;
struct
riva_par
*
par
=
(
struct
riva_par
*
)
fb
->
par
;
struct
rivafb_info
*
fb
=
(
struct
rivafb_info
*
)(
p
->
fb_info
);
rivafb_create_cursor
(
par
,
width
,
height
);
rivafb_create_cursor
(
fb
,
width
,
height
);
return
1
;
}
...
...
@@ -580,9 +593,8 @@ static int rivafb_set_font(struct display *p, int width, int height)
*/
static
void
rivafb_cursor
(
struct
display
*
p
,
int
mode
,
int
x
,
int
y
)
{
struct
fb_info
*
info
=
p
->
fb_info
;
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
riva_cursor
*
c
=
par
->
cursor
;
struct
rivafb_info
*
rinfo
=
(
struct
rivafb_info
*
)(
p
->
fb_info
);
struct
riva_cursor
*
c
=
rinfo
->
cursor
;
if
(
!
c
)
return
;
...
...
@@ -593,7 +605,7 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
return
;
c
->
enable
=
0
;
if
(
c
->
on
)
par
->
riva
.
ShowHideCursor
(
&
par
->
riva
,
0
);
if
(
c
->
on
)
rinfo
->
riva
.
ShowHideCursor
(
&
rinfo
->
riva
,
0
);
c
->
pos
.
x
=
x
;
c
->
pos
.
y
=
y
;
...
...
@@ -604,15 +616,15 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
break
;
case
CM_DRAW
:
case
CM_MOVE
:
if
(
c
->
last_
slice_moves
>
2
||
c
->
prev_slice_moves
>
2
)
{
if
(
c
->
last_
move_delay
<=
1
)
{
/* rapid cursor movement */
c
->
vbl_cnt
=
CURSOR_SHOW_DELAY
;
}
else
{
*
(
par
->
riva
.
CURSORPOS
)
=
(
x
&
0xFFFF
)
|
(
y
<<
16
);
par
->
riva
.
ShowHideCursor
(
&
par
->
riva
,
1
);
*
(
rinfo
->
riva
.
CURSORPOS
)
=
(
x
&
0xFFFF
)
|
(
y
<<
16
);
rinfo
->
riva
.
ShowHideCursor
(
&
rinfo
->
riva
,
1
);
if
(
!
noblink
)
c
->
vbl_cnt
=
CURSOR_HIDE_DELAY
;
c
->
on
=
1
;
}
c
->
last_
slice_moves
++
;
c
->
last_
move_delay
=
0
;
c
->
enable
=
1
;
break
;
}
...
...
@@ -626,6 +638,80 @@ static void rivafb_cursor(struct display *p, int mode, int x, int y)
*
* ------------------------------------------------------------------------- */
/**
* riva_set_dispsw - sets dispsw
* @rinfo: pointer to internal driver struct for a given Riva card
* @disp: pointer to display object
*
* DESCRIPTION:
* Sets up console low level operations depending on the current? color depth
* of the display.
*
* CALLED FROM:
* rivafb_set_var()
* rivafb_switch()
* riva_init_disp()
*/
static
void
riva_set_dispsw
(
struct
rivafb_info
*
rinfo
,
struct
display
*
disp
)
{
int
accel
=
disp
->
var
.
accel_flags
&
FB_ACCELF_TEXT
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rinfo
!=
NULL
);
disp
->
dispsw_data
=
NULL
;
disp
->
type
=
FB_TYPE_PACKED_PIXELS
;
disp
->
type_aux
=
0
;
disp
->
ypanstep
=
1
;
disp
->
ywrapstep
=
0
;
disp
->
can_soft_blank
=
1
;
disp
->
inverse
=
0
;
switch
(
disp
->
var
.
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
rinfo
->
dispsw
=
accel
?
fbcon_riva8
:
fbcon_cfb8
;
disp
->
dispsw
=
&
rinfo
->
dispsw
;
disp
->
line_length
=
disp
->
var
.
xres_virtual
;
disp
->
visual
=
FB_VISUAL_PSEUDOCOLOR
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
rinfo
->
dispsw
=
accel
?
fbcon_riva16
:
fbcon_cfb16
;
disp
->
dispsw_data
=
&
rinfo
->
con_cmap
.
cfb16
;
disp
->
dispsw
=
&
rinfo
->
dispsw
;
disp
->
line_length
=
disp
->
var
.
xres_virtual
*
2
;
disp
->
visual
=
FB_VISUAL_DIRECTCOLOR
;
break
;
#endif
#ifdef FBCON_HAS_CFB32
case
32
:
rinfo
->
dispsw
=
accel
?
fbcon_riva32
:
fbcon_cfb32
;
disp
->
dispsw_data
=
rinfo
->
con_cmap
.
cfb32
;
disp
->
dispsw
=
&
rinfo
->
dispsw
;
disp
->
line_length
=
disp
->
var
.
xres_virtual
*
4
;
disp
->
visual
=
FB_VISUAL_DIRECTCOLOR
;
break
;
#endif
default:
DPRINTK
(
"Setting fbcon_dummy renderer
\n
"
);
rinfo
->
dispsw
=
fbcon_dummy
;
disp
->
dispsw
=
&
rinfo
->
dispsw
;
}
/* FIXME: verify that the above code sets dsp->* fields correctly */
if
(
rinfo
->
cursor
)
{
rinfo
->
dispsw
.
cursor
=
rivafb_cursor
;
rinfo
->
dispsw
.
set_font
=
rivafb_set_font
;
}
DPRINTK
(
"EXIT
\n
"
);
}
/**
* riva_wclut - set CLUT entry
* @chip: pointer to RIVA_HW_INST object
...
...
@@ -652,7 +738,7 @@ static void riva_wclut(RIVA_HW_INST *chip,
/**
* riva_save_state - saves current chip state
* @
par: pointer to riva_par
object containing info for current riva board
* @
rinfo: pointer to rivafb_info
object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
...
...
@@ -662,36 +748,36 @@ static void riva_wclut(RIVA_HW_INST *chip,
* rivafb_init_one()
*/
/* from GGI */
static
void
riva_save_state
(
struct
riva
_par
*
par
,
struct
riva_regs
*
regs
)
static
void
riva_save_state
(
struct
riva
fb_info
*
rinfo
,
struct
riva_regs
*
regs
)
{
int
i
;
par
->
riva
.
LockUnlock
(
&
par
->
riva
,
0
);
rinfo
->
riva
.
LockUnlock
(
&
rinfo
->
riva
,
0
);
par
->
riva
.
UnloadStateExt
(
&
par
->
riva
,
&
regs
->
ext
);
rinfo
->
riva
.
UnloadStateExt
(
&
rinfo
->
riva
,
&
regs
->
ext
);
regs
->
misc_output
=
MISCin
(
par
);
regs
->
misc_output
=
MISCin
(
rinfo
);
for
(
i
=
0
;
i
<
NUM_CRT_REGS
;
i
++
)
{
regs
->
crtc
[
i
]
=
CRTCin
(
par
,
i
);
regs
->
crtc
[
i
]
=
CRTCin
(
rinfo
,
i
);
}
for
(
i
=
0
;
i
<
NUM_ATC_REGS
;
i
++
)
{
regs
->
attr
[
i
]
=
ATTRin
(
par
,
i
);
regs
->
attr
[
i
]
=
ATTRin
(
rinfo
,
i
);
}
for
(
i
=
0
;
i
<
NUM_GRC_REGS
;
i
++
)
{
regs
->
gra
[
i
]
=
GRAin
(
par
,
i
);
regs
->
gra
[
i
]
=
GRAin
(
rinfo
,
i
);
}
for
(
i
=
0
;
i
<
NUM_SEQ_REGS
;
i
++
)
{
regs
->
seq
[
i
]
=
SEQin
(
par
,
i
);
regs
->
seq
[
i
]
=
SEQin
(
rinfo
,
i
);
}
}
/**
* riva_load_state - loads current chip state
* @
par: pointer to riva_par
object containing info for current riva board
* @
rinfo: pointer to rivafb_info
object containing info for current riva board
* @regs: pointer to riva_regs object
*
* DESCRIPTION:
...
...
@@ -703,18 +789,18 @@ static void riva_save_state(struct riva_par *par, struct riva_regs *regs)
* rivafb_remove_one()
*/
/* from GGI */
static
void
riva_load_state
(
struct
riva
_par
*
par
,
struct
riva_regs
*
regs
)
static
void
riva_load_state
(
struct
riva
fb_info
*
rinfo
,
struct
riva_regs
*
regs
)
{
RIVA_HW_STATE
*
state
=
&
regs
->
ext
;
int
i
;
CRTCout
(
par
,
0x11
,
0x00
);
RIVA_HW_STATE
*
state
=
&
regs
->
ext
;
CRTCout
(
rinfo
,
0x11
,
0x00
);
par
->
riva
.
LockUnlock
(
&
par
->
riva
,
0
);
rinfo
->
riva
.
LockUnlock
(
&
rinfo
->
riva
,
0
);
par
->
riva
.
LoadStateExt
(
&
par
->
riva
,
state
);
rinfo
->
riva
.
LoadStateExt
(
&
rinfo
->
riva
,
state
);
MISCout
(
par
,
regs
->
misc_output
);
MISCout
(
rinfo
,
regs
->
misc_output
);
for
(
i
=
0
;
i
<
NUM_CRT_REGS
;
i
++
)
{
switch
(
i
)
{
...
...
@@ -722,44 +808,44 @@ static void riva_load_state(struct riva_par *par, struct riva_regs *regs)
case
0x20
...
0x40
:
break
;
default:
CRTCout
(
par
,
i
,
regs
->
crtc
[
i
]);
CRTCout
(
rinfo
,
i
,
regs
->
crtc
[
i
]);
}
}
for
(
i
=
0
;
i
<
NUM_ATC_REGS
;
i
++
)
{
ATTRout
(
par
,
i
,
regs
->
attr
[
i
]);
ATTRout
(
rinfo
,
i
,
regs
->
attr
[
i
]);
}
for
(
i
=
0
;
i
<
NUM_GRC_REGS
;
i
++
)
{
GRAout
(
par
,
i
,
regs
->
gra
[
i
]);
GRAout
(
rinfo
,
i
,
regs
->
gra
[
i
]);
}
for
(
i
=
0
;
i
<
NUM_SEQ_REGS
;
i
++
)
{
SEQout
(
par
,
i
,
regs
->
seq
[
i
]);
SEQout
(
rinfo
,
i
,
regs
->
seq
[
i
]);
}
}
/**
* riva_load_video_mode - calculate timings
* @
info: pointer to
fb_info object containing info for current riva board
* @
rinfo: pointer to riva
fb_info object containing info for current riva board
* @video_mode: video mode to set
*
* DESCRIPTION:
* Calculate some timings and then send em off to riva_load_state().
*
* CALLED FROM:
* rivafb_set_
p
ar()
* rivafb_set_
v
ar()
*/
static
void
riva_load_video_mode
(
struct
fb_info
*
info
,
static
void
riva_load_video_mode
(
struct
rivafb_info
*
r
info
,
struct
fb_var_screeninfo
*
video_mode
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
riva_regs
newmode
;
int
bpp
,
width
,
hDisplaySize
,
hDisplay
,
hStart
,
hEnd
,
hTotal
,
height
,
vDisplay
,
vStart
,
vEnd
,
vTotal
,
dotClock
;
/* time to calculate */
rivafb_blank
(
1
,
info
);
rivafb_blank
(
1
,
(
struct
fb_info
*
)
rinfo
);
bpp
=
video_mode
->
bits_per_pixel
;
if
(
bpp
==
16
&&
video_mode
->
green
.
length
==
5
)
...
...
@@ -813,27 +899,83 @@ static void riva_load_video_mode(struct fb_info *info,
newmode
.
ext
.
width
=
width
;
newmode
.
ext
.
height
=
height
;
par
->
riva
.
CalcStateExt
(
&
par
->
riva
,
&
newmode
.
ext
,
bpp
,
width
,
rinfo
->
riva
.
CalcStateExt
(
&
rinfo
->
riva
,
&
newmode
.
ext
,
bpp
,
width
,
hDisplaySize
,
hDisplay
,
hStart
,
hEnd
,
hTotal
,
height
,
vDisplay
,
vStart
,
vEnd
,
vTotal
,
dotClock
);
if
(
video_mode
->
sync
&
FB_SYNC_HOR_HIGH_ACT
)
newmode
.
misc_output
&=
~
0x40
;
if
(
video_mode
->
sync
&
FB_SYNC_VERT_HIGH_ACT
)
newmode
.
misc_output
&=
~
0x80
;
rinfo
->
current_state
=
newmode
;
riva_load_state
(
rinfo
,
&
rinfo
->
current_state
);
rinfo
->
riva
.
LockUnlock
(
&
rinfo
->
riva
,
0
);
/* important for HW cursor */
rivafb_download_cursor
(
rinfo
);
}
/**
* riva_board_list_add - maintains board list
* @board_list: root node of list of boards
* @new_node: new node to be added
*
* DESCRIPTION:
* Adds @new_node to the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_init_one()
*/
static
struct
rivafb_info
*
riva_board_list_add
(
struct
rivafb_info
*
board_list
,
struct
rivafb_info
*
new_node
)
{
struct
rivafb_info
*
i_p
=
board_list
;
new_node
->
next
=
NULL
;
if
(
board_list
==
NULL
)
return
new_node
;
par
->
current_state
=
newmode
;
riva_load_state
(
par
,
&
par
->
current_state
);
while
(
i_p
->
next
!=
NULL
)
i_p
=
i_p
->
next
;
i_p
->
next
=
new_node
;
par
->
riva
.
LockUnlock
(
&
par
->
riva
,
0
);
/* important for HW cursor */
rivafb_download_cursor
(
par
);
return
board_list
;
}
/**
* riva_board_list_del - maintains board list
* @board_list: root node of list of boards
* @del_node: node to be removed
*
* DESCRIPTION:
* Removes @del_node from the list referenced by @board_list.
*
* RETURNS:
* New root node
*
* CALLED FROM:
* rivafb_remove_one()
*/
static
struct
rivafb_info
*
riva_board_list_del
(
struct
rivafb_info
*
board_list
,
struct
rivafb_info
*
del_node
)
{
struct
rivafb_info
*
i_p
=
board_list
;
if
(
board_list
==
del_node
)
return
del_node
->
next
;
while
(
i_p
->
next
!=
del_node
)
i_p
=
i_p
->
next
;
i_p
->
next
=
del_node
->
next
;
return
board_list
;
}
/**
* rivafb_do_maximize -
* @
info: pointer to
fb_info object containing info for current riva board
* @
rinfo: pointer to riva
fb_info object containing info for current riva board
* @var:
* @v:
* @nom:
* @den:
*
...
...
@@ -845,13 +987,13 @@ static void riva_load_video_mode(struct fb_info *info,
*
*
* CALLED FROM:
* rivafb_
check
_var()
* rivafb_
set
_var()
*/
static
int
rivafb_do_maximize
(
struct
fb_info
*
info
,
static
int
rivafb_do_maximize
(
struct
rivafb_info
*
r
info
,
struct
fb_var_screeninfo
*
var
,
struct
fb_var_screeninfo
*
v
,
int
nom
,
int
den
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
static
struct
{
int
xres
,
yres
;
}
modes
[]
=
{
...
...
@@ -865,12 +1007,12 @@ static int rivafb_do_maximize(struct fb_info *info,
int
i
;
/* use highest possible virtual resolution */
if
(
v
ar
->
xres_virtual
==
-
1
&&
var
->
yres_virtual
==
-
1
)
{
if
(
v
->
xres_virtual
==
-
1
&&
v
->
yres_virtual
==
-
1
)
{
printk
(
KERN_WARNING
PFX
"using maximum available virtual resolution
\n
"
);
for
(
i
=
0
;
modes
[
i
].
xres
!=
-
1
;
i
++
)
{
if
(
modes
[
i
].
xres
*
nom
/
den
*
modes
[
i
].
yres
<
par
->
ram_amount
/
2
)
rinfo
->
ram_amount
/
2
)
break
;
}
if
(
modes
[
i
].
xres
==
-
1
)
{
...
...
@@ -879,26 +1021,26 @@ static int rivafb_do_maximize(struct fb_info *info,
DPRINTK
(
"EXIT - EINVAL error
\n
"
);
return
-
EINVAL
;
}
v
ar
->
xres_virtual
=
modes
[
i
].
xres
;
v
ar
->
yres_virtual
=
modes
[
i
].
yres
;
v
->
xres_virtual
=
modes
[
i
].
xres
;
v
->
yres_virtual
=
modes
[
i
].
yres
;
printk
(
KERN_INFO
PFX
"virtual resolution set to maximum of %dx%d
\n
"
,
v
ar
->
xres_virtual
,
var
->
yres_virtual
);
}
else
if
(
v
ar
->
xres_virtual
==
-
1
)
{
v
ar
->
xres_virtual
=
(
par
->
ram_amount
*
den
/
(
nom
*
v
ar
->
yres_virtual
*
2
))
&
~
15
;
v
->
xres_virtual
,
v
->
yres_virtual
);
}
else
if
(
v
->
xres_virtual
==
-
1
)
{
v
->
xres_virtual
=
(
rinfo
->
ram_amount
*
den
/
(
nom
*
v
->
yres_virtual
*
2
))
&
~
15
;
printk
(
KERN_WARNING
PFX
"setting virtual X resolution to %d
\n
"
,
v
ar
->
xres_virtual
);
}
else
if
(
v
ar
->
yres_virtual
==
-
1
)
{
v
ar
->
xres_virtual
=
(
var
->
xres_virtual
+
15
)
&
~
15
;
v
ar
->
yres_virtual
=
par
->
ram_amount
*
den
/
(
nom
*
v
ar
->
xres_virtual
*
2
);
"setting virtual X resolution to %d
\n
"
,
v
->
xres_virtual
);
}
else
if
(
v
->
yres_virtual
==
-
1
)
{
v
->
xres_virtual
=
(
v
->
xres_virtual
+
15
)
&
~
15
;
v
->
yres_virtual
=
rinfo
->
ram_amount
*
den
/
(
nom
*
v
->
xres_virtual
*
2
);
printk
(
KERN_WARNING
PFX
"setting virtual Y resolution to %d
\n
"
,
v
ar
->
yres_virtual
);
"setting virtual Y resolution to %d
\n
"
,
v
->
yres_virtual
);
}
else
{
v
ar
->
xres_virtual
=
(
var
->
xres_virtual
+
15
)
&
~
15
;
if
(
v
ar
->
xres_virtual
*
nom
/
den
*
var
->
yres_virtual
>
par
->
ram_amount
)
{
v
->
xres_virtual
=
(
v
->
xres_virtual
+
15
)
&
~
15
;
if
(
v
->
xres_virtual
*
nom
/
den
*
v
->
yres_virtual
>
rinfo
->
ram_amount
)
{
printk
(
KERN_ERR
PFX
"mode %dx%dx%d rejected...resolution too high to fit into video memory!
\n
"
,
var
->
xres
,
var
->
yres
,
var
->
bits_per_pixel
);
...
...
@@ -907,146 +1049,29 @@ static int rivafb_do_maximize(struct fb_info *info,
}
}
if
(
v
ar
->
xres_virtual
*
nom
/
den
>=
8192
)
{
if
(
v
->
xres_virtual
*
nom
/
den
>=
8192
)
{
printk
(
KERN_WARNING
PFX
"virtual X resolution (%d) is too high, lowering to %d
\n
"
,
v
ar
->
xres_virtual
,
8192
*
den
/
nom
-
16
);
v
ar
->
xres_virtual
=
8192
*
den
/
nom
-
16
;
v
->
xres_virtual
,
8192
*
den
/
nom
-
16
);
v
->
xres_virtual
=
8192
*
den
/
nom
-
16
;
}
if
(
v
ar
->
xres_virtual
<
var
->
xres
)
{
if
(
v
->
xres_virtual
<
v
->
xres
)
{
printk
(
KERN_ERR
PFX
"virtual X resolution (%d) is smaller than real
\n
"
,
v
ar
->
xres_virtual
);
"virtual X resolution (%d) is smaller than real
\n
"
,
v
->
xres_virtual
);
return
-
EINVAL
;
}
if
(
v
ar
->
yres_virtual
<
var
->
yres
)
{
if
(
v
->
yres_virtual
<
v
->
yres
)
{
printk
(
KERN_ERR
PFX
"virtual Y resolution (%d) is smaller than real
\n
"
,
v
ar
->
yres_virtual
);
"virtual Y resolution (%d) is smaller than real
\n
"
,
v
->
yres_virtual
);
return
-
EINVAL
;
}
return
0
;
}
/* acceleration routines */
static
inline
void
convert_bgcolor_16
(
u32
*
col
)
{
*
col
=
((
*
col
&
0x00007C00
)
<<
9
)
|
((
*
col
&
0x000003E0
)
<<
6
)
|
((
*
col
&
0x0000001F
)
<<
3
)
|
0xFF000000
;
}
inline
void
wait_for_idle
(
struct
riva_par
*
par
)
{
while
(
par
->
riva
.
Busy
(
&
par
->
riva
));
}
/* set copy ROP, no mask */
static
void
riva_setup_ROP
(
struct
riva_par
*
par
)
{
RIVA_FIFO_FREE
(
par
->
riva
,
Patt
,
5
);
par
->
riva
.
Patt
->
Shape
=
0
;
par
->
riva
.
Patt
->
Color0
=
0xffffffff
;
par
->
riva
.
Patt
->
Color1
=
0xffffffff
;
par
->
riva
.
Patt
->
Monochrome
[
0
]
=
0xffffffff
;
par
->
riva
.
Patt
->
Monochrome
[
1
]
=
0xffffffff
;
RIVA_FIFO_FREE
(
par
->
riva
,
Rop
,
1
);
par
->
riva
.
Rop
->
Rop3
=
0xCC
;
}
void
riva_setup_accel
(
struct
riva_par
*
par
)
{
RIVA_FIFO_FREE
(
par
->
riva
,
Clip
,
2
);
par
->
riva
.
Clip
->
TopLeft
=
0x0
;
par
->
riva
.
Clip
->
WidthHeight
=
0x80008000
;
riva_setup_ROP
(
par
);
wait_for_idle
(
par
);
}
static
inline
void
reverse_order
(
u32
*
l
)
{
u8
*
a
=
(
u8
*
)
l
;
*
a
++
=
byte_rev
[
*
a
];
/* *a++ = byte_rev[*a];
*a++ = byte_rev[*a];*/
*
a
=
byte_rev
[
*
a
];
}
static
void
rivafb_fillrect
(
struct
fb_info
*
info
,
struct
fb_fillrect
*
rect
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
RIVA_FIFO_FREE
(
par
->
riva
,
Rop
,
1
);
par
->
riva
.
Rop
->
Rop3
=
rect
->
rop
?
0x66
:
0xCC
;
RIVA_FIFO_FREE
(
par
->
riva
,
Bitmap
,
1
);
if
(
info
->
fix
.
visual
==
FB_VISUAL_TRUECOLOR
)
par
->
riva
.
Bitmap
->
Color1A
=
((
u32
*
)
(
info
->
pseudo_palette
))[
rect
->
color
];
else
par
->
riva
.
Bitmap
->
Color1A
=
rect
->
color
;
RIVA_FIFO_FREE
(
par
->
riva
,
Bitmap
,
2
);
par
->
riva
.
Bitmap
->
UnclippedRectangle
[
0
].
TopLeft
=
(
rect
->
dx
<<
16
)
|
rect
->
dy
;
par
->
riva
.
Bitmap
->
UnclippedRectangle
[
0
].
WidthHeight
=
(
rect
->
width
<<
16
)
|
rect
->
height
;
RIVA_FIFO_FREE
(
par
->
riva
,
Rop
,
1
);
par
->
riva
.
Rop
->
Rop3
=
0xCC
;
// back to COPY
}
static
void
rivafb_copyarea
(
struct
fb_info
*
info
,
struct
fb_copyarea
*
area
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
RIVA_FIFO_FREE
(
par
->
riva
,
Blt
,
3
);
par
->
riva
.
Blt
->
TopLeftSrc
=
(
area
->
sy
<<
16
)
|
area
->
sx
;
par
->
riva
.
Blt
->
TopLeftDst
=
(
area
->
dy
<<
16
)
|
area
->
dx
;
par
->
riva
.
Blt
->
WidthHeight
=
(
area
->
height
<<
16
)
|
area
->
width
;
}
static
void
rivafb_imageblit
(
struct
fb_info
*
info
,
struct
fb_image
*
image
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
volatile
u32
*
d
;
int
i
,
j
,
cnt
;
u32
cdat2
;
RIVA_FIFO_FREE
(
par
->
riva
,
Bitmap
,
7
);
par
->
riva
.
Bitmap
->
ClipE
.
TopLeft
=
(
image
->
dy
<<
16
)
|
(
image
->
dx
&
0xFFFF
);
par
->
riva
.
Bitmap
->
ClipE
.
BottomRight
=
((
image
->
dy
+
image
->
height
)
<<
16
)
|
((
image
->
dx
+
image
->
width
)
&
0xffff
);
if
(
info
->
var
.
green
.
length
==
6
)
convert_bgcolor_16
(
&
image
->
bg_color
);
if
(
info
->
fix
.
visual
==
FB_VISUAL_TRUECOLOR
)
{
par
->
riva
.
Bitmap
->
Color0E
=
((
u32
*
)
(
info
->
pseudo_palette
))[
image
->
bg_color
];
par
->
riva
.
Bitmap
->
Color1E
=
((
u32
*
)
(
info
->
pseudo_palette
))[
image
->
fg_color
];
}
else
{
par
->
riva
.
Bitmap
->
Color0E
=
image
->
bg_color
;
par
->
riva
.
Bitmap
->
Color1E
=
image
->
fg_color
;
}
par
->
riva
.
Bitmap
->
WidthHeightInE
=
(
image
->
height
<<
16
)
|
32
;
par
->
riva
.
Bitmap
->
WidthHeightOutE
=
(
image
->
height
<<
16
)
|
32
;
par
->
riva
.
Bitmap
->
PointE
=
(
image
->
dy
<<
16
)
|
(
image
->
dx
&
0xFFFF
);
d
=
&
par
->
riva
.
Bitmap
->
MonochromeData01E
;
for
(
i
=
image
->
height
;
i
>
0
;
i
-=
16
)
{
if
(
i
>=
16
)
cnt
=
16
;
else
cnt
=
i
;
RIVA_FIFO_FREE
(
par
->
riva
,
Bitmap
,
cnt
);
for
(
j
=
0
;
j
<
cnt
;
j
++
)
{
if
(
image
->
width
<=
8
)
cdat2
=
*
image
->
data
++
;
else
cdat2
=
*
((
u16
*
)
image
->
data
)
++
;
reverse_order
(
&
cdat2
);
d
[
j
]
=
cdat2
;
}
}
}
/* ------------------------------------------------------------------------- *
*
...
...
@@ -1065,7 +1090,10 @@ static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
* Length of color map
*
* CALLED FROM:
* riva_getcolreg()
* rivafb_setcolreg()
* rivafb_get_cmap()
* rivafb_set_cmap()
*/
static
int
riva_get_cmap_len
(
const
struct
fb_var_screeninfo
*
var
)
{
...
...
@@ -1074,18 +1102,24 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert
(
var
!=
NULL
);
switch
(
var
->
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
rc
=
256
;
/* pseudocolor... 256 entries HW palette */
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
15
:
rc
=
15
;
/* fix for 15 bpp depths on Riva 128 based cards */
break
;
case
16
:
rc
=
16
;
/* directcolor... 16 entries SW palette */
break
;
/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
#ifdef FBCON_HAS_CFB32
case
32
:
rc
=
16
;
/* directcolor... 16 entries SW palette */
break
;
/* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
#endif
default:
/* should not occur */
break
;
...
...
@@ -1094,6 +1128,46 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
return
rc
;
}
/**
* riva_getcolreg
* @regno: register index
* @red: red component
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to rivafb_info object containing info for current riva board
*
* DESCRIPTION:
* Read a single color register and split it into colors/transparent.
* The return values must have a 16 bit magnitude.
*
* RETURNS:
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_get_cmap()
* rivafb_switch()
* fbcmap.c:fb_get_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:fbgen_switch()
*/
static
int
riva_getcolreg
(
unsigned
regno
,
unsigned
*
red
,
unsigned
*
green
,
unsigned
*
blue
,
unsigned
*
transp
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
if
(
regno
>=
riva_get_cmap_len
(
&
rivainfo
->
currcon_display
->
var
))
return
1
;
*
red
=
rivainfo
->
palette
[
regno
].
red
;
*
green
=
rivainfo
->
palette
[
regno
].
green
;
*
blue
=
rivainfo
->
palette
[
regno
].
blue
;
*
transp
=
0
;
return
0
;
}
/**
* rivafb_setcolreg
* @regno: register index
...
...
@@ -1101,7 +1175,7 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
* @green: green component
* @blue: blue component
* @transp: transparency
* @info: pointer to fb_info object containing info for current riva board
* @info: pointer to
riva
fb_info object containing info for current riva board
*
* DESCRIPTION:
* Set a single color register. The values supplied have a 16 bit
...
...
@@ -1111,54 +1185,79 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
* Return != 0 for invalid regno.
*
* CALLED FROM:
* rivafb_set_cmap()
* fbcmap.c:fb_set_cmap()
* fbgen.c:gen_get_cmap()
* fbgen.c:fbgen_get_cmap()
* fbgen.c:do_install_cmap()
* fbgen.c:fbgen_set_var()
* fbgen.c:fbgen_switch()
* fbgen.c:fbgen_blank()
* fbgen.c:fbgen_blank()
*/
static
int
rivafb_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
RIVA_HW_INST
*
chip
=
&
par
->
riva
;
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
RIVA_HW_INST
*
chip
=
&
rivainfo
->
riva
;
struct
display
*
p
;
DPRINTK
(
"ENTER
\n
"
);
if
(
regno
>=
riva_get_cmap_len
(
&
info
->
var
))
assert
(
rivainfo
!=
NULL
);
assert
(
rivainfo
->
currcon_display
!=
NULL
);
p
=
rivainfo
->
currcon_display
;
if
(
regno
>=
riva_get_cmap_len
(
&
p
->
var
))
return
-
EINVAL
;
if
(
info
->
var
.
grayscale
)
{
rivainfo
->
palette
[
regno
].
red
=
red
;
rivainfo
->
palette
[
regno
].
green
=
green
;
rivainfo
->
palette
[
regno
].
blue
=
blue
;
if
(
p
->
var
.
grayscale
)
{
/* gray = 0.30*R + 0.59*G + 0.11*B */
red
=
green
=
blue
=
(
red
*
77
+
green
*
151
+
blue
*
28
)
>>
8
;
}
switch
(
info
->
var
.
bits_per_pixel
)
{
switch
(
p
->
var
.
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
/* "transparent" stuff is completely ignored. */
riva_wclut
(
chip
,
regno
,
red
>>
8
,
green
>>
8
,
blue
>>
8
);
break
;
#endif
/* FBCON_HAS_CFB8 */
#ifdef FBCON_HAS_CFB16
case
16
:
assert
(
regno
<
16
);
if
(
info
->
var
.
green
.
length
==
5
)
{
if
(
p
->
var
.
green
.
length
==
5
)
{
/* 0rrrrrgg gggbbbbb */
((
u16
*
)(
info
->
pseudo_palette
))[
regno
]
=
rivainfo
->
con_cmap
.
cfb16
[
regno
]
=
((
red
&
0xf800
)
>>
1
)
|
((
green
&
0xf800
)
>>
6
)
|
((
blue
&
0xf800
)
>>
11
);
}
else
{
/* rrrrrggg gggbbbbb */
((
u16
*
)(
info
->
pseudo_palette
))[
regno
]
=
rivainfo
->
con_cmap
.
cfb16
[
regno
]
=
((
red
&
0xf800
)
>>
0
)
|
((
green
&
0xf800
)
>>
5
)
|
((
blue
&
0xf800
)
>>
11
);
}
break
;
#endif
/* FBCON_HAS_CFB16 */
#ifdef FBCON_HAS_CFB32
case
32
:
assert
(
regno
<
16
);
((
u32
*
)(
info
->
pseudo_palette
))[
regno
]
=
rivainfo
->
con_cmap
.
cfb32
[
regno
]
=
((
red
&
0xff00
)
<<
8
)
|
((
green
&
0xff00
))
|
((
blue
&
0xff00
)
>>
8
);
break
;
#endif
/* FBCON_HAS_CFB32 */
default:
/* do nothing */
break
;
}
return
0
;
}
...
...
@@ -1170,58 +1269,177 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
*
* ------------------------------------------------------------------------- */
static
int
rivafb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
static
int
rivafb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
struct
display
*
p
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
fix
!=
NULL
);
assert
(
info
!=
NULL
);
assert
(
rivainfo
->
drvr_name
&&
rivainfo
->
drvr_name
[
0
]);
assert
(
rivainfo
->
fb_base_phys
>
0
);
assert
(
rivainfo
->
ram_amount
>
0
);
p
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
memset
(
fix
,
0
,
sizeof
(
struct
fb_fix_screeninfo
));
sprintf
(
fix
->
id
,
"nVidia %s"
,
rivainfo
->
drvr_name
);
fix
->
smem_start
=
rivainfo
->
fb_base_phys
;
fix
->
smem_len
=
rivainfo
->
ram_amount
;
fix
->
type
=
p
->
type
;
fix
->
type_aux
=
p
->
type_aux
;
fix
->
visual
=
p
->
visual
;
fix
->
xpanstep
=
1
;
fix
->
ypanstep
=
1
;
fix
->
ywrapstep
=
0
;
/* FIXME: no ywrap for now */
fix
->
line_length
=
p
->
line_length
;
fix
->
mmio_start
=
rivainfo
->
ctrl_base_phys
;
fix
->
mmio_len
=
rivainfo
->
base0_region_size
;
fix
->
smem_start
=
rivainfo
->
fb_base_phys
;
fix
->
smem_len
=
rivainfo
->
base1_region_size
;
switch
(
rivainfo
->
riva
.
Architecture
)
{
case
NV_ARCH_03
:
fix
->
accel
=
FB_ACCEL_NV3
;
break
;
case
NV_ARCH_04
:
/* riva_hw.c now doesn't distinguish between TNT & TNT2 */
fix
->
accel
=
FB_ACCEL_NV4
;
break
;
case
NV_ARCH_10
:
/* FIXME: ID for GeForce */
fix
->
accel
=
FB_ACCEL_NV4
;
break
;
}
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
info
!=
NULL
);
assert
(
var
!=
NULL
);
*
var
=
(
con
<
0
)
?
rivainfo
->
disp
.
var
:
fb_display
[
con
].
var
;
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
struct
display
*
dsp
;
struct
fb_var_screeninfo
v
;
int
nom
,
den
;
/* translating from pixels->bytes */
int
accel
;
unsigned
chgvar
=
0
;
switch
(
var
->
bits_per_pixel
)
{
DPRINTK
(
"ENTER
\n
"
);
assert
(
info
!=
NULL
);
assert
(
var
!=
NULL
);
DPRINTK
(
"Requested: %dx%dx%d
\n
"
,
var
->
xres
,
var
->
yres
,
var
->
bits_per_pixel
);
DPRINTK
(
" virtual: %dx%d
\n
"
,
var
->
xres_virtual
,
var
->
yres_virtual
);
DPRINTK
(
" offset: (%d,%d)
\n
"
,
var
->
xoffset
,
var
->
yoffset
);
DPRINTK
(
"grayscale: %d
\n
"
,
var
->
grayscale
);
dsp
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
assert
(
dsp
!=
NULL
);
/* if var has changed, we should call changevar() later */
if
(
con
>=
0
)
{
chgvar
=
((
dsp
->
var
.
xres
!=
var
->
xres
)
||
(
dsp
->
var
.
yres
!=
var
->
yres
)
||
(
dsp
->
var
.
xres_virtual
!=
var
->
xres_virtual
)
||
(
dsp
->
var
.
yres_virtual
!=
var
->
yres_virtual
)
||
(
dsp
->
var
.
accel_flags
!=
var
->
accel_flags
)
||
(
dsp
->
var
.
bits_per_pixel
!=
var
->
bits_per_pixel
)
||
memcmp
(
&
dsp
->
var
.
red
,
&
var
->
red
,
sizeof
(
var
->
red
))
||
memcmp
(
&
dsp
->
var
.
green
,
&
var
->
green
,
sizeof
(
var
->
green
))
||
memcmp
(
&
dsp
->
var
.
blue
,
&
var
->
blue
,
sizeof
(
var
->
blue
)));
}
memcpy
(
&
v
,
var
,
sizeof
(
v
));
accel
=
v
.
accel_flags
&
FB_ACCELF_TEXT
;
switch
(
v
.
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB8
case
1
...
8
:
v
ar
->
bits_per_pixel
=
8
;
v
.
bits_per_pixel
=
8
;
nom
=
1
;
den
=
1
;
v
ar
->
red
.
offset
=
0
;
v
ar
->
red
.
length
=
8
;
v
ar
->
green
.
offset
=
0
;
v
ar
->
green
.
length
=
8
;
v
ar
->
blue
.
offset
=
0
;
v
ar
->
blue
.
length
=
8
;
v
.
red
.
offset
=
0
;
v
.
red
.
length
=
8
;
v
.
green
.
offset
=
0
;
v
.
green
.
length
=
8
;
v
.
blue
.
offset
=
0
;
v
.
blue
.
length
=
8
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
9
...
15
:
v
ar
->
green
.
length
=
5
;
v
.
green
.
length
=
5
;
/* fall through */
case
16
:
v
ar
->
bits_per_pixel
=
16
;
v
.
bits_per_pixel
=
16
;
nom
=
2
;
den
=
1
;
if
(
v
ar
->
green
.
length
==
5
)
{
if
(
v
.
green
.
length
==
5
)
{
/* 0rrrrrgg gggbbbbb */
v
ar
->
red
.
offset
=
10
;
v
ar
->
green
.
offset
=
5
;
v
ar
->
blue
.
offset
=
0
;
v
ar
->
red
.
length
=
5
;
v
ar
->
green
.
length
=
5
;
v
ar
->
blue
.
length
=
5
;
v
.
red
.
offset
=
10
;
v
.
green
.
offset
=
5
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
5
;
v
.
green
.
length
=
5
;
v
.
blue
.
length
=
5
;
}
else
{
/* rrrrrggg gggbbbbb */
v
ar
->
red
.
offset
=
11
;
v
ar
->
green
.
offset
=
5
;
v
ar
->
blue
.
offset
=
0
;
v
ar
->
red
.
length
=
5
;
v
ar
->
green
.
length
=
6
;
v
ar
->
blue
.
length
=
5
;
v
.
red
.
offset
=
11
;
v
.
green
.
offset
=
5
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
5
;
v
.
green
.
length
=
6
;
v
.
blue
.
length
=
5
;
}
break
;
#endif
#ifdef FBCON_HAS_CFB32
case
17
...
32
:
v
ar
->
bits_per_pixel
=
32
;
v
.
bits_per_pixel
=
32
;
nom
=
4
;
den
=
1
;
v
ar
->
red
.
offset
=
16
;
v
ar
->
green
.
offset
=
8
;
v
ar
->
blue
.
offset
=
0
;
v
ar
->
red
.
length
=
8
;
v
ar
->
green
.
length
=
8
;
v
ar
->
blue
.
length
=
8
;
v
.
red
.
offset
=
16
;
v
.
green
.
offset
=
8
;
v
.
blue
.
offset
=
0
;
v
.
red
.
length
=
8
;
v
.
green
.
length
=
8
;
v
.
blue
.
length
=
8
;
break
;
#endif
default:
printk
(
KERN_ERR
PFX
"mode %dx%dx%d rejected...color depth not supported.
\n
"
,
...
...
@@ -1230,57 +1448,122 @@ static int rivafb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return
-
EINVAL
;
}
if
(
rivafb_do_maximize
(
info
,
var
,
nom
,
den
)
<
0
)
if
(
rivafb_do_maximize
(
rivainfo
,
var
,
&
v
,
nom
,
den
)
<
0
)
return
-
EINVAL
;
if
(
v
ar
->
xoffset
<
0
)
v
ar
->
xoffset
=
0
;
if
(
v
ar
->
yoffset
<
0
)
v
ar
->
yoffset
=
0
;
if
(
v
.
xoffset
<
0
)
v
.
xoffset
=
0
;
if
(
v
.
yoffset
<
0
)
v
.
yoffset
=
0
;
/* truncate xoffset and yoffset to maximum if too high */
if
(
v
ar
->
xoffset
>
var
->
xres_virtual
-
var
->
xres
)
v
ar
->
xoffset
=
var
->
xres_virtual
-
var
->
xres
-
1
;
if
(
v
.
xoffset
>
v
.
xres_virtual
-
v
.
xres
)
v
.
xoffset
=
v
.
xres_virtual
-
v
.
xres
-
1
;
if
(
v
ar
->
yoffset
>
var
->
yres_virtual
-
var
->
yres
)
v
ar
->
yoffset
=
var
->
yres_virtual
-
var
->
yres
-
1
;
if
(
v
.
yoffset
>
v
.
yres_virtual
-
v
.
yres
)
v
.
yoffset
=
v
.
yres_virtual
-
v
.
yres
-
1
;
var
->
red
.
msb_right
=
var
->
green
.
msb_right
=
var
->
blue
.
msb_right
=
var
->
transp
.
offset
=
var
->
transp
.
length
=
var
->
transp
.
msb_right
=
0
;
var
->
accel_flags
|=
FB_ACCELF_TEXT
;
v
.
red
.
msb_right
=
v
.
green
.
msb_right
=
v
.
blue
.
msb_right
=
v
.
transp
.
offset
=
v
.
transp
.
length
=
v
.
transp
.
msb_right
=
0
;
switch
(
v
.
activate
&
FB_ACTIVATE_MASK
)
{
case
FB_ACTIVATE_TEST
:
DPRINTK
(
"EXIT - FB_ACTIVATE_TEST
\n
"
);
return
0
;
case
FB_ACTIVATE_NXTOPEN
:
/* ?? */
case
FB_ACTIVATE_NOW
:
break
;
/* continue */
default:
DPRINTK
(
"EXIT - unknown activation type
\n
"
);
return
-
EINVAL
;
/* unknown */
}
memcpy
(
&
dsp
->
var
,
&
v
,
sizeof
(
v
));
if
(
chgvar
)
{
riva_set_dispsw
(
rivainfo
,
dsp
);
if
(
accel
)
{
if
(
nomove
)
dsp
->
scrollmode
=
SCROLL_YNOMOVE
;
else
dsp
->
scrollmode
=
0
;
}
else
dsp
->
scrollmode
=
SCROLL_YREDRAW
;
if
(
info
&&
info
->
changevar
)
info
->
changevar
(
con
);
}
rivafb_create_cursor
(
rivainfo
,
fontwidth
(
dsp
),
fontheight
(
dsp
));
riva_load_video_mode
(
rivainfo
,
&
v
);
if
(
accel
)
riva_setup_accel
(
rivainfo
);
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_set_par
(
struct
fb_info
*
info
)
static
int
rivafb_get_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
struct
display
*
dsp
;
switch
(
info
->
var
.
bits_per_pixel
)
{
case
8
:
info
->
fix
.
line_length
=
info
->
var
.
xres_virtual
;
info
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
break
;
case
16
:
info
->
fix
.
line_length
=
info
->
var
.
xres_virtual
*
2
;
info
->
fix
.
visual
=
FB_VISUAL_DIRECTCOLOR
;
break
;
case
32
:
info
->
fix
.
line_length
=
info
->
var
.
xres_virtual
*
4
;
info
->
fix
.
visual
=
FB_VISUAL_DIRECTCOLOR
;
break
;
}
/*
if (par->cursor) {
disp->dispsw.cursor = rivafb_cursor;
disp->dispsw.set_font = rivafb_set_font;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rivainfo
!=
NULL
);
assert
(
cmap
!=
NULL
);
dsp
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
if
(
con
==
info
->
currcon
)
{
/* current console? */
int
rc
=
fb_get_cmap
(
cmap
,
kspc
,
riva_getcolreg
,
info
);
DPRINTK
(
"EXIT - returning %d
\n
"
,
rc
);
return
rc
;
}
else
if
(
dsp
->
cmap
.
len
)
/* non default colormap? */
fb_copy_cmap
(
&
dsp
->
cmap
,
cmap
,
kspc
?
0
:
2
);
else
fb_copy_cmap
(
fb_default_cmap
(
riva_get_cmap_len
(
&
dsp
->
var
)),
cmap
,
kspc
?
0
:
2
);
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_set_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
struct
display
*
dsp
;
unsigned
int
cmap_len
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rivainfo
!=
NULL
);
assert
(
cmap
!=
NULL
);
dsp
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
cmap_len
=
riva_get_cmap_len
(
&
dsp
->
var
);
if
(
dsp
->
cmap
.
len
!=
cmap_len
)
{
int
err
=
fb_alloc_cmap
(
&
dsp
->
cmap
,
cmap_len
,
0
);
if
(
err
)
{
DPRINTK
(
"EXIT - returning %d
\n
"
,
err
);
return
err
;
}
}
rivafb_create_cursor(par, fontwidth(dsp), fontheight(dsp));
*/
if
(
con
==
info
->
currcon
)
{
/* current console? */
int
rc
=
fb_set_cmap
(
cmap
,
kspc
,
info
);
DPRINTK
(
"EXIT - returning %d
\n
"
,
rc
);
return
rc
;
}
else
fb_copy_cmap
(
cmap
,
&
dsp
->
cmap
,
kspc
?
0
:
1
);
DPRINTK
(
"EXIT, returning 0
\n
"
);
riva_load_video_mode
(
info
,
&
info
->
var
);
riva_setup_accel
(
par
);
return
0
;
}
...
...
@@ -1288,7 +1571,7 @@ static int rivafb_set_par(struct fb_info *info)
* rivafb_pan_display
* @var: standard kernel fb changeable data
* @con: TODO
* @info: pointer to fb_info object containing info for current riva board
* @info: pointer to
riva
fb_info object containing info for current riva board
*
* DESCRIPTION:
* Pan (or wrap, depending on the `vmode' field) the display using the
...
...
@@ -1300,58 +1583,132 @@ static int rivafb_set_par(struct fb_info *info)
static
int
rivafb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
display
*
dsp
;
unsigned
int
base
;
struct
display
*
dsp
;
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rivainfo
!=
NULL
);
if
(
var
->
xoffset
>
(
var
->
xres_virtual
-
var
->
xres
))
return
-
EINVAL
;
if
(
var
->
yoffset
>
(
var
->
yres_virtual
-
var
->
yres
))
return
-
EINVAL
;
dsp
=
(
con
<
0
)
?
info
->
disp
:
&
fb_display
[
con
];
dsp
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
{
if
(
var
->
yoffset
<
0
||
var
->
yoffset
>=
info
->
var
.
yres_virtual
||
var
->
yoffset
>=
dsp
->
var
.
yres_virtual
||
var
->
xoffset
)
return
-
EINVAL
;
}
else
{
if
(
var
->
xoffset
+
info
->
var
.
xres
>
info
->
var
.
xres_virtual
||
var
->
yoffset
+
info
->
var
.
yres
>
info
->
var
.
yres_virtual
)
if
(
var
->
xoffset
+
dsp
->
var
.
xres
>
dsp
->
var
.
xres_virtual
||
var
->
yoffset
+
dsp
->
var
.
yres
>
dsp
->
var
.
yres_virtual
)
return
-
EINVAL
;
}
base
=
var
->
yoffset
*
dsp
->
line_length
+
var
->
xoffset
;
if
(
con
==
info
->
currcon
)
par
->
riva
.
SetStartAddress
(
&
par
->
riva
,
base
);
if
(
con
==
info
->
currcon
)
{
rivainfo
->
riva
.
SetStartAddress
(
&
rivainfo
->
riva
,
base
);
}
info
->
var
.
xoffset
=
var
->
xoffset
;
info
->
var
.
yoffset
=
var
->
yoffset
;
dsp
->
var
.
xoffset
=
var
->
xoffset
;
dsp
->
var
.
yoffset
=
var
->
yoffset
;
if
(
var
->
vmode
&
FB_VMODE_YWRAP
)
info
->
var
.
vmode
|=
FB_VMODE_YWRAP
;
dsp
->
var
.
vmode
|=
FB_VMODE_YWRAP
;
else
info
->
var
.
vmode
&=
~
FB_VMODE_YWRAP
;
dsp
->
var
.
vmode
&=
~
FB_VMODE_YWRAP
;
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
,
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rivainfo
!=
NULL
);
/* no rivafb-specific ioctls */
DPRINTK
(
"EXIT, returning -EINVAL
\n
"
);
return
-
EINVAL
;
}
static
int
rivafb_rasterimg
(
struct
fb_info
*
info
,
int
start
)
{
struct
riva
_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
struct
riva
fb_info
*
rinfo
=
(
struct
rivafb_info
*
)
info
;
wait_for_idle
(
par
);
wait_for_idle
(
rinfo
);
return
0
;
}
static
int
rivafb_switch
(
int
con
,
struct
fb_info
*
info
)
{
struct
rivafb_info
*
rivainfo
=
(
struct
rivafb_info
*
)
info
;
struct
fb_cmap
*
cmap
;
struct
display
*
dsp
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rivainfo
!=
NULL
);
dsp
=
(
con
<
0
)
?
rivainfo
->
info
.
disp
:
&
fb_display
[
con
];
if
(
info
->
currcon
>=
0
)
{
/* Do we have to save the colormap? */
cmap
=
&
(
rivainfo
->
currcon_display
->
cmap
);
DPRINTK
(
"switch1: con = %d, cmap.len = %d
\n
"
,
info
->
currcon
,
cmap
->
len
);
if
(
cmap
->
len
)
{
DPRINTK
(
"switch1a: %p %p %p %p
\n
"
,
cmap
->
red
,
cmap
->
green
,
cmap
->
blue
,
cmap
->
transp
);
fb_get_cmap
(
cmap
,
1
,
riva_getcolreg
,
info
);
}
}
info
->
currcon
=
con
;
rivainfo
->
currcon_display
=
dsp
;
rivafb_set_var
(
&
dsp
->
var
,
con
,
info
);
riva_set_dispsw
(
rivainfo
,
dsp
);
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
rivafb_updatevar
(
int
con
,
struct
fb_info
*
info
)
{
int
rc
;
DPRINTK
(
"ENTER
\n
"
);
rc
=
(
con
<
0
)
?
-
EINVAL
:
rivafb_pan_display
(
&
fb_display
[
con
].
var
,
con
,
info
);
DPRINTK
(
"EXIT, returning %d
\n
"
,
rc
);
return
rc
;
}
static
int
rivafb_blank
(
int
blank
,
struct
fb_info
*
info
)
{
struct
riva_par
*
par
=
(
struct
riva_par
*
)
info
->
par
;
unsigned
char
tmp
,
vesa
;
struct
rivafb_info
*
rinfo
=
(
struct
rivafb_info
*
)
info
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rinfo
!=
NULL
);
tmp
=
SEQin
(
par
,
0x01
)
&
~
0x20
;
/* screen on/off */
vesa
=
CRTCin
(
par
,
0x1a
)
&
~
0xc0
;
/* sync on/off */
tmp
=
SEQin
(
rinfo
,
0x01
)
&
~
0x20
;
/* screen on/off */
vesa
=
CRTCin
(
rinfo
,
0x1a
)
&
~
0xc0
;
/* sync on/off */
if
(
blank
)
{
tmp
|=
0x20
;
...
...
@@ -1370,11 +1727,15 @@ static int rivafb_blank(int blank, struct fb_info *info)
}
}
SEQout
(
par
,
0x01
,
tmp
);
CRTCout
(
par
,
0x1a
,
vesa
);
SEQout
(
rinfo
,
0x01
,
tmp
);
CRTCout
(
rinfo
,
0x1a
,
vesa
);
DPRINTK
(
"EXIT
\n
"
);
return
0
;
}
/* ------------------------------------------------------------------------- *
*
* initialization helper functions
...
...
@@ -1384,29 +1745,78 @@ static int rivafb_blank(int blank, struct fb_info *info)
/* kernel interface */
static
struct
fb_ops
riva_fb_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:
rivafb_check_var
,
fb_set_par:
rivafb_set_par
,
fb_get_fix:
rivafb_get_fix
,
fb_get_var:
rivafb_get_var
,
fb_set_var:
rivafb_set_var
,
fb_get_cmap:
rivafb_get_cmap
,
fb_set_cmap:
rivafb_set_cmap
,
fb_setcolreg:
rivafb_setcolreg
,
fb_pan_display:
rivafb_pan_display
,
fb_blank:
rivafb_blank
,
fb_fillrect:
rivafb_fillrect
,
fb_copyarea:
rivafb_copyarea
,
fb_imageblit:
rivafb_imageblit
,
fb_ioctl:
rivafb_ioctl
,
fb_rasterimg:
rivafb_rasterimg
,
};
static
int
__devinit
riva_set_fbinfo
(
struct
fb_info
*
info
)
static
int
__devinit
riva_init_disp_var
(
struct
rivafb_info
*
rinfo
)
{
#ifndef MODULE
if
(
mode_option
)
fb_find_mode
(
&
rinfo
->
disp
.
var
,
&
rinfo
->
info
,
mode_option
,
NULL
,
0
,
NULL
,
8
);
#endif
return
0
;
}
static
int
__devinit
riva_init_disp
(
struct
rivafb_info
*
rinfo
)
{
struct
fb_info
*
info
;
struct
display
*
disp
;
DPRINTK
(
"ENTER
\n
"
);
assert
(
rinfo
!=
NULL
);
info
=
&
rinfo
->
info
;
disp
=
&
rinfo
->
disp
;
disp
->
var
=
rivafb_default_var
;
if
(
noaccel
)
disp
->
var
.
accel_flags
&=
~
FB_ACCELF_TEXT
;
else
disp
->
var
.
accel_flags
|=
FB_ACCELF_TEXT
;
info
->
disp
=
disp
;
/* FIXME: assure that disp->cmap is completely filled out */
rinfo
->
currcon_display
=
disp
;
if
((
riva_init_disp_var
(
rinfo
))
<
0
)
{
DPRINTK
(
"EXIT, returning -1
\n
"
);
return
-
1
;
}
riva_set_dispsw
(
rinfo
,
disp
);
DPRINTK
(
"EXIT, returning 0
\n
"
);
return
0
;
}
static
int
__devinit
riva_set_fbinfo
(
struct
rivafb_info
*
rinfo
)
{
strcpy
(
info
->
modename
,
rivafb_fix
.
id
);
struct
fb_info
*
info
;
assert
(
rinfo
!=
NULL
);
info
=
&
rinfo
->
info
;
strcpy
(
info
->
modename
,
rinfo
->
drvr_name
);
info
->
node
=
NODEV
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
fbops
=
&
riva_fb_ops
;
info
->
fix
=
rivafb_fix
;
info
->
screen_base
=
rinfo
->
fb_base
;
/* FIXME: set monspecs to what??? */
info
->
display_fg
=
NULL
;
...
...
@@ -1415,21 +1825,12 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
info
->
fontname
[
sizeof
(
info
->
fontname
)
-
1
]
=
0
;
info
->
changevar
=
NULL
;
info
->
switch_con
=
gen
_switch
;
info
->
updatevar
=
gen_update_
var
;
info
->
switch_con
=
rivafb
_switch
;
info
->
updatevar
=
rivafb_update
var
;
#ifndef MODULE
if
(
mode_option
)
{
int
err
=
fb_find_mode
(
&
info
->
var
,
info
,
mode_option
,
NULL
,
0
,
NULL
,
8
);
if
(
!
err
||
err
==
4
)
info
->
var
=
rivafb_default_var
;
}
else
#endif
info
->
var
=
rivafb_default_var
;
fb_alloc_cmap
(
&
info
->
cmap
,
riva_get_cmap_len
(
&
info
->
var
),
0
);
if
(
riva_init_disp
(
rinfo
)
<
0
)
/* must be done last */
return
-
1
;
gen_set_var
(
&
info
->
var
,
-
1
,
info
);
return
0
;
}
...
...
@@ -1444,230 +1845,194 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
static
int
__devinit
rivafb_init_one
(
struct
pci_dev
*
pd
,
const
struct
pci_device_id
*
ent
)
{
struct
rivafb_info
*
rinfo
;
struct
riva_chip_info
*
rci
=
&
riva_chip_info
[
ent
->
driver_data
];
struct
riva_par
*
default_par
;
struct
fb_info
*
info
;
int
size
;
assert
(
pd
!=
NULL
);
assert
(
rci
!=
NULL
);
size
=
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
16
;
info
=
kmalloc
(
size
,
GFP_KERNEL
);
if
(
!
info
)
rinfo
=
kmalloc
(
sizeof
(
struct
rivafb_info
),
GFP_KERNEL
);
if
(
!
rinfo
)
goto
err_out
;
memset
(
info
,
0
,
size
);
default_par
=
kmalloc
(
sizeof
(
struct
riva_par
),
GFP_KERNEL
);
if
(
!
default_par
)
goto
err_out
;
memset
(
rinfo
,
0
,
sizeof
(
struct
rivafb_info
));
memset
(
default_par
,
0
,
sizeof
(
struct
riva_par
));
rinfo
->
drvr_name
=
rci
->
name
;
rinfo
->
riva
.
Architecture
=
rci
->
arch_rev
;
info
->
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)(
info
->
disp
+
1
);
rinfo
->
pd
=
pd
;
rinfo
->
base0_region_size
=
pci_resource_len
(
pd
,
0
);
rinfo
->
base1_region_size
=
pci_resource_len
(
pd
,
1
);
strcat
(
rivafb_fix
.
id
,
rci
->
name
);
default_par
->
riva
.
Architecture
=
rci
->
arch_rev
;
assert
(
rinfo
->
base0_region_size
>=
0x00800000
);
/* from GGI */
assert
(
rinfo
->
base1_region_size
>=
0x01000000
);
/* from GGI */
ri
vafb_fix
.
mmio_len
=
pci_resource_len
(
pd
,
0
);
ri
vafb_fix
.
smem_len
=
pci_resource_len
(
pd
,
1
);
ri
nfo
->
ctrl_base_phys
=
pci_resource_start
(
rinfo
->
pd
,
0
);
ri
nfo
->
fb_base_phys
=
pci_resource_start
(
rinfo
->
pd
,
1
);
assert
(
rivafb_fix
.
mmio_len
>=
0x00800000
);
/* from GGI */
assert
(
rivafb_fix
.
smem_len
>=
0x01000000
);
/* from GGI */
rivafb_fix
.
mmio_start
=
pci_resource_start
(
pd
,
0
);
rivafb_fix
.
smem_start
=
pci_resource_start
(
pd
,
1
);
if
(
!
request_mem_region
(
rivafb_fix
.
mmio_start
,
rivafb_fix
.
mmio_len
,
"rivafb"
))
{
if
(
!
request_mem_region
(
rinfo
->
ctrl_base_phys
,
rinfo
->
base0_region_size
,
"rivafb"
))
{
printk
(
KERN_ERR
PFX
"cannot reserve MMIO region
\n
"
);
goto
err_out_kfree
;
}
default_par
->
ctrl_base
=
ioremap
(
rivafb_fix
.
mmio_start
,
rivafb_fix
.
mmio_len
);
if
(
!
default_par
->
ctrl_base
)
{
if
(
!
request_mem_region
(
rinfo
->
fb_base_phys
,
rinfo
->
base1_region_size
,
"rivafb"
))
{
printk
(
KERN_ERR
PFX
"cannot reserve FB region
\n
"
);
goto
err_out_free_base0
;
}
rinfo
->
ctrl_base
=
ioremap
(
rinfo
->
ctrl_base_phys
,
rinfo
->
base0_region_size
);
if
(
!
rinfo
->
ctrl_base
)
{
printk
(
KERN_ERR
PFX
"cannot ioremap MMIO base
\n
"
);
goto
err_out_free_base1
;
}
default_par
->
riva
.
EnableIRQ
=
0
;
default_par
->
riva
.
PRAMDAC
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00680000
);
default_par
->
riva
.
PFB
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00100000
);
default_par
->
riva
.
PFIFO
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00002000
);
default_par
->
riva
.
PGRAPH
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00400000
);
default_par
->
riva
.
PEXTDEV
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00101000
);
default_par
->
riva
.
PTIMER
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00009000
);
default_par
->
riva
.
PMC
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00000000
);
default_par
->
riva
.
FIFO
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00800000
);
default_par
->
riva
.
PCIO
=
(
U008
*
)(
default_par
->
ctrl_base
+
0x00601000
);
default_par
->
riva
.
PDIO
=
(
U008
*
)(
default_par
->
ctrl_base
+
0x00681000
);
default_par
->
riva
.
PVIO
=
(
U008
*
)(
default_par
->
ctrl_base
+
0x000C0000
);
default_par
->
riva
.
IO
=
(
MISCin
(
default_par
)
&
0x01
)
?
0x3D0
:
0x3B0
;
switch
(
default_par
->
riva
.
Architecture
)
{
case
NV_ARCH_03
:
/*
* We have to map the full BASE_1 aperture for Riva128's
* because they use the PRAMIN set in "framebuffer" space
*/
if
(
!
request_mem_region
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
,
"rivafb"
))
{
printk
(
KERN_ERR
PFX
"cannot reserve FB region
\n
"
);
goto
err_out_free_base0
;
rinfo
->
fb_base
=
ioremap
(
rinfo
->
fb_base_phys
,
rinfo
->
base1_region_size
);
if
(
!
rinfo
->
fb_base
)
{
printk
(
KERN_ERR
PFX
"cannot ioremap FB base
\n
"
);
goto
err_out_iounmap_ctrl
;
}
#ifdef CONFIG_MTRR
if
(
!
nomtrr
)
{
rinfo
->
mtrr
.
vram
=
mtrr_add
(
rinfo
->
fb_base_phys
,
rinfo
->
base1_region_size
,
MTRR_TYPE_WRCOMB
,
1
);
if
(
rinfo
->
mtrr
.
vram
<
0
)
{
printk
(
KERN_ERR
PFX
"unable to setup MTRR
\n
"
);
}
else
{
rinfo
->
mtrr
.
vram_valid
=
1
;
/* let there be speed */
printk
(
KERN_INFO
PFX
"RIVA MTRR set to ON
\n
"
);
}
}
#endif
/* CONFIG_MTRR */
info
->
screen_base
=
ioremap
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
printk
(
KERN_ERR
PFX
"cannot ioremap FB base
\n
"
);
goto
err_out_iounmap_ctrl
;
}
rinfo
->
riva
.
EnableIRQ
=
0
;
rinfo
->
riva
.
PRAMDAC
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00680000
);
rinfo
->
riva
.
PFB
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00100000
);
rinfo
->
riva
.
PFIFO
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00002000
);
rinfo
->
riva
.
PGRAPH
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00400000
);
rinfo
->
riva
.
PEXTDEV
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00101000
);
rinfo
->
riva
.
PTIMER
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00009000
);
rinfo
->
riva
.
PMC
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00000000
);
rinfo
->
riva
.
FIFO
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00800000
);
rinfo
->
riva
.
PCIO
=
(
U008
*
)(
rinfo
->
ctrl_base
+
0x00601000
);
rinfo
->
riva
.
PDIO
=
(
U008
*
)(
rinfo
->
ctrl_base
+
0x00681000
);
rinfo
->
riva
.
PVIO
=
(
U008
*
)(
rinfo
->
ctrl_base
+
0x000C0000
);
default_par
->
riva
.
PRAMIN
=
(
unsigned
*
)(
info
->
screen_base
+
0x00C00000
);
rivafb_fix
.
accel
=
FB_ACCEL_NV3
;
rinfo
->
riva
.
IO
=
(
MISCin
(
rinfo
)
&
0x01
)
?
0x3D0
:
0x3B0
;
switch
(
rinfo
->
riva
.
Architecture
)
{
case
NV_ARCH_03
:
rinfo
->
riva
.
PRAMIN
=
(
unsigned
*
)(
rinfo
->
fb_base
+
0x00C00000
);
break
;
case
NV_ARCH_04
:
case
NV_ARCH_10
:
case
NV_ARCH_20
:
/* riva_hw.c now doesn't distinguish between TNT & TNT2 */
default_par
->
riva
.
PCRTC
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00600000
);
default_par
->
riva
.
PRAMIN
=
(
unsigned
*
)(
default_par
->
ctrl_base
+
0x00710000
);
rivafb_fix
.
accel
=
FB_ACCEL_NV4
;
rinfo
->
riva
.
PCRTC
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00600000
);
rinfo
->
riva
.
PRAMIN
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00710000
);
break
;
}
RivaGetConfig
(
&
default_par
->
riva
);
/* unlock io */
CRTCout
(
default_par
,
0x11
,
0xFF
);
/* vgaHWunlock()+riva unlock (0x7F) */
default_par
->
riva
.
LockUnlock
(
&
default_par
->
riva
,
0
);
riva_save_state
(
default_par
,
&
default_par
->
initial_state
);
default_par
->
ram_amount
=
default_par
->
riva
.
RamAmountKBytes
*
1024
;
default_par
->
dclk_max
=
default_par
->
riva
.
MaxVClockFreqKHz
*
1000
;
RivaGetConfig
(
&
rinfo
->
riva
);
if
(
default_par
->
riva
.
Architecture
!=
NV_ARCH_03
)
{
/*
* Now the _normal_ chipsets can just map the amount of real
* physical ram instead of the whole aperture
*/
rivafb_fix
.
smem_len
=
default_par
->
ram_amount
;
/* back to normal */
if
(
!
request_mem_region
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
,
"rivafb"
))
{
printk
(
KERN_ERR
PFX
"cannot reserve FB region
\n
"
);
goto
err_out_free_base0
;
}
assert
(
rinfo
->
pd
!=
NULL
);
info
->
screen_base
=
ioremap
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
printk
(
KERN_ERR
PFX
"cannot ioremap FB base
\n
"
);
goto
err_out_iounmap_ctrl
;
}
}
/* unlock io */
CRTCout
(
rinfo
,
0x11
,
0xFF
);
/* vgaHWunlock() + riva unlock (0x7F) */
rinfo
->
riva
.
LockUnlock
(
&
rinfo
->
riva
,
0
);
#ifdef CONFIG_MTRR
if
(
!
nomtrr
)
{
default_par
->
mtrr
.
vram
=
mtrr_add
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
,
MTRR_TYPE_WRCOMB
,
1
);
if
(
default_par
->
mtrr
.
vram
<
0
)
{
printk
(
KERN_ERR
PFX
"unable to setup MTRR
\n
"
);
}
else
{
default_par
->
mtrr
.
vram_valid
=
1
;
/* let there be speed */
printk
(
KERN_INFO
PFX
"RIVA MTRR set to ON
\n
"
);
}
}
#endif
/* CONFIG_MTRR */
riva_save_state
(
rinfo
,
&
rinfo
->
initial_state
);
if
(
!
nohwcursor
)
default_par
->
cursor
=
rivafb_init_cursor
(
info
);
rinfo
->
ram_amount
=
rinfo
->
riva
.
RamAmountKBytes
*
1024
;
rinfo
->
dclk_max
=
rinfo
->
riva
.
MaxVClockFreqKHz
*
1000
;
i
nfo
->
par
=
default_par
;
i
f
(
!
nohwcursor
)
rinfo
->
cursor
=
rivafb_init_cursor
(
rinfo
)
;
if
(
riva_set_fbinfo
(
info
)
<
0
)
{
if
(
riva_set_fbinfo
(
r
info
)
<
0
)
{
printk
(
KERN_ERR
PFX
"error setting initial video mode
\n
"
);
goto
err_out_cursor
;
}
if
(
register_framebuffer
(
info
)
<
0
)
{
if
(
register_framebuffer
(
(
struct
fb_info
*
)
r
info
)
<
0
)
{
printk
(
KERN_ERR
PFX
"error registering riva framebuffer
\n
"
);
goto
err_out_load_state
;
}
pci_set_drvdata
(
pd
,
info
);
riva_boards
=
riva_board_list_add
(
riva_boards
,
rinfo
);
pci_set_drvdata
(
pd
,
rinfo
);
printk
(
KERN_INFO
PFX
"PCI nVidia NV%
x
framebuffer ver %s (%s, %dMB @ 0x%lX)
\n
"
,
default_par
->
riva
.
Architecture
,
"PCI nVidia NV%
d
framebuffer ver %s (%s, %dMB @ 0x%lX)
\n
"
,
rinfo
->
riva
.
Architecture
,
RIVAFB_VERSION
,
info
->
fix
.
id
,
default_par
->
ram_amount
/
(
1024
*
1024
),
info
->
fix
.
smem_start
);
rinfo
->
drvr_name
,
rinfo
->
ram_amount
/
(
1024
*
1024
),
rinfo
->
fb_base_phys
);
return
0
;
err_out_load_state:
riva_load_state
(
default_par
,
&
default_par
->
initial_state
);
riva_load_state
(
rinfo
,
&
rinfo
->
initial_state
);
err_out_cursor:
rivafb_exit_cursor
(
default_par
);
rivafb_exit_cursor
(
rinfo
);
/* err_out_iounmap_fb: */
iounmap
(
info
->
screen
_base
);
iounmap
(
rinfo
->
fb
_base
);
err_out_iounmap_ctrl:
iounmap
(
default_par
->
ctrl_base
);
iounmap
(
rinfo
->
ctrl_base
);
err_out_free_base1:
release_mem_region
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
release_mem_region
(
rinfo
->
fb_base_phys
,
rinfo
->
base1_region_size
);
err_out_free_base0:
release_mem_region
(
info
->
fix
.
mmio_start
,
info
->
fix
.
mmio_len
);
release_mem_region
(
rinfo
->
ctrl_base_phys
,
rinfo
->
base0_region_size
);
err_out_kfree:
kfree
(
default_par
);
kfree
(
info
);
kfree
(
rinfo
);
err_out:
return
-
ENODEV
;
}
static
void
__devexit
rivafb_remove_one
(
struct
pci_dev
*
pd
)
{
struct
fb_info
*
board
=
pci_get_drvdata
(
pd
);
struct
riva_par
*
par
=
(
struct
riva_par
*
)
board
->
par
;
struct
rivafb_info
*
board
=
pci_get_drvdata
(
pd
);
if
(
!
board
)
return
;
riva_load_state
(
par
,
&
par
->
initial_state
);
riva_boards
=
riva_board_list_del
(
riva_boards
,
board
);
riva_load_state
(
board
,
&
board
->
initial_state
);
unregister_framebuffer
(
board
);
unregister_framebuffer
(
(
struct
fb_info
*
)
board
);
rivafb_exit_cursor
(
par
);
rivafb_exit_cursor
(
board
);
#ifdef CONFIG_MTRR
if
(
par
->
mtrr
.
vram_valid
)
mtrr_del
(
par
->
mtrr
.
vram
,
board
->
fix
.
smem_start
,
board
->
fix
.
smem_len
);
if
(
board
->
mtrr
.
vram_valid
)
mtrr_del
(
board
->
mtrr
.
vram
,
board
->
fb_base_phys
,
board
->
base1_region_size
);
#endif
/* CONFIG_MTRR */
iounmap
(
par
->
ctrl_base
);
iounmap
(
board
->
screen
_base
);
iounmap
(
board
->
ctrl_base
);
iounmap
(
board
->
fb
_base
);
release_mem_region
(
board
->
fix
.
mmio_start
,
board
->
fix
.
mmio_len
);
release_mem_region
(
board
->
f
ix
.
smem_start
,
board
->
fix
.
smem_len
);
release_mem_region
(
board
->
ctrl_base_phys
,
board
->
base0_region_size
);
release_mem_region
(
board
->
f
b_base_phys
,
board
->
base1_region_size
);
kfree
(
par
);
kfree
(
board
);
pci_set_drvdata
(
pd
,
NULL
);
}
/* ------------------------------------------------------------------------- *
*
* initialization
...
...
@@ -1698,6 +2063,10 @@ int __init rivafb_setup(char *options)
}
else
if
(
!
strncmp
(
this_opt
,
"noblink"
,
7
))
{
noblink
=
1
;
}
else
if
(
!
strncmp
(
this_opt
,
"noaccel"
,
7
))
{
noaccel
=
1
;
}
else
if
(
!
strncmp
(
this_opt
,
"nomove"
,
6
))
{
nomove
=
1
;
#ifdef CONFIG_MTRR
}
else
if
(
!
strncmp
(
this_opt
,
"nomtrr"
,
6
))
{
nomtrr
=
1
;
...
...
@@ -1750,6 +2119,10 @@ module_exit(rivafb_exit);
MODULE_PARM
(
font
,
"s"
);
MODULE_PARM_DESC
(
font
,
"Specifies one of the compiled-in fonts (default=none)"
);
MODULE_PARM
(
noaccel
,
"i"
);
MODULE_PARM_DESC
(
noaccel
,
"Disables hardware acceleration (0 or 1=disabled) (default=0)"
);
MODULE_PARM
(
nomove
,
"i"
);
MODULE_PARM_DESC
(
nomove
,
"Enables YSCROLL_NOMOVE (0 or 1=enabled) (default=0)"
);
MODULE_PARM
(
nohwcursor
,
"i"
);
MODULE_PARM_DESC
(
nohwcursor
,
"Disables hardware cursor (0 or 1=disabled) (default=0)"
);
MODULE_PARM
(
noblink
,
"i"
);
...
...
drivers/video/riva/riva_hw.c
View file @
2eaf7c63
...
...
@@ -1220,7 +1220,6 @@ static void CalcStateExt
state
->
repaint1
=
hDisplaySize
<
1280
?
0x04
:
0x00
;
break
;
case
NV_ARCH_10
:
case
NV_ARCH_20
:
nv10UpdateArbitrationSettings
(
VClk
,
pixelDepth
*
8
,
&
(
state
->
arbitration0
),
...
...
@@ -1286,7 +1285,6 @@ static void UpdateFifoState
chip
->
Tri05
=
(
RivaTexturedTriangle05
*
)
&
(
chip
->
FIFO
[
0x0000E000
/
4
]);
break
;
case
NV_ARCH_10
:
case
NV_ARCH_20
:
/*
* Initialize state for the RivaTriangle3D05 routines.
*/
...
...
@@ -1395,7 +1393,6 @@ static void LoadStateExt
chip
->
PGRAPH
[
0x0000067C
/
4
]
=
state
->
pitch3
;
break
;
case
NV_ARCH_10
:
case
NV_ARCH_20
:
LOAD_FIXED_STATE
(
nv10
,
PFIFO
);
LOAD_FIXED_STATE
(
nv10
,
PRAMIN
);
LOAD_FIXED_STATE
(
nv10
,
PGRAPH
);
...
...
@@ -1424,31 +1421,15 @@ static void LoadStateExt
chip
->
Tri03
=
0L
;
break
;
}
if
(
chip
->
Architecture
==
NV_ARCH_10
)
{
chip
->
PGRAPH
[
0x00000640
/
4
]
=
state
->
offset0
;
chip
->
PGRAPH
[
0x00000644
/
4
]
=
state
->
offset1
;
chip
->
PGRAPH
[
0x00000648
/
4
]
=
state
->
offset2
;
chip
->
PGRAPH
[
0x0000064C
/
4
]
=
state
->
offset3
;
chip
->
PGRAPH
[
0x00000670
/
4
]
=
state
->
pitch0
;
chip
->
PGRAPH
[
0x00000674
/
4
]
=
state
->
pitch1
;
chip
->
PGRAPH
[
0x00000678
/
4
]
=
state
->
pitch2
;
chip
->
PGRAPH
[
0x0000067C
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x00000680
/
4
]
=
state
->
pitch3
;
}
else
{
chip
->
PGRAPH
[
0x00000820
/
4
]
=
state
->
offset0
;
chip
->
PGRAPH
[
0x00000824
/
4
]
=
state
->
offset1
;
chip
->
PGRAPH
[
0x00000828
/
4
]
=
state
->
offset2
;
chip
->
PGRAPH
[
0x0000082C
/
4
]
=
state
->
offset3
;
chip
->
PGRAPH
[
0x00000850
/
4
]
=
state
->
pitch0
;
chip
->
PGRAPH
[
0x00000854
/
4
]
=
state
->
pitch1
;
chip
->
PGRAPH
[
0x00000858
/
4
]
=
state
->
pitch2
;
chip
->
PGRAPH
[
0x0000085C
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x00000860
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x00000864
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x000009A4
/
4
]
=
chip
->
PFB
[
0x00000200
/
4
];
chip
->
PGRAPH
[
0x000009A8
/
4
]
=
chip
->
PFB
[
0x00000204
/
4
];
}
chip
->
PGRAPH
[
0x00000640
/
4
]
=
state
->
offset0
;
chip
->
PGRAPH
[
0x00000644
/
4
]
=
state
->
offset1
;
chip
->
PGRAPH
[
0x00000648
/
4
]
=
state
->
offset2
;
chip
->
PGRAPH
[
0x0000064C
/
4
]
=
state
->
offset3
;
chip
->
PGRAPH
[
0x00000670
/
4
]
=
state
->
pitch0
;
chip
->
PGRAPH
[
0x00000674
/
4
]
=
state
->
pitch1
;
chip
->
PGRAPH
[
0x00000678
/
4
]
=
state
->
pitch2
;
chip
->
PGRAPH
[
0x0000067C
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x00000680
/
4
]
=
state
->
pitch3
;
chip
->
PGRAPH
[
0x00000B00
/
4
]
=
chip
->
PFB
[
0x00000240
/
4
];
chip
->
PGRAPH
[
0x00000B04
/
4
]
=
chip
->
PFB
[
0x00000244
/
4
];
chip
->
PGRAPH
[
0x00000B08
/
4
]
=
chip
->
PFB
[
0x00000248
/
4
];
...
...
@@ -1626,7 +1607,6 @@ static void UnloadStateExt
state
->
pitch3
=
chip
->
PGRAPH
[
0x0000067C
/
4
];
break
;
case
NV_ARCH_10
:
case
NV_ARCH_20
:
state
->
offset0
=
chip
->
PGRAPH
[
0x00000640
/
4
];
state
->
offset1
=
chip
->
PGRAPH
[
0x00000644
/
4
];
state
->
offset2
=
chip
->
PGRAPH
[
0x00000648
/
4
];
...
...
drivers/video/riva/riva_hw.h
View file @
2eaf7c63
...
...
@@ -74,8 +74,6 @@ typedef unsigned int U032;
#define NV_ARCH_03 0x03
#define NV_ARCH_04 0x04
#define NV_ARCH_10 0x10
#define NV_ARCH_20 0x20
/***************************************************************************\
* *
* FIFO registers. *
...
...
drivers/video/riva/rivafb.h
View file @
2eaf7c63
...
...
@@ -3,7 +3,6 @@
#include <linux/config.h>
#include <linux/fb.h>
#include <linux/timer.h>
#include <video/fbcon.h>
#include <video/fbcon-cfb4.h>
#include <video/fbcon-cfb8.h>
...
...
@@ -28,35 +27,58 @@ struct riva_regs {
RIVA_HW_STATE
ext
;
};
#define MAX_CURS 32
struct
riva_cursor
{
int
enable
;
int
on
;
int
vbl_cnt
;
int
last_slice_moves
,
prev_slice_moves
;
int
blink_rate
;
struct
{
u16
x
,
y
;
}
pos
,
size
;
unsigned
short
image
[
MAX_CURS
*
MAX_CURS
];
struct
timer_list
*
timer
;
};
typedef
struct
{
unsigned
char
red
,
green
,
blue
,
transp
;
}
riva_cfb8_cmap_t
;
struct
rivafb_info
;
struct
rivafb_info
{
struct
fb_info
info
;
/* kernel framebuffer info */
/* describes the state of a Riva board */
struct
riva_par
{
RIVA_HW_INST
riva
;
/* interface to riva_hw.c */
const
char
*
drvr_name
;
/* Riva hardware board type */
unsigned
long
ctrl_base_phys
;
/* physical control register base addr */
unsigned
long
fb_base_phys
;
/* physical framebuffer base addr */
caddr_t
ctrl_base
;
/* virtual control register base addr */
caddr_t
fb_base
;
/* virtual framebuffer base addr */
unsigned
ram_amount
;
/* amount of RAM on card, in bytes */
unsigned
dclk_max
;
/* max DCLK */
struct
riva_regs
initial_state
;
/* initial startup video mode */
struct
riva_regs
current_state
;
struct
display
disp
;
int
currcon
;
struct
display
*
currcon_display
;
struct
rivafb_info
*
next
;
struct
pci_dev
*
pd
;
/* pointer to board's pci info */
unsigned
base0_region_size
;
/* size of control register region */
unsigned
base1_region_size
;
/* size of framebuffer region */
struct
riva_cursor
*
cursor
;
caddr_t
ctrl_base
;
/* Virtual control register base addr */
struct
display_switch
dispsw
;
riva_cfb8_cmap_t
palette
[
256
];
/* VGA DAC palette cache */
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
union
{
#ifdef FBCON_HAS_CFB16
u_int16_t
cfb16
[
16
];
#endif
#ifdef FBCON_HAS_CFB32
u_int32_t
cfb32
[
16
];
#endif
}
con_cmap
;
#endif
/* FBCON_HAS_CFB16 | FBCON_HAS_CFB32 */
#ifdef CONFIG_MTRR
struct
{
int
vram
;
int
vram_valid
;
}
mtrr
;
struct
{
int
vram
;
int
vram_valid
;
}
mtrr
;
#endif
};
...
...
drivers/video/sa1100fb.c
View file @
2eaf7c63
...
...
@@ -661,7 +661,7 @@ static struct sa1100fb_mach_info xp860_info __initdata = {
static
struct
sa1100fb_mach_info
*
__init
sa1100fb_get_machine_info
(
struct
sa1100
_par
*
par
)
sa1100fb_get_machine_info
(
struct
sa1100
fb_info
*
fbi
)
{
struct
sa1100fb_mach_info
*
inf
=
NULL
;
...
...
@@ -683,7 +683,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_H3XXX
if
(
machine_is_h3600
())
{
inf
=
&
h3600_info
;
par
->
rgb
[
RGB_16
]
=
&
h3600_rgb_16
;
fbi
->
rgb
[
RGB_16
]
=
&
h3600_rgb_16
;
}
if
(
machine_is_h3100
())
{
inf
=
&
h3100_info
;
...
...
@@ -705,7 +705,7 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
#ifdef CONFIG_SA1100_FREEBIRD
if
(
machine_is_freebird
())
{
inf
=
&
freebird_info
;
par
->
rgb
[
RGB_16
]
=
&
freebird_rgb16
;
fbi
->
rgb
[
RGB_16
]
=
&
freebird_rgb16
;
}
#endif
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
...
...
@@ -758,10 +758,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
if
(
machine_is_stork
())
{
#if STORK_TFT
inf
=
&
stork_tft_info
;
par
->
rgb
[
RGB_16
]
=
&
stork_tft_rgb_16
;
fbi
->
rgb
[
RGB_16
]
=
&
stork_tft_rgb_16
;
#else
inf
=
&
stork_dstn_info
;
par
->
rgb
[
RGB_16
]
=
&
stork_dstn_rgb_16
;
fbi
->
rgb
[
RGB_16
]
=
&
stork_dstn_rgb_16
;
#endif
}
#endif
...
...
@@ -773,10 +773,10 @@ sa1100fb_get_machine_info(struct sa1100_par *par)
return
inf
;
}
static
int
sa1100fb_activate_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
);
static
void
set_ctrlr_state
(
struct
sa1100
_par
*
par
,
u_int
state
);
static
int
sa1100fb_activate_var
(
struct
fb_var_screeninfo
*
var
,
struct
sa1100
fb_info
*
);
static
void
set_ctrlr_state
(
struct
sa1100
fb_info
*
fbi
,
u_int
state
);
static
inline
void
sa1100fb_schedule_task
(
struct
sa1100
_par
*
par
,
u_int
state
)
static
inline
void
sa1100fb_schedule_task
(
struct
sa1100
fb_info
*
fbi
,
u_int
state
)
{
unsigned
long
flags
;
...
...
@@ -789,18 +789,43 @@ static inline void sa1100fb_schedule_task(struct sa1100_par *par, u_int state)
* 2. When we are blanking, but immediately unblank before we have
* blanked. We do the "REENABLE" thing here as well, just to be sure.
*/
if
(
par
->
task_state
==
C_ENABLE
&&
state
==
C_REENABLE
)
if
(
fbi
->
task_state
==
C_ENABLE
&&
state
==
C_REENABLE
)
state
=
(
u_int
)
-
1
;
if
(
par
->
task_state
==
C_DISABLE
&&
state
==
C_ENABLE
)
if
(
fbi
->
task_state
==
C_DISABLE
&&
state
==
C_ENABLE
)
state
=
C_REENABLE
;
if
(
state
!=
(
u_int
)
-
1
)
{
par
->
task_state
=
state
;
schedule_task
(
&
par
->
task
);
fbi
->
task_state
=
state
;
schedule_task
(
&
fbi
->
task
);
}
local_irq_restore
(
flags
);
}
/*
* Get the VAR structure pointer for the specified console
*/
static
inline
struct
fb_var_screeninfo
*
get_con_var
(
struct
fb_info
*
info
,
int
con
)
{
return
(
con
==
info
->
currcon
||
con
==
-
1
)
?
&
info
->
var
:
&
fb_display
[
con
].
var
;
}
/*
* Get the DISPLAY structure pointer for the specified console
*/
static
inline
struct
display
*
get_con_display
(
struct
fb_info
*
info
,
int
con
)
{
struct
sa1100fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
return
(
con
<
0
)
?
fbi
->
fb
.
disp
:
&
fb_display
[
con
];
}
/*
* Get the CMAP pointer for the specified console
*/
static
inline
struct
fb_cmap
*
get_con_cmap
(
struct
fb_info
*
info
,
int
con
)
{
return
(
con
==
info
->
currcon
||
con
==
-
1
)
?
&
info
->
cmap
:
&
fb_display
[
con
].
cmap
;
}
static
inline
u_int
chan_to_field
(
u_int
chan
,
struct
fb_bitfield
*
bf
)
{
...
...
@@ -813,13 +838,19 @@ chan_to_field(u_int chan, struct fb_bitfield *bf)
* Convert bits-per-pixel to a hardware palette PBS value.
*/
static
inline
u_int
palette_pbs
(
int
bpp
)
palette_pbs
(
struct
fb_var_screeninfo
*
var
)
{
int
ret
=
0
;
switch
(
bpp
)
{
switch
(
var
->
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB4
case
4
:
ret
=
0
<<
12
;
break
;
#endif
#ifdef FBCON_HAS_CFB8
case
8
:
ret
=
1
<<
12
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
ret
=
2
<<
12
;
break
;
#endif
}
return
ret
;
}
...
...
@@ -828,18 +859,18 @@ static int
sa1100fb_setpalettereg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
trans
,
struct
fb_info
*
info
)
{
struct
sa1100
_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
struct
sa1100
fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
u_int
val
,
ret
=
1
;
if
(
regno
<
par
->
palette_size
)
{
if
(
regno
<
fbi
->
palette_size
)
{
val
=
((
red
>>
4
)
&
0xf00
);
val
|=
((
green
>>
8
)
&
0x0f0
);
val
|=
((
blue
>>
12
)
&
0x00f
);
if
(
regno
==
0
)
val
|=
palette_pbs
(
info
->
var
.
bits_per_pixel
);
val
|=
palette_pbs
(
&
fbi
->
fb
.
var
);
par
->
palette_cpu
[
regno
]
=
val
;
fbi
->
palette_cpu
[
regno
]
=
val
;
ret
=
0
;
}
return
ret
;
...
...
@@ -849,6 +880,8 @@ static int
sa1100fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
trans
,
struct
fb_info
*
info
)
{
struct
sa1100fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
struct
display
*
disp
=
get_con_display
(
info
,
info
->
currcon
);
u_int
val
;
int
ret
=
1
;
...
...
@@ -857,34 +890,33 @@ sa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
* rather than the register number. The register number
* is what you poke into the framebuffer to produce the
* colour you requested.
*
if (inverse) {
*
/
if
(
disp
->
inverse
)
{
red
=
0xffff
-
red
;
green
=
0xffff
-
green
;
blue
=
0xffff
-
blue
;
}
*/
/*
* If greyscale is true, then we convert the RGB value
* to greyscale no mater what visual we are using.
*/
if
(
info
->
var
.
grayscale
)
if
(
fbi
->
fb
.
var
.
grayscale
)
red
=
green
=
blue
=
(
19595
*
red
+
38470
*
green
+
7471
*
blue
)
>>
16
;
switch
(
info
->
fix
.
visual
)
{
switch
(
fbi
->
fb
.
disp
->
visual
)
{
case
FB_VISUAL_TRUECOLOR
:
/*
* 12 or 16-bit True Colour. We encode the RGB value
* according to the RGB bitfield information.
*/
if
(
regno
<
16
)
{
u16
*
pal
=
info
->
pseudo_palette
;
u16
*
pal
=
fbi
->
fb
.
pseudo_palette
;
val
=
chan_to_field
(
red
,
&
info
->
var
.
red
);
val
|=
chan_to_field
(
green
,
&
info
->
var
.
green
);
val
|=
chan_to_field
(
blue
,
&
info
->
var
.
blue
);
val
=
chan_to_field
(
red
,
&
fbi
->
fb
.
var
.
red
);
val
|=
chan_to_field
(
green
,
&
fbi
->
fb
.
var
.
green
);
val
|=
chan_to_field
(
blue
,
&
fbi
->
fb
.
var
.
blue
);
pal
[
regno
]
=
val
;
ret
=
0
;
...
...
@@ -931,20 +963,19 @@ sa1100fb_display_dma_period(struct fb_var_screeninfo *var)
* bitfields, horizontal timing, vertical timing.
*/
static
int
sa1100fb_
check
_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
sa1100fb_
validate
_var
(
struct
fb_var_screeninfo
*
var
,
struct
sa1100fb_info
*
fbi
)
{
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
int
rgbidx
=
RGB_16
,
ret
=
-
EINVAL
;
int
ret
=
-
EINVAL
;
if
(
var
->
xres
<
MIN_XRES
)
var
->
xres
=
MIN_XRES
;
if
(
var
->
yres
<
MIN_YRES
)
var
->
yres
=
MIN_YRES
;
if
(
var
->
xres
>
par
->
max_xres
)
var
->
xres
=
par
->
max_xres
;
if
(
var
->
yres
>
par
->
max_yres
)
var
->
yres
=
par
->
max_yres
;
if
(
var
->
xres
>
fbi
->
max_xres
)
var
->
xres
=
fbi
->
max_xres
;
if
(
var
->
yres
>
fbi
->
max_yres
)
var
->
yres
=
fbi
->
max_yres
;
var
->
xres_virtual
=
var
->
xres_virtual
<
var
->
xres
?
var
->
xres
:
var
->
xres_virtual
;
var
->
yres_virtual
=
...
...
@@ -952,22 +983,23 @@ sa1100fb_check_var(struct fb_var_screeninfo *var,
DPRINTK
(
"var->bits_per_pixel=%d
\n
"
,
var
->
bits_per_pixel
);
switch
(
var
->
bits_per_pixel
)
{
case
4
:
rgbidx
=
RGB_8
;
ret
=
0
;
break
;
case
8
:
rgbidx
=
RGB_8
;
ret
=
0
;
break
;
case
16
:
rgbidx
=
RGB_16
;
ret
=
0
;
break
;
#ifdef FBCON_HAS_CFB4
case
4
:
ret
=
0
;
break
;
#endif
#ifdef FBCON_HAS_CFB8
case
8
:
ret
=
0
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
ret
=
0
;
break
;
#endif
default:
break
;
}
var
->
red
=
par
->
rgb
[
rgbidx
]
->
red
;
var
->
green
=
par
->
rgb
[
rgbidx
]
->
green
;
var
->
blue
=
par
->
rgb
[
rgbidx
]
->
blue
;
var
->
transp
=
par
->
rgb
[
rgbidx
]
->
transp
;
#ifdef CONFIG_CPU_FREQ
printk
(
KERN_DEBUG
"dma period = %d ps, clock = %d kHz
\n
"
,
sa1100fb_display_dma_period
(
var
),
cpufreq_get
());
cpufreq_get
(
smp_processor_id
()
));
#endif
return
ret
;
...
...
@@ -994,26 +1026,24 @@ static inline void sa1100fb_set_truecolor(u_int is_true_color)
}
}
static
int
sa1100fb_
set_par
(
struct
fb_info
*
info
)
static
void
sa1100fb_
hw_set_var
(
struct
fb_var_screeninfo
*
var
,
struct
sa1100fb_info
*
fbi
)
{
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
u_long
palette_mem_size
;
par
->
bpp
=
info
->
var
.
bits_per_pixel
;
par
->
palette_size
=
par
->
bpp
==
8
?
256
:
16
;
fbi
->
palette_size
=
var
->
bits_per_pixel
==
8
?
256
:
16
;
palette_mem_size
=
par
->
palette_size
*
sizeof
(
u16
);
palette_mem_size
=
fbi
->
palette_size
*
sizeof
(
u16
);
DPRINTK
(
"palette_mem_size = 0x%08lx
\n
"
,
(
u_long
)
palette_mem_size
);
par
->
palette_cpu
=
(
u16
*
)(
par
->
map_cpu
+
PAGE_SIZE
-
palette_mem_size
);
par
->
palette_dma
=
par
->
map_dma
+
PAGE_SIZE
-
palette_mem_size
;
fbi
->
palette_cpu
=
(
u16
*
)(
fbi
->
map_cpu
+
PAGE_SIZE
-
palette_mem_size
);
fbi
->
palette_dma
=
fbi
->
map_dma
+
PAGE_SIZE
-
palette_mem_size
;
fb_set_cmap
(
&
info
->
cmap
,
1
,
info
);
fb_set_cmap
(
&
fbi
->
fb
.
cmap
,
1
,
&
fbi
->
fb
);
/* Set board control register to handle new color depth */
sa1100fb_set_truecolor
(
info
->
var
.
bits_per_pixel
>=
16
);
sa1100fb_set_truecolor
(
var
->
bits_per_pixel
>=
16
);
#ifdef CONFIG_SA1100_OMNIMETER
#error Do we have to do this here? We already do it at init time.
...
...
@@ -1021,31 +1051,210 @@ sa1100fb_set_par(struct fb_info *info)
SetLCDContrast
(
DefaultLCDContrast
);
#endif
sa1100fb_activate_var
(
&
info
->
var
,
info
);
sa1100fb_activate_var
(
var
,
fbi
);
fbi
->
palette_cpu
[
0
]
=
(
fbi
->
palette_cpu
[
0
]
&
0xcfff
)
|
palette_pbs
(
var
);
}
/*
* sa1100fb_set_var():
* Set the user defined part of the display for the specified console
*/
static
int
sa1100fb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
struct
sa1100fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
struct
fb_var_screeninfo
*
dvar
=
get_con_var
(
&
fbi
->
fb
,
con
);
struct
display
*
display
=
get_con_display
(
&
fbi
->
fb
,
con
);
int
err
,
chgvar
=
0
,
rgbidx
;
DPRINTK
(
"set_var
\n
"
);
/*
* Decode var contents into a par structure, adjusting any
* out of range values.
*/
err
=
sa1100fb_validate_var
(
var
,
fbi
);
if
(
err
)
return
err
;
if
(
var
->
activate
&
FB_ACTIVATE_TEST
)
return
0
;
if
((
var
->
activate
&
FB_ACTIVATE_MASK
)
!=
FB_ACTIVATE_NOW
)
return
-
EINVAL
;
if
(
dvar
->
xres
!=
var
->
xres
)
chgvar
=
1
;
if
(
dvar
->
yres
!=
var
->
yres
)
chgvar
=
1
;
if
(
dvar
->
xres_virtual
!=
var
->
xres_virtual
)
chgvar
=
1
;
if
(
dvar
->
yres_virtual
!=
var
->
yres_virtual
)
chgvar
=
1
;
if
(
dvar
->
bits_per_pixel
!=
var
->
bits_per_pixel
)
chgvar
=
1
;
if
(
con
<
0
)
chgvar
=
0
;
par
->
palette_cpu
[
0
]
=
(
par
->
palette_cpu
[
0
]
&
0xcfff
)
|
palette_pbs
(
info
->
var
.
bits_per_pixel
);
switch
(
info
->
var
.
bits_per_pixel
)
{
switch
(
var
->
bits_per_pixel
)
{
#ifdef FBCON_HAS_CFB4
case
4
:
if
(
par
->
cmap_static
)
info
->
fix
.
visual
=
FB_VISUAL_STATIC_PSEUDOCOLOR
;
if
(
fbi
->
cmap_static
)
display
->
visual
=
FB_VISUAL_STATIC_PSEUDOCOLOR
;
else
info
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
info
->
fix
.
line_length
=
info
->
var
.
xres
/
2
;
display
->
visual
=
FB_VISUAL_PSEUDOCOLOR
;
display
->
line_length
=
var
->
xres
/
2
;
display
->
dispsw
=
&
fbcon_cfb4
;
rgbidx
=
RGB_8
;
break
;
#endif
#ifdef FBCON_HAS_CFB8
case
8
:
if
(
par
->
cmap_static
)
info
->
fix
.
visual
=
FB_VISUAL_STATIC_PSEUDOCOLOR
;
if
(
fbi
->
cmap_static
)
display
->
visual
=
FB_VISUAL_STATIC_PSEUDOCOLOR
;
else
info
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
info
->
fix
.
line_length
=
info
->
var
.
xres
;
display
->
visual
=
FB_VISUAL_PSEUDOCOLOR
;
display
->
line_length
=
var
->
xres
;
display
->
dispsw
=
&
fbcon_cfb8
;
rgbidx
=
RGB_8
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
16
:
info
->
fix
.
visual
=
FB_VISUAL_TRUECOLOR
;
info
->
fix
.
line_length
=
info
->
var
.
xres
*
2
;
display
->
visual
=
FB_VISUAL_TRUECOLOR
;
display
->
line_length
=
var
->
xres
*
2
;
display
->
dispsw
=
&
fbcon_cfb16
;
display
->
dispsw_data
=
fbi
->
fb
.
pseudo_palette
;
rgbidx
=
RGB_16
;
break
;
#endif
default:
rgbidx
=
0
;
display
->
dispsw
=
&
fbcon_dummy
;
break
;
}
display
->
next_line
=
display
->
line_length
;
display
->
type
=
fbi
->
fb
.
fix
.
type
;
display
->
type_aux
=
fbi
->
fb
.
fix
.
type_aux
;
display
->
ypanstep
=
fbi
->
fb
.
fix
.
ypanstep
;
display
->
ywrapstep
=
fbi
->
fb
.
fix
.
ywrapstep
;
display
->
can_soft_blank
=
1
;
display
->
inverse
=
fbi
->
cmap_inverse
;
*
dvar
=
*
var
;
dvar
->
activate
&=
~
FB_ACTIVATE_ALL
;
/*
* Copy the RGB parameters for this display
* from the machine specific parameters.
*/
dvar
->
red
=
fbi
->
rgb
[
rgbidx
]
->
red
;
dvar
->
green
=
fbi
->
rgb
[
rgbidx
]
->
green
;
dvar
->
blue
=
fbi
->
rgb
[
rgbidx
]
->
blue
;
dvar
->
transp
=
fbi
->
rgb
[
rgbidx
]
->
transp
;
DPRINTK
(
"RGBT length = %d:%d:%d:%d
\n
"
,
dvar
->
red
.
length
,
dvar
->
green
.
length
,
dvar
->
blue
.
length
,
dvar
->
transp
.
length
);
DPRINTK
(
"RGBT offset = %d:%d:%d:%d
\n
"
,
dvar
->
red
.
offset
,
dvar
->
green
.
offset
,
dvar
->
blue
.
offset
,
dvar
->
transp
.
offset
);
/*
* Update the old var. The fbcon drivers still use this.
* Once they are using fbi->fb.var, this can be dropped.
*/
display
->
var
=
*
dvar
;
/*
* If we are setting all the virtual consoles, also set the
* defaults used to create new consoles.
*/
if
(
var
->
activate
&
FB_ACTIVATE_ALL
)
fbi
->
fb
.
disp
->
var
=
*
dvar
;
/*
* If the console has changed and the console has defined
* a changevar function, call that function.
*/
if
(
chgvar
&&
info
&&
fbi
->
fb
.
changevar
)
fbi
->
fb
.
changevar
(
con
);
/* If the current console is selected, activate the new var. */
if
(
con
!=
fbi
->
fb
.
currcon
)
return
0
;
sa1100fb_hw_set_var
(
dvar
,
fbi
);
return
0
;
}
static
int
__do_set_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
)
{
struct
sa1100fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
struct
fb_cmap
*
dcmap
=
get_con_cmap
(
info
,
con
);
int
err
=
0
;
if
(
con
==
-
1
)
con
=
info
->
currcon
;
/* no colormap allocated? (we always have "this" colour map allocated) */
if
(
con
>=
0
)
err
=
fb_alloc_cmap
(
&
fb_display
[
con
].
cmap
,
fbi
->
palette_size
,
0
);
if
(
!
err
&&
con
==
info
->
currcon
)
err
=
fb_set_cmap
(
cmap
,
kspc
,
info
);
if
(
!
err
)
fb_copy_cmap
(
cmap
,
dcmap
,
kspc
?
0
:
1
);
return
err
;
}
static
int
sa1100fb_set_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
)
{
struct
display
*
disp
=
get_con_display
(
info
,
con
);
if
(
disp
->
visual
==
FB_VISUAL_TRUECOLOR
||
disp
->
visual
==
FB_VISUAL_STATIC_PSEUDOCOLOR
)
return
-
EINVAL
;
return
__do_set_cmap
(
cmap
,
kspc
,
con
,
info
);
}
static
int
sa1100fb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
info
)
{
struct
display
*
display
=
get_con_display
(
info
,
con
);
*
fix
=
info
->
fix
;
fix
->
line_length
=
display
->
line_length
;
fix
->
visual
=
display
->
visual
;
return
0
;
}
static
int
sa1100fb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
{
*
var
=
*
get_con_var
(
info
,
con
);
return
0
;
}
static
int
sa1100fb_get_cmap
(
struct
fb_cmap
*
cmap
,
int
kspc
,
int
con
,
struct
fb_info
*
info
)
{
struct
fb_cmap
*
dcmap
=
get_con_cmap
(
info
,
con
);
fb_copy_cmap
(
dcmap
,
cmap
,
kspc
?
0
:
2
);
return
0
;
}
...
...
@@ -1086,21 +1295,21 @@ sa1100fb_set_par(struct fb_info *info)
*/
static
int
sa1100fb_blank
(
int
blank
,
struct
fb_info
*
info
)
{
struct
sa1100
_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
struct
sa1100
fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
int
i
;
DPRINTK
(
"sa1100fb_blank: blank=%d
fix.id
=%s
\n
"
,
blank
,
info
->
fix
.
id
);
DPRINTK
(
"sa1100fb_blank: blank=%d
info->modename
=%s
\n
"
,
blank
,
fbi
->
fb
.
modename
);
switch
(
blank
)
{
case
VESA_POWERDOWN
:
case
VESA_VSYNC_SUSPEND
:
case
VESA_HSYNC_SUSPEND
:
if
(
info
->
disp
->
visual
==
FB_VISUAL_PSEUDOCOLOR
||
info
->
disp
->
visual
==
FB_VISUAL_STATIC_PSEUDOCOLOR
)
for
(
i
=
0
;
i
<
par
->
palette_size
;
i
++
)
if
(
fbi
->
fb
.
disp
->
visual
==
FB_VISUAL_PSEUDOCOLOR
||
fbi
->
fb
.
disp
->
visual
==
FB_VISUAL_STATIC_PSEUDOCOLOR
)
for
(
i
=
0
;
i
<
fbi
->
palette_size
;
i
++
)
sa1100fb_setpalettereg
(
i
,
0
,
0
,
0
,
0
,
info
);
sa1100fb_schedule_task
(
par
,
C_DISABLE
);
sa1100fb_schedule_task
(
fbi
,
C_DISABLE
);
if
(
sa1100fb_blank_helper
)
sa1100fb_blank_helper
(
blank
);
break
;
...
...
@@ -1108,30 +1317,83 @@ static int sa1100fb_blank(int blank, struct fb_info *info)
case
VESA_NO_BLANKING
:
if
(
sa1100fb_blank_helper
)
sa1100fb_blank_helper
(
blank
);
if
(
info
->
disp
->
visual
==
FB_VISUAL_PSEUDOCOLOR
||
info
->
disp
->
visual
==
FB_VISUAL_STATIC_PSEUDOCOLOR
)
fb_set_cmap
(
&
info
->
cmap
,
1
,
info
);
sa1100fb_schedule_task
(
par
,
C_ENABLE
);
if
(
fbi
->
fb
.
disp
->
visual
==
FB_VISUAL_PSEUDOCOLOR
||
fbi
->
fb
.
disp
->
visual
==
FB_VISUAL_STATIC_PSEUDOCOLOR
)
fb_set_cmap
(
&
fbi
->
fb
.
cmap
,
1
,
info
);
sa1100fb_schedule_task
(
fbi
,
C_ENABLE
);
}
return
0
;
}
static
struct
fb_ops
sa1100fb_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:
sa1100fb_check_var
,
fb_set_par:
sa1100fb_set_par
,
fb_get_fix:
sa1100fb_get_fix
,
fb_get_var:
sa1100fb_get_var
,
fb_set_var:
sa1100fb_set_var
,
fb_get_cmap:
sa1100fb_get_cmap
,
fb_set_cmap:
sa1100fb_set_cmap
,
fb_setcolreg:
sa1100fb_setcolreg
,
fb_blank:
sa1100fb_blank
,
fb_fillrect:
cfb_fillrect
,
fb_copyarea:
cfb_copyarea
,
fb_imageblit:
cfb_imageblit
,
};
/*
* sa1100fb_switch():
* Change to the specified console. Palette and video mode
* are changed to the console's stored parameters.
*
* Uh oh, this can be called from a tasklet (IRQ)
*/
static
int
sa1100fb_switch
(
int
con
,
struct
fb_info
*
info
)
{
struct
sa1100fb_info
*
fbi
=
(
struct
sa1100fb_info
*
)
info
;
struct
display
*
disp
;
struct
fb_cmap
*
cmap
;
DPRINTK
(
"con=%d info->modename=%s
\n
"
,
con
,
fbi
->
fb
.
modename
);
if
(
con
==
info
->
currcon
)
return
0
;
if
(
info
->
currcon
>=
0
)
{
disp
=
fb_display
+
info
->
currcon
;
/*
* Save the old colormap and video mode.
*/
disp
->
var
=
fbi
->
fb
.
var
;
if
(
disp
->
cmap
.
len
)
fb_copy_cmap
(
&
fbi
->
fb
.
cmap
,
&
disp
->
cmap
,
0
);
}
info
->
currcon
=
con
;
disp
=
fb_display
+
con
;
/*
* Make sure that our colourmap contains 256 entries.
*/
fb_alloc_cmap
(
&
fbi
->
fb
.
cmap
,
256
,
0
);
if
(
disp
->
cmap
.
len
)
cmap
=
&
disp
->
cmap
;
else
cmap
=
fb_default_cmap
(
1
<<
disp
->
var
.
bits_per_pixel
);
fb_copy_cmap
(
cmap
,
&
fbi
->
fb
.
cmap
,
0
);
fbi
->
fb
.
var
=
disp
->
var
;
fbi
->
fb
.
var
.
activate
=
FB_ACTIVATE_NOW
;
sa1100fb_set_var
(
&
fbi
->
fb
.
var
,
con
,
info
);
return
0
;
}
static
int
sa1100fb_updatevar
(
int
con
,
struct
fb_info
*
info
)
{
DPRINTK
(
"entered
\n
"
);
return
0
;
}
/*
* Calculate the PCD value from the clock rate (in picoseconds).
* We take account of the PPCR clock setting.
...
...
@@ -1141,7 +1403,7 @@ static inline int get_pcd(unsigned int pixclock)
unsigned
int
pcd
;
if
(
pixclock
)
{
pcd
=
cpufreq_get
()
/
100
;
pcd
=
cpufreq_get
(
0
)
/
100
;
pcd
*=
pixclock
;
pcd
/=
10000000
;
pcd
+=
1
;
/* make up for integer math truncations */
...
...
@@ -1171,9 +1433,8 @@ static inline int get_pcd(unsigned int pixclock)
* Configures LCD Controller based on entries in var parameter. Settings are
* only written to the controller if changes were made.
*/
static
int
sa1100fb_activate_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
static
int
sa1100fb_activate_var
(
struct
fb_var_screeninfo
*
var
,
struct
sa1100fb_info
*
fbi
)
{
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
struct
sa1100fb_lcd_reg
new_regs
;
u_int
half_screen_size
,
yres
,
pcd
=
get_pcd
(
var
->
pixclock
);
u_long
flags
;
...
...
@@ -1190,31 +1451,31 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
#if DEBUG_VAR
if
(
var
->
xres
<
16
||
var
->
xres
>
1024
)
printk
(
KERN_ERR
"%s: invalid xres %d
\n
"
,
info
->
fix
.
id
,
var
->
xres
);
fbi
->
fb
.
fix
.
id
,
var
->
xres
);
if
(
var
->
hsync_len
<
1
||
var
->
hsync_len
>
64
)
printk
(
KERN_ERR
"%s: invalid hsync_len %d
\n
"
,
info
->
fix
.
id
,
var
->
hsync_len
);
fbi
->
fb
.
fix
.
id
,
var
->
hsync_len
);
if
(
var
->
left_margin
<
1
||
var
->
left_margin
>
255
)
printk
(
KERN_ERR
"%s: invalid left_margin %d
\n
"
,
info
->
fix
.
id
,
var
->
left_margin
);
fbi
->
fb
.
fix
.
id
,
var
->
left_margin
);
if
(
var
->
right_margin
<
1
||
var
->
right_margin
>
255
)
printk
(
KERN_ERR
"%s: invalid right_margin %d
\n
"
,
info
->
fix
.
id
,
var
->
right_margin
);
fbi
->
fb
.
fix
.
id
,
var
->
right_margin
);
if
(
var
->
yres
<
1
||
var
->
yres
>
1024
)
printk
(
KERN_ERR
"%s: invalid yres %d
\n
"
,
info
->
fix
.
id
,
var
->
yres
);
fbi
->
fb
.
fix
.
id
,
var
->
yres
);
if
(
var
->
vsync_len
<
1
||
var
->
vsync_len
>
64
)
printk
(
KERN_ERR
"%s: invalid vsync_len %d
\n
"
,
info
->
fix
.
id
,
var
->
vsync_len
);
fbi
->
fb
.
fix
.
id
,
var
->
vsync_len
);
if
(
var
->
upper_margin
<
0
||
var
->
upper_margin
>
255
)
printk
(
KERN_ERR
"%s: invalid upper_margin %d
\n
"
,
info
->
fix
.
id
,
var
->
upper_margin
);
fbi
->
fb
.
fix
.
id
,
var
->
upper_margin
);
if
(
var
->
lower_margin
<
0
||
var
->
lower_margin
>
255
)
printk
(
KERN_ERR
"%s: invalid lower_margin %d
\n
"
,
info
->
fix
.
id
,
var
->
lower_margin
);
fbi
->
fb
.
fix
.
id
,
var
->
lower_margin
);
#endif
new_regs
.
lccr0
=
par
->
lccr0
|
new_regs
.
lccr0
=
fbi
->
lccr0
|
LCCR0_LEN
|
LCCR0_LDM
|
LCCR0_BAM
|
LCCR0_ERM
|
LCCR0_LtlEnd
|
LCCR0_DMADel
(
0
);
...
...
@@ -1229,7 +1490,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
* the YRES parameter.
*/
yres
=
var
->
yres
;
if
(
par
->
lccr0
&
LCCR0_Dual
)
if
(
fbi
->
lccr0
&
LCCR0_Dual
)
yres
/=
2
;
new_regs
.
lccr2
=
...
...
@@ -1238,7 +1499,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
LCCR2_BegFrmDel
(
var
->
upper_margin
)
+
LCCR2_EndFrmDel
(
var
->
lower_margin
);
new_regs
.
lccr3
=
par
->
lccr3
|
new_regs
.
lccr3
=
fbi
->
lccr3
|
(
var
->
sync
&
FB_SYNC_HOR_HIGH_ACT
?
LCCR3_HorSnchH
:
LCCR3_HorSnchL
)
|
(
var
->
sync
&
FB_SYNC_VERT_HIGH_ACT
?
LCCR3_VrtSnchH
:
LCCR3_VrtSnchL
)
|
LCCR3_ACBsCntOff
;
...
...
@@ -1256,23 +1517,23 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
/* Update shadow copy atomically */
local_irq_save
(
flags
);
par
->
dbar1
=
par
->
palette_dma
;
par
->
dbar2
=
par
->
screen_dma
+
half_screen_size
;
fbi
->
dbar1
=
fbi
->
palette_dma
;
fbi
->
dbar2
=
fbi
->
screen_dma
+
half_screen_size
;
par
->
reg_lccr0
=
new_regs
.
lccr0
;
par
->
reg_lccr1
=
new_regs
.
lccr1
;
par
->
reg_lccr2
=
new_regs
.
lccr2
;
par
->
reg_lccr3
=
new_regs
.
lccr3
;
fbi
->
reg_lccr0
=
new_regs
.
lccr0
;
fbi
->
reg_lccr1
=
new_regs
.
lccr1
;
fbi
->
reg_lccr2
=
new_regs
.
lccr2
;
fbi
->
reg_lccr3
=
new_regs
.
lccr3
;
local_irq_restore
(
flags
);
/*
* Only update the registers if the controller is enabled
* and something has changed.
*/
if
((
LCCR0
!=
par
->
reg_lccr0
)
||
(
LCCR1
!=
par
->
reg_lccr1
)
||
(
LCCR2
!=
par
->
reg_lccr2
)
||
(
LCCR3
!=
par
->
reg_lccr3
)
||
(
DBAR1
!=
par
->
dbar1
)
||
(
DBAR2
!=
par
->
dbar2
))
sa1100fb_schedule_task
(
par
,
C_REENABLE
);
if
((
LCCR0
!=
fbi
->
reg_lccr0
)
||
(
LCCR1
!=
fbi
->
reg_lccr1
)
||
(
LCCR2
!=
fbi
->
reg_lccr2
)
||
(
LCCR3
!=
fbi
->
reg_lccr3
)
||
(
DBAR1
!=
fbi
->
dbar1
)
||
(
DBAR2
!=
fbi
->
dbar2
))
sa1100fb_schedule_task
(
fbi
,
C_REENABLE
);
return
0
;
}
...
...
@@ -1289,7 +1550,7 @@ static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct fb_info *
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
static
inline
void
sa1100fb_backlight_on
(
struct
sa1100
_par
*
par
)
static
inline
void
sa1100fb_backlight_on
(
struct
sa1100
fb_info
*
fbi
)
{
DPRINTK
(
"backlight on
\n
"
);
...
...
@@ -1302,7 +1563,7 @@ static inline void sa1100fb_backlight_on(struct sa1100_par *par)
* Also, I'm expecting that the backlight stuff should
* be handled differently.
*/
static
inline
void
sa1100fb_backlight_off
(
struct
sa1100
_par
*
par
)
static
inline
void
sa1100fb_backlight_off
(
struct
sa1100
fb_info
*
fbi
)
{
DPRINTK
(
"backlight off
\n
"
);
...
...
@@ -1310,7 +1571,7 @@ static inline void sa1100fb_backlight_off(struct sa1100_par *par)
sa1100fb_backlight_power
(
0
);
}
static
inline
void
sa1100fb_power_up_lcd
(
struct
sa1100
_par
*
par
)
static
inline
void
sa1100fb_power_up_lcd
(
struct
sa1100
fb_info
*
fbi
)
{
DPRINTK
(
"LCD power on
\n
"
);
...
...
@@ -1325,7 +1586,7 @@ static inline void sa1100fb_power_up_lcd(struct sa1100_par *par)
#endif
}
static
inline
void
sa1100fb_power_down_lcd
(
struct
sa1100
_par
*
par
)
static
inline
void
sa1100fb_power_down_lcd
(
struct
sa1100
fb_info
*
fbi
)
{
DPRINTK
(
"LCD power off
\n
"
);
...
...
@@ -1340,7 +1601,7 @@ static inline void sa1100fb_power_down_lcd(struct sa1100_par *par)
#endif
}
static
void
sa1100fb_setup_gpio
(
struct
sa1100
_par
*
par
)
static
void
sa1100fb_setup_gpio
(
struct
sa1100
fb_info
*
fbi
)
{
u_int
mask
=
0
;
...
...
@@ -1356,12 +1617,12 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par)
* clear LDD15 to 12 for 4 or 8bpp modes with active
* panels.
*/
if
((
par
->
reg_lccr0
&
LCCR0_CMS
)
==
LCCR0_Color
&&
(
par
->
reg_lccr0
&
(
LCCR0_Dual
|
LCCR0_Act
))
!=
0
)
{
if
((
fbi
->
reg_lccr0
&
LCCR0_CMS
)
==
LCCR0_Color
&&
(
fbi
->
reg_lccr0
&
(
LCCR0_Dual
|
LCCR0_Act
))
!=
0
)
{
mask
=
GPIO_LDD11
|
GPIO_LDD10
|
GPIO_LDD9
|
GPIO_LDD8
;
if
(
par
->
bpp
>
8
||
(
par
->
reg_lccr0
&
(
LCCR0_Dual
|
LCCR0_Act
))
==
LCCR0_Dual
)
if
(
fbi
->
fb
.
var
.
bits_per_pixel
>
8
||
(
fbi
->
reg_lccr0
&
(
LCCR0_Dual
|
LCCR0_Act
))
==
LCCR0_Dual
)
mask
|=
GPIO_LDD15
|
GPIO_LDD14
|
GPIO_LDD13
|
GPIO_LDD12
;
}
...
...
@@ -1405,23 +1666,23 @@ static void sa1100fb_setup_gpio(struct sa1100_par *par)
}
}
static
void
sa1100fb_enable_controller
(
struct
sa1100
_par
*
par
)
static
void
sa1100fb_enable_controller
(
struct
sa1100
fb_info
*
fbi
)
{
DPRINTK
(
"Enabling LCD controller
\n
"
);
/*
* Make sure the mode bits are present in the first palette entry
*/
par
->
palette_cpu
[
0
]
&=
0xcfff
;
par
->
palette_cpu
[
0
]
|=
palette_pbs
(
par
->
bpp
);
fbi
->
palette_cpu
[
0
]
&=
0xcfff
;
fbi
->
palette_cpu
[
0
]
|=
palette_pbs
(
&
fbi
->
fb
.
var
);
/* Sequence from 11.7.10 */
LCCR3
=
par
->
reg_lccr3
;
LCCR2
=
par
->
reg_lccr2
;
LCCR1
=
par
->
reg_lccr1
;
LCCR0
=
par
->
reg_lccr0
&
~
LCCR0_LEN
;
DBAR1
=
par
->
dbar1
;
DBAR2
=
par
->
dbar2
;
LCCR3
=
fbi
->
reg_lccr3
;
LCCR2
=
fbi
->
reg_lccr2
;
LCCR1
=
fbi
->
reg_lccr1
;
LCCR0
=
fbi
->
reg_lccr0
&
~
LCCR0_LEN
;
DBAR1
=
fbi
->
dbar1
;
DBAR2
=
fbi
->
dbar2
;
LCCR0
|=
LCCR0_LEN
;
#ifdef CONFIG_SA1100_GRAPHICSCLIENT
...
...
@@ -1447,7 +1708,7 @@ static void sa1100fb_enable_controller(struct sa1100_par *par)
DPRINTK
(
"LCCR3 = 0x%08x
\n
"
,
LCCR3
);
}
static
void
sa1100fb_disable_controller
(
struct
sa1100
_par
*
par
)
static
void
sa1100fb_disable_controller
(
struct
sa1100
fb_info
*
fbi
)
{
DECLARE_WAITQUEUE
(
wait
,
current
);
...
...
@@ -1481,7 +1742,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
GPCR
|=
SHANNON_GPIO_DISP_EN
;
}
add_wait_queue
(
&
par
->
ctrlr_wait
,
&
wait
);
add_wait_queue
(
&
fbi
->
ctrlr_wait
,
&
wait
);
set_current_state
(
TASK_UNINTERRUPTIBLE
);
LCSR
=
0xffffffff
;
/* Clear LCD Status Register */
...
...
@@ -1490,7 +1751,7 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
schedule_timeout
(
20
*
HZ
/
1000
);
current
->
state
=
TASK_RUNNING
;
remove_wait_queue
(
&
par
->
ctrlr_wait
,
&
wait
);
remove_wait_queue
(
&
fbi
->
ctrlr_wait
,
&
wait
);
}
/*
...
...
@@ -1498,12 +1759,12 @@ static void sa1100fb_disable_controller(struct sa1100_par *par)
*/
static
void
sa1100fb_handle_irq
(
int
irq
,
void
*
dev_id
,
struct
pt_regs
*
regs
)
{
struct
sa1100
_par
*
par
=
dev_id
;
struct
sa1100
fb_info
*
fbi
=
dev_id
;
unsigned
int
lcsr
=
LCSR
;
if
(
lcsr
&
LCSR_LDD
)
{
LCCR0
|=
LCCR0_LDM
;
wake_up
(
&
par
->
ctrlr_wait
);
wake_up
(
&
fbi
->
ctrlr_wait
);
}
LCSR
=
lcsr
;
...
...
@@ -1514,13 +1775,13 @@ static void sa1100fb_handle_irq(int irq, void *dev_id, struct pt_regs *regs)
* sleep when disabling the LCD controller, or if we get two contending
* processes trying to alter state.
*/
static
void
set_ctrlr_state
(
struct
sa1100
_par
*
par
,
u_int
state
)
static
void
set_ctrlr_state
(
struct
sa1100
fb_info
*
fbi
,
u_int
state
)
{
u_int
old_state
;
down
(
&
par
->
ctrlr_sem
);
down
(
&
fbi
->
ctrlr_sem
);
old_state
=
par
->
state
;
old_state
=
fbi
->
state
;
switch
(
state
)
{
case
C_DISABLE_CLKCHANGE
:
...
...
@@ -1529,8 +1790,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* controller is already disabled, then do nothing.
*/
if
(
old_state
!=
C_DISABLE
&&
old_state
!=
C_DISABLE_PM
)
{
par
->
state
=
state
;
sa1100fb_disable_controller
(
par
);
fbi
->
state
=
state
;
sa1100fb_disable_controller
(
fbi
);
}
break
;
...
...
@@ -1540,12 +1801,12 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* Disable controller
*/
if
(
old_state
!=
C_DISABLE
)
{
par
->
state
=
state
;
fbi
->
state
=
state
;
sa1100fb_backlight_off
(
par
);
sa1100fb_backlight_off
(
fbi
);
if
(
old_state
!=
C_DISABLE_CLKCHANGE
)
sa1100fb_disable_controller
(
par
);
sa1100fb_power_down_lcd
(
par
);
sa1100fb_disable_controller
(
fbi
);
sa1100fb_power_down_lcd
(
fbi
);
}
break
;
...
...
@@ -1555,8 +1816,8 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* do this if we were disabled for the clock change.
*/
if
(
old_state
==
C_DISABLE_CLKCHANGE
)
{
par
->
state
=
C_ENABLE
;
sa1100fb_enable_controller
(
par
);
fbi
->
state
=
C_ENABLE
;
sa1100fb_enable_controller
(
fbi
);
}
break
;
...
...
@@ -1567,9 +1828,9 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* registers.
*/
if
(
old_state
==
C_ENABLE
)
{
sa1100fb_disable_controller
(
par
);
sa1100fb_setup_gpio
(
par
);
sa1100fb_enable_controller
(
par
);
sa1100fb_disable_controller
(
fbi
);
sa1100fb_setup_gpio
(
fbi
);
sa1100fb_enable_controller
(
fbi
);
}
break
;
...
...
@@ -1589,15 +1850,15 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
* turn on the backlight.
*/
if
(
old_state
!=
C_ENABLE
)
{
par
->
state
=
C_ENABLE
;
sa1100fb_setup_gpio
(
par
);
sa1100fb_power_up_lcd
(
par
);
sa1100fb_enable_controller
(
par
);
sa1100fb_backlight_on
(
par
);
fbi
->
state
=
C_ENABLE
;
sa1100fb_setup_gpio
(
fbi
);
sa1100fb_power_up_lcd
(
fbi
);
sa1100fb_enable_controller
(
fbi
);
sa1100fb_backlight_on
(
fbi
);
}
break
;
}
up
(
&
par
->
ctrlr_sem
);
up
(
&
fbi
->
ctrlr_sem
);
}
/*
...
...
@@ -1606,12 +1867,10 @@ static void set_ctrlr_state(struct sa1100_par *par, u_int state)
*/
static
void
sa1100fb_task
(
void
*
dummy
)
{
struct
fb_info
*
info
=
dummy
;
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
struct
sa1100fb_info
*
fbi
=
dummy
;
u_int
state
=
xchg
(
&
fbi
->
task_state
,
-
1
)
;
u_int
state
=
xchg
(
&
par
->
task_state
,
-
1
);
set_ctrlr_state
(
par
,
state
);
set_ctrlr_state
(
fbi
,
state
);
}
#ifdef CONFIG_CPU_FREQ
...
...
@@ -1620,7 +1879,7 @@ static void sa1100fb_task(void *dummy)
* This, together with the SDRAM bandwidth defines the slowest CPU
* frequency that can be selected.
*/
static
unsigned
int
sa1100fb_min_dma_period
(
struct
fb_info
*
info
)
static
unsigned
int
sa1100fb_min_dma_period
(
struct
sa1100fb_info
*
fbi
)
{
unsigned
int
min_period
=
(
unsigned
int
)
-
1
;
int
i
;
...
...
@@ -1631,13 +1890,13 @@ static unsigned int sa1100fb_min_dma_period(struct fb_info *info)
/*
* Do we own this display?
*/
if
(
fb_display
[
i
].
fb_info
!=
info
)
if
(
fb_display
[
i
].
fb_info
!=
&
fbi
->
fb
)
continue
;
/*
* Ok, calculate its DMA period
*/
period
=
sa1100fb_display_dma_period
(
&
info
->
var
);
period
=
sa1100fb_display_dma_period
(
get_con_var
(
&
fbi
->
fb
,
i
)
);
if
(
period
<
min_period
)
min_period
=
period
;
}
...
...
@@ -1654,27 +1913,26 @@ static int
sa1100fb_clkchg_notifier
(
struct
notifier_block
*
nb
,
unsigned
long
val
,
void
*
data
)
{
struct
fb_info
*
info
=
TO_INF
(
nb
,
clockchg
);
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
struct
cpufreq_freqs
*
mm
=
data
;
struct
sa1100fb_info
*
fbi
=
TO_INF
(
nb
,
clockchg
);
struct
cpufreq_minmax
*
mm
=
data
;
u_int
pcd
;
switch
(
val
)
{
case
CPUFREQ_MINMAX
:
printk
(
KERN_DEBUG
"min dma period: %d ps, old clock %d kHz, "
"new clock %d kHz
\n
"
,
sa1100fb_min_dma_period
(
info
),
mm
->
cur
,
mm
->
new
);
"new clock %d kHz
\n
"
,
sa1100fb_min_dma_period
(
fbi
),
mm
->
cur
_freq
,
mm
->
new_freq
);
/* todo: fill in min/max values */
break
;
case
CPUFREQ_PRECHANGE
:
set_ctrlr_state
(
par
,
C_DISABLE_CLKCHANGE
);
set_ctrlr_state
(
fbi
,
C_DISABLE_CLKCHANGE
);
break
;
case
CPUFREQ_POSTCHANGE
:
pcd
=
get_pcd
(
info
->
var
.
pixclock
);
par
->
reg_lccr3
=
(
par
->
reg_lccr3
&
~
0xff
)
|
LCCR3_PixClkDiv
(
pcd
);
set_ctrlr_state
(
par
,
C_ENABLE_CLKCHANGE
);
pcd
=
get_pcd
(
fbi
->
fb
.
var
.
pixclock
);
fbi
->
reg_lccr3
=
(
fbi
->
reg_lccr3
&
~
0xff
)
|
LCCR3_PixClkDiv
(
pcd
);
set_ctrlr_state
(
fbi
,
C_ENABLE_CLKCHANGE
);
break
;
}
return
0
;
...
...
@@ -1689,7 +1947,7 @@ sa1100fb_clkchg_notifier(struct notifier_block *nb, unsigned long val,
static
int
sa1100fb_pm_callback
(
struct
pm_dev
*
pm_dev
,
pm_request_t
req
,
void
*
data
)
{
struct
sa1100
_par
*
par
=
pm_dev
->
data
;
struct
sa1100
fb_info
*
fbi
=
pm_dev
->
data
;
DPRINTK
(
"pm_callback: %d
\n
"
,
req
);
...
...
@@ -1698,10 +1956,10 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
if
(
state
==
0
)
{
/* Enter D0. */
set_ctrlr_state
(
par
,
C_ENABLE_PM
);
set_ctrlr_state
(
fbi
,
C_ENABLE_PM
);
}
else
{
/* Enter D1-D3. Disable the LCD controller. */
set_ctrlr_state
(
par
,
C_DISABLE_PM
);
set_ctrlr_state
(
fbi
,
C_DISABLE_PM
);
}
}
DPRINTK
(
"done
\n
"
);
...
...
@@ -1717,142 +1975,133 @@ sa1100fb_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data)
* cache. Once this area is remapped, all virtual memory
* access to the video memory should occur at the new region.
*/
static
int
__init
sa1100fb_map_video_memory
(
struct
fb_info
*
info
)
static
int
__init
sa1100fb_map_video_memory
(
struct
sa1100fb_info
*
fbi
)
{
struct
sa1100_par
*
par
=
(
struct
sa1100_par
*
)
info
->
par
;
/*
* We reserve one page for the palette, plus the size
* of the framebuffer.
*/
par
->
map_size
=
PAGE_ALIGN
(
info
->
fix
.
smem_len
+
PAGE_SIZE
);
par
->
map_cpu
=
consistent_alloc
(
GFP_KERNEL
,
par
->
map_size
,
&
par
->
map_dma
);
if
(
par
->
map_cpu
)
{
info
->
screen_base
=
par
->
map_cpu
+
PAGE_SIZE
;
par
->
screen_dma
=
par
->
map_dma
+
PAGE_SIZE
;
info
->
fix
.
smem_start
=
par
->
screen_dma
;
fbi
->
map_size
=
PAGE_ALIGN
(
fbi
->
fb
.
fix
.
smem_len
+
PAGE_SIZE
);
fbi
->
map_cpu
=
consistent_alloc
(
GFP_KERNEL
,
fbi
->
map_size
,
&
fbi
->
map_dma
);
if
(
fbi
->
map_cpu
)
{
fbi
->
fb
.
screen_base
=
fbi
->
map_cpu
+
PAGE_SIZE
;
fbi
->
screen_dma
=
fbi
->
map_dma
+
PAGE_SIZE
;
fbi
->
fb
.
fix
.
smem_start
=
fbi
->
screen_dma
;
}
return
par
->
map_cpu
?
0
:
-
ENOMEM
;
return
fbi
->
map_cpu
?
0
:
-
ENOMEM
;
}
/* Fake monspecs to fill in
info
nfo structure */
/* Fake monspecs to fill in
fbi
nfo structure */
static
struct
fb_monspecs
monspecs
__initdata
=
{
30000
,
70000
,
50
,
65
,
0
/* Generic */
};
static
struct
fb_info
*
__init
sa1100fb_init_fbinfo
(
void
)
static
struct
sa1100
fb_info
*
__init
sa1100fb_init_fbinfo
(
void
)
{
struct
sa1100fb_mach_info
*
inf
;
struct
fb_info
*
info
;
struct
sa1100_par
*
par
;
struct
sa1100fb_info
*
fbi
;
info
=
kmalloc
(
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
)
+
fbi
=
kmalloc
(
sizeof
(
struct
sa1100
fb_info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u16
)
*
16
,
GFP_KERNEL
);
if
(
!
info
)
if
(
!
fbi
)
return
NULL
;
memset
(
info
,
0
,
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
));
par
=
kmalloc
(
sizeof
(
struct
sa1100_par
),
GFP_KERNEL
);
memset
(
par
,
0
,
sizeof
(
struct
sa1100_par
));
info
->
currcon
=
-
1
;
strcpy
(
info
->
fix
.
id
,
SA1100_NAME
);
info
->
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fix
.
type_aux
=
0
;
info
->
fix
.
xpanstep
=
0
;
info
->
fix
.
ypanstep
=
0
;
info
->
fix
.
ywrapstep
=
0
;
info
->
fix
.
accel
=
FB_ACCEL_NONE
;
info
->
var
.
nonstd
=
0
;
info
->
var
.
activate
=
FB_ACTIVATE_NOW
;
info
->
var
.
height
=
-
1
;
info
->
var
.
width
=
-
1
;
info
->
var
.
accel_flags
=
0
;
info
->
var
.
vmode
=
FB_VMODE_NONINTERLACED
;
strcpy
(
info
->
modename
,
info
->
fix
.
id
);
strcpy
(
info
->
fontname
,
"Acorn8x8"
);
info
->
fbops
=
&
sa1100fb_ops
;
info
->
changevar
=
NULL
;
info
->
switch_con
=
gen_switch
;
info
->
updatevar
=
gen_update_var
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
info
->
node
=
NODEV
;
info
->
monspecs
=
monspecs
;
info
->
currcon
=
-
1
;
info
->
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)(
info
->
disp
+
1
);
info
->
par
=
par
;
par
->
rgb
[
RGB_8
]
=
&
rgb_8
;
par
->
rgb
[
RGB_16
]
=
&
def_rgb_16
;
inf
=
sa1100fb_get_machine_info
(
par
);
par
->
max_xres
=
inf
->
xres
;
info
->
var
.
xres
=
inf
->
xres
;
info
->
var
.
xres_virtual
=
inf
->
xres
;
par
->
max_yres
=
inf
->
yres
;
info
->
var
.
yres
=
inf
->
yres
;
info
->
var
.
yres_virtual
=
inf
->
yres
;
par
->
max_bpp
=
inf
->
bpp
;
info
->
var
.
bits_per_pixel
=
inf
->
bpp
;
info
->
var
.
pixclock
=
inf
->
pixclock
;
info
->
var
.
hsync_len
=
inf
->
hsync_len
;
info
->
var
.
left_margin
=
inf
->
left_margin
;
info
->
var
.
right_margin
=
inf
->
right_margin
;
info
->
var
.
vsync_len
=
inf
->
vsync_len
;
info
->
var
.
upper_margin
=
inf
->
upper_margin
;
info
->
var
.
lower_margin
=
inf
->
lower_margin
;
info
->
var
.
sync
=
inf
->
sync
;
info
->
var
.
grayscale
=
inf
->
cmap_greyscale
;
par
->
cmap_inverse
=
inf
->
cmap_inverse
;
par
->
cmap_static
=
inf
->
cmap_static
;
par
->
lccr0
=
inf
->
lccr0
;
par
->
lccr3
=
inf
->
lccr3
;
par
->
state
=
C_DISABLE
;
par
->
task_state
=
(
u_char
)
-
1
;
info
->
fix
.
smem_len
=
par
->
max_xres
*
par
->
max_yres
*
par
->
max_bpp
/
8
;
init_waitqueue_head
(
&
par
->
ctrlr_wait
);
INIT_TQUEUE
(
&
par
->
task
,
sa1100fb_task
,
info
);
init_MUTEX
(
&
par
->
ctrlr_sem
);
fb_alloc_cmap
(
&
info
->
cmap
,
256
,
0
);
return
info
;
memset
(
fbi
,
0
,
sizeof
(
struct
sa1100fb_info
)
+
sizeof
(
struct
display
));
fbi
->
fb
.
currcon
=
-
1
;
strcpy
(
fbi
->
fb
.
fix
.
id
,
SA1100_NAME
);
fbi
->
fb
.
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
fbi
->
fb
.
fix
.
type_aux
=
0
;
fbi
->
fb
.
fix
.
xpanstep
=
0
;
fbi
->
fb
.
fix
.
ypanstep
=
0
;
fbi
->
fb
.
fix
.
ywrapstep
=
0
;
fbi
->
fb
.
fix
.
accel
=
FB_ACCEL_NONE
;
fbi
->
fb
.
var
.
nonstd
=
0
;
fbi
->
fb
.
var
.
activate
=
FB_ACTIVATE_NOW
;
fbi
->
fb
.
var
.
height
=
-
1
;
fbi
->
fb
.
var
.
width
=
-
1
;
fbi
->
fb
.
var
.
accel_flags
=
0
;
fbi
->
fb
.
var
.
vmode
=
FB_VMODE_NONINTERLACED
;
strcpy
(
fbi
->
fb
.
modename
,
SA1100_NAME
);
strcpy
(
fbi
->
fb
.
fontname
,
"Acorn8x8"
);
fbi
->
fb
.
fbops
=
&
sa1100fb_ops
;
fbi
->
fb
.
changevar
=
NULL
;
fbi
->
fb
.
switch_con
=
sa1100fb_switch
;
fbi
->
fb
.
updatevar
=
sa1100fb_updatevar
;
fbi
->
fb
.
flags
=
FBINFO_FLAG_DEFAULT
;
fbi
->
fb
.
node
=
NODEV
;
fbi
->
fb
.
monspecs
=
monspecs
;
fbi
->
fb
.
currcon
=
-
1
;
fbi
->
fb
.
disp
=
(
struct
display
*
)(
fbi
+
1
);
fbi
->
fb
.
pseudo_palette
=
(
void
*
)(
fbi
->
fb
.
disp
+
1
);
fbi
->
rgb
[
RGB_8
]
=
&
rgb_8
;
fbi
->
rgb
[
RGB_16
]
=
&
def_rgb_16
;
inf
=
sa1100fb_get_machine_info
(
fbi
);
fbi
->
max_xres
=
inf
->
xres
;
fbi
->
fb
.
var
.
xres
=
inf
->
xres
;
fbi
->
fb
.
var
.
xres_virtual
=
inf
->
xres
;
fbi
->
max_yres
=
inf
->
yres
;
fbi
->
fb
.
var
.
yres
=
inf
->
yres
;
fbi
->
fb
.
var
.
yres_virtual
=
inf
->
yres
;
fbi
->
max_bpp
=
inf
->
bpp
;
fbi
->
fb
.
var
.
bits_per_pixel
=
inf
->
bpp
;
fbi
->
fb
.
var
.
pixclock
=
inf
->
pixclock
;
fbi
->
fb
.
var
.
hsync_len
=
inf
->
hsync_len
;
fbi
->
fb
.
var
.
left_margin
=
inf
->
left_margin
;
fbi
->
fb
.
var
.
right_margin
=
inf
->
right_margin
;
fbi
->
fb
.
var
.
vsync_len
=
inf
->
vsync_len
;
fbi
->
fb
.
var
.
upper_margin
=
inf
->
upper_margin
;
fbi
->
fb
.
var
.
lower_margin
=
inf
->
lower_margin
;
fbi
->
fb
.
var
.
sync
=
inf
->
sync
;
fbi
->
fb
.
var
.
grayscale
=
inf
->
cmap_greyscale
;
fbi
->
cmap_inverse
=
inf
->
cmap_inverse
;
fbi
->
cmap_static
=
inf
->
cmap_static
;
fbi
->
lccr0
=
inf
->
lccr0
;
fbi
->
lccr3
=
inf
->
lccr3
;
fbi
->
state
=
C_DISABLE
;
fbi
->
task_state
=
(
u_char
)
-
1
;
fbi
->
fb
.
fix
.
smem_len
=
fbi
->
max_xres
*
fbi
->
max_yres
*
fbi
->
max_bpp
/
8
;
init_waitqueue_head
(
&
fbi
->
ctrlr_wait
);
INIT_TQUEUE
(
&
fbi
->
task
,
sa1100fb_task
,
fbi
);
init_MUTEX
(
&
fbi
->
ctrlr_sem
);
return
fbi
;
}
int
__init
sa1100fb_init
(
void
)
{
struct
fb_info
*
info
;
struct
sa1100_par
*
par
;
struct
sa1100fb_info
*
fbi
;
int
ret
;
if
(
!
request_mem_region
(
0xb0100000
,
0x10000
,
"LCD"
))
return
-
EBUSY
;
info
=
sa1100fb_init_fbinfo
();
fbi
=
sa1100fb_init_fbinfo
();
ret
=
-
ENOMEM
;
if
(
!
info
)
if
(
!
fbi
)
goto
failed
;
/* Initialize video memory */
ret
=
sa1100fb_map_video_memory
(
info
);
ret
=
sa1100fb_map_video_memory
(
fbi
);
if
(
ret
)
goto
failed
;
ret
=
request_irq
(
IRQ_LCD
,
sa1100fb_handle_irq
,
SA_INTERRUPT
,
"LCD"
,
info
->
par
);
"LCD"
,
fbi
);
if
(
ret
)
{
printk
(
KERN_ERR
"sa1100fb: request_irq failed: %d
\n
"
,
ret
);
goto
failed
;
...
...
@@ -1873,32 +2122,30 @@ int __init sa1100fb_init(void)
}
#endif
gen_set_var
(
&
info
->
var
,
-
1
,
info
);
sa1100fb_set_var
(
&
fbi
->
fb
.
var
,
-
1
,
&
fbi
->
fb
);
ret
=
register_framebuffer
(
info
);
ret
=
register_framebuffer
(
&
fbi
->
fb
);
if
(
ret
<
0
)
goto
failed
;
par
=
info
->
par
;
#ifdef CONFIG_PM
/*
* Note that the console registers this as well, but we want to
* power down the display prior to sleeping.
*/
par
->
pm
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_VGA
,
sa1100fb_pm_callback
);
if
(
par
->
pm
)
par
->
pm
->
data
=
par
;
fbi
->
pm
=
pm_register
(
PM_SYS_DEV
,
PM_SYS_VGA
,
sa1100fb_pm_callback
);
if
(
fbi
->
pm
)
fbi
->
pm
->
data
=
fbi
;
#endif
#ifdef CONFIG_CPU_FREQ
info
->
clockchg
.
notifier_call
=
sa1100fb_clkchg_notifier
;
cpufreq_register_notifier
(
&
info
->
clockchg
);
fbi
->
clockchg
.
notifier_call
=
sa1100fb_clkchg_notifier
;
cpufreq_register_notifier
(
&
fbi
->
clockchg
);
#endif
/*
* Ok, now enable the LCD controller
*/
set_ctrlr_state
(
par
,
C_ENABLE
);
set_ctrlr_state
(
fbi
,
C_ENABLE
);
/* This driver cannot be unloaded at the moment */
MOD_INC_USE_COUNT
;
...
...
@@ -1906,8 +2153,8 @@ int __init sa1100fb_init(void)
return
0
;
failed:
if
(
info
)
kfree
(
info
);
if
(
fbi
)
kfree
(
fbi
);
release_mem_region
(
0xb0100000
,
0x10000
);
return
ret
;
}
...
...
drivers/video/sa1100fb.h
View file @
2eaf7c63
...
...
@@ -61,13 +61,13 @@ struct sa1100fb_lcd_reg {
#define RGB_16 (1)
#define NR_RGB 2
struct
sa1100_par
{
struct
sa1100fb_info
{
struct
fb_info
fb
;
struct
sa1100fb_rgb
*
rgb
[
NR_RGB
];
u_int
max_bpp
;
u_int
max_xres
;
u_int
max_yres
;
u_int
max_bpp
;
u_int
bpp
;
/*
* These are the addresses we mapped
...
...
@@ -86,13 +86,12 @@ struct sa1100_par {
dma_addr_t
dbar1
;
dma_addr_t
dbar2
;
u_int
lccr0
;
u_int
lccr3
;
u_int
cmap_inverse
:
1
,
cmap_static:
1
,
unused:
30
;
u_int
lccr0
;
u_int
lccr3
;
u_int
reg_lccr0
;
u_int
reg_lccr1
;
u_int
reg_lccr2
;
...
...
@@ -103,14 +102,18 @@ struct sa1100_par {
struct
semaphore
ctrlr_sem
;
wait_queue_head_t
ctrlr_wait
;
struct
tq_struct
task
;
#ifdef CONFIG_PM
struct
pm_dev
*
pm
;
#endif
#ifdef CONFIG_CPU_FREQ
struct
notifier_block
clockchg
;
#endif
};
#define __type_entry(ptr,type,member) ((type *)((char *)(ptr)-offsetof(type,member)))
#define TO_INF(ptr,member) __type_entry(ptr,
struct fb_info,
member)
#define TO_INF(ptr,member) __type_entry(ptr,
struct sa1100fb_info,
member)
#define SA1100_PALETTE_MODE_VAL(bpp) (((bpp) & 0x018) << 9)
...
...
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