Commit 87203ecd authored by James Simmons's avatar James Simmons

Ported riva and vga16fb over to new api. Thanks Antonia Daplas!!! More optimizations in fbcon.c

parent 96b01c31
......@@ -69,7 +69,7 @@ obj-$(CONFIG_FB_MAXINE) += maxinefb.o cfbfillrect.o cfbcopyarea.o cfbi
obj-$(CONFIG_FB_TX3912) += tx3912fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_MATROX) += matrox/
obj-$(CONFIG_FB_RIVA) += riva/
obj-$(CONFIG_FB_RIVA) += riva/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_SIS) += sis/
obj-$(CONFIG_FB_ATY) += aty/ cfbimgblt.o
......
......@@ -93,9 +93,6 @@
#include <asm/machdep.h>
#include <asm/setup.h>
#endif
#ifdef CONFIG_FBCON_VGA_PLANES
#include <asm/io.h>
#endif
#define INCLUDE_LINUX_LOGO_DATA
#include <asm/linux_logo.h>
......@@ -160,10 +157,8 @@ static inline void cursor_undrawn(void)
cursor_drawn = 0;
}
#define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1)
/*
* Interface used by the world
*/
......@@ -352,7 +347,7 @@ void set_con2fb_map(int unit, int newidx)
/*
* Accelerated handlers.
*/
void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
void accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct fb_info *info = p->fb_info;
......@@ -369,7 +364,7 @@ void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
info->fbops->fb_copyarea(info, &area);
}
void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy,
void accel_clear(struct vc_data *vc, struct display *p, int sy,
int sx, int height, int width)
{
struct fb_info *info = p->fb_info;
......@@ -385,32 +380,64 @@ void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy,
info->fbops->fb_fillrect(info, &region);
}
void fbcon_accel_putcs(struct vc_data *vc, struct display *p,
void accel_putcs(struct vc_data *vc, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
struct fb_info *info = p->fb_info;
unsigned short charmask = p->charmask;
unsigned int width = ((vc->vc_font.width + 7) >> 3);
unsigned int width = ((vc->vc_font.width + 7)/8);
unsigned int cellsize = vc->vc_font.height * width;
struct fb_image image;
u16 c = scr_readw(s);
static u8 pixmap[8192];
image.fg_color = attr_fgcol(p, c);
image.bg_color = attr_bgcol(p, c);
image.dx = xx * vc->vc_font.width;
image.dy = yy * vc->vc_font.height;
image.width = vc->vc_font.width;
image.height = vc->vc_font.height;
image.depth = 1;
while (count--) {
image.data = p->fontdata +
(scr_readw(s++) & charmask) * vc->vc_font.height * width;
/* pixmap = kmalloc((info->var.bits_per_pixel + 7) >> 3 *
vc->vc_font.height, GFP_KERNEL);
*/
if (!(vc->vc_font.width & 7) && pixmap != NULL) {
unsigned int pitch = width * count, i, j;
char *src, *dst, *dst0;
dst0 = pixmap;
image.width = vc->vc_font.width * count;
image.data = pixmap;
while (count--) {
src = p->fontdata + (scr_readw(s++) & charmask) * cellsize;
dst = dst0;
for (i = image.height; i--; ) {
for (j = 0; j < width; j++)
dst[j] = *src++;
dst += pitch;
}
dst0 += width;
}
info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width;
}
if (info->fbops->fb_sync)
info->fbops->fb_sync(info);
} else {
image.width = vc->vc_font.width;
while (count--) {
image.data = p->fontdata +
(scr_readw(s++) & charmask) * vc->vc_font.height * width;
info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width;
}
}
/*
if (pixmap);
kfree(pixmap);
*/
}
void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
void accel_clear_margins(struct vc_data *vc, struct display *p,
int bottom_only)
{
struct fb_info *info = p->fb_info;
......@@ -442,7 +469,7 @@ void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
}
}
void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
void accel_cursor(struct display *p, int flags, int xx, int yy)
{
static char mask[64], image[64], *dest;
struct vc_data *vc = p->conp;
......@@ -462,7 +489,7 @@ void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
if ((vc->vc_cursor_type & 0x0f) != shape) {
shape = vc->vc_cursor_type & 0x0f;
cursor.set |= FB_CUR_SETSIZE;
cursor.set |= FB_CUR_SETSHAPE;
}
c = scr_readw((u16 *) vc->vc_pos);
......@@ -472,10 +499,7 @@ void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
fgcolor = (int) attr_fgcol(p, c);
bgcolor = (int) attr_bgcol(p, c);
cursor.set |= FB_CUR_SETCMAP;
cursor.image.bg_color = bgcolor;
cursor.image.fg_color = fgcolor;
}
c &= p->charmask;
font = p->fontdata + (c * ((width + 7) / 8) * height);
if (font != dest) {
......@@ -490,7 +514,7 @@ void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
if (cursor.set & FB_CUR_SETSIZE) {
memset(image, 0xff, 64);
cursor.set |= FB_CUR_SETSIZE;
cursor.set |= FB_CUR_SETSHAPE;
}
if (cursor.set & FB_CUR_SETSHAPE) {
......@@ -534,6 +558,8 @@ void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
cursor.image.dy = yy * height;
cursor.image.depth = 1;
cursor.image.data = image;
cursor.image.bg_color = bgcolor;
cursor.image.fg_color = fgcolor;
cursor.mask = mask;
cursor.dest = dest;
cursor.rop = ROP_XOR;
......@@ -822,8 +848,8 @@ static int fbcon_changevar(int con)
vc_resize(con, nr_cols, nr_rows);
else if (CON_IS_VISIBLE(vc) &&
vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
fbcon_accel_clear_margins(vc, p, 0);
update_screen(con);
accel_clear_margins(vc, p, 0);
update_screen(con);
}
if (save) {
q = (unsigned short *) (vc->vc_origin +
......@@ -1017,7 +1043,7 @@ static void fbcon_set_display(int con, int init, int logo)
vc_resize(con, nr_cols, nr_rows);
else if (CON_IS_VISIBLE(vc) &&
vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
fbcon_accel_clear_margins(vc, p, 0);
accel_clear_margins(vc, p, 0);
update_screen(con);
}
if (save) {
......@@ -1114,11 +1140,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
y_break = p->vrows - p->yscroll;
if (sy < y_break && sy + height - 1 >= y_break) {
u_int b = y_break - sy;
fbcon_accel_clear(vc, p, real_y(p, sy), sx, b, width);
fbcon_accel_clear(vc, p, real_y(p, sy + b), sx, height - b,
accel_clear(vc, p, real_y(p, sy), sx, b, width);
accel_clear(vc, p, real_y(p, sy + b), sx, height - b,
width);
} else
fbcon_accel_clear(vc, p, real_y(p, sy), sx, height, width);
accel_clear(vc, p, real_y(p, sy), sx, height, width);
if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
......@@ -1179,7 +1205,7 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
cursor_undrawn();
redraw_cursor = 1;
}
fbcon_accel_putcs(vc, p, s, count, real_y(p, ypos), xpos);
accel_putcs(vc, p, s, count, real_y(p, ypos), xpos);
if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
}
......@@ -1207,7 +1233,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
cursor_on = 0;
if (cursor_drawn)
fbcon_accel_cursor(p, 0, p->cursor_x,
accel_cursor(p, 0, p->cursor_x,
real_y(p, p->cursor_y));
p->cursor_x = vc->vc_x;
......@@ -1221,7 +1247,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
case CM_MOVE:
case CM_DRAW:
if (cursor_drawn)
fbcon_accel_cursor(p, FB_CUR_SETCUR, p->cursor_x,
accel_cursor(p, FB_CUR_SETCUR, p->cursor_x,
real_y(p, p->cursor_y));
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
cursor_on = 1;
......@@ -1244,7 +1270,7 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
flag = 0;
if (!cursor_drawn)
flag = FB_CUR_SETCUR;
fbcon_accel_cursor(p, flag, p->cursor_x,
accel_cursor(p, flag, p->cursor_x,
real_y(p, p->cursor_y));
cursor_drawn ^= 1;
vbl_cursor_cnt = cursor_blink_rate;
......@@ -1313,7 +1339,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc,
p->yscroll += count;
if (p->yscroll > p->vrows - vc->vc_rows) {
fbcon_accel_bmove(p, p->vrows - vc->vc_rows, 0, 0, 0,
accel_bmove(p, p->vrows - vc->vc_rows, 0, 0, 0,
vc->vc_rows, vc->vc_cols);
p->yscroll -= p->vrows - vc->vc_rows;
}
......@@ -1321,7 +1347,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc,
info->var.yoffset = p->yscroll * vc->vc_font.height;
info->var.vmode &= ~FB_VMODE_YWRAP;
update_var(vc->vc_num, info);
fbcon_accel_clear_margins(vc, p, 1);
accel_clear_margins(vc, p, 1);
scrollback_max += count;
if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max;
......@@ -1336,7 +1362,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
p->yscroll -= count;
if (p->yscroll < 0) {
fbcon_accel_bmove(p, 0, 0, p->vrows - vc->vc_rows, 0,
accel_bmove(p, 0, 0, p->vrows - vc->vc_rows, 0,
vc->vc_rows, vc->vc_cols);
p->yscroll += p->vrows - vc->vc_rows;
}
......@@ -1344,7 +1370,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
info->var.yoffset = p->yscroll * vc->vc_font.height;
info->var.vmode &= ~FB_VMODE_YWRAP;
update_var(vc->vc_num, info);
fbcon_accel_clear_margins(vc, p, 1);
accel_clear_margins(vc, p, 1);
scrollback_max -= count;
if (scrollback_max < 0)
scrollback_max = 0;
......@@ -1410,7 +1436,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
if (attr != (c & 0xff00)) {
attr = c & 0xff00;
if (s > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
s - start,
real_y(p, line),
x);
......@@ -1420,7 +1446,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
}
if (c == scr_readw(d)) {
if (s > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
s - start,
real_y(p, line),
x);
......@@ -1435,7 +1461,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
d++;
} while (s < le);
if (s > start)
fbcon_accel_putcs(vc, p, start, s - start,
accel_putcs(vc, p, start, s - start,
real_y(p, line), x);
line++;
if (d == (u16 *) softback_end)
......@@ -1468,7 +1494,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
if (attr != (c & 0xff00)) {
attr = c & 0xff00;
if (s > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
s - start,
real_y(p, line),
x);
......@@ -1478,7 +1504,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
}
if (c == scr_readw(d)) {
if (s > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
s - start,
real_y(p, line),
x);
......@@ -1495,7 +1521,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
d++;
} while (s < le);
if (s > start)
fbcon_accel_putcs(vc, p, start, s - start,
accel_putcs(vc, p, start, s - start,
real_y(p, line), x);
console_conditional_schedule();
if (offset > 0)
......@@ -1574,7 +1600,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i
if (attr != (c & 0xff00)) {
attr = c & 0xff00;
if (d > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
d - start, dy, x);
x += d - start;
start = d;
......@@ -1582,7 +1608,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i
}
if (s >= ls && s < le && c == scr_readw(s)) {
if (d > start) {
fbcon_accel_putcs(vc, p, start,
accel_putcs(vc, p, start,
d - start, dy, x);
x += d - start + 1;
start = d + 1;
......@@ -1595,7 +1621,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i
d++;
} while (d < le);
if (d > start)
fbcon_accel_putcs(vc, p, start, d - start, dy, x);
accel_putcs(vc, p, start, d - start, dy, x);
sy++;
dy++;
}
......@@ -1657,9 +1683,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
goto redraw_up;
switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE:
fbcon_accel_bmove(p, t + count, 0, t, 0,
accel_bmove(p, t + count, 0, t, 0,
b - t - count, vc->vc_cols);
fbcon_accel_clear(vc, p, b - count, 0, count,
accel_clear(vc, p, b - count, 0, count,
vc->vc_cols);
break;
......@@ -1708,7 +1734,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
redraw_up:
fbcon_redraw(vc, p, t, b - t - count,
count * vc->vc_cols);
fbcon_accel_clear(vc, p, real_y(p, b - count), 0,
accel_clear(vc, p, real_y(p, b - count), 0,
count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
......@@ -1724,9 +1750,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
count = vc->vc_rows;
switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE:
fbcon_accel_bmove(p, t, 0, t + count, 0,
accel_bmove(p, t, 0, t + count, 0,
b - t - count, vc->vc_cols);
fbcon_accel_clear(vc, p, t, 0, count, vc->vc_cols);
accel_clear(vc, p, t, 0, count, vc->vc_cols);
break;
case __SCROLL_YWRAP:
......@@ -1773,7 +1799,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count,
-count * vc->vc_cols);
fbcon_accel_clear(vc, p, real_y(p, t), 0, count,
accel_clear(vc, p, real_y(p, t), 0, count,
vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row *
......@@ -1852,7 +1878,7 @@ static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy,
}
return;
}
fbcon_accel_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height,
accel_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height,
width);
}
......@@ -1909,7 +1935,7 @@ static int fbcon_switch(struct vc_data *vc)
update_var(unit, info);
if (vt_cons[unit]->vc_mode == KD_TEXT)
fbcon_accel_clear_margins(vc, p, 0);
accel_clear_margins(vc, p, 0);
if (logo_shown == -2) {
logo_shown = fg_console;
fbcon_show_logo(); /* This is protected above by initmem_freed */
......@@ -1943,18 +1969,18 @@ static int fbcon_blank(struct vc_data *vc, int blank)
height = vc->vc_rows;
y_break = p->vrows - p->yscroll;
if (height > y_break) {
fbcon_accel_clear(vc, p,
accel_clear(vc, p,
real_y(p, 0), 0,
y_break,
vc->vc_cols);
fbcon_accel_clear(vc, p,
accel_clear(vc, p,
real_y(p,
y_break),
0,
height - y_break,
vc->vc_cols);
} else
fbcon_accel_clear(vc, p,
accel_clear(vc, p,
real_y(p, 0), 0,
height,
vc->vc_cols);
......@@ -2151,7 +2177,7 @@ static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op,
}
} else if (CON_IS_VISIBLE(vc)
&& vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
fbcon_accel_clear_margins(vc, p, 0);
accel_clear_margins(vc, p, 0);
update_screen(vc->vc_num);
}
......
......@@ -4,6 +4,6 @@
obj-$(CONFIG_FB_RIVA) += rivafb.o
rivafb-objs := fbdev.o riva_hw.o accel.o
rivafb-objs := fbdev.o riva_hw.o
include $(TOPDIR)/Rules.make
/*
* linux/drivers/video/accel.c - nVidia RIVA 128/TNT/TNT2 fb driver
*
* Copyright 2000 Jindrich Makovicka, Ani Joshi
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of this archive
* for more details.
*/
#include "rivafb.h"
/* acceleration routines */
inline void wait_for_idle(struct rivafb_info *rinfo)
{
while (rinfo->riva.Busy(&rinfo->riva));
}
/* set copy ROP, no mask */
static void riva_setup_ROP(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Patt, 5);
rinfo->riva.Patt->Shape = 0;
rinfo->riva.Patt->Color0 = 0xffffffff;
rinfo->riva.Patt->Color1 = 0xffffffff;
rinfo->riva.Patt->Monochrome[0] = 0xffffffff;
rinfo->riva.Patt->Monochrome[1] = 0xffffffff;
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC;
}
void riva_setup_accel(struct rivafb_info *rinfo)
{
RIVA_FIFO_FREE(rinfo->riva, Clip, 2);
rinfo->riva.Clip->TopLeft = 0x0;
rinfo->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(rinfo);
wait_for_idle(rinfo);
}
static void riva_rectfill(struct rivafb_info *rinfo, int sy,
int sx, int height, int width, u_int color)
{
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 1);
rinfo->riva.Bitmap->Color1A = color;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 2);
rinfo->riva.Bitmap->UnclippedRectangle[0].TopLeft = (sx << 16) | sy;
rinfo->riva.Bitmap->UnclippedRectangle[0].WidthHeight = (width << 16) | height;
}
static void fbcon_riva_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
sx *= fontwidth(p);
sy *= fontheight(p);
dx *= fontwidth(p);
dy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Blt, 3);
rinfo->riva.Blt->TopLeftSrc = (sy << 16) | sx;
rinfo->riva.Blt->TopLeftDst = (dy << 16) | dx;
rinfo->riva.Blt->WidthHeight = (height << 16) | width;
}
static void riva_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only, u32 bgx)
{
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
unsigned int right_start = conp->vc_cols*fontwidth(p);
unsigned int bottom_start = conp->vc_rows*fontheight(p);
unsigned int right_width, bottom_width;
if (!bottom_only && (right_width = p->var.xres - right_start))
riva_rectfill(rinfo, 0, right_start, p->var.yres_virtual,
right_width, bgx);
if ((bottom_width = p->var.yres - bottom_start))
riva_rectfill(rinfo, p->var.yoffset + bottom_start, 0,
bottom_width, right_start, bgx);
}
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,
};
static inline void fbcon_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 fbcon_riva_writechr(struct vc_data *conp, struct display *p,
int c, int fgx, int bgx, int yy, int xx)
{
u8 *cdat;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
int w, h;
volatile u32 *d;
u32 cdat2;
int i, j, cnt;
w = fontwidth(p);
h = fontheight(p);
if (w <= 8)
cdat = p->fontdata + (c & p->charmask) * h;
else
cdat = p->fontdata + ((c & p->charmask) * h << 1);
RIVA_FIFO_FREE(rinfo->riva, Bitmap, 7);
rinfo->riva.Bitmap->ClipE.TopLeft = (yy << 16) | (xx & 0xFFFF);
rinfo->riva.Bitmap->ClipE.BottomRight = ((yy+h) << 16) | ((xx+w) & 0xffff);
rinfo->riva.Bitmap->Color0E = bgx;
rinfo->riva.Bitmap->Color1E = fgx;
rinfo->riva.Bitmap->WidthHeightInE = (h << 16) | 32;
rinfo->riva.Bitmap->WidthHeightOutE = (h << 16) | 32;
rinfo->riva.Bitmap->PointE = (yy << 16) | (xx & 0xFFFF);
d = &rinfo->riva.Bitmap->MonochromeData01E;
for (i = h; i > 0; i-=16) {
if (i >= 16)
cnt = 16;
else
cnt = i;
RIVA_FIFO_FREE(rinfo->riva, Bitmap, cnt);
for (j = 0; j < cnt; j++) {
if (w <= 8)
cdat2 = *cdat++;
else
cdat2 = *((u16*)cdat)++;
fbcon_reverse_order(&cdat2);
d[j] = cdat2;
}
}
}
#ifdef FBCON_HAS_CFB8
void fbcon_riva8_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual;
p->next_plane = 0;
}
static void fbcon_riva8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = attr_bgcol_ec(p, conp);
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = attr_fgcol(p,c);
bgx = attr_bgcol(p,c);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = attr_fgcol(p, c);
bgx = attr_bgcol(p, c);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva8_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0x0f);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
static void fbcon_riva8_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, attr_bgcol_ec(p, conp));
}
struct display_switch fbcon_riva8 = {
.setup = fbcon_riva8_setup,
.bmove = fbcon_riva_bmove,
.clear = fbcon_riva8_clear,
.putc = fbcon_riva8_putc,
.putcs = fbcon_riva8_putcs,
.revc = fbcon_riva8_revc,
.clear_margins =fbcon_riva8_clear_margins,
.fontwidthmask =FONTWIDTHRANGE(4, 16)
};
#endif
#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB32)
static void fbcon_riva1632_revc(struct display *p, int xx, int yy)
{
struct rivafb_info *rinfo = (struct rivafb_info *) (p->fb_info);
xx *= fontwidth(p);
yy *= fontheight(p);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0x66; // XOR
riva_rectfill(rinfo, yy, xx, fontheight(p), fontwidth(p), 0xffffffff);
RIVA_FIFO_FREE(rinfo->riva, Rop, 1);
rinfo->riva.Rop->Rop3 = 0xCC; // back to COPY
}
#endif
#ifdef FBCON_HAS_CFB16
void fbcon_riva16_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<1;
p->next_plane = 0;
}
static void fbcon_riva16_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int16_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static inline void convert_bgcolor_16(u32 *col)
{
*col = ((*col & 0x00007C00) << 9)
| ((*col & 0x000003E0) << 6)
| ((*col & 0x0000001F) << 3)
| 0xFF000000;
}
static void fbcon_riva16_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p,c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva16_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u16 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u16 *)p->dispsw_data)[attr_bgcol(p, c)];
if (p->var.green.length == 6)
convert_bgcolor_16(&bgx);
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva16_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u16 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva16 = {
.setup = fbcon_riva16_setup,
.bmove = fbcon_riva_bmove,
.clear = fbcon_riva16_clear,
.putc = fbcon_riva16_putc,
.putcs = fbcon_riva16_putcs,
.revc = fbcon_riva1632_revc,
.clear_margins =fbcon_riva16_clear_margins,
.fontwidthmask =FONTWIDTHRANGE(4, 16)
};
#endif
#ifdef FBCON_HAS_CFB32
void fbcon_riva32_setup(struct display *p)
{
p->next_line = p->line_length ? p->line_length : p->var.xres_virtual<<2;
p->next_plane = 0;
}
static void fbcon_riva32_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 bgx;
struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info);
bgx = ((u_int32_t*)p->dispsw_data)[attr_bgcol_ec(p, conp)];
sx *= fontwidth(p);
sy *= fontheight(p);
width *= fontwidth(p);
height *= fontheight(p);
riva_rectfill(rinfo, sy, sx, height, width, bgx);
}
static void fbcon_riva32_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u32 fgx,bgx;
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p,c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p,c)];
xx *= fontwidth(p);
yy *= fontheight(p);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
}
static void fbcon_riva32_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy,
int xx)
{
u16 c;
u32 fgx,bgx;
xx *= fontwidth(p);
yy *= fontheight(p);
c = scr_readw(s);
fgx = ((u32 *)p->dispsw_data)[attr_fgcol(p, c)];
bgx = ((u32 *)p->dispsw_data)[attr_bgcol(p, c)];
while (count--) {
c = scr_readw(s++);
fbcon_riva_writechr(conp, p, c, fgx, bgx, yy, xx);
xx += fontwidth(p);
}
}
static void fbcon_riva32_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
riva_clear_margins(conp, p, bottom_only, ((u32 *)p->dispsw_data)[attr_bgcol_ec(p, conp)]);
}
struct display_switch fbcon_riva32 = {
.setup = fbcon_riva32_setup,
.bmove = fbcon_riva_bmove,
.clear = fbcon_riva32_clear,
.putc = fbcon_riva32_putc,
.putcs = fbcon_riva32_putcs,
.revc = fbcon_riva1632_revc,
.clear_margins =fbcon_riva32_clear_margins,
.fontwidthmask =FONTWIDTHRANGE(4, 16)
};
#endif
......@@ -245,11 +245,8 @@ struct riva_cursor {
* ------------------------------------------------------------------------- */
/* command line data, set in rivafb_setup() */
static char fontname[40] __initdata = { 0 };
static u32 pseudo_palette[17];
static char nomove = 0;
static char nohwcursor __initdata = 0;
static char noblink = 0;
#ifdef CONFIG_MTRR
static char nomtrr __initdata = 0;
#endif
......@@ -284,7 +281,7 @@ static struct fb_var_screeninfo rivafb_default_var = {
activate: 0,
height: -1,
width: -1,
accel_flags: FB_ACCELF_TEXT,
accel_flags: FB_ACCELF_TEXT,
pixclock: 39721,
left_margin: 40,
right_margin: 24,
......@@ -400,236 +397,60 @@ static inline unsigned char MISCin(struct riva_par *par)
* ------------------------------------------------------------------------- */
/**
* riva_cursor_timer_handler - blink timer
* @dev_addr: pointer to riva_par object containing info for current riva board
*
* DESCRIPTION:
* Cursor blink timer.
*/
static void riva_cursor_timer_handler(unsigned long dev_addr)
{
struct riva_par *par = (struct riva_par *) dev_addr;
if (!par->cursor) return;
if (!par->cursor->enable) goto out;
if (par->cursor->last_move_delay < 1000)
par->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 (!noblink)
par->cursor->vbl_cnt = par->cursor->blink_rate;
}
out:
par->cursor->timer->expires = jiffies + (HZ / 100);
add_timer(par->cursor->timer);
}
/**
* rivafb_init_cursor - allocates cursor structure and starts blink timer
* @par: pointer to riva_par object containing info for current riva board
*
* DESCRIPTION:
* Allocates cursor structure and starts blink timer.
*
* RETURNS:
* Pointer to allocated cursor structure.
*
* CALLED FROM:
* rivafb_init_one()
*/
static struct riva_cursor * __init rivafb_init_cursor(struct riva_par *par)
{
struct riva_cursor *cursor;
cursor = kmalloc(sizeof(struct riva_cursor), GFP_KERNEL);
if (!cursor) return 0;
memset(cursor, 0, sizeof(*cursor));
cursor->timer = kmalloc(sizeof(*cursor->timer), GFP_KERNEL);
if (!cursor->timer) {
kfree(cursor);
return 0;
}
memset(cursor->timer, 0, sizeof(*cursor->timer));
cursor->blink_rate = DEFAULT_CURSOR_BLINK_RATE;
init_timer(cursor->timer);
cursor->timer->expires = jiffies + (HZ / 100);
cursor->timer->data = (unsigned long)par;
cursor->timer->function = riva_cursor_timer_handler;
add_timer(cursor->timer);
return cursor;
}
/**
* rivafb_exit_cursor - stops blink timer and releases cursor structure
* @par: pointer to riva_par object containing info for current riva board
*
* DESCRIPTION:
* Stops blink timer and releases cursor structure.
*
* CALLED FROM:
* rivafb_init_one()
* rivafb_remove_one()
*/
static void rivafb_exit_cursor(struct riva_par *par)
{
struct riva_cursor *cursor = par->cursor;
if (cursor) {
if (cursor->timer) {
del_timer_sync(cursor->timer);
kfree(cursor->timer);
}
kfree(cursor);
par->cursor = 0;
}
}
/**
* rivafb_download_cursor - writes cursor shape into card registers
* @info: pointer to fb_info object containing info for current riva board
*
* DESCRIPTION:
* Writes cursor shape into card registers.
* rivafb_load_cursor_image - load cursor image to hardware
* @data: address to monochrome bitmap (1 = foreground color, 0 = background)
* @mask: address to mask (1 = write image pixel, 0 = do not write pixel)
* @par: pointer to private data
* @w: width of cursor image in pixels
* @h: height of cursor image in scanlines
* @bg: background color (ARGB1555) - alpha bit determines opacity
* @fg: foreground color (ARGB1555)
*
* DESCRIPTiON:
* Loads cursor image based on a monochrome source and mask bitmap. The
* mask bit determines if the image pixel is to be written to the framebuffer
* or not. The imaage bits determines the color of the pixel, 0 for
* background, 1 for foreground. Only the affected region (as determined
* by @w and @h parameters) will be updated.
*
* CALLED FROM:
* riva_load_video_mode()
* rivafb_cursor()
*/
static void rivafb_download_cursor(struct fb_info *info)
static void rivafb_load_cursor_image(u8 *data, u8 *mask, struct riva_par *par,
int w, int h, u16 bg, u16 fg)
{
struct riva_par *par = (struct riva_par *) info->par;
int i, save;
int *image;
if (!par->cursor) return;
image = (int *)par->cursor->image;
save = par->riva.ShowHideCursor(&par->riva, 0);
for (i = 0; i < (MAX_CURS*MAX_CURS*2)/sizeof(int); i++)
writel(image[i], par->riva.CURSOR + i);
par->riva.ShowHideCursor(&par->riva, save);
}
/**
* rivafb_create_cursor - sets rectangular cursor
* @info: pointer to fb_info object containing info for current riva board
* @width: cursor width in pixels
* @height: cursor height in pixels
*
* DESCRIPTION:
* Sets rectangular cursor.
*
* CALLED FROM:
* rivafb_set_font()
* rivafb_set_var()
*/
static void rivafb_create_cursor(struct fb_info *info, int width, int height)
{
struct riva_par *par = (struct riva_par *) info->par;
struct riva_cursor *c = par->cursor;
int i, j, idx;
if (c) {
if (width <= 0 || height <= 0) {
width = 8;
height = 16;
}
if (width > MAX_CURS) width = MAX_CURS;
if (height > MAX_CURS) height = MAX_CURS;
c->size.x = width;
c->size.y = height;
idx = 0;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++,idx++)
c->image[idx] = CURSOR_COLOR;
for (j = width; j < MAX_CURS; j++,idx++)
c->image[idx] = TRANSPARENT_COLOR;
}
for (i = height; i < MAX_CURS; i++)
for (j = 0; j < MAX_CURS; j++,idx++)
c->image[idx] = TRANSPARENT_COLOR;
}
}
/**
* rivafb_set_font - change font size
* @p: pointer to display object
* @width: font width in pixels
* @height: font height in pixels
*
* DESCRIPTION:
* Callback function called if font settings changed.
*
* RETURNS:
* 1 (Always succeeds.)
*/
static int rivafb_set_font(struct display *p, int width, int height)
{
rivafb_create_cursor(p->fb_info, width, height);
return 1;
}
/**
* rivafb_cursor - cursor handler
* @p: pointer to display object
* @mode: cursor mode (see CM_*)
* @x: cursor x coordinate in characters
* @y: cursor y coordinate in characters
*
* DESCRIPTION:
* Cursor handler.
*/
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;
if (!c) return;
x = x * fontwidth(p) - p->var.xoffset;
y = y * fontheight(p) - p->var.yoffset;
if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable)
return;
c->enable = 0;
if (c->on) par->riva.ShowHideCursor(&par->riva, 0);
c->pos.x = x;
c->pos.y = y;
switch (mode) {
case CM_ERASE:
c->on = 0;
break;
case CM_DRAW:
case CM_MOVE:
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);
if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY;
c->on = 1;
int i, j, k = 0;
u32 b, m, tmp;
for (i = 0; i < h; i++) {
b = *((u32 *)data)++;
m = *((u32 *)mask)++;
for (j = 0; j < w/2; j++) {
tmp = 0;
#if defined (__BIG_ENDIAN)
if (m & (1 << 31))
tmp = (b & (1 << 31)) ? fg << 16 : bg << 16;
b <<= 1;
m <<= 1;
if (m & (1 << 31))
tmp |= (b & (1 << 31)) ? fg : bg;
b <<= 1;
m <<= 1;
#else
if (m & 1)
tmp = (b & 1) ? fg : bg;
b >>= 1;
m >>= 1;
if (m & 1)
tmp |= (b & 1) ? fg << 16 : bg << 16;
b >>= 1;
m >>= 1;
#endif
writel(tmp, par->riva.CURSOR + k++);
}
c->last_move_delay = 0;
c->enable = 1;
break;
k += (MAX_CURS - w)/2;
}
}
......@@ -833,9 +654,6 @@ static void riva_load_video_mode(struct fb_info *info)
par->current_state = newmode;
riva_load_state(par, &par->current_state);
par->riva.LockUnlock(&par->riva, 0); /* important for HW cursor */
rivafb_download_cursor(info);
}
/**
......@@ -961,9 +779,341 @@ void riva_setup_accel(struct riva_par *par)
par->riva.Clip->TopLeft = 0x0;
par->riva.Clip->WidthHeight = 0x80008000;
riva_setup_ROP(par);
}
/**
* rivafb_fillrect - hardware accelerated color fill function
* @info: pointer to fb_info structure
* @rect: pointer to fb_fillrect structure
*
* DESCRIPTION:
* This function fills up a region of framebuffer memory with a solid
* color with a choice of two different ROP's, copy or invert.
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_fillrect(struct fb_info *info, struct fb_fillrect *rect)
{
struct riva_par *par = (struct riva_par *) info->par;
u_int color, rop = 0;
if (info->var.bits_per_pixel == 8)
color = rect->color;
else
color = par->riva_palette[rect->color];
switch (rect->rop) {
case ROP_XOR:
rop = 0x66;
break;
case ROP_COPY:
default:
rop = 0xCC;
break;
}
RIVA_FIFO_FREE(par->riva, Rop, 1);
par->riva.Rop->Rop3 = rop;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
par->riva.Bitmap->Color1A = 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;
}
/**
* rivafb_copyarea - hardware accelerated blit function
* @info: pointer to fb_info structure
* @region: pointer to fb_copyarea structure
*
* DESCRIPTION:
* This copies an area of pixels from one location to another
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_copyarea(struct fb_info *info, struct fb_copyarea *region)
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_FIFO_FREE(par->riva, Blt, 3);
par->riva.Blt->TopLeftSrc = (region->sy << 16) | region->sx;
par->riva.Blt->TopLeftDst = (region->dy << 16) | region->dx;
par->riva.Blt->WidthHeight = (region->height << 16) | region->width;
wait_for_idle(par);
}
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,
};
/**
* rivafb_imageblit: hardware accelerated color expand function
* @info: pointer to fb_info structure
* @image: pointer to fb_image structure
*
* DESCRIPTION:
* If the source is a monochrome bitmap, the function fills up a a region
* of framebuffer memory with pixels whose color is determined by the bit
* setting of the bitmap, 1 - foreground, 0 - background.
*
* If the source is not a monochrome bitmap, color expansion is not done.
* In this case, it is channeled to a software function.
*
* CALLED FROM:
* framebuffer hook
*/
static void rivafb_imageblit(struct fb_info *info, struct fb_image *image)
{
struct riva_par *par = (struct riva_par *) info->par;
u8 *cdat = image->data, *dat;
int w, h, dx, dy;
volatile u32 *d;
u32 fgx = 0, bgx = 0, size, width, mod;
int i, j;
if (image->depth != 1) {
wait_for_idle(par);
cfb_imageblit(info, image);
return;
}
w = image->width;
h = image->height;
dx = image->dx;
dy = image->dy;
width = (w + 7)/8;
size = width * h;
dat = cdat;
for (i = 0; i < size; i++) {
*dat = byte_rev[*dat];
dat++;
}
switch (info->var.bits_per_pixel) {
case 8:
fgx = image->fg_color | ~((1 << 8) - 1);
bgx = image->bg_color | ~((1 << 8) - 1);
break;
case 16:
/* set alpha bit */
if (info->var.green.length == 5) {
fgx = 1 << 15;
bgx = fgx;
}
/* Fall through... */
case 32:
fgx |= par->riva_palette[image->fg_color];
bgx |= par->riva_palette[image->bg_color];
break;
}
RIVA_FIFO_FREE(par->riva, Bitmap, 7);
par->riva.Bitmap->ClipE.TopLeft = (dy << 16) | (dx & 0xFFFF);
par->riva.Bitmap->ClipE.BottomRight = (((dy + h) << 16) |
((dx + w) & 0xffff));
par->riva.Bitmap->Color0E = bgx;
par->riva.Bitmap->Color1E = fgx;
par->riva.Bitmap->WidthHeightInE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->WidthHeightOutE = (h << 16) | ((w + 31) & ~31);
par->riva.Bitmap->PointE = (dy << 16) | (dx & 0xFFFF);
d = &par->riva.Bitmap->MonochromeData01E;
mod = width % 4;
if (width >= 4) {
while (h--) {
size = width / 4;
while (size >= 16) {
RIVA_FIFO_FREE(par->riva, Bitmap, 16);
for (i = 0; i < 16; i++)
d[i] = *((u32 *)cdat)++;
size -= 16;
}
if (size) {
RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (i = 0; i < size; i++)
d[i] = *((u32 *) cdat)++;
}
if (mod) {
u32 tmp;
RIVA_FIFO_FREE(par->riva, Bitmap, 1);
for (i = 0; i < mod; i++)
((u8 *)&tmp)[i] = *cdat++;
d[i] = tmp;
}
}
}
else {
u32 k, tmp;
for (i = h; i > 0; i-=16) {
if (i >= 16)
size = 16;
else
size = i;
RIVA_FIFO_FREE(par->riva, Bitmap, size);
for (j = 0; j < size; j++) {
for (k = 0; k < width; k++)
((u8 *)&tmp)[k] = *cdat++;
d[j] = tmp;
}
}
}
}
/**
* rivafb_cursor - hardware cursor function
* @info: pointer to info structure
* @cursor: pointer to fbcursor structure
*
* DESCRIPTION:
* A cursor function that supports displaying a cursor image via hardware.
* Within the kernel, copy and invert rops are supported. If exported
* to user space, only the copy rop will be supported.
*
* CALLED FROM
* framebuffer hook
*/
static int rivafb_cursor(struct fb_info *info, struct fb_cursor *cursor)
{
static u8 data[MAX_CURS*MAX_CURS/8], mask[MAX_CURS*MAX_CURS/8];
struct riva_par *par = (struct riva_par *) info->par;
int i, j, d_idx = 0, s_idx = 0;
u16 flags = cursor->set, fg, bg;
/*
* Can't do invert if one of the operands (dest) is missing,
* ie, only opaque cursor supported. This should be
* standard for GUI apps.
*/
if (cursor->dest == NULL && cursor->rop == ROP_XOR)
return 1;
if (par->cursor_reset) {
flags = FB_CUR_SETALL;
par->cursor_reset = 0;
}
par->riva.ShowHideCursor(&par->riva, 0);
if (flags & FB_CUR_SETPOS) {
u32 xx, yy, temp;
yy = cursor->image.dy - info->var.yoffset;
xx = cursor->image.dx - info->var.xoffset;
temp = xx & 0xFFFF;
temp |= yy << 16;
*(par->riva.CURSORPOS) = temp;
}
if (flags & FB_CUR_SETSIZE) {
memset(data, 0, MAX_CURS * MAX_CURS/8);
memset(mask, 0, MAX_CURS * MAX_CURS/8);
memset_io(par->riva.CURSOR, 0, MAX_CURS * MAX_CURS * 2);
}
if (flags & (FB_CUR_SETSHAPE | FB_CUR_SETCMAP | FB_CUR_SETDEST)) {
int bg_idx = cursor->image.bg_color;
int fg_idx = cursor->image.fg_color;
switch (cursor->rop) {
case ROP_XOR:
for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8;
j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx] ^
((u8 *)cursor->dest)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
case ROP_COPY:
default:
for (i = 0; i < cursor->image.height; i++) {
for (j = 0; j < (cursor->image.width + 7)/8; j++) {
d_idx = i * MAX_CURS/8 + j;
data[d_idx] = byte_rev[((u8 *)cursor->image.data)[s_idx]];
mask[d_idx] = byte_rev[((u8 *)cursor->mask)[s_idx]];
s_idx++;
}
}
break;
}
bg = ((par->cmap[bg_idx].red & 0xf8) << 7) |
((par->cmap[bg_idx].green & 0xf8) << 2) |
((par->cmap[bg_idx].blue & 0xf8) >> 3) | 1 << 15;
fg = ((par->cmap[fg_idx].red & 0xf8) << 7) |
((par->cmap[fg_idx].green & 0xf8) << 2) |
((par->cmap[fg_idx].blue & 0xf8) >> 3) | 1 << 15;
par->riva.LockUnlock(&par->riva, 0);
rivafb_load_cursor_image(data, mask, par, cursor->image.width,
cursor->image.height, bg, fg);
}
if (cursor->enable)
par->riva.ShowHideCursor(&par->riva, 1);
return 0;
}
static int rivafb_sync(struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
wait_for_idle(par);
return 0;
}
/* ------------------------------------------------------------------------- *
*
* internal fb_ops helper functions
......@@ -992,23 +1142,18 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
assert(var != NULL);
switch (var->bits_per_pixel) {
case 8:
rc = 256; /* pseudocolor... 256 entries HW palette */
switch (var->green.length) {
case 5:
rc = 32; /* fix for 15 bpp depths on Riva 128 based cards */
break;
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 */
case 32:
rc = 16; /* directcolor... 16 entries SW palette */
case 6:
rc = 64; /* directcolor... 16 entries SW palette */
break; /* Mystique: truecolor, 16 entries SW palette, HW palette hardwired into 1:1 mapping */
default:
/* should not occur */
rc = 256; /* pseudocolor... 256 entries HW palette */
break;
}
return rc;
}
......@@ -1021,8 +1166,13 @@ static int riva_get_cmap_len(const struct fb_var_screeninfo *var)
static int rivafb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
int nom, den; /* translating from pixels->bytes */
if (par->riva.Architecture == NV_ARCH_03 &&
var->bits_per_pixel == 16)
var->bits_per_pixel = 15;
switch (var->bits_per_pixel) {
case 1 ... 8:
var->bits_per_pixel = 8;
......@@ -1098,7 +1248,6 @@ static int rivafb_check_var(struct fb_var_screeninfo *var,
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;
return 0;
}
......@@ -1108,7 +1257,21 @@ static int rivafb_set_par(struct fb_info *info)
//rivafb_create_cursor(info, fontwidth(dsp), fontheight(dsp));
riva_load_video_mode(info);
riva_setup_accel(par);
if (info->var.accel_flags) {
riva_setup_accel(par);
info->fbops->fb_fillrect = rivafb_fillrect;
info->fbops->fb_copyarea = rivafb_copyarea;
info->fbops->fb_imageblit = rivafb_imageblit;
info->fbops->fb_cursor = rivafb_cursor;
info->fbops->fb_sync = rivafb_sync;
}
else {
info->fbops->fb_fillrect = cfb_fillrect;
info->fbops->fb_copyarea = cfb_copyarea;
info->fbops->fb_imageblit = cfb_imageblit;
info->fbops->fb_cursor = soft_cursor;
info->fbops->fb_sync = NULL;
}
info->fix.line_length = (info->var.xres_virtual * (info->var.bits_per_pixel >> 3));
info->fix.visual = (info->var.bits_per_pixel == 8) ?
......@@ -1129,7 +1292,7 @@ static int rivafb_set_par(struct fb_info *info)
*
* This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag
*/
static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
static int rivafb_pan_display(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct riva_par *par = (struct riva_par *) info->par;
......@@ -1152,9 +1315,7 @@ static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
base = var->yoffset * info->fix.line_length + var->xoffset;
if (con == info->currcon) {
par->riva.SetStartAddress(&par->riva, base);
}
par->riva.SetStartAddress(&par->riva, base);
info->var.xoffset = var->xoffset;
info->var.yoffset = var->yoffset;
......@@ -1163,6 +1324,15 @@ static int rivafb_pan_display(struct fb_var_screeninfo *var, int con,
info->var.vmode |= FB_VMODE_YWRAP;
else
info->var.vmode &= ~FB_VMODE_YWRAP;
/*
* HACK: The hardware cursor occasionally disappears during fast scrolling.
* We just reset the cursor each time we change the start address.
* This also has a beneficial side effect of restoring the cursor
* image when switching from X.
*/
par->cursor_reset = 1;
DPRINTK("EXIT, returning 0\n");
return 0;
}
......@@ -1231,6 +1401,7 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
{
struct riva_par *par = (struct riva_par *) info->par;
RIVA_HW_INST *chip = &par->riva;
int i;
if (regno >= riva_get_cmap_len(&info->var))
return -EINVAL;
......@@ -1241,34 +1412,74 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
(red * 77 + green * 151 + blue * 28) >> 8;
}
switch (info->var.bits_per_pixel) {
case 8:
/* "transparent" stuff is completely ignored. */
riva_wclut(chip, regno, red >> 8, green >> 8, blue >> 8);
break;
case 16:
assert(regno < 16);
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
((u16 *)(info->pseudo_palette))[regno] =
((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
if (!regno) {
for (i = 0; i < 256; i++) {
par->cmap[i].red = 0;
par->cmap[i].green = 0;
par->cmap[i].blue = 0;
}
}
par->cmap[regno].red = (u8) red;
par->cmap[regno].green = (u8) green;
par->cmap[regno].blue = (u8) blue;
if (info->var.green.length == 5) {
/* RGB555: all components have 32 entries, 8 indices apart */
for (i = 0; i < 8; i++)
riva_wclut(chip, (regno*8)+i, (u8) red, (u8) green, (u8) blue);
}
else if (info->var.green.length == 6) {
/*
* RGB 565: red and blue have 32 entries, 8 indices apart, while
* green has 64 entries, 4 indices apart
*/
if (regno < 32) {
for (i = 0; i < 8; i++) {
riva_wclut(chip, (regno*8)+i, (u8) red,
par->cmap[regno*2].green,
(u8) blue);
}
}
for (i = 0; i < 4; i++) {
riva_wclut(chip, (regno*4)+i, par->cmap[regno/2].red,
(u8) green, par->cmap[regno/2].blue);
}
}
else {
riva_wclut(chip, regno, (u8) red, (u8) green, (u8) blue);
}
if (regno < 16) {
switch (info->var.bits_per_pixel) {
case 16:
if (info->var.green.length == 5) {
/* 0rrrrrgg gggbbbbb */
((u32 *)(info->pseudo_palette))[regno] =
(regno << 10) | (regno << 5) | regno;
par->riva_palette[regno] =
((red & 0xf800) >> 1) |
((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11);
} else {
/* rrrrrggg gggbbbbb */
((u32 *)(info->pseudo_palette))[regno] =
(regno << 11) | (regno << 6) | regno;
par->riva_palette[regno] = ((red & 0xf800) >> 0) |
((green & 0xf800) >> 5) | ((blue & 0xf800) >> 11);
}
break;
case 32:
((u32 *)(info->pseudo_palette))[regno] =
(regno << 16) | (regno << 8) | regno;
par->riva_palette[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
default:
/* do nothing */
break;
}
break;
case 32:
assert(regno < 16);
((u32 *)(info->pseudo_palette))[regno] =
((red & 0xff00) << 8) |
((green & 0xff00)) | ((blue & 0xff00) >> 8);
break;
default:
/* do nothing */
break;
}
return 0;
}
......@@ -1281,25 +1492,23 @@ static int rivafb_setcolreg(unsigned regno, unsigned red, unsigned green,
/* kernel interface */
static struct fb_ops riva_fb_ops = {
owner: THIS_MODULE,
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_setcolreg: rivafb_setcolreg,
fb_pan_display: rivafb_pan_display,
fb_blank: rivafb_blank,
fb_fillrect: cfb_fillrect,
fb_copyarea: cfb_copyarea,
fb_imageblit: cfb_imageblit,
.owner = THIS_MODULE,
.fb_check_var = rivafb_check_var,
.fb_set_par = rivafb_set_par,
.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_cursor = rivafb_cursor,
.fb_sync = rivafb_sync,
};
static int __devinit riva_set_fbinfo(struct fb_info *info)
{
unsigned int cmap_len;
strcpy(info->modename, rivafb_fix.id);
info->node = NODEV;
info->flags = FBINFO_FLAG_DEFAULT;
info->fbops = &riva_fb_ops;
......@@ -1309,12 +1518,7 @@ static int __devinit riva_set_fbinfo(struct fb_info *info)
/* FIXME: set monspecs to what??? */
info->display_fg = NULL;
info->pseudo_palette = pseudo_palette;
strncpy(info->fontname, fontname, sizeof(info->fontname));
info->fontname[sizeof(info->fontname) - 1] = 0;
info->changevar = NULL;
info->switch_con = gen_switch;
info->updatevar = gen_update_var;
cmap_len = riva_get_cmap_len(&info->var);
fb_alloc_cmap(&info->cmap, cmap_len, 0);
#ifndef MODULE
......@@ -1341,8 +1545,7 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
assert(pd != NULL);
assert(rci != NULL);
info = kmalloc(sizeof(struct fb_info) + sizeof(struct display),
GFP_KERNEL);
info = kmalloc(sizeof(struct fb_info), GFP_KERNEL);
if (!info)
goto err_out;
......@@ -1350,7 +1553,7 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
if (!default_par)
goto err_out_kfree;
memset(info, 0, sizeof(struct fb_info) + sizeof(struct display));
memset(info, 0, sizeof(struct fb_info));
memset(default_par, 0, sizeof(struct riva_par));
strcat(rivafb_fix.id, rci->name);
......@@ -1449,13 +1652,10 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
CRTCout(default_par, 0x11, 0xFF);/* vgaHWunlock() + riva unlock(0x7F) */
default_par->riva.LockUnlock(&default_par->riva, 0);
info->disp = (struct display *)(info + 1);
info->par = default_par;
riva_save_state(default_par, &default_par->initial_state);
if (!nohwcursor) default_par->cursor = rivafb_init_cursor(default_par);
if (riva_set_fbinfo(info) < 0) {
printk(KERN_ERR PFX "error setting initial video mode\n");
goto err_out_cursor;
......@@ -1482,7 +1682,6 @@ static int __devinit rivafb_init_one(struct pci_dev *pd,
err_out_load_state:
riva_load_state(default_par, &default_par->initial_state);
err_out_cursor:
rivafb_exit_cursor(default_par);
/* err_out_iounmap_fb: */
iounmap(info->screen_base);
err_out_iounmap_ctrl:
......@@ -1509,8 +1708,6 @@ static void __devexit rivafb_remove_one(struct pci_dev *pd)
unregister_framebuffer(info);
rivafb_exit_cursor(par);
#ifdef CONFIG_MTRR
if (par->mtrr.vram_valid)
mtrr_del(par->mtrr.vram, info->fix.smem_start,
......@@ -1545,27 +1742,12 @@ int __init rivafb_setup(char *options)
while ((this_opt = strsep(&options, ",")) != NULL) {
if (!*this_opt)
continue;
if (!strncmp(this_opt, "font:", 5)) {
char *p;
int i;
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, "noblink", 7)) {
noblink = 1;
} else if (!strncmp(this_opt, "nomove", 6)) {
if (!strncmp(this_opt, "nomove", 6)) {
nomove = 1;
#ifdef CONFIG_MTRR
} else if (!strncmp(this_opt, "nomtrr", 6)) {
nomtrr = 1;
#endif
} else if (!strncmp(this_opt, "nohwcursor", 10)) {
nohwcursor = 1;
} else
mode_option = this_opt;
}
......@@ -1616,10 +1798,6 @@ 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");
MODULE_PARM_DESC(noblink, "Disables hardware cursor blinking (0 or 1=disabled) (default=0)");
#ifdef CONFIG_MTRR
MODULE_PARM(nomtrr, "i");
MODULE_PARM_DESC(nomtrr, "Disables MTRR support (0 or 1=disabled) (default=0)");
......
......@@ -3,7 +3,6 @@
#include <linux/config.h>
#include <linux/fb.h>
#include <video/fbcon.h>
#include "riva_hw.h"
/* GGI compatibility macros */
......@@ -23,6 +22,10 @@ struct riva_regs {
RIVA_HW_STATE ext;
};
typedef struct {
unsigned char red, green, blue, transp;
} riva_cfb8_cmap_t;
struct riva_par {
RIVA_HW_INST riva; /* interface to riva_hw.c */
......@@ -32,7 +35,10 @@ struct riva_par {
struct riva_regs initial_state; /* initial startup video mode */
struct riva_regs current_state;
struct riva_cursor *cursor;
riva_cfb8_cmap_t cmap[256]; /* VGA DAC palette cache */
u32 riva_palette[16];
u32 cursor_data[32 * 32/4];
int cursor_reset;
#ifdef CONFIG_MTRR
struct { int vram; int vram_valid; } mtrr;
#endif
......
......@@ -1062,8 +1062,10 @@ void vga_8planes_copyarea(struct fb_info *info, struct fb_copyarea *area)
}
} else {
line_ofs = info->fix.line_length - area->width;
dest = info->screen_base + area->dx + area->width + (area->dy + height - 1) * info->fix.line_length;
src = info->screen_base + area->sx + area->width + (area->sy + height - 1) * info->fix.line_length;
dest = info->screen_base + area->dx + area->width +
(area->dy + height - 1) * info->fix.line_length;
src = info->screen_base + area->sx + area->width +
(area->sy + height - 1) * info->fix.line_length;
while (height--) {
for (x = 0; x < area->width; x++) {
--src;
......@@ -1147,8 +1149,10 @@ void vga16fb_copyarea(struct fb_info *info, struct fb_copyarea *area)
dst += line_ofs;
}
} else {
dst = info->screen_base + (area->dx/8) + width + (area->dy + height - 1) * info->fix.line_length;
src = info->screen_base + (area->sx/8) + width + (area->sy + height - 1) * info->fix.line_length;
dst = info->screen_base + (area->dx/8) + width +
(area->dy + height - 1) * info->fix.line_length;
src = info->screen_base + (area->sx/8) + width +
(area->sy + height - 1) * info->fix.line_length;
while (height--) {
for (x = 0; x < width; x++) {
dst--;
......@@ -1224,68 +1228,120 @@ void vga_8planes_imageblit(struct fb_info *info, struct fb_image *image)
void vga_imageblit_expand(struct fb_info *info, struct fb_image *image)
{
char *where = info->screen_base + (image->dx/image->width) + image->dy * info->fix.line_length;
char *where = info->screen_base + (image->dx/8) +
image->dy * info->fix.line_length;
struct vga16fb_par *par = (struct vga16fb_par *) info->par;
u8 *cdat = image->data;
int y;
u8 *cdat = image->data, *dst;
int x, y;
switch (info->fix.type) {
case FB_TYPE_VGA_PLANES:
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
if (par->isVGA) {
setmode(2);
setop(0);
setsr(0xf);
setcolor(image->fg_color);
selectmask();
setmask(0xff);
writeb(image->bg_color, where);
rmb();
readb(where); /* fill latches */
setmode(3);
wmb();
for (y = 0; y < image->height; y++, where += info->fix.line_length)
writeb(cdat[y], where);
wmb();
} else {
setmode(0);
setop(0);
setsr(0xf);
setcolor(image->bg_color);
selectmask();
setmask(0xff);
for (y = 0; y < image->height; y++, where += info->fix.line_length)
rmw(where);
where -= info->fix.line_length * y;
setcolor(image->fg_color);
selectmask();
for (y = 0; y < image->height; y++, where += info->fix.line_length)
if (cdat[y]) {
setmask(cdat[y]);
rmw(where);
case FB_TYPE_VGA_PLANES:
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4) {
if (par->isVGA) {
setmode(2);
setop(0);
setsr(0xf);
setcolor(image->fg_color);
selectmask();
setmask(0xff);
writeb(image->bg_color, where);
rmb();
readb(where); /* fill latches */
setmode(3);
wmb();
for (y = 0; y < image->height; y++) {
dst = where;
for (x = image->width/8; x--;)
writeb(*cdat++, dst++);
where += info->fix.line_length;
}
wmb();
} else {
setmode(0);
setop(0);
setsr(0xf);
setcolor(image->bg_color);
selectmask();
setmask(0xff);
for (y = 0; y < image->height; y++) {
dst = where;
for (x=image->width/8; x--;){
rmw(dst);
setcolor(image->fg_color);
selectmask();
if (*cdat) {
setmask(*cdat++);
rmw(dst++);
}
}
where += info->fix.line_length;
}
} else
vga_8planes_imageblit(info, image);
break;
}
} else
vga_8planes_imageblit(info, image);
break;
#ifdef FBCON_HAS_VGA
case FB_TYPE_TEXT:
break;
case FB_TYPE_TEXT:
break;
#endif
case FB_TYPE_PACKED_PIXELS:
default:
cfb_imageblit(info, image);
break;
case FB_TYPE_PACKED_PIXELS:
default:
cfb_imageblit(info, image);
break;
}
}
void vga_imageblit_color(struct fb_info *info, struct fb_image *image)
{
/*
* Draw logo
*/
struct vga16fb_par *par = (struct vga16fb_par *) info->par;
char *where = info->screen_base + image->dy * info->fix.line_length +
image->dx/8;
char *cdat = image->data, *dst;
int x, y;
switch (info->fix.type) {
case FB_TYPE_VGA_PLANES:
if (info->fix.type_aux == FB_AUX_VGA_PLANES_VGA4 &&
par->isVGA) {
setsr(0xf);
setop(0);
setmode(0);
for (y = 0; y < image->height; y++) {
for (x = 0; x < image->width; x++) {
dst = where + x/8;
setcolor(*cdat);
selectmask();
setmask(1 << (7 - (x % 8)));
fb_readb(dst);
fb_writeb(0, dst);
cdat++;
}
where += info->fix.line_length;
}
}
break;
case FB_TYPE_PACKED_PIXELS:
cfb_imageblit(info, image);
break;
default:
break;
}
}
void vga16fb_imageblit(struct fb_info *info, struct fb_image *image)
{
if (image->depth == 1)
vga_imageblit_expand(info, image);
else if (image->depth == info->var.bits_per_pixel)
vga_imageblit_color(info, image);
}
static struct fb_ops vga16fb_ops = {
......@@ -1298,6 +1354,7 @@ static struct fb_ops vga16fb_ops = {
.fb_fillrect = vga16fb_fillrect,
.fb_copyarea = vga16fb_copyarea,
.fb_imageblit = vga16fb_imageblit,
.fb_cursor = soft_cursor,
};
int vga16fb_setup(char *options)
......@@ -1349,6 +1406,11 @@ int __init vga16fb_init(void)
i = (vga16fb_defined.bits_per_pixel == 8) ? 256 : 16;
fb_alloc_cmap(&vga16fb.cmap, i, 0);
if (vga16fb_check_var(&vga16fb.var, &vga16fb))
return -EINVAL;
vga16fb_update_fix(&vga16fb);
if (register_framebuffer(&vga16fb) < 0) {
iounmap(vga16fb.screen_base);
return -EINVAL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment