Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
2079b4ad
Commit
2079b4ad
authored
Mar 02, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[FRAMEBUFFER]: Convert TCX driver to new APIs.
parent
7e2fb365
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
501 additions
and
370 deletions
+501
-370
drivers/video/Kconfig
drivers/video/Kconfig
+1
-1
drivers/video/Makefile
drivers/video/Makefile
+2
-1
drivers/video/fbmem.c
drivers/video/fbmem.c
+5
-0
drivers/video/tcx.c
drivers/video/tcx.c
+493
-0
drivers/video/tcxfb.c
drivers/video/tcxfb.c
+0
-368
No files found.
drivers/video/Kconfig
View file @
2079b4ad
...
...
@@ -818,7 +818,7 @@ config FB_FFB
config FB_TCX
bool "TCX (SS4/SS5 only) support"
depends on FB_SBUS
&& SPARC32
depends on FB_SBUS
help
This is the frame buffer device driver for the TCX 24/8bit frame
buffer.
...
...
drivers/video/Makefile
View file @
2079b4ad
...
...
@@ -71,7 +71,6 @@ obj-$(CONFIG_FB_PVR2) += pvr2fb.o
obj-$(CONFIG_FB_VOODOO1)
+=
sstfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
# One by one these are being converted over to the new APIs
#obj-$(CONFIG_FB_TCX) += tcxfb.o sbusfb.o
#obj-$(CONFIG_FB_LEO) += leofb.o sbusfb.o
obj-$(CONFIG_FB_FFB)
+=
ffb.o sbuslib.o cfbimgblt.o cfbcopyarea.o
...
...
@@ -84,6 +83,8 @@ obj-$(CONFIG_FB_CG14) += cg14.o sbuslib.o cfbimgblt.o cfbcopyarea.o
cfbfillrect.o
obj-$(CONFIG_FB_P9100)
+=
p9100.o sbuslib.o cfbimgblt.o cfbcopyarea.o
\
cfbfillrect.o
obj-$(CONFIG_FB_TCX)
+=
tcx.o sbuslib.o cfbimgblt.o cfbcopyarea.o
\
cfbfillrect.o
# Files generated that shall be removed upon make clean
clean-files
:=
promcon_tbl.c
...
...
drivers/video/fbmem.c
View file @
2079b4ad
...
...
@@ -156,6 +156,8 @@ extern int cg14_init(void);
extern
int
cg14_setup
(
char
*
);
extern
int
p9100_init
(
void
);
extern
int
p9100_setup
(
char
*
);
extern
int
tcx_init
(
void
);
extern
int
tcx_setup
(
char
*
);
static
struct
{
const
char
*
name
;
...
...
@@ -265,6 +267,9 @@ static struct {
#ifdef CONFIG_FB_P9100
{
"p9100"
,
p9100_init
,
p9100_setup
},
#endif
#ifdef CONFIG_FB_TCX
{
"tcx"
,
tcx_init
,
tcx_setup
},
#endif
/*
* Generic drivers that are used as fallbacks
...
...
drivers/video/tcx.c
0 → 100644
View file @
2079b4ad
/* tcx.c: TCX frame buffer driver
*
* Copyright (C) 2003 David S. Miller (davem@redhat.com)
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
*
* Driver layout based loosely on tgafb.c, see that file for credits.
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fb.h>
#include <linux/mm.h>
#include <asm/io.h>
#include <asm/sbus.h>
#include <asm/oplib.h>
#include <asm/fbio.h>
#include "sbuslib.h"
/*
* Local functions.
*/
static
int
tcx_check_var
(
struct
fb_var_screeninfo
*
,
struct
fb_info
*
);
static
int
tcx_set_par
(
struct
fb_info
*
);
static
int
tcx_setcolreg
(
unsigned
,
unsigned
,
unsigned
,
unsigned
,
unsigned
,
struct
fb_info
*
);
static
int
tcx_blank
(
int
,
struct
fb_info
*
);
static
int
tcx_mmap
(
struct
fb_info
*
,
struct
file
*
,
struct
vm_area_struct
*
);
/*
* Frame buffer operations
*/
static
struct
fb_ops
tcx_ops
=
{
.
owner
=
THIS_MODULE
,
.
fb_check_var
=
tcx_check_var
,
.
fb_set_par
=
tcx_set_par
,
.
fb_setcolreg
=
tcx_setcolreg
,
.
fb_blank
=
tcx_blank
,
.
fb_fillrect
=
cfb_fillrect
,
.
fb_copyarea
=
cfb_copyarea
,
.
fb_imageblit
=
cfb_imageblit
,
.
fb_mmap
=
tcx_mmap
,
.
fb_cursor
=
soft_cursor
,
};
/* THC definitions */
#define TCX_THC_MISC_REV_SHIFT 16
#define TCX_THC_MISC_REV_MASK 15
#define TCX_THC_MISC_VSYNC_DIS (1 << 25)
#define TCX_THC_MISC_HSYNC_DIS (1 << 24)
#define TCX_THC_MISC_RESET (1 << 12)
#define TCX_THC_MISC_VIDEO (1 << 10)
#define TCX_THC_MISC_SYNC (1 << 9)
#define TCX_THC_MISC_VSYNC (1 << 8)
#define TCX_THC_MISC_SYNC_ENAB (1 << 7)
#define TCX_THC_MISC_CURS_RES (1 << 6)
#define TCX_THC_MISC_INT_ENAB (1 << 5)
#define TCX_THC_MISC_INT (1 << 4)
#define TCX_THC_MISC_INIT 0x9f
#define TCX_THC_REV_REV_SHIFT 20
#define TCX_THC_REV_REV_MASK 15
#define TCX_THC_REV_MINREV_SHIFT 28
#define TCX_THC_REV_MINREV_MASK 15
/* The contents are unknown */
struct
tcx_tec
{
volatile
u32
tec_matrix
;
volatile
u32
tec_clip
;
volatile
u32
tec_vdc
;
};
struct
tcx_thc
{
volatile
u32
thc_rev
;
u32
thc_pad0
[
511
];
volatile
u32
thc_hs
;
/* hsync timing */
volatile
u32
thc_hsdvs
;
volatile
u32
thc_hd
;
volatile
u32
thc_vs
;
/* vsync timing */
volatile
u32
thc_vd
;
volatile
u32
thc_refresh
;
volatile
u32
thc_misc
;
u32
thc_pad1
[
56
];
volatile
u32
thc_cursxy
;
/* cursor x,y position (16 bits each) */
volatile
u32
thc_cursmask
[
32
];
/* cursor mask bits */
volatile
u32
thc_cursbits
[
32
];
/* what to show where mask enabled */
};
struct
bt_regs
{
volatile
u32
addr
;
volatile
u32
color_map
;
volatile
u32
control
;
volatile
u32
cursor
;
};
#define TCX_MMAP_ENTRIES 14
struct
tcx_par
{
spinlock_t
lock
;
struct
bt_regs
*
bt
;
struct
tcx_thc
*
thc
;
struct
tcx_tec
*
tec
;
volatile
u32
*
cplane
;
u32
flags
;
#define TCX_FLAG_BLANKED 0x00000001
unsigned
long
physbase
;
unsigned
long
fbsize
;
struct
sbus_mmap_map
mmap_map
[
TCX_MMAP_ENTRIES
];
int
lowdepth
;
struct
sbus_dev
*
sdev
;
struct
list_head
list
;
};
/* Reset control plane so that WID is 8-bit plane. */
static
void
__tcx_set_control_plane
(
struct
tcx_par
*
par
)
{
volatile
u32
*
p
,
*
pend
;
if
(
par
->
lowdepth
)
return
;
p
=
par
->
cplane
;
if
(
p
==
NULL
)
return
;
for
(
pend
=
p
+
par
->
fbsize
;
p
<
pend
;
p
++
)
{
u32
tmp
=
sbus_readl
(
p
);
tmp
&=
0xffffff
;
sbus_writel
(
tmp
,
p
);
}
}
static
void
tcx_reset
(
struct
fb_info
*
info
)
{
struct
tcx_par
*
par
=
(
struct
tcx_par
*
)
info
->
par
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
par
->
lock
,
flags
);
__tcx_set_control_plane
(
par
);
spin_unlock_irqrestore
(
&
par
->
lock
,
flags
);
}
/**
* tcx_check_var - Optional function. Validates a var passed in.
* @var: frame buffer variable screen structure
* @info: frame buffer structure that represents a single frame buffer
*/
static
int
tcx_check_var
(
struct
fb_var_screeninfo
*
var
,
struct
fb_info
*
info
)
{
if
(
var
->
bits_per_pixel
!=
8
)
return
-
EINVAL
;
if
(
var
->
xres_virtual
!=
var
->
xres
||
var
->
yres_virtual
!=
var
->
yres
)
return
-
EINVAL
;
if
(
var
->
nonstd
)
return
-
EINVAL
;
if
((
var
->
vmode
&
FB_VMODE_MASK
)
!=
FB_VMODE_NONINTERLACED
)
return
-
EINVAL
;
if
(
var
->
xres
!=
info
->
var
.
xres
||
var
->
yres
!=
info
->
var
.
yres
)
return
-
EINVAL
;
return
0
;
}
/**
* tcx_set_par - Optional function. Alters the hardware state.
* @info: frame buffer structure that represents a single frame buffer
*/
static
int
tcx_set_par
(
struct
fb_info
*
info
)
{
return
0
;
}
/**
* tcx_setcolreg - Optional function. Sets a color register.
* @regno: boolean, 0 copy local, 1 get_user() function
* @red: frame buffer colormap structure
* @green: The green value which can be up to 16 bits wide
* @blue: The blue value which can be up to 16 bits wide.
* @transp: If supported the alpha value which can be up to 16 bits wide.
* @info: frame buffer info structure
*/
static
int
tcx_setcolreg
(
unsigned
regno
,
unsigned
red
,
unsigned
green
,
unsigned
blue
,
unsigned
transp
,
struct
fb_info
*
info
)
{
struct
tcx_par
*
par
=
(
struct
tcx_par
*
)
info
->
par
;
struct
bt_regs
*
bt
=
par
->
bt
;
unsigned
long
flags
;
if
(
regno
>=
256
)
return
1
;
red
>>=
8
;
green
>>=
8
;
blue
>>=
8
;
spin_lock_irqsave
(
&
par
->
lock
,
flags
);
sbus_writel
(
regno
<<
24
,
&
bt
->
addr
);
sbus_writel
(
red
<<
24
,
&
bt
->
color_map
);
sbus_writel
(
green
<<
24
,
&
bt
->
color_map
);
sbus_writel
(
blue
<<
24
,
&
bt
->
color_map
);
spin_unlock_irqrestore
(
&
par
->
lock
,
flags
);
return
0
;
}
/**
* tcx_blank - Optional function. Blanks the display.
* @blank_mode: the blank mode we want.
* @info: frame buffer structure that represents a single frame buffer
*/
static
int
tcx_blank
(
int
blank
,
struct
fb_info
*
info
)
{
struct
tcx_par
*
par
=
(
struct
tcx_par
*
)
info
->
par
;
struct
tcx_thc
*
thc
=
par
->
thc
;
unsigned
long
flags
;
u32
val
;
spin_lock_irqsave
(
&
par
->
lock
,
flags
);
val
=
sbus_readl
(
&
thc
->
thc_misc
);
switch
(
blank
)
{
case
0
:
/* Unblanking */
val
&=
~
(
TCX_THC_MISC_VSYNC_DIS
|
TCX_THC_MISC_HSYNC_DIS
);
val
|=
TCX_THC_MISC_VIDEO
;
par
->
flags
&=
~
TCX_FLAG_BLANKED
;
break
;
case
1
:
/* Normal blanking */
val
&=
~
TCX_THC_MISC_VIDEO
;
par
->
flags
|=
TCX_FLAG_BLANKED
;
break
;
case
2
:
/* VESA blank (vsync off) */
val
|=
TCX_THC_MISC_VSYNC_DIS
;
break
;
case
3
:
/* VESA blank (hsync off) */
val
|=
TCX_THC_MISC_HSYNC_DIS
;
break
;
case
4
:
/* Poweroff */
break
;
};
sbus_writel
(
val
,
&
thc
->
thc_misc
);
spin_unlock_irqrestore
(
&
par
->
lock
,
flags
);
return
0
;
}
static
struct
sbus_mmap_map
__tcx_mmap_map
[
TCX_MMAP_ENTRIES
]
=
{
{
TCX_RAM8BIT
,
0
,
SBUS_MMAP_FBSIZE
(
1
)
},
{
TCX_RAM24BIT
,
0
,
SBUS_MMAP_FBSIZE
(
4
)
},
{
TCX_UNK3
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_UNK4
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_CONTROLPLANE
,
0
,
SBUS_MMAP_FBSIZE
(
4
)
},
{
TCX_UNK6
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_UNK7
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_TEC
,
0
,
PAGE_SIZE
},
{
TCX_BTREGS
,
0
,
PAGE_SIZE
},
{
TCX_THC
,
0
,
PAGE_SIZE
},
{
TCX_DHC
,
0
,
PAGE_SIZE
},
{
TCX_ALT
,
0
,
PAGE_SIZE
},
{
TCX_UNK2
,
0
,
0x20000
},
{
0
,
0
,
0
}
};
static
int
tcx_mmap
(
struct
fb_info
*
info
,
struct
file
*
file
,
struct
vm_area_struct
*
vma
)
{
struct
tcx_par
*
par
=
(
struct
tcx_par
*
)
info
->
par
;
return
sbusfb_mmap_helper
(
par
->
mmap_map
,
par
->
physbase
,
par
->
fbsize
,
par
->
sdev
->
reg_addrs
[
0
].
which_io
,
vma
);
}
/*
* Initialisation
*/
static
void
tcx_init_fix
(
struct
fb_info
*
info
,
int
linebytes
)
{
struct
tcx_par
*
par
=
(
struct
tcx_par
*
)
info
->
par
;
const
char
*
tcx_name
;
if
(
par
->
lowdepth
)
tcx_name
=
"TCX8"
;
else
tcx_name
=
"TCX24"
;
strncpy
(
info
->
fix
.
id
,
tcx_name
,
sizeof
(
info
->
fix
.
id
)
-
1
);
info
->
fix
.
id
[
sizeof
(
info
->
fix
.
id
)
-
1
]
=
0
;
info
->
fix
.
type
=
FB_TYPE_PACKED_PIXELS
;
info
->
fix
.
visual
=
FB_VISUAL_PSEUDOCOLOR
;
info
->
fix
.
line_length
=
linebytes
;
info
->
fix
.
accel
=
FB_ACCEL_SUN_TCX
;
}
struct
all_info
{
struct
fb_info
info
;
struct
tcx_par
par
;
struct
list_head
list
;
};
static
LIST_HEAD
(
tcx_list
);
static
void
tcx_init_one
(
struct
sbus_dev
*
sdev
)
{
struct
all_info
*
all
;
int
linebytes
,
i
;
all
=
kmalloc
(
sizeof
(
*
all
),
GFP_KERNEL
);
if
(
!
all
)
{
printk
(
KERN_ERR
"tcx: Cannot allocate memory.
\n
"
);
return
;
}
memset
(
all
,
0
,
sizeof
(
*
all
));
INIT_LIST_HEAD
(
&
all
->
list
);
spin_lock_init
(
&
all
->
par
.
lock
);
all
->
par
.
sdev
=
sdev
;
all
->
par
.
lowdepth
=
prom_getbool
(
sdev
->
prom_node
,
"tcx-8-bit"
);
sbusfb_fill_var
(
&
all
->
info
.
var
,
sdev
->
prom_node
,
8
);
linebytes
=
prom_getintdefault
(
sdev
->
prom_node
,
"linebytes"
,
all
->
info
.
var
.
xres
);
all
->
par
.
fbsize
=
PAGE_ALIGN
(
linebytes
*
all
->
info
.
var
.
yres
);
all
->
par
.
tec
=
(
struct
tcx_tec
*
)
sbus_ioremap
(
&
sdev
->
resource
[
7
],
0
,
sizeof
(
struct
tcx_tec
),
"tcx tec"
);
all
->
par
.
thc
=
(
struct
tcx_thc
*
)
sbus_ioremap
(
&
sdev
->
resource
[
9
],
0
,
sizeof
(
struct
tcx_thc
),
"tcx thc"
);
all
->
par
.
bt
=
(
struct
bt_regs
*
)
sbus_ioremap
(
&
sdev
->
resource
[
8
],
0
,
sizeof
(
struct
bt_regs
),
"tcx dac"
);
memcpy
(
&
all
->
par
.
mmap_map
,
&
__tcx_mmap_map
,
sizeof
(
all
->
par
.
mmap_map
));
if
(
!
all
->
par
.
lowdepth
)
{
all
->
par
.
cplane
=
(
volatile
u32
*
)
sbus_ioremap
(
&
sdev
->
resource
[
4
],
0
,
all
->
par
.
fbsize
*
sizeof
(
u32
),
"tcx cplane"
);
}
else
{
all
->
par
.
mmap_map
[
1
].
size
=
SBUS_MMAP_EMPTY
;
all
->
par
.
mmap_map
[
4
].
size
=
SBUS_MMAP_EMPTY
;
all
->
par
.
mmap_map
[
5
].
size
=
SBUS_MMAP_EMPTY
;
all
->
par
.
mmap_map
[
6
].
size
=
SBUS_MMAP_EMPTY
;
}
all
->
par
.
physbase
=
0
;
for
(
i
=
0
;
i
<
TCX_MMAP_ENTRIES
;
i
++
)
{
int
j
;
switch
(
i
)
{
case
10
:
j
=
12
;
break
;
case
11
:
case
12
:
j
=
i
-
1
;
break
;
default:
j
=
i
;
break
;
};
all
->
par
.
mmap_map
[
i
].
poff
=
sdev
->
reg_addrs
[
j
].
phys_addr
;
}
all
->
info
.
node
=
NODEV
;
all
->
info
.
flags
=
FBINFO_FLAG_DEFAULT
;
all
->
info
.
fbops
=
&
tcx_ops
;
#ifdef CONFIG_SPARC32
all
->
info
.
screen_base
=
(
char
*
)
prom_getintdefault
(
sdev
->
prom_node
,
"address"
,
0
);
#endif
if
(
!
all
->
info
.
screen_base
)
all
->
info
.
screen_base
=
(
char
*
)
sbus_ioremap
(
&
sdev
->
resource
[
0
],
0
,
all
->
par
.
fbsize
,
"tcx ram"
);
all
->
info
.
currcon
=
-
1
;
all
->
info
.
par
=
&
all
->
par
;
/* Initialize brooktree DAC. */
sbus_writel
(
0x04
<<
24
,
&
all
->
par
.
bt
->
addr
);
/* color planes */
sbus_writel
(
0xff
<<
24
,
&
all
->
par
.
bt
->
control
);
sbus_writel
(
0x05
<<
24
,
&
all
->
par
.
bt
->
addr
);
sbus_writel
(
0x00
<<
24
,
&
all
->
par
.
bt
->
control
);
sbus_writel
(
0x06
<<
24
,
&
all
->
par
.
bt
->
addr
);
/* overlay plane */
sbus_writel
(
0x73
<<
24
,
&
all
->
par
.
bt
->
control
);
sbus_writel
(
0x07
<<
24
,
&
all
->
par
.
bt
->
addr
);
sbus_writel
(
0x00
<<
24
,
&
all
->
par
.
bt
->
control
);
tcx_reset
(
&
all
->
info
);
tcx_blank
(
0
,
&
all
->
info
);
if
(
fb_alloc_cmap
(
&
all
->
info
.
cmap
,
256
,
0
))
{
printk
(
KERN_ERR
"tcx: Could not allocate color map.
\n
"
);
kfree
(
all
);
return
;
}
tcx_set_par
(
&
all
->
info
);
tcx_init_fix
(
&
all
->
info
,
linebytes
);
if
(
register_framebuffer
(
&
all
->
info
)
<
0
)
{
printk
(
KERN_ERR
"tcx: Could not register framebuffer.
\n
"
);
fb_dealloc_cmap
(
&
all
->
info
.
cmap
);
kfree
(
all
);
return
;
}
list_add
(
&
all
->
list
,
&
tcx_list
);
printk
(
"tcx: %s at %lx:%lx, %s
\n
"
,
sdev
->
prom_name
,
(
long
)
sdev
->
reg_addrs
[
0
].
which_io
,
(
long
)
sdev
->
reg_addrs
[
0
].
phys_addr
,
all
->
par
.
lowdepth
?
"8-bit only"
:
"24-bit depth"
);
}
int
__init
tcx_init
(
void
)
{
struct
sbus_bus
*
sbus
;
struct
sbus_dev
*
sdev
;
for_all_sbusdev
(
sdev
,
sbus
)
{
if
(
!
strcmp
(
sdev
->
prom_name
,
"tcx"
))
tcx_init_one
(
sdev
);
}
return
0
;
}
void
__exit
tcx_exit
(
void
)
{
struct
list_head
*
pos
,
*
tmp
;
list_for_each_safe
(
pos
,
tmp
,
&
tcx_list
)
{
struct
all_info
*
all
=
list_entry
(
pos
,
typeof
(
*
all
),
list
);
unregister_framebuffer
(
&
all
->
info
);
fb_dealloc_cmap
(
&
all
->
info
.
cmap
);
kfree
(
all
);
}
}
int
__init
tcx_setup
(
char
*
arg
)
{
/* No cmdline options yet... */
return
0
;
}
#ifdef MODULE
module_init
(
tcx_init
);
module_exit
(
tcx_exit
);
#endif
MODULE_DESCRIPTION
(
"framebuffer driver for TCX chipsets"
);
MODULE_AUTHOR
(
"David S. Miller <davem@redhat.com>"
);
MODULE_LICENSE
(
"GPL"
);
drivers/video/tcxfb.c
deleted
100644 → 0
View file @
7e2fb365
/* $Id: tcxfb.c,v 1.13 2001/09/19 00:04:33 davem Exp $
* tcxfb.c: TCX 24/8bit frame buffer driver
*
* Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
* Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
* Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
*/
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/string.h>
#include <linux/mm.h>
#include <linux/tty.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/init.h>
#include <linux/selection.h>
#include <video/sbusfb.h>
#include <asm/io.h>
#include <asm/sbus.h>
#include <video/fbcon-cfb8.h>
/* THC definitions */
#define TCX_THC_MISC_REV_SHIFT 16
#define TCX_THC_MISC_REV_MASK 15
#define TCX_THC_MISC_VSYNC_DIS (1 << 25)
#define TCX_THC_MISC_HSYNC_DIS (1 << 24)
#define TCX_THC_MISC_RESET (1 << 12)
#define TCX_THC_MISC_VIDEO (1 << 10)
#define TCX_THC_MISC_SYNC (1 << 9)
#define TCX_THC_MISC_VSYNC (1 << 8)
#define TCX_THC_MISC_SYNC_ENAB (1 << 7)
#define TCX_THC_MISC_CURS_RES (1 << 6)
#define TCX_THC_MISC_INT_ENAB (1 << 5)
#define TCX_THC_MISC_INT (1 << 4)
#define TCX_THC_MISC_INIT 0x9f
#define TCX_THC_REV_REV_SHIFT 20
#define TCX_THC_REV_REV_MASK 15
#define TCX_THC_REV_MINREV_SHIFT 28
#define TCX_THC_REV_MINREV_MASK 15
/* The contents are unknown */
struct
tcx_tec
{
volatile
u32
tec_matrix
;
volatile
u32
tec_clip
;
volatile
u32
tec_vdc
;
};
struct
tcx_thc
{
volatile
u32
thc_rev
;
u32
thc_pad0
[
511
];
volatile
u32
thc_hs
;
/* hsync timing */
volatile
u32
thc_hsdvs
;
volatile
u32
thc_hd
;
volatile
u32
thc_vs
;
/* vsync timing */
volatile
u32
thc_vd
;
volatile
u32
thc_refresh
;
volatile
u32
thc_misc
;
u32
thc_pad1
[
56
];
volatile
u32
thc_cursxy
;
/* cursor x,y position (16 bits each) */
volatile
u32
thc_cursmask
[
32
];
/* cursor mask bits */
volatile
u32
thc_cursbits
[
32
];
/* what to show where mask enabled */
};
static
struct
sbus_mmap_map
tcx_mmap_map
[]
=
{
{
TCX_RAM8BIT
,
0
,
SBUS_MMAP_FBSIZE
(
1
)
},
{
TCX_RAM24BIT
,
0
,
SBUS_MMAP_FBSIZE
(
4
)
},
{
TCX_UNK3
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_UNK4
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_CONTROLPLANE
,
0
,
SBUS_MMAP_FBSIZE
(
4
)
},
{
TCX_UNK6
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_UNK7
,
0
,
SBUS_MMAP_FBSIZE
(
8
)
},
{
TCX_TEC
,
0
,
PAGE_SIZE
},
{
TCX_BTREGS
,
0
,
PAGE_SIZE
},
{
TCX_THC
,
0
,
PAGE_SIZE
},
{
TCX_DHC
,
0
,
PAGE_SIZE
},
{
TCX_ALT
,
0
,
PAGE_SIZE
},
{
TCX_UNK2
,
0
,
0x20000
},
{
0
,
0
,
0
}
};
static
void
__tcx_set_control_plane
(
struct
fb_info_sbusfb
*
fb
)
{
u32
*
p
,
*
pend
;
p
=
fb
->
s
.
tcx
.
cplane
;
if
(
p
==
NULL
)
return
;
for
(
pend
=
p
+
fb
->
type
.
fb_size
;
p
<
pend
;
p
++
)
{
u32
tmp
=
sbus_readl
(
p
);
tmp
&=
0xffffff
;
sbus_writel
(
tmp
,
p
);
}
}
static
void
tcx_switch_from_graph
(
struct
fb_info_sbusfb
*
fb
)
{
unsigned
long
flags
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
/* Reset control plane to 8bit mode if necessary */
if
(
fb
->
open
&&
fb
->
mmaped
)
__tcx_set_control_plane
(
fb
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
static
void
tcx_loadcmap
(
struct
fb_info_sbusfb
*
fb
,
struct
display
*
p
,
int
index
,
int
count
)
{
struct
bt_regs
*
bt
=
fb
->
s
.
tcx
.
bt
;
unsigned
long
flags
;
int
i
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
sbus_writel
(
index
<<
24
,
&
bt
->
addr
);
for
(
i
=
index
;
count
--
;
i
++
){
sbus_writel
(
fb
->
color_map
CM
(
i
,
0
)
<<
24
,
&
bt
->
color_map
);
sbus_writel
(
fb
->
color_map
CM
(
i
,
1
)
<<
24
,
&
bt
->
color_map
);
sbus_writel
(
fb
->
color_map
CM
(
i
,
2
)
<<
24
,
&
bt
->
color_map
);
}
sbus_writel
(
0
,
&
bt
->
addr
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
static
void
tcx_restore_palette
(
struct
fb_info_sbusfb
*
fb
)
{
struct
bt_regs
*
bt
=
fb
->
s
.
tcx
.
bt
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
sbus_writel
(
0
,
&
bt
->
addr
);
sbus_writel
(
0xffffffff
,
&
bt
->
color_map
);
sbus_writel
(
0xffffffff
,
&
bt
->
color_map
);
sbus_writel
(
0xffffffff
,
&
bt
->
color_map
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
static
void
tcx_setcursormap
(
struct
fb_info_sbusfb
*
fb
,
u8
*
red
,
u8
*
green
,
u8
*
blue
)
{
struct
bt_regs
*
bt
=
fb
->
s
.
tcx
.
bt
;
unsigned
long
flags
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
/* Note the 2 << 24 is different from cg6's 1 << 24 */
sbus_writel
(
2
<<
24
,
&
bt
->
addr
);
sbus_writel
(
red
[
0
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
green
[
0
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
blue
[
0
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
3
<<
24
,
&
bt
->
addr
);
sbus_writel
(
red
[
1
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
green
[
1
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
blue
[
1
]
<<
24
,
&
bt
->
cursor
);
sbus_writel
(
0
,
&
bt
->
addr
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
/* Set cursor shape */
static
void
tcx_setcurshape
(
struct
fb_info_sbusfb
*
fb
)
{
struct
tcx_thc
*
thc
=
fb
->
s
.
tcx
.
thc
;
unsigned
long
flags
;
int
i
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
for
(
i
=
0
;
i
<
32
;
i
++
){
sbus_writel
(
fb
->
cursor
.
bits
[
0
][
i
],
&
thc
->
thc_cursmask
[
i
]);
sbus_writel
(
fb
->
cursor
.
bits
[
1
][
i
],
&
thc
->
thc_cursbits
[
i
]);
}
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
/* Load cursor information */
static
void
tcx_setcursor
(
struct
fb_info_sbusfb
*
fb
)
{
struct
cg_cursor
*
c
=
&
fb
->
cursor
;
unsigned
long
flags
;
unsigned
int
v
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
if
(
c
->
enable
)
v
=
((
c
->
cpos
.
fbx
-
c
->
chot
.
fbx
)
<<
16
)
|
((
c
->
cpos
.
fby
-
c
->
chot
.
fby
)
&
0xffff
);
else
/* Magic constant to turn off the cursor */
v
=
((
65536
-
32
)
<<
16
)
|
(
65536
-
32
);
sbus_writel
(
v
,
&
fb
->
s
.
tcx
.
thc
->
thc_cursxy
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
static
int
tcx_blank
(
struct
fb_info_sbusfb
*
fb
)
{
unsigned
long
flags
;
u32
tmp
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
tmp
=
sbus_readl
(
&
fb
->
s
.
tcx
.
thc
->
thc_misc
);
tmp
&=
~
TCX_THC_MISC_VIDEO
;
/* This should put us in power-save */
tmp
|=
TCX_THC_MISC_VSYNC_DIS
;
tmp
|=
TCX_THC_MISC_HSYNC_DIS
;
sbus_writel
(
tmp
,
&
fb
->
s
.
tcx
.
thc
->
thc_misc
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
return
0
;
}
static
int
tcx_unblank
(
struct
fb_info_sbusfb
*
fb
)
{
unsigned
long
flags
;
u32
tmp
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
tmp
=
sbus_readl
(
&
fb
->
s
.
tcx
.
thc
->
thc_misc
);
tmp
&=
~
TCX_THC_MISC_VSYNC_DIS
;
tmp
&=
~
TCX_THC_MISC_HSYNC_DIS
;
tmp
|=
TCX_THC_MISC_VIDEO
;
sbus_writel
(
tmp
,
&
fb
->
s
.
tcx
.
thc
->
thc_misc
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
return
0
;
}
static
void
tcx_reset
(
struct
fb_info_sbusfb
*
fb
)
{
unsigned
long
flags
;
u32
tmp
;
spin_lock_irqsave
(
&
fb
->
lock
,
flags
);
if
(
fb
->
open
&&
fb
->
mmaped
)
__tcx_set_control_plane
(
fb
);
/* Turn off stuff in the Transform Engine. */
sbus_writel
(
0
,
&
fb
->
s
.
tcx
.
tec
->
tec_matrix
);
sbus_writel
(
0
,
&
fb
->
s
.
tcx
.
tec
->
tec_clip
);
sbus_writel
(
0
,
&
fb
->
s
.
tcx
.
tec
->
tec_vdc
);
/* Enable cursor in Brooktree DAC. */
sbus_writel
(
0x06
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
addr
);
tmp
=
sbus_readl
(
&
fb
->
s
.
tcx
.
bt
->
control
);
tmp
|=
0x03
<<
24
;
sbus_writel
(
tmp
,
&
fb
->
s
.
tcx
.
bt
->
control
);
spin_unlock_irqrestore
(
&
fb
->
lock
,
flags
);
}
static
void
tcx_margins
(
struct
fb_info_sbusfb
*
fb
,
struct
display
*
p
,
int
x_margin
,
int
y_margin
)
{
fb
->
info
.
screen_base
+=
(
y_margin
-
fb
->
y_margin
)
*
p
->
fb_info
->
fix
.
line_length
+
(
x_margin
-
fb
->
x_margin
);
}
static
char
idstring
[
60
]
__initdata
=
{
0
};
char
__init
*
tcxfb_init
(
struct
fb_info_sbusfb
*
fb
)
{
struct
fb_fix_screeninfo
*
fix
=
&
fb
->
info
.
fix
;
struct
display
*
disp
=
&
fb
->
disp
;
struct
fbtype
*
type
=
&
fb
->
type
;
struct
sbus_dev
*
sdev
=
fb
->
sbdp
;
unsigned
long
phys
=
sdev
->
reg_addrs
[
0
].
phys_addr
;
int
lowdepth
,
i
,
j
;
#ifndef FBCON_HAS_CFB8
return
NULL
;
#endif
lowdepth
=
prom_getbool
(
fb
->
prom_node
,
"tcx-8-bit"
);
if
(
lowdepth
)
{
strcpy
(
fb
->
info
.
modename
,
"TCX8"
);
strcpy
(
fix
->
id
,
"TCX8"
);
}
else
{
strcpy
(
fb
->
info
.
modename
,
"TCX24"
);
strcpy
(
fix
->
id
,
"TCX24"
);
}
fix
->
line_length
=
fb
->
info
.
var
.
xres_virtual
;
fix
->
accel
=
FB_ACCEL_SUN_TCX
;
disp
->
scrollmode
=
SCROLL_YREDRAW
;
if
(
!
fb
->
info
.
screen_base
)
{
fb
->
info
.
screen_base
=
(
char
*
)
sbus_ioremap
(
&
sdev
->
resource
[
0
],
0
,
type
->
fb_size
,
"tcx ram"
);
}
fb
->
info
.
screen_base
+=
fix
->
line_length
*
fb
->
y_margin
+
fb
->
x_margin
;
fb
->
s
.
tcx
.
tec
=
(
struct
tcx_tec
*
)
sbus_ioremap
(
&
sdev
->
resource
[
7
],
0
,
sizeof
(
struct
tcx_tec
),
"tcx tec"
);
fb
->
s
.
tcx
.
thc
=
(
struct
tcx_thc
*
)
sbus_ioremap
(
&
sdev
->
resource
[
9
],
0
,
sizeof
(
struct
tcx_thc
),
"tcx thc"
);
fb
->
s
.
tcx
.
bt
=
(
struct
bt_regs
*
)
sbus_ioremap
(
&
sdev
->
resource
[
8
],
0
,
sizeof
(
struct
bt_regs
),
"tcx dac"
);
if
(
!
lowdepth
)
{
fb
->
s
.
tcx
.
cplane
=
(
u32
*
)
sbus_ioremap
(
&
sdev
->
resource
[
4
],
0
,
type
->
fb_size
*
sizeof
(
u32
),
"tcx cplane"
);
type
->
fb_depth
=
24
;
fb
->
switch_from_graph
=
tcx_switch_from_graph
;
}
else
{
/* As there can be one tcx in a machine only, we can write directly into
tcx_mmap_map */
tcx_mmap_map
[
1
].
size
=
SBUS_MMAP_EMPTY
;
tcx_mmap_map
[
4
].
size
=
SBUS_MMAP_EMPTY
;
tcx_mmap_map
[
5
].
size
=
SBUS_MMAP_EMPTY
;
tcx_mmap_map
[
6
].
size
=
SBUS_MMAP_EMPTY
;
}
fb
->
dispsw
=
fbcon_cfb8
;
fb
->
margins
=
tcx_margins
;
fb
->
loadcmap
=
tcx_loadcmap
;
if
(
prom_getbool
(
fb
->
prom_node
,
"hw-cursor"
))
{
fb
->
setcursor
=
tcx_setcursor
;
fb
->
setcursormap
=
tcx_setcursormap
;
fb
->
setcurshape
=
tcx_setcurshape
;
}
fb
->
restore_palette
=
tcx_restore_palette
;
fb
->
blank
=
tcx_blank
;
fb
->
unblank
=
tcx_unblank
;
fb
->
reset
=
tcx_reset
;
fb
->
physbase
=
0
;
for
(
i
=
0
;
i
<
13
;
i
++
)
{
/* tcx_mmap_map has to be sorted by voff, while
order of phys registers from PROM differs a little
bit. Here is the correction */
switch
(
i
)
{
case
10
:
j
=
12
;
break
;
case
11
:
case
12
:
j
=
i
-
1
;
break
;
default:
j
=
i
;
break
;
}
tcx_mmap_map
[
i
].
poff
=
fb
->
sbdp
->
reg_addrs
[
j
].
phys_addr
;
}
fb
->
mmap_map
=
tcx_mmap_map
;
/* Initialize Brooktree DAC */
sbus_writel
(
0x04
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
addr
);
/* color planes */
sbus_writel
(
0xff
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
control
);
sbus_writel
(
0x05
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
addr
);
sbus_writel
(
0x00
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
control
);
sbus_writel
(
0x06
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
addr
);
/* overlay plane */
sbus_writel
(
0x73
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
control
);
sbus_writel
(
0x07
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
addr
);
sbus_writel
(
0x00
<<
24
,
&
fb
->
s
.
tcx
.
bt
->
control
);
sprintf
(
idstring
,
"tcx at %x.%08lx Rev %d.%d %s"
,
fb
->
iospace
,
phys
,
((
sbus_readl
(
&
fb
->
s
.
tcx
.
thc
->
thc_rev
)
>>
TCX_THC_REV_REV_SHIFT
)
&
TCX_THC_REV_REV_MASK
),
((
sbus_readl
(
&
fb
->
s
.
tcx
.
thc
->
thc_rev
)
>>
TCX_THC_REV_MINREV_SHIFT
)
&
TCX_THC_REV_MINREV_MASK
),
lowdepth
?
"8-bit only"
:
"24-bit depth"
);
tcx_reset
(
fb
);
return
idstring
;
}
MODULE_LICENSE
(
"GPL"
);
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