Commit 0dc1531b authored by James Simmons's avatar James Simmons

Moved over fbcon to use the accel api only. This will shrink the code considerably.

parent c83e515d
...@@ -3024,6 +3024,7 @@ EXPORT_SYMBOL(vc_resize); ...@@ -3024,6 +3024,7 @@ EXPORT_SYMBOL(vc_resize);
EXPORT_SYMBOL(fg_console); EXPORT_SYMBOL(fg_console);
EXPORT_SYMBOL(console_blank_hook); EXPORT_SYMBOL(console_blank_hook);
EXPORT_SYMBOL(vt_cons); EXPORT_SYMBOL(vt_cons);
EXPORT_SYMBOL(vc_cons);
#ifndef VT_SINGLE_DRIVER #ifndef VT_SINGLE_DRIVER
EXPORT_SYMBOL(take_over_console); EXPORT_SYMBOL(take_over_console);
EXPORT_SYMBOL(give_up_console); EXPORT_SYMBOL(give_up_console);
......
...@@ -85,7 +85,7 @@ config DUMMY_CONSOLE ...@@ -85,7 +85,7 @@ config DUMMY_CONSOLE
default y default y
config FRAMEBUFFER_CONSOLE config FRAMEBUFFER_CONSOLE
bool "Framebuffer Console support" tristate "Framebuffer Console support"
depends on FB depends on FB
config PCI_CONSOLE config PCI_CONSOLE
...@@ -118,48 +118,6 @@ config FBCON_ADVANCED ...@@ -118,48 +118,6 @@ config FBCON_ADVANCED
If unsure, say N. If unsure, say N.
config FBCON_AFB
tristate "Amiga bitplanes support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default m if !FBCON_ADVANCED && FB_AMIGA=m
default y if !FBCON_ADVANCED && FB_AMIGA=y
help
This is the low level frame buffer console driver for 1 to 8
bitplanes (2 to 256 colors) on Amiga.
config FBCON_ILBM
tristate "Amiga interleaved bitplanes support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default m if !FBCON_ADVANCED && FB_AMIGA=m
default y if !FBCON_ADVANCED && FB_AMIGA=y
help
This is the low level frame buffer console driver for 1 to 8
interleaved bitplanes (2 to 256 colors) on Amiga.
config FBCON_IPLAN2P2
tristate "Atari interleaved bitplanes (2 planes) support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default y if !FBCON_ADVANCED && FB_ATARI
help
This is the low level frame buffer console driver for 2 interleaved
bitplanes (4 colors) on Atari.
config FBCON_IPLAN2P4
tristate "Atari interleaved bitplanes (4 planes) support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default y if !FBCON_ADVANCED && FB_ATARI
help
This is the low level frame buffer console driver for 4 interleaved
bitplanes (16 colors) on Atari.
config FBCON_IPLAN2P8
tristate "Atari interleaved bitplanes (8 planes) support" if FBCON_ADVANCED
depends on FRAMEBUFFER_CONSOLE
default y if !FBCON_ADVANCED && FB_ATARI
help
This is the low level frame buffer console driver for 8 interleaved
bitplanes (256 colors) on Atari.
# Guess what we need # Guess what we need
config FBCON_STI config FBCON_STI
tristate tristate
......
...@@ -5,9 +5,7 @@ ...@@ -5,9 +5,7 @@
# All of the (potential) objects that export symbols. # All of the (potential) objects that export symbols.
# This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'. # This list comes from 'grep -l EXPORT_SYMBOL *.[hc]'.
export-objs := fbcon.o fbcon-accel.o fbcon-afb.o fbcon-ilbm.o \ export-objs := fbcon.o
fbcon-iplan2p2.o fbcon-iplan2p4.o fbcon-iplan2p8.o \
fbcon-hga.o
# Each configuration option enables a list of files. # Each configuration option enables a list of files.
...@@ -17,6 +15,8 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o ...@@ -17,6 +15,8 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o
obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o
obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o
obj-$(CONFIG_MDA_CONSOLE) += mdacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o fonts.o
obj-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o obj-$(CONFIG_FONT_SUN8x16) += font_sun8x16.o
obj-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o obj-$(CONFIG_FONT_SUN12x22) += font_sun12x22.o
...@@ -27,15 +27,8 @@ obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o ...@@ -27,15 +27,8 @@ obj-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o
obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o obj-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o
obj-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o obj-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o
obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o fonts.o fbcon-accel.o
# Generic Low Level Drivers # Generic Low Level Drivers
obj-$(CONFIG_FBCON_AFB) += fbcon-afb.o
obj-$(CONFIG_FBCON_ILBM) += fbcon-ilbm.o
obj-$(CONFIG_FBCON_IPLAN2P2) += fbcon-iplan2p2.o
obj-$(CONFIG_FBCON_IPLAN2P4) += fbcon-iplan2p4.o
obj-$(CONFIG_FBCON_IPLAN2P8) += fbcon-iplan2p8.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
# Files generated that shall be removed upon make clean # Files generated that shall be removed upon make clean
......
/*
* linux/drivers/video/fbcon-accel.c -- Framebuffer accel console wrapper
*
* Created 20 Feb 2001 by James Simmons <jsimmons@users.sf.net>
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include "fbcon.h"
#include "fbcon-accel.h"
void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct fb_info *info = p->fb_info;
struct vc_data *vc = p->conp;
struct fb_copyarea area;
area.sx = sx * vc->vc_font.width;
area.sy = sy * vc->vc_font.height;
area.dx = dx * vc->vc_font.width;
area.dy = dy * vc->vc_font.height;
area.height = height * vc->vc_font.height;
area.width = width * vc->vc_font.width;
info->fbops->fb_copyarea(info, &area);
}
void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy,
int sx, int height, int width)
{
struct fb_info *info = p->fb_info;
struct fb_fillrect region;
region.color = attr_bgcol_ec(p, vc);
region.dx = sx * vc->vc_font.width;
region.dy = sy * vc->vc_font.height;
region.width = width * vc->vc_font.width;
region.height = height * vc->vc_font.height;
region.rop = ROP_COPY;
info->fbops->fb_fillrect(info, &region);
}
void fbcon_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);
struct fb_image image;
u16 c = scr_readw(s);
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;
info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width;
}
}
void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
int bottom_only)
{
struct fb_info *info = p->fb_info;
unsigned int cw = vc->vc_font.width;
unsigned int ch = vc->vc_font.height;
unsigned int rw = info->var.xres % cw;
unsigned int bh = info->var.yres % ch;
unsigned int rs = info->var.xres - rw;
unsigned int bs = info->var.yres - bh;
struct fb_fillrect region;
region.color = attr_bgcol_ec(p, vc);
region.rop = ROP_COPY;
if (rw && !bottom_only) {
region.dx = info->var.xoffset + rs;
region.dy = 0;
region.width = rw;
region.height = info->var.yres_virtual;
info->fbops->fb_fillrect(info, &region);
}
if (bh) {
region.dx = info->var.xoffset;
region.dy = info->var.yoffset + bs;
region.width = rs;
region.height = bh;
info->fbops->fb_fillrect(info, &region);
}
}
void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
{
static char mask[64], image[64], *dest;
struct vc_data *vc = p->conp;
static int fgcolor, bgcolor, shape, width, height;
struct fb_info *info = p->fb_info;
struct fb_cursor cursor;
int c;
char *font;
cursor.set = FB_CUR_SETPOS;
if (width != vc->vc_font.width || height != vc->vc_font.height) {
width = vc->vc_font.width;
height = vc->vc_font.height;
cursor.set |= FB_CUR_SETSIZE;
}
if ((vc->vc_cursor_type & 0x0f) != shape) {
shape = vc->vc_cursor_type & 0x0f;
cursor.set |= FB_CUR_SETSHAPE;
}
c = scr_readw((u16 *) vc->vc_pos);
if (fgcolor != (int) attr_fgcol(p, c) ||
bgcolor != (int) attr_bgcol(p, c)) {
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) {
dest = font;
cursor.set |= FB_CUR_SETDEST;
}
if (flags & FB_CUR_SETCUR)
cursor.enable = 1;
else
cursor.enable = 0;
if (cursor.set & FB_CUR_SETSIZE) {
memset(image, 0xff, 64);
cursor.set |= FB_CUR_SETSHAPE;
}
if (cursor.set & FB_CUR_SETSHAPE) {
int w, cur_height, size, i = 0;
w = (width + 7) / 8;
switch (shape) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = height / 3;
break;
case CUR_LOWER_HALF:
cur_height = height / 2;
break;
case CUR_TWO_THIRDS:
cur_height = (height * 2) / 3;
break;
case CUR_BLOCK:
default:
cur_height = height;
break;
}
size = (height - cur_height) * w;
while (size--)
mask[i++] = 0;
size = cur_height * w;
while (size--)
mask[i++] = 0xff;
}
cursor.image.width = width;
cursor.image.height = height;
cursor.image.dx = xx * width;
cursor.image.dy = yy * height;
cursor.image.depth = 1;
cursor.image.data = image;
cursor.mask = mask;
cursor.dest = dest;
cursor.rop = ROP_XOR;
if (info->fbops->fb_cursor)
info->fbops->fb_cursor(info, &cursor);
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_accel = {
.bmove = fbcon_accel_bmove,
.clear = fbcon_accel_clear,
.putcs = fbcon_accel_putcs,
.clear_margins = fbcon_accel_clear_margins,
.cursor = fbcon_accel_cursor,
.fontwidthmask = FONTWIDTHRANGE(1, 16)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{
}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_accel);
EXPORT_SYMBOL(fbcon_accel_bmove);
EXPORT_SYMBOL(fbcon_accel_clear);
EXPORT_SYMBOL(fbcon_accel_putcs);
EXPORT_SYMBOL(fbcon_accel_clear_margins);
/*
* FBcon low-level driver that is a wrapper for the accel engine.
*/
#ifndef _VIDEO_FBCON_ACCEL_H
#define _VIDEO_FBCON_ACCEL_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_ACCEL) || defined(CONFIG_FBCON_ACCEL_MODULE)
#define FBCON_HAS_ACCEL
#endif
#else
#if defined(CONFIG_FBCON_ACCEL)
#define FBCON_HAS_ACCEL
#endif
#endif
extern struct display_switch fbcon_accel;
extern void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width);
extern void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy,
int sx, int height, int width);
extern void fbcon_accel_putc(struct vc_data *vc, struct display *p, int c,
int yy, int xx);
extern void fbcon_accel_putcs(struct vc_data *vc, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_accel_revc(struct display *p, int xx, int yy);
extern void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
int bottom_only);
#endif /* _VIDEO_FBCON_ACCEL_H */
/*
* linux/drivers/video/afb.c -- Low level frame buffer operations for
* bitplanes la Amiga
*
* Created 5 Apr 1997 by Geert Uytterhoeven
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include "fbcon.h"
#include "fbcon-afb.h"
/*
* Bitplanes la Amiga
*/
static u8 expand_table[1024] = {
/* bg = fg = 0 */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* bg = 0, fg = 1 */
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
/* bg = 1, fg = 0 */
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
0xef, 0xee, 0xed, 0xec, 0xeb, 0xea, 0xe9, 0xe8,
0xe7, 0xe6, 0xe5, 0xe4, 0xe3, 0xe2, 0xe1, 0xe0,
0xdf, 0xde, 0xdd, 0xdc, 0xdb, 0xda, 0xd9, 0xd8,
0xd7, 0xd6, 0xd5, 0xd4, 0xd3, 0xd2, 0xd1, 0xd0,
0xcf, 0xce, 0xcd, 0xcc, 0xcb, 0xca, 0xc9, 0xc8,
0xc7, 0xc6, 0xc5, 0xc4, 0xc3, 0xc2, 0xc1, 0xc0,
0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8,
0xb7, 0xb6, 0xb5, 0xb4, 0xb3, 0xb2, 0xb1, 0xb0,
0xaf, 0xae, 0xad, 0xac, 0xab, 0xaa, 0xa9, 0xa8,
0xa7, 0xa6, 0xa5, 0xa4, 0xa3, 0xa2, 0xa1, 0xa0,
0x9f, 0x9e, 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98,
0x97, 0x96, 0x95, 0x94, 0x93, 0x92, 0x91, 0x90,
0x8f, 0x8e, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88,
0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81, 0x80,
0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78,
0x77, 0x76, 0x75, 0x74, 0x73, 0x72, 0x71, 0x70,
0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68,
0x67, 0x66, 0x65, 0x64, 0x63, 0x62, 0x61, 0x60,
0x5f, 0x5e, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58,
0x57, 0x56, 0x55, 0x54, 0x53, 0x52, 0x51, 0x50,
0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48,
0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40,
0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38,
0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, 0x30,
0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28,
0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, 0x20,
0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18,
0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10,
0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08,
0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00,
/* bg = fg = 1 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
void fbcon_afb_setup(struct display *p)
{
if (p->fb_info->fix.line_length)
p->next_line = p->fb_info->fix.line_length;
else
p->next_line = p->var.xres_virtual>>3;
p->next_plane = p->var.yres_virtual*p->next_line;
}
void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
u8 *src, *dest, *src0, *dest0;
u_short i, j;
if (sx == 0 && dx == 0 && width == p->next_line) {
src = p->fb_info->screen_base+sy*fontheight(p)*width;
dest = p->fb_info->screen_base+dy*fontheight(p)*width;
i = p->var.bits_per_pixel;
do {
fb_memmove(dest, src, height*fontheight(p)*width);
src += p->next_plane;
dest += p->next_plane;
} while (--i);
} else if (dy <= sy) {
src0 = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
dest0 = p->fb_info->screen_base+dy*fontheight(p)*p->next_line+dx;
i = p->var.bits_per_pixel;
do {
src = src0;
dest = dest0;
j = height*fontheight(p);
do {
fb_memmove(dest, src, width);
src += p->next_line;
dest += p->next_line;
} while (--j);
src0 += p->next_plane;
dest0 += p->next_plane;
} while (--i);
} else {
src0 = p->fb_info->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
dest0 = p->fb_info->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
i = p->var.bits_per_pixel;
do {
src = src0;
dest = dest0;
j = height*fontheight(p);
do {
src -= p->next_line;
dest -= p->next_line;
fb_memmove(dest, src, width);
} while (--j);
src0 += p->next_plane;
dest0 += p->next_plane;
} while (--i);
}
}
void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest, *dest0;
u_short i, j;
int bg;
dest0 = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
bg = attr_bgcol_ec(p,conp);
i = p->var.bits_per_pixel;
do {
dest = dest0;
j = height*fontheight(p);
do {
if (bg & 1)
fb_memset255(dest, width);
else
fb_memclear(dest, width);
dest += p->next_line;
} while (--j);
bg >>= 1;
dest0 += p->next_plane;
} while (--i);
}
void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
u8 *dest, *dest0, *cdat, *cdat0, *expand;
u_short i, j;
int fg, bg;
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
cdat0 = p->fontdata+(c&p->charmask)*fontheight(p);
fg = attr_fgcol(p,c);
bg = attr_bgcol(p,c);
i = p->var.bits_per_pixel;
do {
dest = dest0;
cdat = cdat0;
expand = expand_table;
if (bg & 1)
expand += 512;
if (fg & 1)
expand += 256;
j = fontheight(p);
do {
*dest = expand[*cdat++];
dest += p->next_line;
} while (--j);
bg >>= 1;
fg >>= 1;
dest0 += p->next_plane;
} while (--i);
}
/*
* I've split the console character loop in two parts
* (cfr. fbcon_putcs_ilbm())
*/
void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
u8 *dest, *dest0, *dest1, *expand;
u8 *cdat1, *cdat2, *cdat3, *cdat4, *cdat10, *cdat20, *cdat30, *cdat40;
u_short i, j;
u16 c1, c2, c3, c4;
int fg0, bg0, fg, bg;
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
c1 = scr_readw(s);
fg0 = attr_fgcol(p, c1);
bg0 = attr_bgcol(p, c1);
while (count--)
if (xx&3 || count < 3) { /* Slow version */
c1 = scr_readw(s++) & p->charmask;
dest1 = dest0++;
xx++;
cdat10 = p->fontdata+c1*fontheight(p);
fg = fg0;
bg = bg0;
i = p->var.bits_per_pixel;
do {
dest = dest1;
cdat1 = cdat10;
expand = expand_table;
if (bg & 1)
expand += 512;
if (fg & 1)
expand += 256;
j = fontheight(p);
do {
*dest = expand[*cdat1++];
dest += p->next_line;
} while (--j);
bg >>= 1;
fg >>= 1;
dest1 += p->next_plane;
} while (--i);
} else { /* Fast version */
c1 = scr_readw(&s[0]) & p->charmask;
c2 = scr_readw(&s[1]) & p->charmask;
c3 = scr_readw(&s[2]) & p->charmask;
c4 = scr_readw(&s[3]) & p->charmask;
dest1 = dest0;
cdat10 = p->fontdata+c1*fontheight(p);
cdat20 = p->fontdata+c2*fontheight(p);
cdat30 = p->fontdata+c3*fontheight(p);
cdat40 = p->fontdata+c4*fontheight(p);
fg = fg0;
bg = bg0;
i = p->var.bits_per_pixel;
do {
dest = dest1;
cdat1 = cdat10;
cdat2 = cdat20;
cdat3 = cdat30;
cdat4 = cdat40;
expand = expand_table;
if (bg & 1)
expand += 512;
if (fg & 1)
expand += 256;
j = fontheight(p);
do {
#if defined(__BIG_ENDIAN)
*(u32 *)dest = expand[*cdat1++]<<24 |
expand[*cdat2++]<<16 |
expand[*cdat3++]<<8 |
expand[*cdat4++];
#elif defined(__LITTLE_ENDIAN)
*(u32 *)dest = expand[*cdat1++] |
expand[*cdat2++]<<8 |
expand[*cdat3++]<<16 |
expand[*cdat4++]<<24;
#else
#error FIXME: No endianness??
#endif
dest += p->next_line;
} while (--j);
bg >>= 1;
fg >>= 1;
dest1 += p->next_plane;
} while (--i);
s += 4;
dest0 += 4;
xx += 4;
count -= 3;
}
}
void fbcon_afb_revc(struct display *p, int xx, int yy)
{
u8 *dest, *dest0;
u_short i, j;
int mask;
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
mask = p->fgcol ^ p->bgcol;
/*
* This should really obey the individual character's
* background and foreground colors instead of simply
* inverting.
*/
i = p->var.bits_per_pixel;
do {
if (mask & 1) {
dest = dest0;
j = fontheight(p);
do {
*dest = ~*dest;
dest += p->next_line;
} while (--j);
}
mask >>= 1;
dest0 += p->next_plane;
} while (--i);
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_afb = {
setup: fbcon_afb_setup,
bmove: fbcon_afb_bmove,
clear: fbcon_afb_clear,
putc: fbcon_afb_putc,
putcs: fbcon_afb_putcs,
revc: fbcon_afb_revc,
fontwidthmask: FONTWIDTH(8)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_afb);
EXPORT_SYMBOL(fbcon_afb_setup);
EXPORT_SYMBOL(fbcon_afb_bmove);
EXPORT_SYMBOL(fbcon_afb_clear);
EXPORT_SYMBOL(fbcon_afb_putc);
EXPORT_SYMBOL(fbcon_afb_putcs);
EXPORT_SYMBOL(fbcon_afb_revc);
/*
* FBcon low-level driver for Amiga bitplanes (afb)
*/
#ifndef _VIDEO_FBCON_AFB_H
#define _VIDEO_FBCON_AFB_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_AFB) || defined(CONFIG_FBCON_AFB_MODULE)
#define FBCON_HAS_AFB
#endif
#else
#if defined(CONFIG_FBCON_AFB)
#define FBCON_HAS_AFB
#endif
#endif
extern struct display_switch fbcon_afb;
extern void fbcon_afb_setup(struct display *p);
extern void fbcon_afb_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
extern void fbcon_afb_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
extern void fbcon_afb_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx);
extern void fbcon_afb_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_afb_revc(struct display *p, int xx, int yy);
#endif
/*
* linux/drivers/video/ilbm.c -- Low level frame buffer operations for
* interleaved bitplanes la Amiga
*
* Created 5 Apr 1997 by Geert Uytterhoeven
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include "fbcon.h"
#include "fbcon-ilbm.h"
/*
* Interleaved bitplanes la Amiga
*
* This code heavily relies on the fact that
*
* next_line == interleave == next_plane*bits_per_pixel
*
* But maybe it can be merged with the code for normal bitplanes without
* much performance loss?
*/
void fbcon_ilbm_setup(struct display *p)
{
if (p->fb_info->fix.line_length) {
p->next_line = p->fb_info->fix.line_length*p->var.bits_per_pixel;
p->next_plane = p->fb_info->fix.line_length;
} else {
p->next_line = p->fb_info->fix.type_aux;
p->next_plane = p->fb_info->fix.type_aux/p->var.bits_per_pixel;
}
}
void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
if (sx == 0 && dx == 0 && width == p->next_plane)
fb_memmove(p->fb_info->screen_base+dy*fontheight(p)*p->next_line,
p->fb_info->screen_base+sy*fontheight(p)*p->next_line,
height*fontheight(p)*p->next_line);
else {
u8 *src, *dest;
u_int i;
if (dy <= sy) {
src = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
dest = p->fb_info->screen_base+dy*fontheight(p)*p->next_line+dx;
for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
fb_memmove(dest, src, width);
src += p->next_plane;
dest += p->next_plane;
}
} else {
src = p->fb_info->screen_base+(sy+height)*fontheight(p)*p->next_line+sx;
dest = p->fb_info->screen_base+(dy+height)*fontheight(p)*p->next_line+dx;
for (i = p->var.bits_per_pixel*height*fontheight(p); i--;) {
src -= p->next_plane;
dest -= p->next_plane;
fb_memmove(dest, src, width);
}
}
}
}
void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width)
{
u8 *dest;
u_int i, rows;
int bg, bg0;
dest = p->fb_info->screen_base+sy*fontheight(p)*p->next_line+sx;
bg0 = attr_bgcol_ec(p,conp);
for (rows = height*fontheight(p); rows--;) {
bg = bg0;
for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
if (bg & 1)
fb_memset255(dest, width);
else
fb_memclear(dest, width);
bg >>= 1;
}
}
}
void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c, int yy,
int xx)
{
u8 *dest, *cdat;
u_int rows, i;
u8 d;
int fg0, bg0, fg, bg;
dest = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
cdat = p->fontdata+(c&p->charmask)*fontheight(p);
fg0 = attr_fgcol(p,c);
bg0 = attr_bgcol(p,c);
for (rows = fontheight(p); rows--;) {
d = *cdat++;
fg = fg0;
bg = bg0;
for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
if (bg & 1){
if (fg & 1)
*dest = 0xff;
else
*dest = ~d;
}else{
if (fg & 1)
*dest = d;
else
*dest = 0x00;
}
bg >>= 1;
fg >>= 1;
}
}
}
/*
* I've split the console character loop in two parts:
*
* - slow version: this blits one character at a time
*
* - fast version: this blits 4 characters at a time at a longword
* aligned address, to reduce the number of expensive
* Chip RAM accesses.
*
* Experiments on my A4000/040 revealed that this makes a console switch
* on a 640x400 screen with 256 colors about 3 times faster.
*
* -- Geert
*/
void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
u8 *dest0, *dest, *cdat1, *cdat2, *cdat3, *cdat4;
u_int rows, i;
u16 c1, c2, c3, c4;
u32 d;
int fg0, bg0, fg, bg;
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
c1 = scr_readw(s);
fg0 = attr_fgcol(p, c1);
bg0 = attr_bgcol(p, c1);
while (count--)
if (xx&3 || count < 3) { /* Slow version */
c1 = scr_readw(s++) & p->charmask;
dest = dest0++;
xx++;
cdat1 = p->fontdata+c1*fontheight(p);
for (rows = fontheight(p); rows--;) {
d = *cdat1++;
fg = fg0;
bg = bg0;
for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
if (bg & 1){
if (fg & 1)
*dest = 0xff;
else
*dest = ~d;
}else{
if (fg & 1)
*dest = d;
else
*dest = 0x00;
}
bg >>= 1;
fg >>= 1;
}
}
} else { /* Fast version */
c1 = scr_readw(&s[0]) & p->charmask;
c2 = scr_readw(&s[1]) & p->charmask;
c3 = scr_readw(&s[2]) & p->charmask;
c4 = scr_readw(&s[3]) & p->charmask;
dest = dest0;
cdat1 = p->fontdata+c1*fontheight(p);
cdat2 = p->fontdata+c2*fontheight(p);
cdat3 = p->fontdata+c3*fontheight(p);
cdat4 = p->fontdata+c4*fontheight(p);
for (rows = fontheight(p); rows--;) {
#if defined(__BIG_ENDIAN)
d = *cdat1++<<24 | *cdat2++<<16 | *cdat3++<<8 | *cdat4++;
#elif defined(__LITTLE_ENDIAN)
d = *cdat1++ | *cdat2++<<8 | *cdat3++<<16 | *cdat4++<<24;
#else
#error FIXME: No endianness??
#endif
fg = fg0;
bg = bg0;
for (i = p->var.bits_per_pixel; i--; dest += p->next_plane) {
if (bg & 1){
if (fg & 1)
*(u32 *)dest = 0xffffffff;
else
*(u32 *)dest = ~d;
}else{
if (fg & 1)
*(u32 *)dest = d;
else
*(u32 *)dest = 0x00000000;
}
bg >>= 1;
fg >>= 1;
}
}
s += 4;
dest0 += 4;
xx += 4;
count -= 3;
}
}
void fbcon_ilbm_revc(struct display *p, int xx, int yy)
{
u8 *dest, *dest0;
u_int rows, i;
int mask;
dest0 = p->fb_info->screen_base+yy*fontheight(p)*p->next_line+xx;
mask = p->fgcol ^ p->bgcol;
/*
* This should really obey the individual character's
* background and foreground colors instead of simply
* inverting.
*/
for (i = p->var.bits_per_pixel; i--; dest0 += p->next_plane) {
if (mask & 1) {
dest = dest0;
for (rows = fontheight(p); rows--; dest += p->next_line)
*dest = ~*dest;
}
mask >>= 1;
}
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_ilbm = {
setup: fbcon_ilbm_setup,
bmove: fbcon_ilbm_bmove,
clear: fbcon_ilbm_clear,
putc: fbcon_ilbm_putc,
putcs: fbcon_ilbm_putcs,
revc: fbcon_ilbm_revc,
fontwidthmask: FONTWIDTH(8)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_ilbm);
EXPORT_SYMBOL(fbcon_ilbm_setup);
EXPORT_SYMBOL(fbcon_ilbm_bmove);
EXPORT_SYMBOL(fbcon_ilbm_clear);
EXPORT_SYMBOL(fbcon_ilbm_putc);
EXPORT_SYMBOL(fbcon_ilbm_putcs);
EXPORT_SYMBOL(fbcon_ilbm_revc);
/*
* FBcon low-level driver for Amiga interleaved bitplanes (ilbm)
*/
#ifndef _VIDEO_FBCON_ILBM_H
#define _VIDEO_FBCON_ILBM_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_ILBM) || defined(CONFIG_FBCON_ILBM_MODULE)
#define FBCON_HAS_ILBM
#endif
#else
#if defined(CONFIG_FBCON_ILBM)
#define FBCON_HAS_ILBM
#endif
#endif
extern struct display_switch fbcon_ilbm;
extern void fbcon_ilbm_setup(struct display *p);
extern void fbcon_ilbm_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
extern void fbcon_ilbm_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width);
extern void fbcon_ilbm_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx);
extern void fbcon_ilbm_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_ilbm_revc(struct display *p, int xx, int yy);
#endif /* _VIDEO_FBCON_ILBM_H */
/*
* linux/drivers/video/fbcon-iplan2p2.c -- Low level frame buffer operations
* for interleaved bitplanes la Atari (2
* planes, 2 bytes interleave)
*
* Created 5 Apr 1997 by Geert Uytterhoeven
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/byteorder.h>
#ifdef __mc68000__
#include <asm/setup.h>
#endif
#include "fbcon.h"
#include "fbcon-iplan2p2.h"
/*
* Interleaved bitplanes la Atari (2 planes, 2 bytes interleave)
*/
/* Increment/decrement 2 plane addresses */
#define INC_2P(p) do { if (!((long)(++(p)) & 1)) (p) += 2; } while(0)
#define DEC_2P(p) do { if ((long)(--(p)) & 1) (p) -= 2; } while(0)
/* Convert a standard 4 bit color to our 2 bit color assignment:
* If at least two RGB channels are active, the low bit is turned on;
* The intensity bit (b3) is shifted into b1.
*/
static const u8 color_2p[] = { 0, 0, 0, 1, 0, 1, 1, 1, 2, 2, 2, 3, 2, 3, 3, 3 };
#define COLOR_2P(c) color_2p[c]
/* Perform the m68k movepw operation. */
static inline void movepw(u8 *d, u16 val)
{
#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepw %1,%0@(0)" : : "a" (d), "d" (val));
#else
d[0] = (val >> 16) & 0xff;
d[2] = val & 0xff;
#endif
}
/* Sets the bytes in the visible column at d, height h, to the value
* val for a 2 plane screen. The bits of the color in 'color' are
* moved (8 times) to the respective bytes. This means:
*
* for(h times; d += bpr)
* *d = (color & 1) ? 0xff : 0;
* *(d+2) = (color & 2) ? 0xff : 0;
*/
static __inline__ void memclear_2p_col(void *d, size_t h, u16 val, int bpr)
{
u8 *dd = d;
do {
movepw(dd, val);
dd += bpr;
} while (--h);
}
/* Sets a 2 plane region from 'd', length 'count' bytes, to the color
* in val1. 'd' has to be an even address and count must be divisible
* by 8, because only whole words and all planes are accessed. I.e.:
*
* for(count/4 times)
* *d = *(d+1) = (color & 1) ? 0xff : 0;
* *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
*/
static __inline__ void memset_even_2p(void *d, size_t count, u32 val)
{
u32 *dd = d;
count /= 4;
while (count--)
*dd++ = val;
}
/* Copies a 2 plane column from 's', height 'h', to 'd'. */
static __inline__ void memmove_2p_col (void *d, void *s, int h, int bpr)
{
u8 *dd = d, *ss = s;
while (h--) {
dd[0] = ss[0];
dd[2] = ss[2];
dd += bpr;
ss += bpr;
}
}
/* This expands a 2 bit color into a short for movepw (2 plane) operations. */
static const u16 two2byte[] = {
0x0000, 0xff00, 0x00ff, 0xffff
};
static __inline__ u16 expand2w(u8 c)
{
return two2byte[c];
}
/* This expands a 2 bit color into one long for a movel operation
* (2 planes).
*/
static const u32 two2word[] = {
#ifndef __LITTLE_ENDIAN
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
#else
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#endif
};
static __inline__ u32 expand2l(u8 c)
{
return two2word[c];
}
/* This duplicates a byte 2 times into a short. */
static __inline__ u16 dup2w(u8 c)
{
u16 rv;
rv = c;
rv |= c << 8;
return rv;
}
void fbcon_iplan2p2_setup(struct display *p)
{
p->next_line = p->var.xres_virtual>>2;
p->next_plane = 2;
}
void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
/* bmove() has to distinguish two major cases: If both, source and
* destination, start at even addresses or both are at odd
* addresses, just the first odd and last even column (if present)
* require special treatment (memmove_col()). The rest between
* then can be copied by normal operations, because all adjacent
* bytes are affected and are to be stored in the same order.
* The pathological case is when the move should go from an odd
* address to an even or vice versa. Since the bytes in the plane
* words must be assembled in new order, it seems wisest to make
* all movements by memmove_col().
*/
if (sx == 0 && dx == 0 && width * 2 == p->next_line) {
/* Special (but often used) case: Moving whole lines can be
* done with memmove()
*/
fb_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p),
p->fb_info->screen_base + sy * p->next_line * fontheight(p),
p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
int linesize;
u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
if (fontheightlog(p)) {
linesize = bytes << fontheightlog(p);
colsize = height << fontheightlog(p);
} else {
linesize = bytes * fontheight(p);
colsize = height * fontheight(p);
}
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
if (sx & 1) {
memmove_2p_col(dst, src, colsize, bytes);
src += 3;
dst += 3;
--width;
}
if (width > 1) {
for (rows = colsize; rows > 0; --rows) {
fb_memmove(dst, src, (width>>1)*4);
src += bytes;
dst += bytes;
}
}
if (width & 1) {
src -= colsize * bytes;
dst -= colsize * bytes;
memmove_2p_col(dst + (width>>1)*4, src + (width>>1)*4,
colsize, bytes);
}
} else {
if (!((sx+width-1) & 1)) {
src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*4;
dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*4;
memmove_2p_col(dst, src, colsize, bytes);
--width;
}
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
if (width > 1) {
src += colsize * bytes + (sx & 1)*3;
dst += colsize * bytes + (sx & 1)*3;
for(rows = colsize; rows > 0; --rows) {
src -= bytes;
dst -= bytes;
fb_memmove(dst, src, (width>>1)*4);
}
}
if (width & 1)
memmove_2p_col(dst-3, src-3, colsize, bytes);
}
} else {
/* odd->even or even->odd */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
for (cols = width; cols > 0; --cols) {
memmove_2p_col(dst, src, colsize, bytes);
INC_2P(src);
INC_2P(dst);
}
} else {
sx += width-1;
dx += width-1;
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*4 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*4 + (dx & 1);
for(cols = width; cols > 0; --cols) {
memmove_2p_col(dst, src, colsize, bytes);
DEC_2P(src);
DEC_2P(dst);
}
}
}
}
}
void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 offset;
u8 *start;
int rows;
int bytes = p->next_line;
int lines;
u32 size;
u32 cval;
u16 pcval;
cval = expand2l (COLOR_2P (attr_bgcol_ec(p,conp)));
if (fontheightlog(p))
lines = height << fontheightlog(p);
else
lines = height * fontheight(p);
if (sx == 0 && width * 2 == bytes) {
if (fontheightlog(p))
offset = (sy * bytes) << fontheightlog(p);
else
offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_2p(p->fb_info->screen_base+offset, size, cval);
} else {
if (fontheightlog(p))
offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*4 + (sx & 1);
else
offset = sy * bytes * fontheight(p) + (sx>>1)*4 + (sx & 1);
start = p->fb_info->screen_base + offset;
pcval = expand2w(COLOR_2P(attr_bgcol_ec(p,conp)));
/* Clears are split if the region starts at an odd column or
* end at an even column. These extra columns are spread
* across the interleaved planes. All in between can be
* cleared by normal fb_memclear_small(), because both bytes of
* the single plane words are affected.
*/
if (sx & 1) {
memclear_2p_col(start, lines, pcval, bytes);
start += 3;
width--;
}
if (width & 1) {
memclear_2p_col(start + (width>>1)*4, lines, pcval, bytes);
width--;
}
if (width) {
for (rows = lines; rows-- ; start += bytes)
memset_even_2p(start, width*2, cval);
}
}
}
void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u8 *dest;
u8 *cdat;
int rows;
int bytes = p->next_line;
u16 eorx, fgx, bgx, fdx;
if (fontheightlog(p)) {
dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*4 + (xx & 1));
cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
} else {
dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*4 + (xx & 1));
cdat = p->fontdata + (c & p->charmask) * fontheight(p);
}
fgx = expand2w(COLOR_2P(attr_fgcol(p,c)));
bgx = expand2w(COLOR_2P(attr_bgcol(p,c)));
eorx = fgx ^ bgx;
for (rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
movepw(dest, (fdx & eorx) ^ bgx);
}
}
void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
u8 *dest, *dest0;
u8 *cdat;
u16 c;
int rows;
int bytes;
u16 eorx, fgx, bgx, fdx;
bytes = p->next_line;
if (fontheightlog(p))
dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*4 + (xx & 1));
else
dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*4 + (xx & 1));
c = scr_readw(s);
fgx = expand2w(COLOR_2P(attr_fgcol(p, c)));
bgx = expand2w(COLOR_2P(attr_bgcol(p, c)));
eorx = fgx ^ bgx;
while (count--) {
c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
cdat = p->fontdata + c * fontheight(p);
for (rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup2w(*cdat++);
movepw(dest, (fdx & eorx) ^ bgx);
}
INC_2P(dest0);
}
}
void fbcon_iplan2p2_revc(struct display *p, int xx, int yy)
{
u8 *dest;
int j;
int bytes;
if (fontheightlog(p))
dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) + (xx>>1)*4 + (xx & 1));
else
dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) +
(xx>>1)*4 + (xx & 1));
j = fontheight(p);
bytes = p->next_line;
while (j--) {
/* This should really obey the individual character's
* background and foreground colors instead of simply
* inverting.
*/
dest[0] = ~dest[0];
dest[2] = ~dest[2];
dest += bytes;
}
}
void fbcon_iplan2p2_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
u32 offset;
int bytes;
int lines;
u32 cval;
/* No need to handle right margin, cannot occur with fontwidth == 8 */
bytes = p->next_line;
if (fontheightlog(p)) {
lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
} else {
lines = p->var.yres - conp->vc_rows * fontheight(p);
offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
}
if (lines) {
cval = expand2l(COLOR_2P(attr_bgcol_ec(p,conp)));
memset_even_2p(p->fb_info->screen_base+offset, lines * bytes, cval);
}
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_iplan2p2 = {
setup: fbcon_iplan2p2_setup,
bmove: fbcon_iplan2p2_bmove,
clear: fbcon_iplan2p2_clear,
putc: fbcon_iplan2p2_putc,
putcs: fbcon_iplan2p2_putcs,
revc: fbcon_iplan2p2_revc,
clear_margins: fbcon_iplan2p2_clear_margins,
fontwidthmask: FONTWIDTH(8)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_iplan2p2);
EXPORT_SYMBOL(fbcon_iplan2p2_setup);
EXPORT_SYMBOL(fbcon_iplan2p2_bmove);
EXPORT_SYMBOL(fbcon_iplan2p2_clear);
EXPORT_SYMBOL(fbcon_iplan2p2_putc);
EXPORT_SYMBOL(fbcon_iplan2p2_putcs);
EXPORT_SYMBOL(fbcon_iplan2p2_revc);
EXPORT_SYMBOL(fbcon_iplan2p2_clear_margins);
/*
* FBcon low-level driver for Atari interleaved bitplanes (2 planes) (iplan2p2)
*/
#ifndef _VIDEO_FBCON_IPLAN2P2_H
#define _VIDEO_FBCON_IPLAN2P2_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_IPLAN2P2) || defined(CONFIG_FBCON_IPLAN2P2_MODULE)
#define FBCON_HAS_IPLAN2P2
#endif
#else
#if defined(CONFIG_FBCON_IPLAN2P2)
#define FBCON_HAS_IPLAN2P2
#endif
#endif
extern struct display_switch fbcon_iplan2p2;
extern void fbcon_iplan2p2_setup(struct display *p);
extern void fbcon_iplan2p2_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width);
extern void fbcon_iplan2p2_clear(struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width);
extern void fbcon_iplan2p2_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx);
extern void fbcon_iplan2p2_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_iplan2p2_revc(struct display *p, int xx, int yy);
#endif /* _VIDEO_FBCON_IPLAN2P2_H */
/*
* linux/drivers/video/fbcon-iplan2p4.c -- Low level frame buffer operations
* for interleaved bitplanes la Atari (4
* planes, 2 bytes interleave)
*
* Created 5 Apr 1997 by Geert Uytterhoeven
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/byteorder.h>
#ifdef __mc68000__
#include <asm/setup.h>
#endif
#include "fbcon.h"
#include "fbcon-iplan2p4.h"
/*
* Interleaved bitplanes la Atari (4 planes, 2 bytes interleave)
*/
/* Increment/decrement 4 plane addresses */
#define INC_4P(p) do { if (!((long)(++(p)) & 1)) (p) += 6; } while(0)
#define DEC_4P(p) do { if ((long)(--(p)) & 1) (p) -= 6; } while(0)
/* Perform the m68k movepl operation. */
static inline void movepl(u8 *d, u32 val)
{
#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepl %1,%0@(0)" : : "a" (d), "d" (val));
#else
d[0] = (val >> 24) & 0xff;
d[2] = (val >> 16) & 0xff;
d[4] = (val >> 8) & 0xff;
d[6] = val & 0xff;
#endif
}
/* Sets the bytes in the visible column at d, height h, to the value
* val for a 4 plane screen. The bits of the color in 'color' are
* moved (8 times) to the respective bytes. This means:
*
* for(h times; d += bpr)
* *d = (color & 1) ? 0xff : 0;
* *(d+2) = (color & 2) ? 0xff : 0;
* *(d+4) = (color & 4) ? 0xff : 0;
* *(d+6) = (color & 8) ? 0xff : 0;
*/
static __inline__ void memclear_4p_col(void *d, size_t h, u32 val, int bpr)
{
u8 *dd = d;
do {
movepl(dd, val);
dd += bpr;
} while (--h);
}
/* Sets a 4 plane region from 'd', length 'count' bytes, to the color
* in val1/val2. 'd' has to be an even address and count must be divisible
* by 8, because only whole words and all planes are accessed. I.e.:
*
* for(count/8 times)
* *d = *(d+1) = (color & 1) ? 0xff : 0;
* *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
* *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
* *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
*/
static __inline__ void memset_even_4p(void *d, size_t count, u32 val1,
u32 val2)
{
u32 *dd = d;
count /= 8;
while (count--) {
*dd++ = val1;
*dd++ = val2;
}
}
/* Copies a 4 plane column from 's', height 'h', to 'd'. */
static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr)
{
u8 *dd = d, *ss = s;
while (h--) {
dd[0] = ss[0];
dd[2] = ss[2];
dd[4] = ss[4];
dd[6] = ss[6];
dd += bpr;
ss += bpr;
}
}
/* This expands a 4 bit color into a long for movepl (4 plane) operations. */
static const u32 four2byte[] = {
0x00000000, 0xff000000, 0x00ff0000, 0xffff0000,
0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff,
0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff
};
static __inline__ u32 expand4l(u8 c)
{
return four2byte[c];
}
/* This expands a 4 bit color into two longs for two movel operations
* (4 planes).
*/
static const u32 two2word[] = {
#ifndef __LITTLE_ENDIAN
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff,
#else
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff,
#endif
};
static __inline__ void expand4dl(u8 c, u32 *ret1, u32 *ret2)
{
*ret1 = two2word[c & 3];
*ret2 = two2word[c >> 2];
}
/* This duplicates a byte 4 times into a long. */
static __inline__ u32 dup4l(u8 c)
{
u32 rv;
rv = c;
rv |= rv << 8;
rv |= rv << 16;
return rv;
}
void fbcon_iplan2p4_setup(struct display *p)
{
p->next_line = p->var.xres_virtual>>1;
p->next_plane = 2;
}
void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
/* bmove() has to distinguish two major cases: If both, source and
* destination, start at even addresses or both are at odd
* addresses, just the first odd and last even column (if present)
* require special treatment (memmove_col()). The rest between
* then can be copied by normal operations, because all adjacent
* bytes are affected and are to be stored in the same order.
* The pathological case is when the move should go from an odd
* address to an even or vice versa. Since the bytes in the plane
* words must be assembled in new order, it seems wisest to make
* all movements by memmove_col().
*/
if (sx == 0 && dx == 0 && width * 4 == p->next_line) {
/* Special (but often used) case: Moving whole lines can be
*done with memmove()
*/
fb_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p),
p->fb_info->screen_base + sy * p->next_line * fontheight(p),
p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
int linesize;
u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
if (fontheightlog(p)) {
linesize = bytes << fontheightlog(p);
colsize = height << fontheightlog(p);
} else {
linesize = bytes * fontheight(p);
colsize = height * fontheight(p);
}
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
if (sx & 1) {
memmove_4p_col(dst, src, colsize, bytes);
src += 7;
dst += 7;
--width;
}
if (width > 1) {
for(rows = colsize; rows > 0; --rows) {
fb_memmove(dst, src, (width>>1)*8);
src += bytes;
dst += bytes;
}
}
if (width & 1) {
src -= colsize * bytes;
dst -= colsize * bytes;
memmove_4p_col(dst + (width>>1)*8, src + (width>>1)*8,
colsize, bytes);
}
} else {
if (!((sx+width-1) & 1)) {
src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*8;
dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*8;
memmove_4p_col(dst, src, colsize, bytes);
--width;
}
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
if (width > 1) {
src += colsize * bytes + (sx & 1)*7;
dst += colsize * bytes + (sx & 1)*7;
for(rows = colsize; rows > 0; --rows) {
src -= bytes;
dst -= bytes;
fb_memmove(dst, src, (width>>1)*8);
}
}
if (width & 1) {
memmove_4p_col(dst-7, src-7, colsize, bytes);
}
}
} else {
/* odd->even or even->odd */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
for(cols = width; cols > 0; --cols) {
memmove_4p_col(dst, src, colsize, bytes);
INC_4P(src);
INC_4P(dst);
}
} else {
sx += width-1;
dx += width-1;
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*8 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*8 + (dx & 1);
for(cols = width; cols > 0; --cols) {
memmove_4p_col(dst, src, colsize, bytes);
DEC_4P(src);
DEC_4P(dst);
}
}
}
}
}
void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 offset;
u8 *start;
int rows;
int bytes = p->next_line;
int lines;
u32 size;
u32 cval1, cval2, pcval;
expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
if (fontheightlog(p))
lines = height << fontheightlog(p);
else
lines = height * fontheight(p);
if (sx == 0 && width * 4 == bytes) {
if (fontheightlog(p))
offset = (sy * bytes) << fontheightlog(p);
else
offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_4p(p->fb_info->screen_base+offset, size, cval1, cval2);
} else {
if (fontheightlog(p))
offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*8 + (sx & 1);
else
offset = sy * bytes * fontheight(p) + (sx>>1)*8 + (sx & 1);
start = p->fb_info->screen_base + offset;
pcval = expand4l(attr_bgcol_ec(p,conp));
/* Clears are split if the region starts at an odd column or
* end at an even column. These extra columns are spread
* across the interleaved planes. All in between can be
* cleared by normal fb_memclear_small(), because both bytes of
* the single plane words are affected.
*/
if (sx & 1) {
memclear_4p_col(start, lines, pcval, bytes);
start += 7;
width--;
}
if (width & 1) {
memclear_4p_col(start + (width>>1)*8, lines, pcval, bytes);
width--;
}
if (width) {
for(rows = lines; rows-- ; start += bytes)
memset_even_4p(start, width*4, cval1, cval2);
}
}
}
void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u8 *dest;
u8 *cdat;
int rows;
int bytes = p->next_line;
u32 eorx, fgx, bgx, fdx;
if (fontheightlog(p)) {
dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*8 + (xx & 1));
cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
} else {
dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*8 + (xx & 1));
cdat = p->fontdata + (c & p->charmask) * fontheight(p);
}
fgx = expand4l(attr_fgcol(p,c));
bgx = expand4l(attr_bgcol(p,c));
eorx = fgx ^ bgx;
for(rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl(dest, (fdx & eorx) ^ bgx);
}
}
void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
u8 *dest, *dest0;
u8 *cdat;
u16 c;
int rows;
int bytes;
u32 eorx, fgx, bgx, fdx;
bytes = p->next_line;
if (fontheightlog(p))
dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*8 + (xx & 1));
else
dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*8 + (xx & 1));
c = scr_readw(s);
fgx = expand4l(attr_fgcol(p, c));
bgx = expand4l(attr_bgcol(p, c));
eorx = fgx ^ bgx;
while (count--) {
/* I think, unrolling the loops like in the 1 plane case isn't
* practicable here, because the body is much longer for 4
* planes (mostly the dup4l()). I guess, unrolling this would
* need more than 256 bytes and so exceed the instruction
* cache :-(
*/
c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
cdat = p->fontdata + c * fontheight(p);
for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl(dest, (fdx & eorx) ^ bgx);
}
INC_4P(dest0);
}
}
void fbcon_iplan2p4_revc(struct display *p, int xx, int yy)
{
u8 *dest;
int j;
int bytes;
if (fontheightlog(p))
dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
(xx>>1)*8 + (xx & 1));
else
dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) +
(xx>>1)*8 + (xx & 1));
j = fontheight(p);
bytes = p->next_line;
while (j--) {
/* This should really obey the individual character's
* background and foreground colors instead of simply
* inverting.
*/
dest[0] = ~dest[0];
dest[2] = ~dest[2];
dest[4] = ~dest[4];
dest[6] = ~dest[6];
dest += bytes;
}
}
void fbcon_iplan2p4_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
u32 offset;
int bytes;
int lines;
u32 cval1, cval2;
/* No need to handle right margin, cannot occur with fontwidth == 8 */
bytes = p->next_line;
if (fontheightlog(p)) {
lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
} else {
lines = p->var.yres - conp->vc_rows * fontheight(p);
offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
}
if (lines) {
expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2);
memset_even_4p(p->fb_info->screen_base+offset, lines * bytes, cval1, cval2);
}
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_iplan2p4 = {
setup: fbcon_iplan2p4_setup,
bmove: fbcon_iplan2p4_bmove,
clear: fbcon_iplan2p4_clear,
putc: fbcon_iplan2p4_putc,
putcs: fbcon_iplan2p4_putcs,
revc: fbcon_iplan2p4_revc,
clear_margins: fbcon_iplan2p4_clear_margins,
fontwidthmask: FONTWIDTH(8)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_iplan2p4);
EXPORT_SYMBOL(fbcon_iplan2p4_setup);
EXPORT_SYMBOL(fbcon_iplan2p4_bmove);
EXPORT_SYMBOL(fbcon_iplan2p4_clear);
EXPORT_SYMBOL(fbcon_iplan2p4_putc);
EXPORT_SYMBOL(fbcon_iplan2p4_putcs);
EXPORT_SYMBOL(fbcon_iplan2p4_revc);
EXPORT_SYMBOL(fbcon_iplan2p4_clear_margins);
/*
* FBcon low-level driver for Atari interleaved bitplanes (4 planes) (iplan2p4)
*/
#ifndef _VIDEO_FBCON_IPLAN2P4_H
#define _VIDEO_FBCON_IPLAN2P4_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_IPLAN2P4) || defined(CONFIG_FBCON_IPLAN2P4_MODULE)
#define FBCON_HAS_IPLAN2P4
#endif
#else
#if defined(CONFIG_FBCON_IPLAN2P4)
#define FBCON_HAS_IPLAN2P4
#endif
#endif
extern struct display_switch fbcon_iplan2p4;
extern void fbcon_iplan2p4_setup(struct display *p);
extern void fbcon_iplan2p4_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width);
extern void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width);
extern void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx);
extern void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_iplan2p4_revc(struct display *p, int xx, int yy);
#endif /* _VIDEO_FBCON_IPLAN2P4_H */
/*
* linux/drivers/video/iplan2p8.c -- Low level frame buffer operations for
* interleaved bitplanes la Atari (8
* planes, 2 bytes interleave)
*
* Created 5 Apr 1997 by Geert Uytterhoeven
*
* 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 <linux/module.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/byteorder.h>
#ifdef __mc68000__
#include <asm/setup.h>
#endif
#include "fbcon.h"
#include "fbcon-iplan2p8.h"
/*
* Interleaved bitplanes la Atari (8 planes, 2 bytes interleave)
*
* In 8 plane mode, 256 colors would be possible, but only the first
* 16 are used by the console code (the upper 4 bits are
* background/unused). For that, the following functions mask off the
* higher 4 bits of each color.
*/
/* Increment/decrement 8 plane addresses */
#define INC_8P(p) do { if (!((long)(++(p)) & 1)) (p) += 14; } while(0)
#define DEC_8P(p) do { if ((long)(--(p)) & 1) (p) -= 14; } while(0)
/* Perform the m68k movepl operation extended to 64 bits. */
static inline void movepl2(u8 *d, u32 val1, u32 val2)
{
#if defined __mc68000__ && !defined CPU_M68060_ONLY
asm volatile ("movepl %1,%0@(0); movepl %2,%0@(8)"
: : "a" (d), "d" (val1), "d" (val2));
#else
d[0] = (val1 >> 24) & 0xff;
d[2] = (val1 >> 16) & 0xff;
d[4] = (val1 >> 8) & 0xff;
d[6] = val1 & 0xff;
d[8] = (val2 >> 24) & 0xff;
d[10] = (val2 >> 16) & 0xff;
d[12] = (val2 >> 8) & 0xff;
d[14] = val2 & 0xff;
#endif
}
/* Sets the bytes in the visible column at d, height h, to the value
* val1,val2 for a 8 plane screen. The bits of the color in 'color' are
* moved (8 times) to the respective bytes. This means:
*
* for(h times; d += bpr)
* *d = (color & 1) ? 0xff : 0;
* *(d+2) = (color & 2) ? 0xff : 0;
* *(d+4) = (color & 4) ? 0xff : 0;
* *(d+6) = (color & 8) ? 0xff : 0;
* *(d+8) = (color & 16) ? 0xff : 0;
* *(d+10) = (color & 32) ? 0xff : 0;
* *(d+12) = (color & 64) ? 0xff : 0;
* *(d+14) = (color & 128) ? 0xff : 0;
*/
static __inline__ void memclear_8p_col(void *d, size_t h, u32 val1,
u32 val2, int bpr)
{
u8 *dd = d;
do {
movepl2(dd, val1, val2);
dd += bpr;
} while (--h);
}
/* Sets a 8 plane region from 'd', length 'count' bytes, to the color
* val1..val4. 'd' has to be an even address and count must be divisible
* by 16, because only whole words and all planes are accessed. I.e.:
*
* for(count/16 times)
* *d = *(d+1) = (color & 1) ? 0xff : 0;
* *(d+2) = *(d+3) = (color & 2) ? 0xff : 0;
* *(d+4) = *(d+5) = (color & 4) ? 0xff : 0;
* *(d+6) = *(d+7) = (color & 8) ? 0xff : 0;
* *(d+8) = *(d+9) = (color & 16) ? 0xff : 0;
* *(d+10) = *(d+11) = (color & 32) ? 0xff : 0;
* *(d+12) = *(d+13) = (color & 64) ? 0xff : 0;
* *(d+14) = *(d+15) = (color & 128) ? 0xff : 0;
*/
static __inline__ void memset_even_8p(void *d, size_t count, u32 val1,
u32 val2, u32 val3, u32 val4)
{
u32 *dd = d;
count /= 16;
while (count--) {
*dd++ = val1;
*dd++ = val2;
*dd++ = val3;
*dd++ = val4;
}
}
/* Copies a 8 plane column from 's', height 'h', to 'd'. */
static __inline__ void memmove_8p_col (void *d, void *s, int h, int bpr)
{
u8 *dd = d, *ss = s;
while (h--) {
dd[0] = ss[0];
dd[2] = ss[2];
dd[4] = ss[4];
dd[6] = ss[6];
dd[8] = ss[8];
dd[10] = ss[10];
dd[12] = ss[12];
dd[14] = ss[14];
dd += bpr;
ss += bpr;
}
}
/* This expands a 8 bit color into two longs for two movepl (8 plane)
* operations.
*/
static const u32 four2long[] =
{
0x00000000, 0xff000000, 0x00ff0000, 0xffff0000,
0x0000ff00, 0xff00ff00, 0x00ffff00, 0xffffff00,
0x000000ff, 0xff0000ff, 0x00ff00ff, 0xffff00ff,
0x0000ffff, 0xff00ffff, 0x00ffffff, 0xffffffff,
};
static __inline__ void expand8dl(u8 c, u32 *ret1, u32 *ret2)
{
*ret1 = four2long[c & 15];
*ret2 = four2long[c >> 4];
}
/* This expands a 8 bit color into four longs for four movel operations
* (8 planes).
*/
static const u32 two2word[] =
{
#ifndef __LITTLE_ENDIAN
0x00000000, 0xffff0000, 0x0000ffff, 0xffffffff
#else
0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff
#endif
};
static inline void expand8ql(u8 c, u32 *rv1, u32 *rv2, u32 *rv3, u32 *rv4)
{
*rv1 = two2word[c & 4];
*rv2 = two2word[(c >> 2) & 4];
*rv3 = two2word[(c >> 4) & 4];
*rv4 = two2word[c >> 6];
}
/* This duplicates a byte 4 times into a long. */
static __inline__ u32 dup4l(u8 c)
{
u32 rv;
rv = c;
rv |= rv << 8;
rv |= rv << 16;
return rv;
}
void fbcon_iplan2p8_setup(struct display *p)
{
p->next_line = p->var.xres_virtual;
p->next_plane = 2;
}
void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
/* bmove() has to distinguish two major cases: If both, source and
* destination, start at even addresses or both are at odd
* addresses, just the first odd and last even column (if present)
* require special treatment (memmove_col()). The rest between
* then can be copied by normal operations, because all adjacent
* bytes are affected and are to be stored in the same order.
* The pathological case is when the move should go from an odd
* address to an even or vice versa. Since the bytes in the plane
* words must be assembled in new order, it seems wisest to make
* all movements by memmove_col().
*/
if (sx == 0 && dx == 0 && width * 8 == p->next_line) {
/* Special (but often used) case: Moving whole lines can be
* done with memmove()
*/
fast_memmove(p->fb_info->screen_base + dy * p->next_line * fontheight(p),
p->fb_info->screen_base + sy * p->next_line * fontheight(p),
p->next_line * height * fontheight(p));
} else {
int rows, cols;
u8 *src;
u8 *dst;
int bytes = p->next_line;
int linesize;
u_int colsize;
u_int upwards = (dy < sy) || (dy == sy && dx < sx);
if (fontheightlog(p)) {
linesize = bytes << fontheightlog(p);
colsize = height << fontheightlog(p);
} else {
linesize = bytes * fontheight(p);
colsize = height * fontheight(p);
}
if ((sx & 1) == (dx & 1)) {
/* odd->odd or even->even */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
if (sx & 1) {
memmove_8p_col(dst, src, colsize, bytes);
src += 15;
dst += 15;
--width;
}
if (width > 1) {
for(rows = colsize; rows > 0; --rows) {
fast_memmove (dst, src, (width >> 1) * 16);
src += bytes;
dst += bytes;
}
}
if (width & 1) {
src -= colsize * bytes;
dst -= colsize * bytes;
memmove_8p_col(dst + (width>>1)*16, src + (width>>1)*16,
colsize, bytes);
}
} else {
if (!((sx+width-1) & 1)) {
src = p->fb_info->screen_base + sy * linesize + ((sx+width-1)>>1)*16;
dst = p->fb_info->screen_base + dy * linesize + ((dx+width-1)>>1)*16;
memmove_8p_col(dst, src, colsize, bytes);
--width;
}
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
if (width > 1) {
src += colsize * bytes + (sx & 1)*15;
dst += colsize * bytes + (sx & 1)*15;
for(rows = colsize; rows > 0; --rows) {
src -= bytes;
dst -= bytes;
fast_memmove (dst, src, (width>>1)*16);
}
}
if (width & 1)
memmove_8p_col(dst-15, src-15, colsize, bytes);
}
} else {
/* odd->even or even->odd */
if (upwards) {
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
for(cols = width; cols > 0; --cols) {
memmove_8p_col(dst, src, colsize, bytes);
INC_8P(src);
INC_8P(dst);
}
} else {
sx += width-1;
dx += width-1;
src = p->fb_info->screen_base + sy * linesize + (sx>>1)*16 + (sx & 1);
dst = p->fb_info->screen_base + dy * linesize + (dx>>1)*16 + (dx & 1);
for(cols = width; cols > 0; --cols) {
memmove_8p_col(dst, src, colsize, bytes);
DEC_8P(src);
DEC_8P(dst);
}
}
}
}
}
void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p, int sy,
int sx, int height, int width)
{
u32 offset;
u8 *start;
int rows;
int bytes = p->next_line;
int lines;
u32 size;
u32 cval1, cval2, cval3, cval4, pcval1, pcval2;
expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
if (fontheightlog(p))
lines = height << fontheightlog(p);
else
lines = height * fontheight(p);
if (sx == 0 && width * 8 == bytes) {
if (fontheightlog(p))
offset = (sy * bytes) << fontheightlog(p);
else
offset = sy * bytes * fontheight(p);
size = lines * bytes;
memset_even_8p(p->fb_info->screen_base+offset, size, cval1, cval2, cval3, cval4);
} else {
if (fontheightlog(p))
offset = ((sy * bytes) << fontheightlog(p)) + (sx>>1)*16 + (sx & 1);
else
offset = sy * bytes * fontheight(p) + (sx>>1)*16 + (sx & 1);
start = p->fb_info->screen_base + offset;
expand8dl(attr_bgcol_ec(p,conp), &pcval1, &pcval2);
/* Clears are split if the region starts at an odd column or
* end at an even column. These extra columns are spread
* across the interleaved planes. All in between can be
* cleared by normal fb_memclear_small(), because both bytes of
* the single plane words are affected.
*/
if (sx & 1) {
memclear_8p_col(start, lines, pcval1, pcval2, bytes);
start += 7;
width--;
}
if (width & 1) {
memclear_8p_col(start + (width>>1)*16, lines, pcval1,
pcval2, bytes);
width--;
}
if (width)
for(rows = lines; rows-- ; start += bytes)
memset_even_8p(start, width*8, cval1, cval2, cval3, cval4);
}
}
void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx)
{
u8 *dest;
u8 *cdat;
int rows;
int bytes = p->next_line;
u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
if (fontheightlog(p)) {
dest = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*16 + (xx & 1));
cdat = p->fontdata + ((c & p->charmask) << fontheightlog(p));
} else {
dest = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*16 + (xx & 1));
cdat = p->fontdata + (c & p->charmask) * fontheight(p);
}
expand8dl(attr_fgcol(p,c), &fgx1, &fgx2);
expand8dl(attr_bgcol(p,c), &bgx1, &bgx2);
eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
for(rows = fontheight(p) ; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
}
}
void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx)
{
u8 *dest, *dest0;
u8 *cdat;
u16 c;
int rows;
int bytes;
u32 eorx1, eorx2, fgx1, fgx2, bgx1, bgx2, fdx;
bytes = p->next_line;
if (fontheightlog(p))
dest0 = (p->fb_info->screen_base + ((yy * bytes) << fontheightlog(p)) +
(xx>>1)*16 + (xx & 1));
else
dest0 = (p->fb_info->screen_base + yy * bytes * fontheight(p) +
(xx>>1)*16 + (xx & 1));
c = scr_readw(s);
expand8dl(attr_fgcol(p, c), &fgx1, &fgx2);
expand8dl(attr_bgcol(p, c), &bgx1, &bgx2);
eorx1 = fgx1 ^ bgx1; eorx2 = fgx2 ^ bgx2;
while (count--) {
/* I think, unrolling the loops like in the 1 plane case isn't
* practicable here, because the body is much longer for 4
* planes (mostly the dup4l()). I guess, unrolling this would
* need more than 256 bytes and so exceed the instruction
* cache :-(
*/
c = scr_readw(s++) & p->charmask;
if (fontheightlog(p))
cdat = p->fontdata + (c << fontheightlog(p));
else
cdat = p->fontdata + c * fontheight(p);
for(rows = fontheight(p), dest = dest0; rows-- ; dest += bytes) {
fdx = dup4l(*cdat++);
movepl2(dest, (fdx & eorx1) ^ bgx1, (fdx & eorx2) ^ bgx2);
}
INC_8P(dest0);
}
}
void fbcon_iplan2p8_revc(struct display *p, int xx, int yy)
{
u8 *dest;
int j;
int bytes;
if (fontheightlog(p))
dest = (p->fb_info->screen_base + ((yy * p->next_line) << fontheightlog(p)) +
(xx>>1)*16 + (xx & 1));
else
dest = (p->fb_info->screen_base + yy * p->next_line * fontheight(p) +
(xx>>1)*16 + (xx & 1));
j = fontheight(p);
bytes = p->next_line;
while (j--) {
/* This should really obey the individual character's
* background and foreground colors instead of simply
* inverting. For 8 plane mode, only the lower 4 bits of the
* color are inverted, because only these color registers have
* been set up.
*/
dest[0] = ~dest[0];
dest[2] = ~dest[2];
dest[4] = ~dest[4];
dest[6] = ~dest[6];
dest += bytes;
}
}
void fbcon_iplan2p8_clear_margins(struct vc_data *conp, struct display *p,
int bottom_only)
{
u32 offset;
int bytes;
int lines;
u32 cval1, cval2, cval3, cval4;
/* No need to handle right margin, cannot occur with fontwidth == 8 */
bytes = p->next_line;
if (fontheightlog(p)) {
lines = p->var.yres - (conp->vc_rows << fontheightlog(p));
offset = ((p->yscroll + conp->vc_rows) * bytes) << fontheightlog(p);
} else {
lines = p->var.yres - conp->vc_rows * fontheight(p);
offset = (p->yscroll + conp->vc_rows) * bytes * fontheight(p);
}
if (lines) {
expand8ql(attr_bgcol_ec(p,conp), &cval1, &cval2, &cval3, &cval4);
memset_even_8p(p->fb_info->screen_base+offset, lines * bytes,
cval1, cval2, cval3, cval4);
}
}
/*
* `switch' for the low level operations
*/
struct display_switch fbcon_iplan2p8 = {
setup: fbcon_iplan2p8_setup,
bmove: fbcon_iplan2p8_bmove,
clear: fbcon_iplan2p8_clear,
putc: fbcon_iplan2p8_putc,
putcs: fbcon_iplan2p8_putcs,
revc: fbcon_iplan2p8_revc,
clear_margins: fbcon_iplan2p8_clear_margins,
fontwidthmask: FONTWIDTH(8)
};
#ifdef MODULE
MODULE_LICENSE("GPL");
int init_module(void)
{
return 0;
}
void cleanup_module(void)
{}
#endif /* MODULE */
/*
* Visible symbols for modules
*/
EXPORT_SYMBOL(fbcon_iplan2p8);
EXPORT_SYMBOL(fbcon_iplan2p8_setup);
EXPORT_SYMBOL(fbcon_iplan2p8_bmove);
EXPORT_SYMBOL(fbcon_iplan2p8_clear);
EXPORT_SYMBOL(fbcon_iplan2p8_putc);
EXPORT_SYMBOL(fbcon_iplan2p8_putcs);
EXPORT_SYMBOL(fbcon_iplan2p8_revc);
EXPORT_SYMBOL(fbcon_iplan2p8_clear_margins);
/*
* FBcon low-level driver for Atari interleaved bitplanes (8 planes) (iplan2p8)
*/
#ifndef _VIDEO_FBCON_IPLAN2P8_H
#define _VIDEO_FBCON_IPLAN2P8_H
#include <linux/config.h>
#ifdef MODULE
#if defined(CONFIG_FBCON_IPLAN2P8) || defined(CONFIG_FBCON_IPLAN2P8_MODULE)
#define FBCON_HAS_IPLAN2P8
#endif
#else
#if defined(CONFIG_FBCON_IPLAN2P8)
#define FBCON_HAS_IPLAN2P8
#endif
#endif
extern struct display_switch fbcon_iplan2p8;
extern void fbcon_iplan2p8_setup(struct display *p);
extern void fbcon_iplan2p8_bmove(struct display *p, int sy, int sx, int dy,
int dx, int height, int width);
extern void fbcon_iplan2p8_clear(struct vc_data *conp, struct display *p,
int sy, int sx, int height, int width);
extern void fbcon_iplan2p8_putc(struct vc_data *conp, struct display *p, int c,
int yy, int xx);
extern void fbcon_iplan2p8_putcs(struct vc_data *conp, struct display *p,
const unsigned short *s, int count, int yy, int xx);
extern void fbcon_iplan2p8_revc(struct display *p, int xx, int yy);
#endif /* _VIDEO_FBCON_IPLAN2P8_H */
...@@ -138,15 +138,6 @@ static int softback_lines; ...@@ -138,15 +138,6 @@ static int softback_lines;
static void fbcon_free_font(struct display *); static void fbcon_free_font(struct display *);
static int fbcon_set_origin(struct vc_data *); static int fbcon_set_origin(struct vc_data *);
/*
* Emmanuel: fbcon will now use a hardware cursor if the
* low-level driver provides a non-NULL dispsw->cursor pointer,
* in which case the hardware should do blinking, etc.
*
* if dispsw->cursor is NULL, use Atari alike software cursor
*/
static int cursor_drawn; static int cursor_drawn;
#define CURSOR_DRAW_DELAY (1) #define CURSOR_DRAW_DELAY (1)
...@@ -268,12 +259,7 @@ void gen_set_disp(int con, struct fb_info *info) ...@@ -268,12 +259,7 @@ void gen_set_disp(int con, struct fb_info *info)
struct display *display = fb_display + con; struct display *display = fb_display + con;
display->can_soft_blank = info->fbops->fb_blank ? 1 : 0; display->can_soft_blank = info->fbops->fb_blank ? 1 : 0;
#ifdef FBCON_HAS_ACCEL
display->scrollmode = SCROLL_YNOMOVE; display->scrollmode = SCROLL_YNOMOVE;
display->dispsw = &fbcon_accel;
#else
display->dispsw = &fbcon_dummy;
#endif
fbcon_changevar(con); fbcon_changevar(con);
return; return;
} }
...@@ -327,11 +313,201 @@ void set_con2fb_map(int unit, int newidx) ...@@ -327,11 +313,201 @@ void set_con2fb_map(int unit, int newidx)
} }
/* /*
* Low Level Operations * Accelerated handlers.
*/ */
void fbcon_accel_bmove(struct display *p, int sy, int sx, int dy, int dx,
int height, int width)
{
struct fb_info *info = p->fb_info;
struct vc_data *vc = p->conp;
struct fb_copyarea area;
area.sx = sx * vc->vc_font.width;
area.sy = sy * vc->vc_font.height;
area.dx = dx * vc->vc_font.width;
area.dy = dy * vc->vc_font.height;
area.height = height * vc->vc_font.height;
area.width = width * vc->vc_font.height;
info->fbops->fb_copyarea(info, &area);
}
void fbcon_accel_clear(struct vc_data *vc, struct display *p, int sy,
int sx, int height, int width)
{
struct fb_info *info = p->fb_info;
struct fb_fillrect region;
region.color = attr_bgcol_ec(p, vc);
region.dx = sx * vc->vc_font.width;
region.dy = sy * vc->vc_font.height;
region.width = width * vc->vc_font.width;
region.height = height * vc->vc_font.height;
region.rop = ROP_COPY;
info->fbops->fb_fillrect(info, &region);
}
void fbcon_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);
struct fb_image image;
u16 c = scr_readw(s);
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;
info->fbops->fb_imageblit(info, &image);
image.dx += vc->vc_font.width;
}
}
void fbcon_accel_clear_margins(struct vc_data *vc, struct display *p,
int bottom_only)
{
struct fb_info *info = p->fb_info;
unsigned int cw = vc->vc_font.width;
unsigned int ch = vc->vc_font.height;
unsigned int rw = info->var.xres % cw;
unsigned int bh = info->var.yres % ch;
unsigned int rs = info->var.xres - rw;
unsigned int bs = info->var.yres - bh;
struct fb_fillrect region;
region.color = attr_bgcol_ec(p, vc);
region.rop = ROP_COPY;
if (rw & !bottom_only) {
region.dx = info->var.xoffset + rs;
region.dy = 0;
region.width = rw;
region.height = info->var.yres_virtual;
info->fbops->fb_fillrect(info, &region);
}
if (bh) {
region.dx = info->var.xoffset;
region.dy = info->var.yoffset + bs;
region.width = rs;
region.height = bh;
info->fbops->fb_fillrect(info, &region);
}
}
void fbcon_accel_cursor(struct display *p, int flags, int xx, int yy)
{
static char mask[64], image[64], *dest;
struct vc_data *vc = p->conp;
static int fgcolor, bgcolor, shape, width, height;
struct fb_info *info = p->fb_info;
struct fb_cursor cursor;
char *font;
int c;
cursor.set = FB_CUR_SETPOS;
if (width != vc->vc_font.width || height != vc->vc_font.height) {
width = vc->vc_font.width;
height = vc->vc_font.height;
cursor.set |= FB_CUR_SETSIZE;
}
if ((vc->vc_cursor_type & 0x0f) != shape) {
shape = vc->vc_cursor_type & 0x0f;
cursor.set |= FB_CUR_SETSIZE;
}
c = scr_readw((u16 *) vc->vc_pos);
if (fgcolor != (int) attr_fgcol(p, c) ||
bgcolor != (int) attr_bgcol(p, c)) {
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) {
dest = font;
cursor.set |= FB_CUR_SETDEST;
}
if (flags & FB_CUR_SETCUR)
cursor.enable = 1;
else
cursor.enable = 0;
if (cursor.set & FB_CUR_SETSIZE) {
memset(image, 0xff, 64);
cursor.set |= FB_CUR_SETSIZE;
}
struct display_switch fbcon_dummy; if (cursor.set & FB_CUR_SETSHAPE) {
int w, cur_height, size, i = 0;
w = (width + 7) / 8;
switch (shape) {
case CUR_NONE:
cur_height = 0;
break;
case CUR_UNDERLINE:
cur_height = (height < 10) ? 1 : 2;
break;
case CUR_LOWER_THIRD:
cur_height = height/3;
break;
case CUR_LOWER_HALF:
cur_height = height/2;
break;
case CUR_TWO_THIRDS:
cur_height = (height * 2)/3;
break;
case CUR_BLOCK:
default:
cur_height = height;
break;
}
size = (height - cur_height) * w;
while (size--)
mask[i++] = 0;
size = cur_height * w;
while (size--)
mask[i++] = 0xff;
}
cursor.image.width = width;
cursor.image.height = height;
cursor.image.dx = xx * width;
cursor.image.dy = yy * height;
cursor.image.depth = 1;
cursor.image.data = image;
cursor.mask = mask;
cursor.dest = dest;
cursor.rop = ROP_XOR;
if (info->fbops->fb_cursor)
info->fbops->fb_cursor(info, &cursor);
}
/*
* Low Level Operations
*/
/* NOTE: fbcon cannot be __init: it may be called from take_over_console later */ /* NOTE: fbcon cannot be __init: it may be called from take_over_console later */
static const char *fbcon_startup(void) static const char *fbcon_startup(void)
...@@ -502,12 +678,11 @@ static void fbcon_deinit(struct vc_data *vc) ...@@ -502,12 +678,11 @@ static void fbcon_deinit(struct vc_data *vc)
struct display *p = &fb_display[unit]; struct display *p = &fb_display[unit];
fbcon_free_font(p); fbcon_free_font(p);
p->dispsw = &fbcon_dummy;
p->conp = 0; p->conp = 0;
} }
#define fontwidthvalid(p,w) ((p)->dispsw->fontwidthmask & FONTWIDTH(w)) #define fontwidthvalid(p,w) ((p)->fontwidthmask & FONTWIDTH(w))
static int fbcon_changevar(int con) static int fbcon_changevar(int con)
{ {
...@@ -564,7 +739,6 @@ static int fbcon_changevar(int con) ...@@ -564,7 +739,6 @@ static int fbcon_changevar(int con)
printk(KERN_ERR printk(KERN_ERR
"fbcon_set_display: No support for fontwidth %d\n", "fbcon_set_display: No support for fontwidth %d\n",
vc->vc_font.width); vc->vc_font.width);
p->dispsw = &fbcon_dummy;
} }
updatescrollmode(p, vc); updatescrollmode(p, vc);
...@@ -600,18 +774,11 @@ static int fbcon_changevar(int con) ...@@ -600,18 +774,11 @@ static int fbcon_changevar(int con)
p->charmask = 0x1ff; p->charmask = 0x1ff;
} }
if (p->dispsw == &fbcon_dummy)
printk(KERN_WARNING
"fbcon_set_display: type %d (aux %d, depth %d) not "
"supported\n", info->fix.type, info->fix.type_aux,
info->var.bits_per_pixel);
if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows)
vc_resize(con, nr_cols, nr_rows); vc_resize(con, nr_cols, nr_rows);
else if (CON_IS_VISIBLE(vc) && else if (CON_IS_VISIBLE(vc) &&
vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
if (p->dispsw->clear_margins) fbcon_accel_clear_margins(vc, p, 0);
p->dispsw->clear_margins(vc, p, 0);
update_screen(con); update_screen(con);
} }
if (save) { if (save) {
...@@ -716,7 +883,6 @@ static void fbcon_set_display(int con, int init, int logo) ...@@ -716,7 +883,6 @@ static void fbcon_set_display(int con, int init, int logo)
printk(KERN_ERR printk(KERN_ERR
"fbcon_set_display: No support for fontwidth %d\n", "fbcon_set_display: No support for fontwidth %d\n",
vc->vc_font.width); vc->vc_font.width);
p->dispsw = &fbcon_dummy;
} }
updatescrollmode(p, vc); updatescrollmode(p, vc);
...@@ -802,19 +968,12 @@ static void fbcon_set_display(int con, int init, int logo) ...@@ -802,19 +968,12 @@ static void fbcon_set_display(int con, int init, int logo)
p->charmask = 0x1ff; p->charmask = 0x1ff;
} }
if (p->dispsw == &fbcon_dummy)
printk(KERN_WARNING
"fbcon_set_display: type %d (aux %d, depth %d) not "
"supported\n", info->fix.type, info->fix.type_aux,
info->var.bits_per_pixel);
if (!init) { if (!init) {
if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows) if (vc->vc_cols != nr_cols || vc->vc_rows != nr_rows)
vc_resize(con, nr_cols, nr_rows); vc_resize(con, nr_cols, nr_rows);
else if (CON_IS_VISIBLE(vc) && else if (CON_IS_VISIBLE(vc) &&
vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
if (p->dispsw->clear_margins) fbcon_accel_clear_margins(vc, p, 0);
p->dispsw->clear_margins(vc, p, 0);
update_screen(con); update_screen(con);
} }
if (save) { if (save) {
...@@ -911,11 +1070,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, ...@@ -911,11 +1070,11 @@ static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height,
y_break = p->vrows - p->yscroll; y_break = p->vrows - p->yscroll;
if (sy < y_break && sy + height - 1 >= y_break) { if (sy < y_break && sy + height - 1 >= y_break) {
u_int b = y_break - sy; u_int b = y_break - sy;
p->dispsw->clear(vc, p, real_y(p, sy), sx, b, width); fbcon_accel_clear(vc, p, real_y(p, sy), sx, b, width);
p->dispsw->clear(vc, p, real_y(p, sy + b), sx, height - b, fbcon_accel_clear(vc, p, real_y(p, sy + b), sx, height - b,
width); width);
} else } else
p->dispsw->clear(vc, p, real_y(p, sy), sx, height, width); fbcon_accel_clear(vc, p, real_y(p, sy), sx, height, width);
if (redraw_cursor) if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY; vbl_cursor_cnt = CURSOR_DRAW_DELAY;
...@@ -976,7 +1135,7 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s, ...@@ -976,7 +1135,7 @@ static void fbcon_putcs(struct vc_data *vc, const unsigned short *s,
cursor_undrawn(); cursor_undrawn();
redraw_cursor = 1; redraw_cursor = 1;
} }
p->dispsw->putcs(vc, p, s, count, real_y(p, ypos), xpos); fbcon_accel_putcs(vc, p, s, count, real_y(p, ypos), xpos);
if (redraw_cursor) if (redraw_cursor)
vbl_cursor_cnt = CURSOR_DRAW_DELAY; vbl_cursor_cnt = CURSOR_DRAW_DELAY;
} }
...@@ -1004,7 +1163,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ...@@ -1004,7 +1163,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
cursor_on = 0; cursor_on = 0;
if (cursor_drawn) if (cursor_drawn)
p->dispsw->cursor(p, 0, p->cursor_x, fbcon_accel_cursor(p, 0, p->cursor_x,
real_y(p, p->cursor_y)); real_y(p, p->cursor_y));
p->cursor_x = vc->vc_x; p->cursor_x = vc->vc_x;
...@@ -1018,7 +1177,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ...@@ -1018,7 +1177,7 @@ static void fbcon_cursor(struct vc_data *vc, int mode)
case CM_MOVE: case CM_MOVE:
case CM_DRAW: case CM_DRAW:
if (cursor_drawn) if (cursor_drawn)
p->dispsw->cursor(p, FB_CUR_SETCUR, p->cursor_x, fbcon_accel_cursor(p, FB_CUR_SETCUR, p->cursor_x,
real_y(p, p->cursor_y)); real_y(p, p->cursor_y));
vbl_cursor_cnt = CURSOR_DRAW_DELAY; vbl_cursor_cnt = CURSOR_DRAW_DELAY;
cursor_on = 1; cursor_on = 1;
...@@ -1041,7 +1200,7 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp) ...@@ -1041,7 +1200,7 @@ static void fbcon_vbl_handler(int irq, void *dummy, struct pt_regs *fp)
flag = 0; flag = 0;
if (!cursor_drawn) if (!cursor_drawn)
flag = FB_CUR_SETCUR; flag = FB_CUR_SETCUR;
p->dispsw->cursor(p, flag, p->cursor_x, fbcon_accel_cursor(p, flag, p->cursor_x,
real_y(p, p->cursor_y)); real_y(p, p->cursor_y));
cursor_drawn ^= 1; cursor_drawn ^= 1;
vbl_cursor_cnt = cursor_blink_rate; vbl_cursor_cnt = cursor_blink_rate;
...@@ -1110,7 +1269,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc, ...@@ -1110,7 +1269,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc,
p->yscroll += count; p->yscroll += count;
if (p->yscroll > p->vrows - vc->vc_rows) { if (p->yscroll > p->vrows - vc->vc_rows) {
p->dispsw->bmove(p, p->vrows - vc->vc_rows, 0, 0, 0, fbcon_accel_bmove(p, p->vrows - vc->vc_rows, 0, 0, 0,
vc->vc_rows, vc->vc_cols); vc->vc_rows, vc->vc_cols);
p->yscroll -= p->vrows - vc->vc_rows; p->yscroll -= p->vrows - vc->vc_rows;
} }
...@@ -1118,8 +1277,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc, ...@@ -1118,8 +1277,7 @@ static __inline__ void ypan_up(struct display *p, struct vc_data *vc,
info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.yoffset = p->yscroll * vc->vc_font.height;
info->var.vmode &= ~FB_VMODE_YWRAP; info->var.vmode &= ~FB_VMODE_YWRAP;
update_var(vc->vc_num, info); update_var(vc->vc_num, info);
if (p->dispsw->clear_margins) fbcon_accel_clear_margins(vc, p, 1);
p->dispsw->clear_margins(vc, p, 1);
scrollback_max += count; scrollback_max += count;
if (scrollback_max > scrollback_phys_max) if (scrollback_max > scrollback_phys_max)
scrollback_max = scrollback_phys_max; scrollback_max = scrollback_phys_max;
...@@ -1134,7 +1292,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc, ...@@ -1134,7 +1292,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
p->yscroll -= count; p->yscroll -= count;
if (p->yscroll < 0) { if (p->yscroll < 0) {
p->dispsw->bmove(p, 0, 0, p->vrows - vc->vc_rows, 0, fbcon_accel_bmove(p, 0, 0, p->vrows - vc->vc_rows, 0,
vc->vc_rows, vc->vc_cols); vc->vc_rows, vc->vc_cols);
p->yscroll += p->vrows - vc->vc_rows; p->yscroll += p->vrows - vc->vc_rows;
} }
...@@ -1142,8 +1300,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc, ...@@ -1142,8 +1300,7 @@ static __inline__ void ypan_down(struct display *p, struct vc_data *vc,
info->var.yoffset = p->yscroll * vc->vc_font.height; info->var.yoffset = p->yscroll * vc->vc_font.height;
info->var.vmode &= ~FB_VMODE_YWRAP; info->var.vmode &= ~FB_VMODE_YWRAP;
update_var(vc->vc_num, info); update_var(vc->vc_num, info);
if (p->dispsw->clear_margins) fbcon_accel_clear_margins(vc, p, 1);
p->dispsw->clear_margins(vc, p, 1);
scrollback_max -= count; scrollback_max -= count;
if (scrollback_max < 0) if (scrollback_max < 0)
scrollback_max = 0; scrollback_max = 0;
...@@ -1209,7 +1366,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, ...@@ -1209,7 +1366,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
if (attr != (c & 0xff00)) { if (attr != (c & 0xff00)) {
attr = c & 0xff00; attr = c & 0xff00;
if (s > start) { if (s > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
s - start, s - start,
real_y(p, line), real_y(p, line),
x); x);
...@@ -1219,7 +1376,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, ...@@ -1219,7 +1376,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
} }
if (c == scr_readw(d)) { if (c == scr_readw(d)) {
if (s > start) { if (s > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
s - start, s - start,
real_y(p, line), real_y(p, line),
x); x);
...@@ -1234,7 +1391,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p, ...@@ -1234,7 +1391,7 @@ static void fbcon_redraw_softback(struct vc_data *vc, struct display *p,
d++; d++;
} while (s < le); } while (s < le);
if (s > start) if (s > start)
p->dispsw->putcs(vc, p, start, s - start, fbcon_accel_putcs(vc, p, start, s - start,
real_y(p, line), x); real_y(p, line), x);
line++; line++;
if (d == (u16 *) softback_end) if (d == (u16 *) softback_end)
...@@ -1267,7 +1424,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p, ...@@ -1267,7 +1424,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
if (attr != (c & 0xff00)) { if (attr != (c & 0xff00)) {
attr = c & 0xff00; attr = c & 0xff00;
if (s > start) { if (s > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
s - start, s - start,
real_y(p, line), real_y(p, line),
x); x);
...@@ -1277,7 +1434,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p, ...@@ -1277,7 +1434,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
} }
if (c == scr_readw(d)) { if (c == scr_readw(d)) {
if (s > start) { if (s > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
s - start, s - start,
real_y(p, line), real_y(p, line),
x); x);
...@@ -1294,7 +1451,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p, ...@@ -1294,7 +1451,7 @@ static void fbcon_redraw(struct vc_data *vc, struct display *p,
d++; d++;
} while (s < le); } while (s < le);
if (s > start) if (s > start)
p->dispsw->putcs(vc, p, start, s - start, fbcon_accel_putcs(vc, p, start, s - start,
real_y(p, line), x); real_y(p, line), x);
console_conditional_schedule(); console_conditional_schedule();
if (offset > 0) if (offset > 0)
...@@ -1373,7 +1530,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i ...@@ -1373,7 +1530,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i
if (attr != (c & 0xff00)) { if (attr != (c & 0xff00)) {
attr = c & 0xff00; attr = c & 0xff00;
if (d > start) { if (d > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
d - start, dy, x); d - start, dy, x);
x += d - start; x += d - start;
start = d; start = d;
...@@ -1381,7 +1538,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i ...@@ -1381,7 +1538,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 (s >= ls && s < le && c == scr_readw(s)) {
if (d > start) { if (d > start) {
p->dispsw->putcs(vc, p, start, fbcon_accel_putcs(vc, p, start,
d - start, dy, x); d - start, dy, x);
x += d - start + 1; x += d - start + 1;
start = d + 1; start = d + 1;
...@@ -1394,7 +1551,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i ...@@ -1394,7 +1551,7 @@ void fbcon_redraw_bmove(struct vc_data *vc, struct display *p, int sy, int sx, i
d++; d++;
} while (d < le); } while (d < le);
if (d > start) if (d > start)
p->dispsw->putcs(vc, p, start, d - start, dy, x); fbcon_accel_putcs(vc, p, start, d - start, dy, x);
sy++; sy++;
dy++; dy++;
} }
...@@ -1456,9 +1613,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1456,9 +1613,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
goto redraw_up; goto redraw_up;
switch (p->scrollmode & __SCROLL_YMASK) { switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE: case __SCROLL_YMOVE:
p->dispsw->bmove(p, t + count, 0, t, 0, fbcon_accel_bmove(p, t + count, 0, t, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
p->dispsw->clear(vc, p, b - count, 0, count, fbcon_accel_clear(vc, p, b - count, 0, count,
vc->vc_cols); vc->vc_cols);
break; break;
...@@ -1507,7 +1664,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1507,7 +1664,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
redraw_up: redraw_up:
fbcon_redraw(vc, p, t, b - t - count, fbcon_redraw(vc, p, t, b - t - count,
count * vc->vc_cols); count * vc->vc_cols);
p->dispsw->clear(vc, p, real_y(p, b - count), 0, fbcon_accel_clear(vc, p, real_y(p, b - count), 0,
count, vc->vc_cols); count, vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin + scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row * vc->vc_size_row *
...@@ -1523,9 +1680,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1523,9 +1680,9 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
count = vc->vc_rows; count = vc->vc_rows;
switch (p->scrollmode & __SCROLL_YMASK) { switch (p->scrollmode & __SCROLL_YMASK) {
case __SCROLL_YMOVE: case __SCROLL_YMOVE:
p->dispsw->bmove(p, t, 0, t + count, 0, fbcon_accel_bmove(p, t, 0, t + count, 0,
b - t - count, vc->vc_cols); b - t - count, vc->vc_cols);
p->dispsw->clear(vc, p, t, 0, count, vc->vc_cols); fbcon_accel_clear(vc, p, t, 0, count, vc->vc_cols);
break; break;
case __SCROLL_YWRAP: case __SCROLL_YWRAP:
...@@ -1572,7 +1729,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, ...@@ -1572,7 +1729,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir,
redraw_down: redraw_down:
fbcon_redraw(vc, p, b - 1, b - t - count, fbcon_redraw(vc, p, b - 1, b - t - count,
-count * vc->vc_cols); -count * vc->vc_cols);
p->dispsw->clear(vc, p, real_y(p, t), 0, count, fbcon_accel_clear(vc, p, real_y(p, t), 0, count,
vc->vc_cols); vc->vc_cols);
scr_memsetw((unsigned short *) (vc->vc_origin + scr_memsetw((unsigned short *) (vc->vc_origin +
vc->vc_size_row * vc->vc_size_row *
...@@ -1651,7 +1808,7 @@ static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy, ...@@ -1651,7 +1808,7 @@ static void fbcon_bmove_rec(struct display *p, int sy, int sx, int dy,
} }
return; return;
} }
p->dispsw->bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height, fbcon_accel_bmove(p, real_y(p, sy), sx, real_y(p, dy), dx, height,
width); width);
} }
...@@ -1707,8 +1864,8 @@ static int fbcon_switch(struct vc_data *vc) ...@@ -1707,8 +1864,8 @@ static int fbcon_switch(struct vc_data *vc)
update_var(unit, info); update_var(unit, info);
if (p->dispsw->clear_margins && vt_cons[unit]->vc_mode == KD_TEXT) if (vt_cons[unit]->vc_mode == KD_TEXT)
p->dispsw->clear_margins(vc, p, 0); fbcon_accel_clear_margins(vc, p, 0);
if (logo_shown == -2) { if (logo_shown == -2) {
logo_shown = fg_console; logo_shown = fg_console;
fbcon_show_logo(); /* This is protected above by initmem_freed */ fbcon_show_logo(); /* This is protected above by initmem_freed */
...@@ -1742,18 +1899,18 @@ static int fbcon_blank(struct vc_data *vc, int blank) ...@@ -1742,18 +1899,18 @@ static int fbcon_blank(struct vc_data *vc, int blank)
height = vc->vc_rows; height = vc->vc_rows;
y_break = p->vrows - p->yscroll; y_break = p->vrows - p->yscroll;
if (height > y_break) { if (height > y_break) {
p->dispsw->clear(vc, p, fbcon_accel_clear(vc, p,
real_y(p, 0), 0, real_y(p, 0), 0,
y_break, y_break,
vc->vc_cols); vc->vc_cols);
p->dispsw->clear(vc, p, fbcon_accel_clear(vc, p,
real_y(p, real_y(p,
y_break), y_break),
0, 0,
height - y_break, height - y_break,
vc->vc_cols); vc->vc_cols);
} else } else
p->dispsw->clear(vc, p, fbcon_accel_clear(vc, p,
real_y(p, 0), 0, real_y(p, 0), 0,
height, height,
vc->vc_cols); vc->vc_cols);
...@@ -1950,8 +2107,7 @@ static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op, ...@@ -1950,8 +2107,7 @@ static int fbcon_do_set_font(struct vc_data *vc, struct console_font_op *op,
} }
} else if (CON_IS_VISIBLE(vc) } else if (CON_IS_VISIBLE(vc)
&& vt_cons[vc->vc_num]->vc_mode == KD_TEXT) { && vt_cons[vc->vc_num]->vc_mode == KD_TEXT) {
if (p->dispsw->clear_margins) fbcon_accel_clear_margins(vc, p, 0);
p->dispsw->clear_margins(vc, p, 0);
update_screen(vc->vc_num); update_screen(vc->vc_num);
} }
...@@ -2613,22 +2769,18 @@ const struct consw fb_con = { ...@@ -2613,22 +2769,18 @@ const struct consw fb_con = {
.con_getxy = fbcon_getxy, .con_getxy = fbcon_getxy,
}; };
#ifdef MODULE
MODULE_LICENSE("GPL");
/* int init_module(void)
* Dummy Low Level Operations
*/
static void fbcon_dummy_op(void)
{ {
return 0;
} }
#define DUMMY (void *)fbcon_dummy_op void cleanup_module(void)
{
struct display_switch fbcon_dummy = { }
.bmove = DUMMY, #endif
.clear = DUMMY,
.putcs = DUMMY,
};
/* /*
* Visible symbols for modules * Visible symbols for modules
...@@ -2637,7 +2789,6 @@ struct display_switch fbcon_dummy = { ...@@ -2637,7 +2789,6 @@ struct display_switch fbcon_dummy = {
EXPORT_SYMBOL(fb_display); EXPORT_SYMBOL(fb_display);
EXPORT_SYMBOL(fbcon_redraw_bmove); EXPORT_SYMBOL(fbcon_redraw_bmove);
EXPORT_SYMBOL(fbcon_redraw_clear); EXPORT_SYMBOL(fbcon_redraw_clear);
EXPORT_SYMBOL(fbcon_dummy);
EXPORT_SYMBOL(fb_con); EXPORT_SYMBOL(fb_con);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
...@@ -18,28 +18,6 @@ ...@@ -18,28 +18,6 @@
#include <asm/io.h> #include <asm/io.h>
struct display;
/*
* `switch' for the Low Level Operations
*/
struct display_switch {
void (*bmove)(struct display *p, int sy, int sx, int dy, int dx,
int height, int width);
/* for clear, conp may be NULL, which means use a blanking (black) color */
void (*clear)(struct vc_data *conp, struct display *p, int sy, int sx,
int height, int width);
void (*putcs)(struct vc_data *conp, struct display *p, const unsigned short *s,
int count, int yy, int xx);
void (*cursor)(struct display *p, int flags, int xx, int yy);
void (*clear_margins)(struct vc_data *conp, struct display *p,
int bottom_only);
unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */
};
extern struct display_switch fbcon_dummy;
/* /*
* This is the interface between the low-level console driver and the * This is the interface between the low-level console driver and the
* low-level frame buffer device * low-level frame buffer device
...@@ -65,6 +43,7 @@ struct display { ...@@ -65,6 +43,7 @@ struct display {
short yscroll; /* Hardware scrolling */ short yscroll; /* Hardware scrolling */
unsigned char fgshift, bgshift; unsigned char fgshift, bgshift;
unsigned short charmask; /* 0xff or 0x1ff */ unsigned short charmask; /* 0xff or 0x1ff */
unsigned int fontwidthmask; /* 1 at (1 << (width - 1)) if width is supported */
}; };
/* drivers/video/console/fbcon.c */ /* drivers/video/console/fbcon.c */
......
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