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
Show 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
...
...
@@ -109,36 +109,35 @@ static struct fb_var_screeninfo default_var = {
1024
,
768
,
1024
,
768
,
0
,
0
,
8
,
0
,
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
8
,
0
},
{
0
,
0
,
0
},
0
,
0
,
-
1
,
-
1
,
0
,
12699
,
160
,
32
,
28
,
1
,
96
,
3
,
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_VERT_HIGH_ACT
,
FB_VMODE_NONINTERLACED
FB_SYNC_HOR_HIGH_ACT
|
FB_SYNC_VERT_HIGH_ACT
,
FB_VMODE_NONINTERLACED
};
#endif
/* CONFIG_PPC */
/* default modedb mode */
/* 640x480, 60 Hz, Non-Interlaced (25.172 MHz dotclock) */
static
struct
fb_videomode
defaultmode
__initdata
=
{
refresh:
60
,
xres:
640
,
yres:
480
,
pixclock:
39722
,
left_margin:
48
,
right_margin:
16
,
upper_margin:
33
,
lower_margin:
10
,
hsync_len:
96
,
vsync_len:
2
,
sync:
0
,
vmode:
FB_VMODE_NONINTERLACED
refresh:
60
,
xres:
640
,
yres:
480
,
pixclock:
39722
,
left_margin:
48
,
right_margin:
16
,
upper_margin:
33
,
lower_margin:
10
,
hsync_len:
96
,
vsync_len:
2
,
sync:
0
,
vmode:
FB_VMODE_NONINTERLACED
};
static
struct
fb_fix_screeninfo
aty128fb_fix
__initdata
=
{
id:
"ATY Rage128"
,
type:
FB_TYPE_PACKED_PIXELS
,
visual:
FB_VISUAL_PSEUDOCOLOR
,
xpanstep:
8
,
ypanstep:
1
,
mmio_len:
0x1fff
,
accel:
FB_ACCEL_ATI_RAGE128
id:
"ATY Rage128"
,
type:
FB_TYPE_PACKED_PIXELS
,
visual:
FB_VISUAL_PSEUDOCOLOR
,
xpanstep:
8
,
ypanstep:
1
,
mmio_len:
0x1fff
,
accel:
FB_ACCEL_ATI_RAGE128
};
/* struct to hold chip description information */
...
...
@@ -156,21 +155,19 @@ enum {
};
/* supported Rage128 chipsets */
static
struct
aty128_chip_info
aty128_pci_probe_list
[]
__initdata
=
{
static
struct
aty128_chip_info
aty128_pci_probe_list
[]
__initdata
=
{
{
"Rage128 RE (PCI)"
,
PCI_DEVICE_ID_ATI_RAGE128_RE
,
rage_128
},
{
"Rage128 RF (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_RF
,
rage_128
},
{
"Rage128 RK (PCI)"
,
PCI_DEVICE_ID_ATI_RAGE128_RK
,
rage_128
},
{
"Rage128 RL (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_RL
,
rage_128
},
{
"Rage128 Pro PF (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_PF
,
rage_128_pro
},
{
"Rage128 Pro PR (PCI)"
,
PCI_DEVICE_ID_ATI_RAGE128_PR
,
rage_128_pro
},
{
"Rage128 Pro TR (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_U3
,
rage_128_pro
},
{
"Rage128 Pro PF (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_PF
,
rage_128_pro
},
{
"Rage128 Pro PR (PCI)"
,
PCI_DEVICE_ID_ATI_RAGE128_PR
,
rage_128_pro
},
{
"Rage128 Pro TR (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_U3
,
rage_128_pro
},
{
"Rage Mobility M3 (PCI)"
,
PCI_DEVICE_ID_ATI_RAGE128_LE
,
rage_M3
},
{
"Rage Mobility M3 (AGP)"
,
PCI_DEVICE_ID_ATI_RAGE128_LF
,
rage_M3
},
{
NULL
,
0
,
rage_128
}
};
};
/* packed BIOS settings */
#ifndef CONFIG_PPC
...
...
@@ -227,6 +224,7 @@ static const struct aty128_meminfo ddr_sgram =
static
char
fontname
[
40
]
__initdata
=
{
0
};
static
int
noaccel
__initdata
=
0
;
#ifdef MODULE
static
char
*
font
__initdata
=
NULL
;
static
char
*
mode
__initdata
=
NULL
;
...
...
@@ -265,7 +263,7 @@ struct aty128_crtc {
u32
pitch
;
u32
offset
,
offset_cntl
;
u32
xoffset
,
yoffset
;
u32
vyres
;
u32
vxres
,
vyres
;
u32
bpp
;
};
...
...
@@ -285,79 +283,136 @@ struct aty128fb_par {
struct
aty128_crtc
crtc
;
struct
aty128_pll
pll
;
struct
aty128_ddafifo
fifo_reg
;
const
struct
aty128_meminfo
*
mem
;
/* onboard mem info */
u32
accel_flags
;
#ifdef CONFIG_MTRR
struct
{
int
vram
;
int
vram_valid
;
}
mtrr
;
#endif
};
struct
fb_info_aty128
{
struct
fb_info
fb_info
;
struct
fb_info_aty128
*
next
;
struct
aty128_constants
constants
;
/* PLL and others */
void
*
regbase
;
/* remapped mmio */
int
chip_gen
;
const
struct
aty128_meminfo
*
mem
;
/* onboard mem info */
int
blitter_may_be_busy
;
int
fifo_slots
;
/* free slots in FIFO (64 max) */
int
chip_gen
;
#ifdef CONFIG_MTRR
struct
{
int
vram
;
int
vram_valid
;
}
mtrr
;
#endif
};
static
struct
fb_info_aty128
*
board_list
=
NULL
;
#define round_div(n, d) ((n+(d/2))/d)
/*
* Interface used by the world
*/
int
aty128fb_init
(
void
);
int
aty128fb_setup
(
char
*
options
);
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
);
static
int
aty128fb_set_par
(
struct
fb_info
*
info
);
static
int
aty128fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
static
int
aty128fb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
info
);
static
int
aty128fb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
);
static
int
aty128fb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
);
static
int
aty128fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
);
static
int
aty128fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
);
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
info
);
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
fb
);
static
int
aty128fb_rasterimg
(
struct
fb_info
*
info
,
int
start
);
/*
* Interface to the low level console driver
*/
int
aty128fb_init
(
void
);
static
int
aty128fbcon_switch
(
int
con
,
struct
fb_info
*
fb
);
/*
* Internal routines
*/
static
void
aty128_encode_fix
(
struct
fb_fix_screeninfo
*
fix
,
struct
aty128fb_par
*
par
,
const
struct
fb_info_aty128
*
info
);
static
void
aty128_set_dispsw
(
struct
display
*
disp
,
struct
fb_info_aty128
*
info
,
int
bpp
,
int
accel
);
static
int
aty128_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
aty128fb_par
*
par
,
const
struct
fb_info_aty128
*
info
);
static
int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
,
const
struct
fb_info
*
info
);
const
struct
fb_info_aty128
*
info
);
static
int
aty128_pci_register
(
struct
pci_dev
*
pdev
,
const
struct
aty128_chip_info
*
aci
);
static
struct
fb_info_aty128
*
aty128_board_list_add
(
struct
fb_info_aty128
*
board_list
,
struct
fb_info_aty128
*
new_node
);
#if !defined(CONFIG_PPC) && !defined(__sparc__)
static
void
__init
aty128_get_pllinfo
(
struct
aty128fb_par
*
par
,
static
void
__init
aty128_get_pllinfo
(
struct
fb_info_aty128
*
info
,
char
*
bios_seg
);
static
char
__init
*
aty128find_ROM
(
struct
fb_info
*
info
);
static
char
__init
*
aty128find_ROM
(
struct
fb_info
_aty128
*
info
);
#endif
static
void
aty128_timings
(
struct
aty128fb_par
*
par
);
static
void
aty128_init_engine
(
struct
aty128fb_par
*
par
,
struct
fb_info
*
info
);
static
void
aty128_reset_engine
(
struct
aty128fb_par
*
par
);
static
void
aty128_flush_pixel_cache
(
struct
aty128fb_par
*
par
);
static
void
do_wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
);
static
void
wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
);
static
void
wait_for_idle
(
struct
aty128fb_par
*
par
);
static
void
aty128_timings
(
struct
fb_info_aty128
*
info
);
static
void
aty128_init_engine
(
const
struct
aty128fb_par
*
par
,
struct
fb_info_aty128
*
info
);
static
void
aty128_reset_engine
(
const
struct
fb_info_aty128
*
info
);
static
void
aty128_flush_pixel_cache
(
const
struct
fb_info_aty128
*
info
);
static
void
do_wait_for_fifo
(
u16
entries
,
struct
fb_info_aty128
*
info
);
static
void
wait_for_fifo
(
u16
entries
,
struct
fb_info_aty128
*
info
);
static
void
wait_for_idle
(
struct
fb_info_aty128
*
info
);
static
u32
bpp_to_depth
(
u32
bpp
);
#ifdef FBCON_HAS_CFB8
static
struct
display_switch
fbcon_aty128_8
;
static
void
fbcon_aty8_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
);
static
void
fbcon_aty8_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
);
#endif
#ifdef FBCON_HAS_CFB16
static
struct
display_switch
fbcon_aty128_16
;
static
void
fbcon_aty16_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
);
static
void
fbcon_aty16_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
);
#endif
#ifdef FBCON_HAS_CFB24
static
struct
display_switch
fbcon_aty128_24
;
static
void
fbcon_aty24_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
);
static
void
fbcon_aty24_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
);
#endif
#ifdef FBCON_HAS_CFB32
static
struct
display_switch
fbcon_aty128_32
;
static
void
fbcon_aty32_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
);
static
void
fbcon_aty32_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
);
#endif
static
struct
fb_ops
aty128fb_ops
=
{
owner:
THIS_MODULE
,
fb_get_fix:
gen
_get_fix
,
fb_get_var:
gen
_get_var
,
fb_set_var:
gen
_set_var
,
fb_get_fix:
aty128fb
_get_fix
,
fb_get_var:
aty128fb
_get_var
,
fb_set_var:
aty128fb
_set_var
,
fb_get_cmap:
gen_get_cmap
,
fb_set_cmap:
gen_set_cmap
,
fb_check_var:
aty128fb_check_var
,
fb_set_par:
aty128fb_set_par
,
fb_setcolreg:
aty128fb_setcolreg
,
fb_pan_display:
aty128fb_pan_display
,
fb_blank:
aty128fb_blank
,
fb_fillrect:
cfb_fillrect
,
fb_copyarea:
cfb_copyarea
,
fb_imageblit:
cfb_imageblit
,
fb_rasterimg:
aty128fb_rasterimg
,
};
#ifdef CONFIG_PMAC_BACKLIGHT
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
);
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
);
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
);
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
);
static
struct
backlight_controller
aty128_backlight_controller
=
{
aty128_set_backlight_enable
,
...
...
@@ -371,55 +426,60 @@ static struct backlight_controller aty128_backlight_controller = {
* using the other register aperture. TODO.
*/
static
inline
u32
_aty_ld_le32
(
volatile
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
_aty_ld_le32
(
volatile
unsigned
int
regindex
,
const
struct
fb_info_aty128
*
info
)
{
u32
val
;
#if defined(__powerpc__)
asm
(
"lwbrx %0,%1,%2;eieio"
:
"=r"
(
val
)
:
"b"
(
regindex
),
"r"
(
par
->
regbase
));
asm
(
"lwbrx %0,%1,%2;eieio"
:
"=r"
(
val
)
:
"b"
(
regindex
),
"r"
(
info
->
regbase
));
#else
val
=
readl
(
par
->
regbase
+
regindex
);
val
=
readl
(
info
->
regbase
+
regindex
);
#endif
return
val
;
}
static
inline
void
_aty_st_le32
(
volatile
unsigned
int
regindex
,
u32
val
,
const
struct
aty128fb_par
*
par
)
_aty_st_le32
(
volatile
unsigned
int
regindex
,
u32
val
,
const
struct
fb_info_aty128
*
info
)
{
#if defined(__powerpc__)
asm
(
"stwbrx %0,%1,%2;eieio"
:
:
"r"
(
val
),
"b"
(
regindex
),
"r"
(
par
->
regbase
)
:
"memory"
);
asm
(
"stwbrx %0,%1,%2;eieio"
:
:
"r"
(
val
),
"b"
(
regindex
),
"r"
(
info
->
regbase
)
:
"memory"
);
#else
writel
(
val
,
par
->
regbase
+
regindex
);
writel
(
val
,
info
->
regbase
+
regindex
);
#endif
}
static
inline
u8
_aty_ld_8
(
unsigned
int
regindex
,
const
struct
aty128fb_par
*
par
)
_aty_ld_8
(
unsigned
int
regindex
,
const
struct
fb_info_aty128
*
info
)
{
return
readb
(
par
->
regbase
+
regindex
);
return
readb
(
info
->
regbase
+
regindex
);
}
static
inline
void
_aty_st_8
(
unsigned
int
regindex
,
u8
val
,
const
struct
aty128fb_par
*
par
)
_aty_st_8
(
unsigned
int
regindex
,
u8
val
,
const
struct
fb_info_aty128
*
info
)
{
writeb
(
val
,
par
->
regbase
+
regindex
);
writeb
(
val
,
info
->
regbase
+
regindex
);
}
#define aty_ld_le32(regindex) _aty_ld_le32(regindex,
par
)
#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val,
par
)
#define aty_ld_8(regindex) _aty_ld_8(regindex,
par
)
#define aty_st_8(regindex, val) _aty_st_8(regindex, val,
par
)
#define aty_ld_le32(regindex) _aty_ld_le32(regindex,
info
)
#define aty_st_le32(regindex, val) _aty_st_le32(regindex, val,
info
)
#define aty_ld_8(regindex) _aty_ld_8(regindex,
info
)
#define aty_st_8(regindex, val) _aty_st_8(regindex, val,
info
)
/*
* Functions to read from/write to the pll registers
*/
#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index,
par
)
#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val,
par
)
#define aty_ld_pll(pll_index) _aty_ld_pll(pll_index,
info
)
#define aty_st_pll(pll_index, val) _aty_st_pll(pll_index, val,
info
)
static
u32
_aty_ld_pll
(
unsigned
int
pll_index
,
const
struct
aty128fb_par
*
par
)
_aty_ld_pll
(
unsigned
int
pll_index
,
const
struct
fb_info_aty128
*
info
)
{
aty_st_8
(
CLOCK_CNTL_INDEX
,
pll_index
&
0x1F
);
return
aty_ld_le32
(
CLOCK_CNTL_DATA
);
...
...
@@ -427,7 +487,8 @@ _aty_ld_pll(unsigned int pll_index, const struct aty128fb_par *par)
static
void
_aty_st_pll
(
unsigned
int
pll_index
,
u32
val
,
const
struct
aty128fb_par
*
par
)
_aty_st_pll
(
unsigned
int
pll_index
,
u32
val
,
const
struct
fb_info_aty128
*
info
)
{
aty_st_8
(
CLOCK_CNTL_INDEX
,
(
pll_index
&
0x1F
)
|
PLL_WR_EN
);
aty_st_le32
(
CLOCK_CNTL_DATA
,
val
);
...
...
@@ -435,19 +496,21 @@ _aty_st_pll(unsigned int pll_index, u32 val, const struct aty128fb_par *par)
/* return true when the PLL has completed an atomic update */
static
int
aty_pll_readupdate
(
const
struct
aty128fb_par
*
par
)
static
int
aty_pll_readupdate
(
const
struct
fb_info_aty128
*
info
)
{
return
!
(
aty_ld_pll
(
PPLL_REF_DIV
)
&
PPLL_ATOMIC_UPDATE_R
);
}
static
void
aty_pll_wait_readupdate
(
const
struct
aty128fb_par
*
par
)
static
void
aty_pll_wait_readupdate
(
const
struct
fb_info_aty128
*
info
)
{
unsigned
long
timeout
=
jiffies
+
HZ
/
100
;
// should be more than enough
unsigned
long
timeout
=
jiffies
+
HZ
/
100
;
// should be more than enough
int
reset
=
1
;
while
(
time_before
(
jiffies
,
timeout
))
if
(
aty_pll_readupdate
(
par
))
{
if
(
aty_pll_readupdate
(
info
))
{
reset
=
0
;
break
;
}
...
...
@@ -458,9 +521,10 @@ static void aty_pll_wait_readupdate(const struct aty128fb_par *par)
/* tell PLL to update */
static
void
aty_pll_writeupdate
(
const
struct
aty128fb_par
*
par
)
static
void
aty_pll_writeupdate
(
const
struct
fb_info_aty128
*
info
)
{
aty_pll_wait_readupdate
(
par
);
aty_pll_wait_readupdate
(
info
);
aty_st_pll
(
PPLL_REF_DIV
,
aty_ld_pll
(
PPLL_REF_DIV
)
|
PPLL_ATOMIC_UPDATE_W
);
...
...
@@ -468,7 +532,8 @@ static void aty_pll_writeupdate(const struct aty128fb_par *par)
/* write to the scratch register to test r/w functionality */
static
int
__init
register_test
(
const
struct
aty128fb_par
*
par
)
static
int
__init
register_test
(
const
struct
fb_info_aty128
*
info
)
{
u32
val
;
int
flag
=
0
;
...
...
@@ -491,51 +556,56 @@ static int __init register_test(const struct aty128fb_par *par)
/*
* Accelerator engine functions
*/
static
void
do_wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
static
void
do_wait_for_fifo
(
u16
entries
,
struct
fb_info_aty128
*
info
)
{
int
i
;
for
(;;)
{
for
(
i
=
0
;
i
<
2000000
;
i
++
)
{
par
->
fifo_slots
=
aty_ld_le32
(
GUI_STAT
)
&
0x0fff
;
if
(
par
->
fifo_slots
>=
entries
)
info
->
fifo_slots
=
aty_ld_le32
(
GUI_STAT
)
&
0x0fff
;
if
(
info
->
fifo_slots
>=
entries
)
return
;
}
aty128_reset_engine
(
par
);
aty128_reset_engine
(
info
);
}
}
static
void
wait_for_idle
(
struct
aty128fb_par
*
par
)
static
void
wait_for_idle
(
struct
fb_info_aty128
*
info
)
{
int
i
;
do_wait_for_fifo
(
64
,
par
);
do_wait_for_fifo
(
64
,
info
);
for
(;;)
{
for
(
i
=
0
;
i
<
2000000
;
i
++
)
{
if
(
!
(
aty_ld_le32
(
GUI_STAT
)
&
(
1
<<
31
)))
{
aty128_flush_pixel_cache
(
par
);
par
->
blitter_may_be_busy
=
0
;
aty128_flush_pixel_cache
(
info
);
info
->
blitter_may_be_busy
=
0
;
return
;
}
}
aty128_reset_engine
(
par
);
aty128_reset_engine
(
info
);
}
}
static
void
wait_for_fifo
(
u16
entries
,
struct
aty128fb_par
*
par
)
static
void
wait_for_fifo
(
u16
entries
,
struct
fb_info_aty128
*
info
)
{
if
(
par
->
fifo_slots
<
entries
)
do_wait_for_fifo
(
64
,
par
);
par
->
fifo_slots
-=
entries
;
if
(
info
->
fifo_slots
<
entries
)
do_wait_for_fifo
(
64
,
info
);
info
->
fifo_slots
-=
entries
;
}
static
void
aty128_flush_pixel_cache
(
struct
aty128fb_par
*
par
)
static
void
aty128_flush_pixel_cache
(
const
struct
fb_info_aty128
*
info
)
{
u32
tmp
;
int
i
;
u32
tmp
;
tmp
=
aty_ld_le32
(
PC_NGUI_CTLSTAT
);
tmp
&=
~
(
0x00ff
);
...
...
@@ -548,11 +618,12 @@ static void aty128_flush_pixel_cache(struct aty128fb_par *par)
}
static
void
aty128_reset_engine
(
struct
aty128fb_par
*
par
)
static
void
aty128_reset_engine
(
const
struct
fb_info_aty128
*
info
)
{
u32
gen_reset_cntl
,
clock_cntl_index
,
mclk_cntl
;
aty128_flush_pixel_cache
(
par
);
aty128_flush_pixel_cache
(
info
);
clock_cntl_index
=
aty_ld_le32
(
CLOCK_CNTL_INDEX
);
mclk_cntl
=
aty_ld_pll
(
MCLK_CNTL
);
...
...
@@ -577,25 +648,25 @@ static void aty128_reset_engine(struct aty128fb_par *par)
static
void
aty128_init_engine
(
struct
aty128fb_par
*
par
,
struct
fb_info
*
info
)
aty128_init_engine
(
const
struct
aty128fb_par
*
par
,
struct
fb_info_aty128
*
info
)
{
u32
pitch_value
;
wait_for_idle
(
par
);
wait_for_idle
(
info
);
/* 3D scaler not spoken here */
wait_for_fifo
(
1
,
par
);
wait_for_fifo
(
1
,
info
);
aty_st_le32
(
SCALE_3D_CNTL
,
0x00000000
);
aty128_reset_engine
(
par
);
aty128_reset_engine
(
info
);
pitch_value
=
par
->
crtc
.
pitch
;
if
(
par
->
crtc
.
bpp
==
24
)
{
pitch_value
=
pitch_value
*
3
;
}
wait_for_fifo
(
4
,
par
);
wait_for_fifo
(
4
,
info
);
/* setup engine offset registers */
aty_st_le32
(
DEFAULT_OFFSET
,
0x00000000
);
...
...
@@ -620,9 +691,10 @@ aty128_init_engine(struct aty128fb_par *par,
GMC_DP_SRC_RECT
|
GMC_3D_FCN_EN_CLR
|
GMC_DST_CLR_CMP_FCN_CLEAR
|
GMC_AUX_CLIP_CLEAR
|
GMC_WRITE_MASK_SET
);
GMC_AUX_CLIP_CLEAR
|
GMC_WRITE_MASK_SET
);
wait_for_fifo
(
8
,
par
);
wait_for_fifo
(
8
,
info
);
/* clear the line drawing registers */
aty_st_le32
(
DST_BRES_ERR
,
0
);
aty_st_le32
(
DST_BRES_INC
,
0
);
...
...
@@ -640,12 +712,13 @@ aty128_init_engine(struct aty128fb_par *par,
aty_st_le32
(
DP_WRITE_MASK
,
0xFFFFFFFF
);
/* Wait for all the writes to be completed before returning */
wait_for_idle
(
par
);
wait_for_idle
(
info
);
}
/* convert bpp values to their register representation */
static
u32
bpp_to_depth
(
u32
bpp
)
static
u32
bpp_to_depth
(
u32
bpp
)
{
if
(
bpp
<=
8
)
return
DST_8BPP
;
...
...
@@ -667,7 +740,7 @@ static u32 bpp_to_depth(u32 bpp)
/* Program the CRTC registers */
static
void
aty128_set_crtc
(
const
struct
aty128_crtc
*
crtc
,
const
struct
aty128fb_par
*
par
)
const
struct
fb_info_aty128
*
info
)
{
aty_st_le32
(
CRTC_GEN_CNTL
,
crtc
->
gen_cntl
);
aty_st_le32
(
CRTC_H_TOTAL_DISP
,
crtc
->
h_total
);
...
...
@@ -687,9 +760,9 @@ aty128_set_crtc(const struct aty128_crtc *crtc,
static
int
aty128_var_to_crtc
(
struct
fb_var_screeninfo
*
var
,
aty128_var_to_crtc
(
const
struct
fb_var_screeninfo
*
var
,
struct
aty128_crtc
*
crtc
,
const
struct
fb_info
*
info
)
const
struct
fb_info_aty128
*
info
)
{
u32
xres
,
yres
,
vxres
,
vyres
,
xoffset
,
yoffset
,
bpp
;
u32
left
,
right
,
upper
,
lower
,
hslen
,
vslen
,
sync
,
vmode
;
...
...
@@ -744,7 +817,7 @@ aty128_var_to_crtc(struct fb_var_screeninfo *var,
bytpp
=
mode_bytpp
[
depth
];
/* make sure there is enough video ram for the mode */
if
((
u32
)
(
vxres
*
vyres
*
bytpp
)
>
info
->
fix
.
smem_len
)
{
if
((
u32
)(
vxres
*
vyres
*
bytpp
)
>
info
->
fb_info
.
fix
.
smem_len
)
{
printk
(
KERN_ERR
"aty128fb: Not enough memory for mode
\n
"
);
return
-
EINVAL
;
}
...
...
@@ -787,11 +860,10 @@ aty128_var_to_crtc(struct fb_var_screeninfo *var,
crtc
->
h_total
=
h_total
|
(
h_disp
<<
16
);
crtc
->
v_total
=
v_total
|
(
v_disp
<<
16
);
crtc
->
h_sync_strt_wid
=
hsync_strt_pix
[
bytpp
]
|
(
h_sync_strt
<<
3
)
|
(
h_sync_wid
<<
16
)
|
(
h_sync_pol
<<
23
);
crtc
->
v_sync_strt_wid
=
v_sync_strt
|
(
v_sync_wid
<<
16
)
|
(
v_sync_pol
<<
23
);
crtc
->
h_sync_strt_wid
=
hsync_strt_pix
[
bytpp
]
|
(
h_sync_strt
<<
3
)
|
(
h_sync_wid
<<
16
)
|
(
h_sync_pol
<<
23
);
crtc
->
v_sync_strt_wid
=
v_sync_strt
|
(
v_sync_wid
<<
16
)
|
(
v_sync_pol
<<
23
);
crtc
->
pitch
=
vxres
>>
3
;
...
...
@@ -802,7 +874,7 @@ aty128_var_to_crtc(struct fb_var_screeninfo *var,
else
crtc
->
offset_cntl
=
0
;
var
->
xres_virtual
=
vxres
;
crtc
->
vxres
=
vxres
;
crtc
->
vyres
=
vyres
;
crtc
->
xoffset
=
xoffset
;
crtc
->
yoffset
=
yoffset
;
...
...
@@ -812,7 +884,8 @@ aty128_var_to_crtc(struct fb_var_screeninfo *var,
}
static
int
aty128_bpp_to_var
(
int
pix_width
,
struct
fb_var_screeninfo
*
var
)
static
int
aty128_bpp_to_var
(
int
pix_width
,
struct
fb_var_screeninfo
*
var
)
{
/* fill in pixel info */
...
...
@@ -876,8 +949,7 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
struct
fb_var_screeninfo
*
var
)
{
u32
xres
,
yres
,
left
,
right
,
upper
,
lower
,
hslen
,
vslen
,
sync
;
u32
h_total
,
h_disp
,
h_sync_strt
,
h_sync_dly
,
h_sync_wid
,
h_sync_pol
;
u32
h_total
,
h_disp
,
h_sync_strt
,
h_sync_dly
,
h_sync_wid
,
h_sync_pol
;
u32
v_total
,
v_disp
,
v_sync_strt
,
v_sync_wid
,
v_sync_pol
,
c_sync
;
u32
pix_width
;
...
...
@@ -913,6 +985,7 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
var
->
xres
=
xres
;
var
->
yres
=
yres
;
var
->
xres_virtual
=
crtc
->
vxres
;
var
->
yres_virtual
=
crtc
->
vyres
;
var
->
xoffset
=
crtc
->
xoffset
;
var
->
yoffset
=
crtc
->
yoffset
;
...
...
@@ -929,7 +1002,7 @@ aty128_crtc_to_var(const struct aty128_crtc *crtc,
}
static
void
aty128_set_pll
(
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
aty128_set_pll
(
struct
aty128_pll
*
pll
,
const
struct
fb_info_aty128
*
info
)
{
u32
div3
;
...
...
@@ -937,18 +1010,16 @@ aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
{
2
,
0
,
1
,
4
,
2
,
2
,
6
,
2
,
3
,
2
,
2
,
2
,
7
};
/* select PPLL_DIV_3 */
aty_st_le32
(
CLOCK_CNTL_INDEX
,
aty_ld_le32
(
CLOCK_CNTL_INDEX
)
|
(
3
<<
8
));
aty_st_le32
(
CLOCK_CNTL_INDEX
,
aty_ld_le32
(
CLOCK_CNTL_INDEX
)
|
(
3
<<
8
));
/* reset PLL */
aty_st_pll
(
PPLL_CNTL
,
aty_ld_pll
(
PPLL_CNTL
)
|
PPLL_RESET
|
PPLL_ATOMIC_UPDATE_EN
);
aty_ld_pll
(
PPLL_CNTL
)
|
PPLL_RESET
|
PPLL_ATOMIC_UPDATE_EN
);
/* write the reference divider */
aty_pll_wait_readupdate
(
par
);
aty_st_pll
(
PPLL_REF_DIV
,
par
->
constants
.
ref_divider
&
0x3ff
);
aty_pll_writeupdate
(
par
);
aty_pll_wait_readupdate
(
info
);
aty_st_pll
(
PPLL_REF_DIV
,
info
->
constants
.
ref_divider
&
0x3ff
);
aty_pll_writeupdate
(
info
);
div3
=
aty_ld_pll
(
PPLL_DIV_3
);
div3
&=
~
PPLL_FB3_DIV_MASK
;
...
...
@@ -957,13 +1028,13 @@ aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
div3
|=
post_conv
[
pll
->
post_divider
]
<<
16
;
/* write feedback and post dividers */
aty_pll_wait_readupdate
(
par
);
aty_pll_wait_readupdate
(
info
);
aty_st_pll
(
PPLL_DIV_3
,
div3
);
aty_pll_writeupdate
(
par
);
aty_pll_writeupdate
(
info
);
aty_pll_wait_readupdate
(
par
);
aty_pll_wait_readupdate
(
info
);
aty_st_pll
(
HTOTAL_CNTL
,
0
);
/* no horiz crtc adjustment */
aty_pll_writeupdate
(
par
);
aty_pll_writeupdate
(
info
);
/* clear the reset, just in case */
aty_st_pll
(
PPLL_CNTL
,
aty_ld_pll
(
PPLL_CNTL
)
&
~
PPLL_RESET
);
...
...
@@ -972,10 +1043,10 @@ aty128_set_pll(struct aty128_pll *pll, const struct aty128fb_par *par)
static
int
aty128_var_to_pll
(
u32
period_in_ps
,
struct
aty128_pll
*
pll
,
const
struct
aty128fb_par
*
par
)
const
struct
fb_info_aty128
*
info
)
{
const
struct
aty128_constants
c
=
par
->
constants
;
unsigned
char
post_dividers
[]
=
{
1
,
2
,
4
,
8
,
3
,
6
,
12
};
const
struct
aty128_constants
c
=
info
->
constants
;
unsigned
char
post_dividers
[]
=
{
1
,
2
,
4
,
8
,
3
,
6
,
12
};
u32
output_freq
;
u32
vclk
;
/* in .01 MHz */
int
i
;
...
...
@@ -987,7 +1058,7 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
if
(
vclk
>
c
.
ppll_max
)
vclk
=
c
.
ppll_max
;
if
(
vclk
*
12
<
c
.
ppll_min
)
vclk
=
c
.
ppll_min
/
12
;
vclk
=
c
.
ppll_min
/
12
;
/* now, find an acceptable divider */
for
(
i
=
0
;
i
<
sizeof
(
post_dividers
);
i
++
)
{
...
...
@@ -1014,9 +1085,8 @@ aty128_var_to_pll(u32 period_in_ps, struct aty128_pll *pll,
static
int
aty128_pll_to_var
(
const
struct
aty128_pll
*
pll
,
struct
fb_var_screeninfo
*
var
,
const
struct
fb_info
*
info
)
aty128_pll_to_var
(
const
struct
aty128_pll
*
pll
,
struct
fb_var_screeninfo
*
var
,
const
struct
fb_info_aty128
*
info
)
{
var
->
pixclock
=
100000000
/
pll
->
vclk
;
...
...
@@ -1026,7 +1096,7 @@ aty128_pll_to_var(const struct aty128_pll *pll,
static
void
aty128_set_fifo
(
const
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128fb_par
*
par
)
const
struct
fb_info_aty128
*
info
)
{
aty_st_le32
(
DDA_CONFIG
,
dsp
->
dda_config
);
aty_st_le32
(
DDA_ON_OFF
,
dsp
->
dda_on_off
);
...
...
@@ -1036,13 +1106,13 @@ aty128_set_fifo(const struct aty128_ddafifo *dsp,
static
int
aty128_ddafifo
(
struct
aty128_ddafifo
*
dsp
,
const
struct
aty128_pll
*
pll
,
u32
bpp
,
const
struct
fb_info
*
info
)
u32
bpp
,
const
struct
fb_info_aty128
*
info
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
const
struct
aty128_meminfo
*
m
=
par
->
mem
;
u32
xclk
=
par
->
constants
.
xclk
;
u32
fifo_width
=
par
->
constants
.
fifo_width
;
u32
fifo_depth
=
par
->
constants
.
fifo_depth
;
const
struct
aty128_meminfo
*
m
=
info
->
mem
;
u32
xclk
=
info
->
constants
.
xclk
;
u32
fifo_width
=
info
->
constants
.
fifo_width
;
u32
fifo_depth
=
info
->
constants
.
fifo_depth
;
s32
x
,
b
,
p
,
ron
,
roff
;
u32
n
,
d
;
...
...
@@ -1056,7 +1126,11 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
ron
=
4
*
m
->
MB
+
3
*
((
m
->
Trcd
-
2
>
0
)
?
m
->
Trcd
-
2
:
0
)
+
2
*
m
->
Trp
+
m
->
Twr
+
m
->
CL
+
m
->
Tr2w
+
x
;
2
*
m
->
Trp
+
m
->
Twr
+
m
->
CL
+
m
->
Tr2w
+
x
;
DBG
(
"x %x
\n
"
,
x
);
...
...
@@ -1091,14 +1165,16 @@ aty128_ddafifo(struct aty128_ddafifo *dsp,
/*
* This actually sets the video mode.
*/
static
int
aty128fb_set_par
(
struct
fb_info
*
info
)
static
void
aty128_set_par
(
struct
aty128fb_par
*
par
,
struct
fb_info_aty128
*
info
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
u32
config
;
if
(
par
->
blitter_may_be_busy
)
wait_for_idle
(
par
);
info
->
fb_info
.
par
=
par
;
if
(
info
->
blitter_may_be_busy
)
wait_for_idle
(
info
);
/* clear all registers that may interfere with mode setting */
aty_st_le32
(
OVR_CLR
,
0
);
...
...
@@ -1116,9 +1192,9 @@ aty128fb_set_par(struct fb_info *info)
aty_st_8
(
CRTC_EXT_CNTL
+
1
,
4
);
/* turn video off */
aty128_set_crtc
(
&
par
->
crtc
,
par
);
aty128_set_pll
(
&
par
->
pll
,
par
);
aty128_set_fifo
(
&
par
->
fifo_reg
,
par
);
aty128_set_crtc
(
&
par
->
crtc
,
info
);
aty128_set_pll
(
&
par
->
pll
,
info
);
aty128_set_fifo
(
&
par
->
fifo_reg
,
info
);
config
=
aty_ld_le32
(
CONFIG_CNTL
)
&
~
3
;
...
...
@@ -1132,19 +1208,16 @@ aty128fb_set_par(struct fb_info *info)
aty_st_le32
(
CONFIG_CNTL
,
config
);
aty_st_8
(
CRTC_EXT_CNTL
+
1
,
0
);
/* turn the video back on */
if
(
info
->
var
.
accel_flags
&
FB_ACCELF_TEXT
)
if
(
par
->
accel_flags
&
FB_ACCELF_TEXT
)
aty128_init_engine
(
par
,
info
);
#if defined(CONFIG_BOOTX_TEXT)
btext_update_display
(
info
->
fix
.
smem_start
,
(((
par
->
crtc
.
h_total
>>
16
)
&
0xff
)
+
1
)
*
8
,
((
par
->
crtc
.
v_total
>>
16
)
&
0x7ff
)
+
1
,
btext_update_display
(
info
->
f
b_info
.
f
ix
.
smem_start
,
(((
par
->
crtc
.
h_total
>>
16
)
&
0xff
)
+
1
)
*
8
,
((
par
->
crtc
.
v_total
>>
16
)
&
0x7ff
)
+
1
,
par
->
crtc
.
bpp
,
par
->
crtc
.
vxres
*
par
->
crtc
.
bpp
/
8
);
par
->
crtc
.
vxres
*
par
->
crtc
.
bpp
/
8
);
#endif
/* CONFIG_BOOTX_TEXT */
info
->
fix
.
line_length
=
(
info
->
var
.
xres_virtual
*
info
->
var
.
bits_per_pixel
)
>>
3
;
info
->
fix
.
visual
=
info
->
var
.
bits_per_pixel
<=
8
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_DIRECTCOLOR
;
return
0
;
}
/*
...
...
@@ -1153,29 +1226,90 @@ aty128fb_set_par(struct fb_info *info)
static
int
aty128_decode_var
(
struct
fb_var_screeninfo
*
var
,
struct
aty128fb_par
*
par
,
const
struct
fb_info
*
info
)
const
struct
fb_info_aty128
*
info
)
{
int
err
;
if
((
err
=
aty128_var_to_crtc
(
var
,
&
par
->
crtc
,
info
)))
return
err
;
if
((
err
=
aty128_var_to_pll
(
var
->
pixclock
,
&
par
->
pll
,
par
)))
if
((
err
=
aty128_var_to_pll
(
var
->
pixclock
,
&
par
->
pll
,
info
)))
return
err
;
if
((
err
=
aty128_ddafifo
(
&
par
->
fifo_reg
,
&
par
->
pll
,
par
->
crtc
.
bpp
,
info
)))
if
((
err
=
aty128_ddafifo
(
&
par
->
fifo_reg
,
&
par
->
pll
,
par
->
crtc
.
bpp
,
info
)))
return
err
;
if
(
var
->
accel_flags
&
FB_ACCELF_TEXT
)
par
->
accel_flags
=
FB_ACCELF_TEXT
;
else
par
->
accel_flags
=
0
;
return
0
;
}
static
int
aty128fb_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
aty128_encode_var
(
struct
fb_var_screeninfo
*
var
,
const
struct
aty128fb_par
*
par
,
const
struct
fb_info_aty128
*
info
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
int
err
;
if
((
err
=
aty128_crtc_to_var
(
&
par
->
crtc
,
var
)))
return
err
;
if
((
err
=
aty128_pll_to_var
(
&
par
->
pll
,
var
,
info
)))
return
err
;
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
transp
.
msb_right
=
0
;
var
->
nonstd
=
0
;
var
->
activate
=
0
;
var
->
height
=
-
1
;
var
->
width
=
-
1
;
var
->
accel_flags
=
par
->
accel_flags
;
return
0
;
}
/*
* Get the User Defined Part of the Display
*/
static
int
aty128fb_get_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
const
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
fb
->
par
;
if
(
con
==
-
1
)
aty128_encode_var
(
var
,
par
,
info
);
else
*
var
=
fb_display
[
con
].
var
;
return
0
;
}
/*
* Set the User Defined Part of the Display
*/
static
int
aty128fb_set_var
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
fb
)
{
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
aty128fb_par
par
;
struct
display
*
display
;
int
oldxres
,
oldyres
,
oldvxres
,
oldvyres
,
oldbpp
,
oldaccel
;
int
accel
,
err
;
display
=
(
con
>=
0
)
?
&
fb_display
[
con
]
:
fb
->
disp
;
/* basic (in)sanity checks */
if
(
!
var
->
xres
)
var
->
xres
=
1
;
...
...
@@ -1203,28 +1337,141 @@ aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
return
-
EINVAL
;
}
var
->
red
.
msb_right
=
0
;
var
->
green
.
msb_right
=
0
;
var
->
blue
.
msb_right
=
0
;
var
->
transp
.
msb_right
=
0
;
if
((
err
=
aty128_decode_var
(
var
,
&
par
,
info
)))
return
err
;
var
->
nonstd
=
0
;
var
->
activate
=
0
;
aty128_encode_var
(
var
,
&
par
,
info
);
var
->
height
=
-
1
;
var
->
width
=
-
1
;
if
((
var
->
activate
&
FB_ACTIVATE_MASK
)
==
FB_ACTIVATE_TEST
)
return
0
;
if
((
err
=
aty128_decode_var
(
var
,
par
,
info
)))
return
err
;
oldxres
=
display
->
var
.
xres
;
oldyres
=
display
->
var
.
yres
;
oldvxres
=
display
->
var
.
xres_virtual
;
oldvyres
=
display
->
var
.
yres_virtual
;
oldbpp
=
display
->
var
.
bits_per_pixel
;
oldaccel
=
display
->
var
.
accel_flags
;
display
->
var
=
*
var
;
if
(
oldxres
!=
var
->
xres
||
oldyres
!=
var
->
yres
||
oldvxres
!=
var
->
xres_virtual
||
oldvyres
!=
var
->
yres_virtual
||
oldbpp
!=
var
->
bits_per_pixel
||
oldaccel
!=
var
->
accel_flags
)
{
struct
fb_fix_screeninfo
fix
;
aty128_encode_fix
(
&
fix
,
&
par
,
info
);
display
->
visual
=
fix
.
visual
;
display
->
type
=
fix
.
type
;
display
->
type_aux
=
fix
.
type_aux
;
display
->
ypanstep
=
fix
.
ypanstep
;
display
->
ywrapstep
=
fix
.
ywrapstep
;
display
->
line_length
=
fix
.
line_length
;
display
->
can_soft_blank
=
1
;
display
->
inverse
=
0
;
accel
=
var
->
accel_flags
&
FB_ACCELF_TEXT
;
aty128_set_dispsw
(
display
,
info
,
par
.
crtc
.
bpp
,
accel
);
if
(
accel
)
display
->
scrollmode
=
SCROLL_YNOMOVE
;
else
display
->
scrollmode
=
SCROLL_YREDRAW
;
if
((
err
=
aty128_crtc_to_var
(
&
par
->
crtc
,
var
)))
return
err
;
if
(
info
->
fb_info
.
changevar
)
(
*
info
->
fb_info
.
changevar
)(
con
);
}
if
((
err
=
aty128_pll_to_var
(
&
par
->
pll
,
var
,
info
)))
if
(
!
info
->
fb_info
.
display_fg
||
info
->
fb_info
.
display_fg
->
vc_num
==
con
)
aty128_set_par
(
&
par
,
info
);
if
(
oldbpp
!=
var
->
bits_per_pixel
)
{
if
((
err
=
fb_alloc_cmap
(
&
display
->
cmap
,
0
,
0
)))
return
err
;
do_install_cmap
(
con
,
&
info
->
fb_info
);
}
return
0
;
}
static
void
aty128_set_dispsw
(
struct
display
*
disp
,
struct
fb_info_aty128
*
info
,
int
bpp
,
int
accel
)
{
switch
(
bpp
)
{
#ifdef FBCON_HAS_CFB8
case
8
:
disp
->
dispsw
=
accel
?
&
fbcon_aty128_8
:
&
fbcon_cfb8
;
break
;
#endif
#ifdef FBCON_HAS_CFB16
case
15
:
case
16
:
disp
->
dispsw
=
accel
?
&
fbcon_aty128_16
:
&
fbcon_cfb16
;
disp
->
dispsw_data
=
info
->
fb_info
.
pseudo_palette
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
24
:
disp
->
dispsw
=
accel
?
&
fbcon_aty128_24
:
&
fbcon_cfb24
;
disp
->
dispsw_data
=
info
->
fb_info
.
pseudo_palette
;
break
;
#endif
#ifdef FBCON_HAS_CFB32
case
32
:
disp
->
dispsw
=
accel
?
&
fbcon_aty128_32
:
&
fbcon_cfb32
;
disp
->
dispsw_data
=
info
->
fb_info
.
pseudo_palette
;
break
;
#endif
default:
disp
->
dispsw
=
&
fbcon_dummy
;
}
}
static
void
aty128_encode_fix
(
struct
fb_fix_screeninfo
*
fix
,
struct
aty128fb_par
*
par
,
const
struct
fb_info_aty128
*
info
)
{
memset
(
fix
,
0
,
sizeof
(
struct
fb_fix_screeninfo
));
strcpy
(
fix
->
id
,
info
->
fb_info
.
fix
.
id
);
fix
->
smem_start
=
info
->
fb_info
.
fix
.
smem_start
;
fix
->
mmio_start
=
info
->
fb_info
.
fix
.
mmio_start
;
fix
->
smem_len
=
info
->
fb_info
.
fix
.
smem_len
;
fix
->
mmio_len
=
info
->
fb_info
.
fix
.
mmio_len
;
fix
->
type
=
info
->
fb_info
.
fix
.
type
;
fix
->
type_aux
=
info
->
fb_info
.
fix
.
type_aux
;
fix
->
line_length
=
(
par
->
crtc
.
vxres
*
par
->
crtc
.
bpp
)
>>
3
;
fix
->
visual
=
par
->
crtc
.
bpp
<=
8
?
FB_VISUAL_PSEUDOCOLOR
:
FB_VISUAL_DIRECTCOLOR
;
fix
->
ywrapstep
=
info
->
fb_info
.
fix
.
ywrapstep
;
fix
->
xpanstep
=
info
->
fb_info
.
fix
.
xpanstep
;
fix
->
ypanstep
=
info
->
fb_info
.
fix
.
ypanstep
;
fix
->
accel
=
info
->
fb_info
.
fix
.
accel
;
return
;
}
/*
* Get the Fixed Part of the Display
*/
static
int
aty128fb_get_fix
(
struct
fb_fix_screeninfo
*
fix
,
int
con
,
struct
fb_info
*
fb
)
{
const
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
fb
->
par
;
aty128_decode_var
(
&
fb_display
[
con
].
var
,
par
,
info
);
aty128_encode_fix
(
fix
,
par
,
info
);
return
0
;
}
/*
* Pan or Wrap the Display
*
...
...
@@ -1232,9 +1479,10 @@ aty128fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
*/
static
int
aty128fb_pan_display
(
struct
fb_var_screeninfo
*
var
,
int
con
,
struct
fb_info
*
info
)
struct
fb_info
*
fb
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
fb
->
par
;
u32
xoffset
,
yoffset
;
u32
offset
;
u32
xres
,
yres
;
...
...
@@ -1242,79 +1490,36 @@ aty128fb_pan_display(struct fb_var_screeninfo *var, int con,
xres
=
(((
par
->
crtc
.
h_total
>>
16
)
&
0xff
)
+
1
)
<<
3
;
yres
=
((
par
->
crtc
.
v_total
>>
16
)
&
0x7ff
)
+
1
;
xoffset
=
(
var
->
xoffset
+
7
)
&
~
7
;
xoffset
=
(
var
->
xoffset
+
7
)
&
~
7
;
yoffset
=
var
->
yoffset
;
if
(
xoffset
+
xres
>
info
->
var
.
xres_virtual
||
yoffset
+
yres
>
par
->
crtc
.
vyres
)
if
(
xoffset
+
xres
>
par
->
crtc
.
vxres
||
yoffset
+
yres
>
par
->
crtc
.
vyres
)
return
-
EINVAL
;
par
->
crtc
.
xoffset
=
xoffset
;
par
->
crtc
.
yoffset
=
yoffset
;
offset
=
((
yoffset
*
info
->
var
.
xres_virtual
+
xoffset
)
*
par
->
crtc
.
bpp
)
>>
6
;
offset
=
((
yoffset
*
par
->
crtc
.
vxres
+
xoffset
)
*
par
->
crtc
.
bpp
)
>>
6
;
aty_st_le32
(
CRTC_OFFSET
,
offset
);
return
0
;
}
/*
* Accelerated functions
*/
static
void
aty128fb_rectcopy
(
int
srcx
,
int
srcy
,
int
dstx
,
int
dsty
,
u_int
width
,
u_int
height
,
struct
fb_info
*
info
)
static
int
aty128fb_rasterimg
(
struct
fb_info
*
info
,
int
start
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
u32
save_dp_datatype
,
save_dp_cntl
,
bppval
;
if
(
!
width
||
!
height
)
return
;
bppval
=
bpp_to_depth
(
par
->
crtc
.
bpp
);
if
(
bppval
==
DST_24BPP
)
{
srcx
*=
3
;
dstx
*=
3
;
width
*=
3
;
}
else
if
(
bppval
==
-
EINVAL
)
{
printk
(
"aty128fb: invalid depth
\n
"
);
return
;
}
wait_for_fifo
(
2
,
par
);
save_dp_datatype
=
aty_ld_le32
(
DP_DATATYPE
);
save_dp_cntl
=
aty_ld_le32
(
DP_CNTL
);
wait_for_fifo
(
6
,
par
);
aty_st_le32
(
SRC_Y_X
,
(
srcy
<<
16
)
|
srcx
);
aty_st_le32
(
DP_MIX
,
ROP3_SRCCOPY
|
DP_SRC_RECT
);
aty_st_le32
(
DP_CNTL
,
DST_X_LEFT_TO_RIGHT
|
DST_Y_TOP_TO_BOTTOM
);
aty_st_le32
(
DP_DATATYPE
,
save_dp_datatype
|
bppval
|
SRC_DSTCOLOR
);
aty_st_le32
(
DST_Y_X
,
(
dsty
<<
16
)
|
dstx
);
aty_st_le32
(
DST_HEIGHT_WIDTH
,
(
height
<<
16
)
|
width
);
par
->
blitter_may_be_busy
=
1
;
wait_for_fifo
(
2
,
par
);
aty_st_le32
(
DP_DATATYPE
,
save_dp_datatype
);
aty_st_le32
(
DP_CNTL
,
save_dp_cntl
);
}
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)
info
;
static
int
aty128fb_rasterimg
(
struct
fb_info
*
info
,
int
start
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
if
(
par
->
blitter_may_be_busy
)
wait_for_idle
(
par
);
return
0
;
}
int
__init
aty128fb_setup
(
char
*
options
)
int
__init
aty128fb_setup
(
char
*
options
)
{
char
*
this_opt
;
...
...
@@ -1326,28 +1531,28 @@ int __init aty128fb_setup(char *options)
char
*
p
;
int
i
;
p
=
this_opt
+
5
;
p
=
this_opt
+
5
;
for
(
i
=
0
;
i
<
sizeof
(
fontname
)
-
1
;
i
++
)
if
(
!*
p
||
*
p
==
' '
||
*
p
==
','
)
break
;
memcpy
(
fontname
,
this_opt
+
5
,
i
);
fontname
[
i
]
=
0
;
}
else
if
(
!
strncmp
(
this_opt
,
"noaccel"
,
7
))
{
noaccel
=
1
;
}
#ifdef CONFIG_MTRR
else
if
(
!
strncmp
(
this_opt
,
"nomtrr"
,
6
))
{
else
if
(
!
strncmp
(
this_opt
,
"nomtrr"
,
6
))
{
mtrr
=
0
;
}
#endif
#ifdef CONFIG_PPC
/* vmode and cmode depreciated */
else
if
(
!
strncmp
(
this_opt
,
"vmode:"
,
6
))
{
unsigned
int
vmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
unsigned
int
vmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
if
(
vmode
>
0
&&
vmode
<=
VMODE_MAX
)
default_vmode
=
vmode
;
}
else
if
(
!
strncmp
(
this_opt
,
"cmode:"
,
6
))
{
unsigned
int
cmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
unsigned
int
cmode
=
simple_strtoul
(
this_opt
+
6
,
NULL
,
0
);
switch
(
cmode
)
{
case
0
:
case
8
:
...
...
@@ -1376,8 +1581,7 @@ int __init aty128fb_setup(char *options)
*/
static
int
__init
aty128_init
(
struct
fb_info
*
info
,
struct
aty128fb_par
*
par
,
struct
pci_dev
*
pdev
,
const
char
*
name
)
aty128_init
(
struct
fb_info_aty128
*
info
,
struct
aty128fb_par
*
par
,
struct
pci_dev
*
pdev
,
const
char
*
name
)
{
struct
fb_var_screeninfo
var
;
u32
dac
;
...
...
@@ -1386,15 +1590,13 @@ aty128_init(struct fb_info *info, struct aty128fb_par *par,
const
struct
aty128_chip_info
*
aci
=
&
aty128_pci_probe_list
[
0
];
char
*
video_card
=
"Rage128"
;
if
(
!
info
->
fix
.
smem_len
)
/* may have already been probed */
info
->
fix
.
smem_len
=
aty_ld_le32
(
CONFIG_MEMSIZE
)
&
0x03FFFFFF
;
if
(
!
info
->
fb_info
.
fix
.
smem_len
)
/* may have already been probed */
info
->
fb_info
.
fix
.
smem_len
=
aty_ld_le32
(
CONFIG_MEMSIZE
)
&
0x03FFFFFF
;
#ifdef CONFIG_MTRR
if
(
mtrr
)
{
par
->
mtrr
.
vram
=
mtrr_add
(
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
,
MTRR_TYPE_WRCOMB
,
1
);
par
->
mtrr
.
vram
=
mtrr_add
(
info
->
fb_info
.
fix
.
smem_start
,
info
->
fb_info
.
fix
.
smem_len
,
MTRR_TYPE_WRCOMB
,
1
);
par
->
mtrr
.
vram_valid
=
1
;
/* let there be speed */
printk
(
KERN_INFO
"aty128fb: Rage128 MTRR set to ON
\n
"
);
...
...
@@ -1405,43 +1607,35 @@ aty128_init(struct fb_info *info, struct aty128fb_par *par,
chip_rev
=
(
aty_ld_le32
(
CONFIG_CNTL
)
>>
16
)
&
0x1F
;
/* put a name with the face */
while
(
aci
->
name
&&
pdev
->
device
!=
aci
->
device
)
{
aci
++
;
}
video_card
=
(
char
*
)
aci
->
name
;
par
->
chip_gen
=
aci
->
chip_gen
;
while
(
aci
->
name
&&
pdev
->
device
!=
aci
->
device
)
{
aci
++
;
}
video_card
=
(
char
*
)
aci
->
name
;
info
->
chip_gen
=
aci
->
chip_gen
;
printk
(
KERN_INFO
"aty128fb: %s [chip rev 0x%x] "
,
video_card
,
chip_rev
);
printk
(
KERN_INFO
"aty128fb: %s [chip rev 0x%x] "
,
video_card
,
chip_rev
);
if
(
info
->
fix
.
smem_len
%
(
1024
*
1024
)
==
0
)
printk
(
"%dM %s
\n
"
,
info
->
fix
.
smem_len
/
(
1024
*
1024
),
par
->
mem
->
name
);
if
(
info
->
fb_info
.
fix
.
smem_len
%
(
1024
*
1024
)
==
0
)
printk
(
"%dM %s
\n
"
,
info
->
fb_info
.
fix
.
smem_len
/
(
1024
*
1024
),
info
->
mem
->
name
);
else
printk
(
"%dk %s
\n
"
,
info
->
fix
.
smem_len
/
1024
,
par
->
mem
->
name
);
printk
(
"%dk %s
\n
"
,
info
->
fb_info
.
fix
.
smem_len
/
1024
,
info
->
mem
->
name
);
/* fill in info */
strcpy
(
info
->
modename
,
info
->
fix
.
id
);
info
->
node
=
NODEV
;
info
->
fbops
=
&
aty128fb_ops
;
strcpy
(
info
->
fontname
,
fontname
);
info
->
changevar
=
NULL
;
info
->
switch_con
=
ge
n_switch
;
info
->
updatevar
=
NULL
;
info
->
flags
=
FBINFO_FLAG_DEFAULT
;
strcpy
(
info
->
fb_info
.
modename
,
info
->
fb_info
.
fix
.
id
);
info
->
fb_info
.
node
=
NODEV
;
info
->
fb_info
.
fbops
=
&
aty128fb_ops
;
strcpy
(
info
->
fb_info
.
fontname
,
fontname
);
info
->
fb_info
.
changevar
=
NULL
;
info
->
fb_info
.
switch_con
=
&
aty128fbco
n_switch
;
info
->
fb_info
.
updatevar
=
NULL
;
info
->
fb_info
.
flags
=
FBINFO_FLAG_DEFAULT
;
var
=
default_var
;
#ifdef CONFIG_PPC
if
(
_machine
==
_MACH_Pmac
)
{
if
(
mode_option
)
{
if
(
!
mac_find_mode
(
&
var
,
info
,
mode_option
,
8
))
if
(
!
mac_find_mode
(
&
var
,
&
info
->
fb_info
,
mode_option
,
8
))
var
=
default_var
;
}
else
{
if
(
default_vmode
<=
0
||
default_vmode
>
VMODE_MAX
)
if
(
default_vmode
<=
0
||
default_vmode
>
VMODE_MAX
)
default_vmode
=
VMODE_1024_768_60
;
/* iMacs need that resolution
...
...
@@ -1467,27 +1661,25 @@ aty128_init(struct fb_info *info, struct aty128fb_par *par,
if
(
machine_is_compatible
(
"PowerBook3,2"
))
default_vmode
=
VMODE_1152_768_60
;
if
(
default_cmode
<
CMODE_8
||
default_cmode
>
CMODE_32
)
if
(
default_cmode
<
CMODE_8
||
default_cmode
>
CMODE_32
)
default_cmode
=
CMODE_8
;
if
(
mac_vmode_to_var
(
default_vmode
,
default_cmode
,
&
var
))
if
(
mac_vmode_to_var
(
default_vmode
,
default_cmode
,
&
var
))
var
=
default_var
;
}
}
else
#endif
/* CONFIG_PPC */
{
if
(
fb_find_mode
(
&
var
,
info
,
mode_option
,
NULL
,
0
,
if
(
fb_find_mode
(
&
var
,
&
info
->
fb_info
,
mode_option
,
NULL
,
0
,
&
defaultmode
,
8
)
==
0
)
var
=
default_var
;
}
if
(
noaccel
)
var
.
accel_flags
&=
~
FB_ACCELF_TEXT
;
else
var
.
accel_flags
|=
FB_ACCELF_TEXT
;
info
->
var
=
var
;
if
(
aty128_decode_var
(
&
var
,
par
,
info
))
{
printk
(
KERN_ERR
"aty128fb: Cannot set default mode.
\n
"
);
return
0
;
...
...
@@ -1502,43 +1694,61 @@ aty128_init(struct fb_info *info, struct aty128fb_par *par,
/* turn off bus mastering, just in case */
aty_st_le32
(
BUS_CNTL
,
aty_ld_le32
(
BUS_CNTL
)
|
BUS_MASTER_DIS
);
gen_set_var
(
&
var
,
-
1
,
info
);
aty128fb_set_var
(
&
var
,
-
1
,
&
info
->
fb_
info
);
aty128_init_engine
(
par
,
info
);
board_list
=
aty128_board_list_add
(
board_list
,
info
);
size
=
(
var
.
bits_per_pixel
<=
8
)
?
256
:
32
;
fb_alloc_cmap
(
&
info
->
cmap
,
size
,
0
);
fb_alloc_cmap
(
&
info
->
fb_info
.
cmap
,
size
,
0
);
if
(
register_framebuffer
(
info
)
<
0
)
if
(
register_framebuffer
(
&
info
->
fb_
info
)
<
0
)
return
0
;
#ifdef CONFIG_PMAC_BACKLIGHT
/* Could be extended to Rage128Pro LVDS output too */
if
(
info
->
chip_gen
==
rage_M3
)
register_backlight_controller
(
&
aty128_backlight_controller
,
par
,
"ati"
);
register_backlight_controller
(
&
aty128_backlight_controller
,
info
,
"ati"
);
#endif
/* CONFIG_PMAC_BACKLIGHT */
printk
(
KERN_INFO
"fb%d: %s frame buffer device on %s
\n
"
,
GET_FB_IDX
(
info
->
node
),
info
->
fix
.
id
,
name
);
GET_FB_IDX
(
info
->
fb_info
.
node
),
info
->
fb_info
.
fix
.
id
,
name
);
return
1
;
/* success! */
}
int
__init
aty128fb_init
(
void
)
/* add a new card to the list ++ajoshi */
static
struct
fb_info_aty128
*
aty128_board_list_add
(
struct
fb_info_aty128
*
board_list
,
struct
fb_info_aty128
*
new_node
)
{
struct
fb_info_aty128
*
i_p
=
board_list
;
new_node
->
next
=
NULL
;
if
(
board_list
==
NULL
)
return
new_node
;
while
(
i_p
->
next
!=
NULL
)
i_p
=
i_p
->
next
;
i_p
->
next
=
new_node
;
return
board_list
;
}
int
__init
aty128fb_init
(
void
)
{
#ifdef CONFIG_PCI
struct
pci_dev
*
pdev
=
NULL
;
const
struct
aty128_chip_info
*
aci
=
&
aty128_pci_probe_list
[
0
];
while
(
aci
->
name
!=
NULL
)
{
pdev
=
pci_find_device
(
PCI_VENDOR_ID_ATI
,
aci
->
device
,
pdev
);
pdev
=
pci_find_device
(
PCI_VENDOR_ID_ATI
,
aci
->
device
,
pdev
);
while
(
pdev
!=
NULL
)
{
if
(
aty128_pci_register
(
pdev
,
aci
)
==
0
)
return
0
;
pdev
=
pci_find_device
(
PCI_VENDOR_ID_ATI
,
aci
->
device
,
pdev
);
pdev
=
pci_find_device
(
PCI_VENDOR_ID_ATI
,
aci
->
device
,
pdev
);
}
aci
++
;
}
...
...
@@ -1554,12 +1764,12 @@ static int __init
aty128_pci_register
(
struct
pci_dev
*
pdev
,
const
struct
aty128_chip_info
*
aci
)
{
struct
aty128fb_par
*
par
=
NULL
;
struct
fb_info
*
info
=
NULL
;
struct
fb_info_aty128
*
info
=
NULL
;
struct
aty128fb_par
*
par
;
int
err
;
#if !defined(CONFIG_PPC) && !defined(__sparc__)
char
*
bios_seg
=
NULL
;
#endif
int
err
;
/* Enable device in PCI config */
if
((
err
=
pci_enable_device
(
pdev
)))
{
...
...
@@ -1569,8 +1779,7 @@ aty128_pci_register(struct pci_dev *pdev,
}
aty128fb_fix
.
smem_start
=
pci_resource_start
(
pdev
,
0
);
if
(
!
request_mem_region
(
aty128fb_fix
.
smem_start
,
pci_resource_len
(
pdev
,
0
),
if
(
!
request_mem_region
(
aty128fb_fix
.
smem_start
,
pci_resource_len
(
pdev
,
0
),
"aty128fb FB"
))
{
printk
(
KERN_ERR
"aty128fb: cannot reserve frame "
"buffer memory
\n
"
);
...
...
@@ -1578,20 +1787,15 @@ aty128_pci_register(struct pci_dev *pdev,
}
aty128fb_fix
.
mmio_start
=
pci_resource_start
(
pdev
,
2
);
if
(
!
request_mem_region
(
aty128fb_fix
.
mmio_start
,
pci_resource_len
(
pdev
,
2
),
if
(
!
request_mem_region
(
aty128fb_fix
.
mmio_start
,
pci_resource_len
(
pdev
,
2
),
"aty128fb MMIO"
))
{
printk
(
KERN_ERR
"aty128fb: cannot reserve MMIO region
\n
"
);
goto
err_free_mmio
;
}
/* We have the resources. Now virtualize them */
if
(
!
(
info
=
kmalloc
(
sizeof
(
struct
fb_info
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
17
,
GFP_ATOMIC
)))
{
printk
(
KERN_ERR
"aty128fb: can't alloc fb_info
\n
"
);
if
(
!
(
info
=
kmalloc
(
sizeof
(
struct
fb_info_aty128
)
+
sizeof
(
struct
display
)
+
sizeof
(
u32
)
*
17
,
GFP_ATOMIC
)))
{
printk
(
KERN_ERR
"aty128fb: can't alloc fb_info_aty128
\n
"
);
goto
err_unmap_out
;
}
...
...
@@ -1600,68 +1804,66 @@ aty128_pci_register(struct pci_dev *pdev,
goto
err_unmap_out
;
}
memset
(
info
,
0
,
sizeof
(
struct
fb_info
));
memset
(
info
,
0
,
sizeof
(
struct
fb_info
_aty128
));
memset
(
par
,
0
,
sizeof
(
struct
aty128fb_par
));
info
->
disp
=
(
struct
display
*
)
(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)
(
info
->
disp
+
1
);
info
->
par
=
par
;
info
->
fb_info
.
disp
=
(
struct
display
*
)
(
info
+
1
);
info
->
fb_info
.
pseudo_palette
=
(
void
*
)(
info
->
fb_info
.
disp
+
1
);
info
->
fb_info
.
par
=
par
;
info
->
currcon
=
-
1
;
info
->
fix
=
aty128fb_fix
;
info
->
fb_info
.
currcon
=
-
1
;
info
->
f
b_info
.
f
ix
=
aty128fb_fix
;
/* Virtualize mmio region */
par
->
regbase
=
ioremap
(
aty128fb_fix
.
mmio_start
,
0x1FFF
);
info
->
regbase
=
ioremap
(
aty128fb_fix
.
mmio_start
,
0x1FFF
);
if
(
!
par
->
regbase
)
if
(
!
info
->
regbase
)
goto
err_free_info
;
/* Grab memory size from the card */
info
->
fix
.
smem_len
=
aty_ld_le32
(
CONFIG_MEMSIZE
)
&
0x03FFFFFF
;
info
->
fb_info
.
fix
.
smem_len
=
aty_ld_le32
(
CONFIG_MEMSIZE
)
&
0x03FFFFFF
;
/* Virtualize the framebuffer */
info
->
screen_base
=
ioremap
(
aty128fb_fix
.
smem_start
,
info
->
fix
.
smem_len
);
info
->
fb_info
.
screen_base
=
ioremap
(
aty128fb_fix
.
smem_start
,
info
->
fb_info
.
fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
iounmap
((
void
*
)
par
->
regbase
);
if
(
!
info
->
fb_info
.
screen_base
)
{
iounmap
((
void
*
)
info
->
regbase
);
goto
err_free_info
;
}
/* If we can't test scratch registers, something is seriously wrong */
if
(
!
register_test
(
par
))
{
printk
(
KERN_ERR
"aty128fb: Can't write to video register!
\n
"
);
if
(
!
register_test
(
info
))
{
printk
(
KERN_ERR
"aty128fb: Can't write to video register!
\n
"
);
goto
err_out
;
}
#if !defined(CONFIG_PPC) && !defined(__sparc__)
if
(
!
(
bios_seg
=
aty128find_ROM
(
info
)))
printk
(
KERN_INFO
"aty128fb: Rage128 BIOS not located. "
"Guessing...
\n
"
);
else
{
printk
(
KERN_INFO
"aty128fb: Rage128 BIOS located at "
"segment %4.4X
\n
"
,
(
unsigned
int
)
bios_seg
);
aty128_get_pllinfo
(
par
,
bios_seg
);
"segment %4.4X
\n
"
,
(
unsigned
int
)
bios_seg
);
aty128_get_pllinfo
(
info
,
bios_seg
);
}
#endif
aty128_timings
(
par
);
aty128_timings
(
info
);
if
(
!
aty128_init
(
info
,
par
,
pdev
,
"PCI"
))
goto
err_out
;
return
0
;
err_out:
iounmap
(
info
->
screen_base
);
iounmap
(
par
->
regbase
);
err_free_info:
err_out:
iounmap
(
info
->
fb_info
.
screen_base
);
iounmap
(
info
->
regbase
);
err_free_info:
kfree
(
info
);
err_unmap_out:
err_unmap_out:
release_mem_region
(
pci_resource_start
(
pdev
,
2
),
pci_resource_len
(
pdev
,
2
));
err_free_mmio:
err_free_mmio:
release_mem_region
(
pci_resource_start
(
pdev
,
0
),
pci_resource_len
(
pdev
,
0
));
err_free_fb:
err_free_fb:
release_mem_region
(
pci_resource_start
(
pdev
,
1
),
pci_resource_len
(
pdev
,
1
));
return
-
ENODEV
;
...
...
@@ -1671,7 +1873,8 @@ aty128_pci_register(struct pci_dev *pdev,
/* PPC and Sparc cannot read video ROM */
#if !defined(CONFIG_PPC) && !defined(__sparc__)
static
char
__init
*
aty128find_ROM
(
struct
fb_info
*
info
)
static
char
__init
*
aty128find_ROM
(
struct
fb_info_aty128
*
info
)
{
u32
segstart
;
char
*
rom_base
;
...
...
@@ -1681,14 +1884,12 @@ static char __init * aty128find_ROM(struct fb_info *info)
char
aty_rom_sig
[]
=
"761295520"
;
/* ATI ROM Signature */
char
R128_sig
[]
=
"R128"
;
/* Rage128 ROM identifier */
for
(
segstart
=
0x000c0000
;
segstart
<
0x000f0000
;
segstart
+=
0x00001000
)
{
for
(
segstart
=
0x000c0000
;
segstart
<
0x000f0000
;
segstart
+=
0x00001000
)
{
stage
=
1
;
rom_base
=
(
char
*
)
ioremap
(
segstart
,
0x1000
);
rom_base
=
(
char
*
)
ioremap
(
segstart
,
0x1000
);
if
((
*
rom_base
==
0x55
)
&&
(((
*
(
rom_base
+
1
))
&
0xff
)
==
0xaa
))
if
((
*
rom_base
==
0x55
)
&&
(((
*
(
rom_base
+
1
))
&
0xff
)
==
0xaa
))
stage
=
2
;
if
(
stage
!=
2
)
{
...
...
@@ -1697,9 +1898,7 @@ static char __init * aty128find_ROM(struct fb_info *info)
}
rom
=
rom_base
;
for
(
i
=
0
;
(
i
<
128
-
strlen
(
aty_rom_sig
))
&&
(
stage
!=
3
);
i
++
)
{
for
(
i
=
0
;
(
i
<
128
-
strlen
(
aty_rom_sig
))
&&
(
stage
!=
3
);
i
++
)
{
if
(
aty_rom_sig
[
0
]
==
*
rom
)
if
(
strncmp
(
aty_rom_sig
,
rom
,
strlen
(
aty_rom_sig
))
==
0
)
...
...
@@ -1733,7 +1932,7 @@ static char __init * aty128find_ROM(struct fb_info *info)
static
void
__init
aty128_get_pllinfo
(
struct
aty128fb_par
*
par
,
char
*
bios_seg
)
aty128_get_pllinfo
(
struct
fb_info_aty128
*
info
,
char
*
bios_seg
)
{
void
*
bios_header
;
void
*
header_ptr
;
...
...
@@ -1753,23 +1952,24 @@ aty128_get_pllinfo(struct aty128fb_par *par, char *bios_seg)
memcpy_fromio
(
&
pll
,
header_ptr
,
50
);
par
->
constants
.
ppll_max
=
pll
.
PCLK_max_freq
;
par
->
constants
.
ppll_min
=
pll
.
PCLK_min_freq
;
par
->
constants
.
xclk
=
(
u32
)
pll
.
XCLK
;
par
->
constants
.
ref_divider
=
(
u32
)
pll
.
PCLK_ref_divider
;
par
->
constants
.
dotclock
=
(
u32
)
pll
.
PCLK_ref_freq
;
info
->
constants
.
ppll_max
=
pll
.
PCLK_max_freq
;
info
->
constants
.
ppll_min
=
pll
.
PCLK_min_freq
;
info
->
constants
.
xclk
=
(
u32
)
pll
.
XCLK
;
info
->
constants
.
ref_divider
=
(
u32
)
pll
.
PCLK_ref_divider
;
info
->
constants
.
dotclock
=
(
u32
)
pll
.
PCLK_ref_freq
;
DBG
(
"ppll_max %d ppll_min %d xclk %d ref_divider %d dotclock %d
\n
"
,
par
->
constants
.
ppll_max
,
par
->
constants
.
ppll_min
,
par
->
constants
.
xclk
,
par
->
constants
.
ref_divider
,
par
->
constants
.
dotclock
);
info
->
constants
.
ppll_max
,
info
->
constants
.
ppll_min
,
info
->
constants
.
xclk
,
info
->
constants
.
ref_divider
,
info
->
constants
.
dotclock
);
}
#endif
/* !CONFIG_PPC */
/* fill in known card constants if pll_block is not available */
static
void
__init
aty128_timings
(
struct
aty128fb_par
*
par
)
static
void
__init
aty128_timings
(
struct
fb_info_aty128
*
info
)
{
#ifdef CONFIG_PPC
/* instead of a table lookup, assume OF has properly
...
...
@@ -1779,11 +1979,12 @@ static void __init aty128_timings(struct aty128fb_par *par)
u32
x_mpll_ref_fb_div
;
u32
xclk_cntl
;
u32
Nx
,
M
;
unsigned
PostDivSet
[]
=
{
0
,
1
,
2
,
4
,
8
,
3
,
6
,
12
};
unsigned
PostDivSet
[]
=
{
0
,
1
,
2
,
4
,
8
,
3
,
6
,
12
};
#endif
if
(
!
par
->
constants
.
dotclock
)
par
->
constants
.
dotclock
=
2950
;
if
(
!
info
->
constants
.
dotclock
)
info
->
constants
.
dotclock
=
2950
;
#ifdef CONFIG_PPC
x_mpll_ref_fb_div
=
aty_ld_pll
(
X_MPLL_REF_FB_DIV
);
...
...
@@ -1791,55 +1992,84 @@ static void __init aty128_timings(struct aty128fb_par *par)
Nx
=
(
x_mpll_ref_fb_div
&
0x00ff00
)
>>
8
;
M
=
x_mpll_ref_fb_div
&
0x0000ff
;
par
->
constants
.
xclk
=
round_div
((
2
*
Nx
*
par
->
constants
.
dotclock
),
(
M
*
PostDivSet
[
xclk_cntl
]));
info
->
constants
.
xclk
=
round_div
((
2
*
Nx
*
info
->
constants
.
dotclock
),
(
M
*
PostDivSet
[
xclk_cntl
]));
par
->
constants
.
ref_divider
=
info
->
constants
.
ref_divider
=
aty_ld_pll
(
PPLL_REF_DIV
)
&
PPLL_REF_DIV_MASK
;
#endif
if
(
!
par
->
constants
.
ref_divider
)
{
par
->
constants
.
ref_divider
=
0x3b
;
if
(
!
info
->
constants
.
ref_divider
)
{
info
->
constants
.
ref_divider
=
0x3b
;
aty_st_pll
(
X_MPLL_REF_FB_DIV
,
0x004c4c1e
);
aty_pll_writeupdate
(
par
);
aty_pll_writeupdate
(
info
);
}
aty_st_pll
(
PPLL_REF_DIV
,
par
->
constants
.
ref_divider
);
aty_pll_writeupdate
(
par
);
aty_st_pll
(
PPLL_REF_DIV
,
info
->
constants
.
ref_divider
);
aty_pll_writeupdate
(
info
);
/* from documentation */
if
(
!
par
->
constants
.
ppll_min
)
par
->
constants
.
ppll_min
=
12500
;
if
(
!
par
->
constants
.
ppll_max
)
par
->
constants
.
ppll_max
=
25000
;
/* 23000 on some cards? */
if
(
!
par
->
constants
.
xclk
)
par
->
constants
.
xclk
=
0x1d4d
;
/* same as mclk */
if
(
!
info
->
constants
.
ppll_min
)
info
->
constants
.
ppll_min
=
12500
;
if
(
!
info
->
constants
.
ppll_max
)
info
->
constants
.
ppll_max
=
25000
;
/* 23000 on some cards? */
if
(
!
info
->
constants
.
xclk
)
info
->
constants
.
xclk
=
0x1d4d
;
/* same as mclk */
par
->
constants
.
fifo_width
=
128
;
par
->
constants
.
fifo_depth
=
32
;
info
->
constants
.
fifo_width
=
128
;
info
->
constants
.
fifo_depth
=
32
;
switch
(
aty_ld_le32
(
MEM_CNTL
)
&
0x3
)
{
case
0
:
par
->
mem
=
&
sdr_128
;
info
->
mem
=
&
sdr_128
;
break
;
case
1
:
par
->
mem
=
&
sdr_sgram
;
info
->
mem
=
&
sdr_sgram
;
break
;
case
2
:
par
->
mem
=
&
ddr_sgram
;
info
->
mem
=
&
ddr_sgram
;
break
;
default:
par
->
mem
=
&
sdr_sgram
;
info
->
mem
=
&
sdr_sgram
;
}
}
static
int
aty128fbcon_switch
(
int
con
,
struct
fb_info
*
fb
)
{
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
display
*
disp
;
struct
aty128fb_par
par
;
if
(
info
->
fb_info
.
currcon
>=
0
)
{
disp
=
fb_display
+
info
->
fb_info
.
currcon
;
if
(
disp
->
cmap
.
len
)
fb_copy_cmap
(
&
info
->
fb_info
.
cmap
,
&
disp
->
cmap
,
0
);
}
/* set the current console */
fb
->
currcon
=
con
;
aty128_decode_var
(
&
fb_display
[
con
].
var
,
&
par
,
info
);
aty128_set_par
(
&
par
,
info
);
aty128_set_dispsw
(
&
fb_display
[
con
],
info
,
par
.
crtc
.
bpp
,
par
.
accel_flags
&
FB_ACCELF_TEXT
);
do_install_cmap
(
con
,
fb
);
return
1
;
}
/*
* Blank the display.
*/
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
info
)
static
int
aty128fb_blank
(
int
blank
,
struct
fb_info
*
fb
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
u8
state
=
0
;
#ifdef CONFIG_PMAC_BACKLIGHT
...
...
@@ -1854,7 +2084,7 @@ static int aty128fb_blank(int blank, struct fb_info *info)
if
(
blank
&
VESA_POWERDOWN
)
state
|=
4
;
aty_st_8
(
CRTC_EXT_CNTL
+
1
,
state
);
aty_st_8
(
CRTC_EXT_CNTL
+
1
,
state
);
#ifdef CONFIG_PMAC_BACKLIGHT
if
((
_machine
==
_MACH_Pmac
)
&&
!
blank
)
...
...
@@ -1870,9 +2100,10 @@ static int aty128fb_blank(int blank, struct fb_info *info)
*/
static
int
aty128fb_setcolreg
(
u_int
regno
,
u_int
red
,
u_int
green
,
u_int
blue
,
u_int
transp
,
struct
fb_info
*
info
)
u_int
transp
,
struct
fb_info
*
fb
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
fb
;
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
fb
->
par
;
u32
col
;
if
(
regno
>
255
)
...
...
@@ -1890,23 +2121,19 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if
((
par
->
crtc
.
bpp
>
8
)
&&
(
regno
==
0
))
{
int
i
;
if
(
par
->
chip_gen
==
rage_M3
)
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
&
~
DAC_PALETTE_ACCESS_CNTL
);
if
(
info
->
chip_gen
==
rage_M3
)
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
&
~
DAC_PALETTE_ACCESS_CNTL
);
for
(
i
=
16
;
i
<
256
;
i
++
)
{
for
(
i
=
16
;
i
<
256
;
i
++
)
{
aty_st_8
(
PALETTE_INDEX
,
i
);
col
=
(
i
<<
16
)
|
(
i
<<
8
)
|
i
;
aty_st_le32
(
PALETTE_DATA
,
col
);
}
if
(
par
->
chip_gen
==
rage_M3
)
{
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
|
DAC_PALETTE_ACCESS_CNTL
);
if
(
info
->
chip_gen
==
rage_M3
)
{
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
|
DAC_PALETTE_ACCESS_CNTL
);
for
(
i
=
16
;
i
<
256
;
i
++
)
{
for
(
i
=
16
;
i
<
256
;
i
++
)
{
aty_st_8
(
PALETTE_INDEX
,
i
);
col
=
(
i
<<
16
)
|
(
i
<<
8
)
|
i
;
aty_st_le32
(
PALETTE_DATA
,
col
);
...
...
@@ -1916,10 +2143,8 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
/* initialize palette */
if
(
par
->
chip_gen
==
rage_M3
)
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
&
~
DAC_PALETTE_ACCESS_CNTL
);
if
(
info
->
chip_gen
==
rage_M3
)
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
&
~
DAC_PALETTE_ACCESS_CNTL
);
if
(
par
->
crtc
.
bpp
==
16
)
aty_st_8
(
PALETTE_INDEX
,
(
regno
<<
3
));
...
...
@@ -1927,10 +2152,8 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
aty_st_8
(
PALETTE_INDEX
,
regno
);
col
=
(
red
<<
16
)
|
(
green
<<
8
)
|
blue
;
aty_st_le32
(
PALETTE_DATA
,
col
);
if
(
par
->
chip_gen
==
rage_M3
)
{
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
|
DAC_PALETTE_ACCESS_CNTL
);
if
(
info
->
chip_gen
==
rage_M3
)
{
aty_st_le32
(
DAC_CNTL
,
aty_ld_le32
(
DAC_CNTL
)
|
DAC_PALETTE_ACCESS_CNTL
);
if
(
par
->
crtc
.
bpp
==
16
)
aty_st_8
(
PALETTE_INDEX
,
(
regno
<<
3
));
else
...
...
@@ -1940,22 +2163,25 @@ aty128fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
if
(
regno
<
16
)
switch
(
par
->
crtc
.
bpp
)
{
#ifdef FBCON_HAS_CFB16
case
9
...
16
:
((
u32
*
)
(
info
->
pseudo_palette
))[
regno
]
=
(
regno
<<
10
)
|
(
regno
<<
5
)
|
regno
;
((
u32
*
)
(
info
->
fb_info
.
pseudo_palette
))[
regno
]
=
(
regno
<<
10
)
|
(
regno
<<
5
)
|
regno
;
break
;
#endif
#ifdef FBCON_HAS_CFB24
case
17
...
24
:
((
u32
*
)
(
info
->
pseudo_palette
))[
regno
]
=
(
regno
<<
16
)
|
(
regno
<<
8
)
|
regno
;
((
u32
*
)
(
info
->
fb_info
.
pseudo_palette
))[
regno
]
=
(
regno
<<
16
)
|
(
regno
<<
8
)
|
regno
;
break
;
case
25
...
32
:{
#endif
#ifdef FBCON_HAS_CFB32
case
25
...
32
:
{
u32
i
;
i
=
(
regno
<<
8
)
|
regno
;
((
u32
*
)
(
info
->
pseudo_palette
))[
regno
]
=
(
i
<<
16
)
|
i
;
((
u32
*
)
(
info
->
fb_info
.
pseudo_palette
))[
regno
]
=
(
i
<<
16
)
|
i
;
break
;
}
#endif
}
return
0
;
}
...
...
@@ -1966,9 +2192,10 @@ static int backlight_conv[] = {
0x73
,
0x68
,
0x5d
,
0x52
,
0x47
,
0x3c
,
0x31
,
0x24
};
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
)
static
int
aty128_set_backlight_enable
(
int
on
,
int
level
,
void
*
data
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
data
;
struct
fb_info_aty128
*
info
=
(
struct
fb_info_aty128
*
)
data
;
unsigned
int
reg
=
aty_ld_le32
(
LVDS_GEN_CNTL
);
reg
|=
LVDS_BL_MOD_EN
|
LVDS_BLON
;
...
...
@@ -1984,7 +2211,8 @@ static int aty128_set_backlight_enable(int on, int level, void *data)
return
0
;
}
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
)
static
int
aty128_set_backlight_level
(
int
level
,
void
*
data
)
{
return
aty128_set_backlight_enable
(
1
,
level
,
data
);
}
...
...
@@ -1996,10 +2224,10 @@ static int aty128_set_backlight_level(int level, void *data)
static
inline
void
aty128_rectcopy
(
int
srcx
,
int
srcy
,
int
dstx
,
int
dsty
,
u_int
width
,
u_int
height
,
struct
fb_info
*
info
)
u_int
width
,
u_int
height
,
struct
fb_info_aty128
*
info
)
{
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
par
;
struct
aty128fb_par
*
par
=
(
struct
aty128fb_par
*
)
info
->
fb_info
.
par
;
u32
save_dp_datatype
,
save_dp_cntl
,
bppval
;
if
(
!
width
||
!
height
)
...
...
@@ -2015,11 +2243,11 @@ aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
return
;
}
wait_for_fifo
(
2
,
par
);
wait_for_fifo
(
2
,
info
);
save_dp_datatype
=
aty_ld_le32
(
DP_DATATYPE
);
save_dp_cntl
=
aty_ld_le32
(
DP_CNTL
);
wait_for_fifo
(
6
,
par
);
wait_for_fifo
(
6
,
info
);
aty_st_le32
(
SRC_Y_X
,
(
srcy
<<
16
)
|
srcx
);
aty_st_le32
(
DP_MIX
,
ROP3_SRCCOPY
|
DP_SRC_RECT
);
aty_st_le32
(
DP_CNTL
,
DST_X_LEFT_TO_RIGHT
|
DST_Y_TOP_TO_BOTTOM
);
...
...
@@ -2028,40 +2256,256 @@ aty128_rectcopy(int srcx, int srcy, int dstx, int dsty,
aty_st_le32
(
DST_Y_X
,
(
dsty
<<
16
)
|
dstx
);
aty_st_le32
(
DST_HEIGHT_WIDTH
,
(
height
<<
16
)
|
width
);
par
->
blitter_may_be_busy
=
1
;
info
->
blitter_may_be_busy
=
1
;
wait_for_fifo
(
2
,
par
);
wait_for_fifo
(
2
,
info
);
aty_st_le32
(
DP_DATATYPE
,
save_dp_datatype
);
aty_st_le32
(
DP_CNTL
,
save_dp_cntl
);
}
/*
* Text mode accelerated functions
*/
static
void
fbcon_aty128_bmove
(
struct
display
*
p
,
int
sy
,
int
sx
,
int
dy
,
int
dx
,
int
height
,
int
width
)
{
sx
*=
fontwidth
(
p
);
sy
*=
fontheight
(
p
);
dx
*=
fontwidth
(
p
);
dy
*=
fontheight
(
p
);
width
*=
fontwidth
(
p
);
height
*=
fontheight
(
p
);
aty128_rectcopy
(
sx
,
sy
,
dx
,
dy
,
width
,
height
,
(
struct
fb_info_aty128
*
)
p
->
fb_info
);
}
#ifdef FBCON_HAS_CFB8
static
void
fbcon_aty8_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb8_putc
(
conp
,
p
,
c
,
yy
,
xx
);
}
static
void
fbcon_aty8_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb8_putcs
(
conp
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
fbcon_aty8_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb8_clear_margins
(
conp
,
p
,
bottom_only
);
}
static
struct
display_switch
fbcon_aty128_8
=
{
setup:
fbcon_cfb8_setup
,
bmove:
fbcon_aty128_bmove
,
clear:
fbcon_cfb8_clear
,
putc:
fbcon_aty8_putc
,
putcs:
fbcon_aty8_putcs
,
revc:
fbcon_cfb8_revc
,
clear_margins:
fbcon_aty8_clear_margins
,
fontwidthmask:
FONTWIDTH
(
4
)
|
FONTWIDTH
(
8
)
|
FONTWIDTH
(
12
)
|
FONTWIDTH
(
16
)
};
#endif
#ifdef FBCON_HAS_CFB16
static
void
fbcon_aty16_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb16_putc
(
conp
,
p
,
c
,
yy
,
xx
);
}
static
void
fbcon_aty16_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb16_putcs
(
conp
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
fbcon_aty16_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb16_clear_margins
(
conp
,
p
,
bottom_only
);
}
static
struct
display_switch
fbcon_aty128_16
=
{
setup:
fbcon_cfb16_setup
,
bmove:
fbcon_aty128_bmove
,
clear:
fbcon_cfb16_clear
,
putc:
fbcon_aty16_putc
,
putcs:
fbcon_aty16_putcs
,
revc:
fbcon_cfb16_revc
,
clear_margins:
fbcon_aty16_clear_margins
,
fontwidthmask:
FONTWIDTH
(
4
)
|
FONTWIDTH
(
8
)
|
FONTWIDTH
(
12
)
|
FONTWIDTH
(
16
)
};
#endif
#ifdef FBCON_HAS_CFB24
static
void
fbcon_aty24_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb24_putc
(
conp
,
p
,
c
,
yy
,
xx
);
}
static
void
fbcon_aty24_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb24_putcs
(
conp
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
fbcon_aty24_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb24_clear_margins
(
conp
,
p
,
bottom_only
);
}
static
struct
display_switch
fbcon_aty128_24
=
{
setup:
fbcon_cfb24_setup
,
bmove:
fbcon_aty128_bmove
,
clear:
fbcon_cfb24_clear
,
putc:
fbcon_aty24_putc
,
putcs:
fbcon_aty24_putcs
,
revc:
fbcon_cfb24_revc
,
clear_margins:
fbcon_aty24_clear_margins
,
fontwidthmask:
FONTWIDTH
(
4
)
|
FONTWIDTH
(
8
)
|
FONTWIDTH
(
12
)
|
FONTWIDTH
(
16
)
};
#endif
#ifdef FBCON_HAS_CFB32
static
void
fbcon_aty32_putc
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
c
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb32_putc
(
conp
,
p
,
c
,
yy
,
xx
);
}
static
void
fbcon_aty32_putcs
(
struct
vc_data
*
conp
,
struct
display
*
p
,
const
unsigned
short
*
s
,
int
count
,
int
yy
,
int
xx
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb32_putcs
(
conp
,
p
,
s
,
count
,
yy
,
xx
);
}
static
void
fbcon_aty32_clear_margins
(
struct
vc_data
*
conp
,
struct
display
*
p
,
int
bottom_only
)
{
struct
fb_info_aty128
*
fb
=
(
struct
fb_info_aty128
*
)(
p
->
fb_info
);
if
(
fb
->
blitter_may_be_busy
)
wait_for_idle
(
fb
);
fbcon_cfb32_clear_margins
(
conp
,
p
,
bottom_only
);
}
static
struct
display_switch
fbcon_aty128_32
=
{
setup:
fbcon_cfb32_setup
,
bmove:
fbcon_aty128_bmove
,
clear:
fbcon_cfb32_clear
,
putc:
fbcon_aty32_putc
,
putcs:
fbcon_aty32_putcs
,
revc:
fbcon_cfb32_revc
,
clear_margins:
fbcon_aty32_clear_margins
,
fontwidthmask:
FONTWIDTH
(
4
)
|
FONTWIDTH
(
8
)
|
FONTWIDTH
(
12
)
|
FONTWIDTH
(
16
)
};
#endif
#ifdef MODULE
MODULE_AUTHOR
(
"(c)1999-2000 Brad Douglas <brad@neruo.com>"
);
MODULE_DESCRIPTION
(
"FBDev driver for ATI Rage128 / Pro cards"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_PARM
(
noaccel
,
"i"
);
MODULE_PARM_DESC
(
noaccel
,
"Disable hardware acceleration (0 or 1=disabled) (default=0)"
);
MODULE_PARM
(
font
,
"s"
);
MODULE_PARM_DESC
(
font
,
"Specify one of the compiled-in fonts (default=none)"
);
MODULE_PARM_DESC
(
font
,
"Specify one of the compiled-in fonts (default=none)"
);
MODULE_PARM
(
mode
,
"s"
);
MODULE_PARM_DESC
(
mode
,
"Specify resolution as
\"
<xres>x<yres>[-<bpp>][@<refresh>]
\"
"
);
MODULE_PARM_DESC
(
mode
,
"Specify resolution as
\"
<xres>x<yres>[-<bpp>][@<refresh>]
\"
"
);
#ifdef CONFIG_MTRR
MODULE_PARM
(
nomtrr
,
"i"
);
MODULE_PARM_DESC
(
nomtrr
,
"Disable MTRR support (0 or 1=disabled) (default=0)"
);
MODULE_PARM_DESC
(
nomtrr
,
"Disable MTRR support (0 or 1=disabled) (default=0)"
);
#endif
int
__init
init_module
(
void
)
int
__init
init_module
(
void
)
{
if
(
noaccel
)
{
noaccel
=
1
;
printk
(
KERN_INFO
"aty128fb: Parameter NOACCEL set
\n
"
);
}
if
(
font
)
{
strncpy
(
fontname
,
font
,
sizeof
(
fontname
)
-
1
);
printk
(
KERN_INFO
"aty128fb: Parameter FONT set to %s
\n
"
,
font
);
strncpy
(
fontname
,
font
,
sizeof
(
fontname
)
-
1
);
printk
(
KERN_INFO
"aty128fb: Parameter FONT set to %s
\n
"
,
font
);
}
if
(
mode
)
{
mode_option
=
mode
;
printk
(
KERN_INFO
"aty128fb: Parameter MODE set to %s
\n
"
,
mode
);
printk
(
KERN_INFO
"aty128fb: Parameter MODE set to %s
\n
"
,
mode
);
}
#ifdef CONFIG_MTRR
if
(
nomtrr
)
{
...
...
@@ -2074,22 +2518,25 @@ int __init init_module(void)
return
0
;
}
void
__exit
cleanup_module
(
void
)
void
__exit
cleanup_module
(
void
)
{
struct
fb_info
*
info
=
board_list
;
struct
fb_info_aty128
*
info
=
board_list
;
struct
aty128fb_par
*
par
;
par
=
info
->
par
;
while
(
board_list
)
{
info
=
board_list
;
board_list
=
board_list
->
next
;
par
=
info
->
fb_info
.
par
;
unregister_framebuffer
(
info
);
unregister_framebuffer
(
&
info
->
fb_
info
);
#ifdef CONFIG_MTRR
if
(
par
->
mtrr
.
vram_valid
)
mtrr_del
(
par
->
mtrr
.
vram
,
info
->
fix
.
smem_start
,
info
->
fix
.
smem_len
);
mtrr_del
(
par
->
mtrr
.
vram
,
info
->
fb_info
.
fix
.
smem_start
,
info
->
fb_info
.
fix
.
smem_len
);
#endif
/* CONFIG_MTRR */
iounmap
(
par
->
regbase
);
iounmap
(
info
->
screen_base
);
iounmap
(
info
->
regbase
);
iounmap
(
info
->
fb_info
.
screen_base
);
release_mem_region
(
pci_resource_start
(
info
->
pdev
,
0
),
pci_resource_len
(
info
->
pdev
,
0
));
...
...
@@ -2097,6 +2544,8 @@ void __exit cleanup_module(void)
pci_resource_len
(
info
->
pdev
,
1
));
release_mem_region
(
pci_resource_start
(
info
->
pdev
,
2
),
pci_resource_len
(
info
->
pdev
,
2
));
kfree
(
info
);
}
}
#endif
/* MODULE */
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
;
RIVA_HW_STATE
*
state
=
&
regs
->
ext
;
CRTCout
(
par
,
0x11
,
0x00
);
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
;
while
(
i_p
->
next
!=
NULL
)
i_p
=
i_p
->
next
;
i_p
->
next
=
new_node
;
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
;
par
->
current_state
=
newmode
;
riva_load_state
(
par
,
&
par
->
current_state
);
while
(
i_p
->
next
!=
del_node
)
i_p
=
i_p
->
next
;
i_p
->
next
=
del_node
->
next
;
par
->
riva
.
LockUnlock
(
&
par
->
riva
,
0
);
/* important for HW cursor */
rivafb_download_cursor
(
par
);
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
;
return
0
;
}
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
;
if
(
regno
>=
riva_get_cmap_len
(
&
info
->
var
))
DPRINTK
(
"ENTER
\n
"
);
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
(
var
->
xoffset
>
var
->
xres_virtual
-
var
->
xres
)
var
->
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
.
yoffset
>
v
.
yres_virtual
-
v
.
yres
)
v
.
yoffset
=
v
.
yres_virtual
-
v
.
yres
-
1
;
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
(
var
->
yoffset
>
var
->
yres_virtual
-
var
->
yres
)
var
->
yoffset
=
var
->
yres_virtual
-
var
->
yres
-
1
;
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
);
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
;
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
;
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
;
}
/*
if (par->cursor) {
disp->dispsw.cursor = rivafb_cursor;
disp->dispsw.set_font = rivafb_set_font;
}
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
);
memset
(
rinfo
,
0
,
sizeof
(
struct
rivafb_info
)
);
default_par
=
kmalloc
(
sizeof
(
struct
riva_par
),
GFP_KERNEL
);
if
(
!
default_par
)
goto
err_out
;
memset
(
default_par
,
0
,
sizeof
(
struct
riva_par
));
info
->
disp
=
(
struct
display
*
)(
info
+
1
);
info
->
pseudo_palette
=
(
void
*
)(
info
->
disp
+
1
);
rinfo
->
drvr_name
=
rci
->
name
;
rinfo
->
riva
.
Architecture
=
rci
->
arch_rev
;
strcat
(
rivafb_fix
.
id
,
rci
->
name
);
default_par
->
riva
.
Architecture
=
rci
->
arch_rev
;
rinfo
->
pd
=
pd
;
rinfo
->
base0_region_size
=
pci_resource_len
(
pd
,
0
);
rinfo
->
base1_region_size
=
pci_resource_len
(
pd
,
1
);
rivafb_fix
.
mmio_len
=
pci_resource_len
(
pd
,
0
);
rivafb_fix
.
smem_len
=
pci_resource_len
(
pd
,
1
);
assert
(
rinfo
->
base0_region_size
>=
0x00800000
);
/* from GGI */
assert
(
rinfo
->
base1_region_size
>=
0x01000000
);
/* from GGI */
assert
(
rivafb_fix
.
mmio_len
>=
0x00800000
);
/* from GGI */
assert
(
rivafb_fix
.
smem_len
>=
0x01000000
);
/* from GGI */
rinfo
->
ctrl_base_phys
=
pci_resource_start
(
rinfo
->
pd
,
0
);
rinfo
->
fb_base_phys
=
pci_resource_start
(
rinfo
->
pd
,
1
);
rivafb_fix
.
mmio_start
=
pci_resource_start
(
pd
,
0
);
rivafb_fix
.
smem_start
=
pci_resource_start
(
pd
,
1
);
if
(
!
request_mem_region
(
rivafb_fix
.
mmio_start
,
rivafb_fix
.
mmio_len
,
"rivafb"
))
{
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
)
{
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"
))
{
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
;
}
info
->
screen_base
=
ioremap
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
);
if
(
!
info
->
screen_base
)
{
printk
(
KERN_ERR
PFX
"cannot ioremap FB base
\n
"
);
goto
err_out_iounmap_ctrl
;
}
default_par
->
riva
.
PRAMIN
=
(
unsigned
*
)(
info
->
screen_base
+
0x00C00000
);
rivafb_fix
.
accel
=
FB_ACCEL_NV3
;
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
;
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
;
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
;
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
->
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
;
}
info
->
screen_base
=
ioremap
(
rivafb_fix
.
smem_start
,
rivafb_fix
.
smem_len
);
if
(
!
info
->
screen
_base
)
{
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
)
{
default_par
->
mtrr
.
vram
=
mtrr_add
(
rivafb_fix
.
smem_start
,
ri
vafb_fix
.
smem_len
,
MTRR_TYPE_WRCOMB
,
1
);
if
(
default_par
->
mtrr
.
vram
<
0
)
{
rinfo
->
mtrr
.
vram
=
mtrr_add
(
rinfo
->
fb_base_phys
,
ri
nfo
->
base1_region_size
,
MTRR_TYPE_WRCOMB
,
1
);
if
(
rinfo
->
mtrr
.
vram
<
0
)
{
printk
(
KERN_ERR
PFX
"unable to setup MTRR
\n
"
);
}
else
{
default_par
->
mtrr
.
vram_valid
=
1
;
rinfo
->
mtrr
.
vram_valid
=
1
;
/* let there be speed */
printk
(
KERN_INFO
PFX
"RIVA MTRR set to ON
\n
"
);
}
}
#endif
/* CONFIG_MTRR */
if
(
!
nohwcursor
)
default_par
->
cursor
=
rivafb_init_cursor
(
info
);
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
);
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
:
rinfo
->
riva
.
PCRTC
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00600000
);
rinfo
->
riva
.
PRAMIN
=
(
unsigned
*
)(
rinfo
->
ctrl_base
+
0x00710000
);
break
;
}
info
->
par
=
default_par
;
RivaGetConfig
(
&
rinfo
->
riva
)
;
if
(
riva_set_fbinfo
(
info
)
<
0
)
{
/* back to normal */
assert
(
rinfo
->
pd
!=
NULL
);
/* unlock io */
CRTCout
(
rinfo
,
0x11
,
0xFF
);
/* vgaHWunlock() + riva unlock (0x7F) */
rinfo
->
riva
.
LockUnlock
(
&
rinfo
->
riva
,
0
);
riva_save_state
(
rinfo
,
&
rinfo
->
initial_state
);
rinfo
->
ram_amount
=
rinfo
->
riva
.
RamAmountKBytes
*
1024
;
rinfo
->
dclk_max
=
rinfo
->
riva
.
MaxVClockFreqKHz
*
1000
;
if
(
!
nohwcursor
)
rinfo
->
cursor
=
rivafb_init_cursor
(
rinfo
);
if
(
riva_set_fbinfo
(
rinfo
)
<
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,8 +1421,6 @@ 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
;
...
...
@@ -1435,20 +1430,6 @@ static void LoadStateExt
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
[
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,33 +27,56 @@ 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
;
#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
);
par
->
palette_cpu
[
0
]
=
(
par
->
palette_cpu
[
0
]
&
0xcfff
)
|
palette_pbs
(
info
->
var
.
bits_per_pixel
);
fbi
->
palette_cpu
[
0
]
=
(
fbi
->
palette_cpu
[
0
]
&
0xcfff
)
|
palette_pbs
(
var
);
}
switch
(
info
->
var
.
bits_per_pixel
)
{
/*
* 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
;
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
;
u_int
state
=
xchg
(
&
par
->
task_state
,
-
1
);
struct
sa1100fb_info
*
fbi
=
dummy
;
u_int
state
=
xchg
(
&
fbi
->
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