diff options
Diffstat (limited to 'drivers/video/fbcon-iplan2p4.c')
-rw-r--r-- | drivers/video/fbcon-iplan2p4.c | 262 |
1 files changed, 101 insertions, 161 deletions
diff --git a/drivers/video/fbcon-iplan2p4.c b/drivers/video/fbcon-iplan2p4.c index e3a10f0ea..b299701c4 100644 --- a/drivers/video/fbcon-iplan2p4.c +++ b/drivers/video/fbcon-iplan2p4.c @@ -14,41 +14,13 @@ #include <linux/tty.h> #include <linux/console.h> #include <linux/string.h> +#include <linux/config.h> #include <linux/fb.h> -#include "fbcon.h" - - -#ifndef __mc68000__ -#error No support for non-m68k yet -#endif - - - /* - * Prototypes - */ - -static int open_iplan2p4(struct display *p); -static void release_iplan2p4(void); -static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, - int height, int width); -static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width); -static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, - int yy, int xx); -static void putcs_iplan2p4(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx); -static void rev_char_iplan2p4(struct display *p, int xx, int yy); - - - /* - * `switch' for the low level operations - */ +#include <asm/byteorder.h> -static struct display_switch dispsw_iplan2p4 = { - open_iplan2p4, release_iplan2p4, bmove_iplan2p4, clear_iplan2p4, - putc_iplan2p4, putcs_iplan2p4, rev_char_iplan2p4 -}; +#include "fbcon.h" +#include "fbcon-iplan2p4.h" /* @@ -60,6 +32,18 @@ static struct display_switch dispsw_iplan2p4 = { #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 CONFIG_OPTIMIZE_060 + 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 the bis of the color in 'color' are @@ -72,15 +56,13 @@ static struct display_switch dispsw_iplan2p4 = { * *(d+6) = (color & 8) ? 0xff : 0; */ -static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr) +static __inline__ void memclear_4p_col(void *d, size_t h, u32 val, int bpr) { -#ifdef __mc68000__ - __asm__ __volatile__ ("1: movepl %4,%0@(0)\n\t" - "addal %5,%0\n\t" - "dbra %1,1b" - : "=a" (d), "=d" (h) - : "0" (d), "1" (h - 1), "d" (val), "r" (bpr)); -#endif /* !m68k */ + u8 *dd = d; + do { + movepl(dd, val); + dd += bpr; + } while (--h); } /* Sets a 4 plane region from 'd', length 'count' bytes, to the color @@ -94,10 +76,10 @@ static __inline__ void memclear_4p_col(void *d, size_t h, u_long val, int bpr) * *(d+6) = *(d+7) = (color & 8) ? 0xff : 0; */ -static __inline__ void memset_even_4p(void *d, size_t count, u_long val1, - u_long val2) +static __inline__ void memset_even_4p(void *d, size_t count, u32 val1, + u32 val2) { - u_long *dd = d; + u32 *dd = d; count /= 8; while (count--) { @@ -110,7 +92,7 @@ static __inline__ void memset_even_4p(void *d, size_t count, u_long val1, static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr) { - u_char *dd = d, *ss = s; + u8 *dd = d, *ss = s; while (h--) { dd[0] = ss[0]; @@ -125,99 +107,59 @@ static __inline__ void memmove_4p_col (void *d, void *s, int h, int bpr) /* This expands a 4 bit color into a long for movepl (4 plane) operations. */ -static __inline__ u_long expand4l(u_char c) +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) { - u_long rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - "lsll #8,%0\n\t" - "lsrb #1,%2\n\t" - "scs %0\n\t" - : "=&d" (rv), "=d" (c) - : "1" (c)); -#endif /* !m68k */ - return(rv); + return four2byte[c]; } + /* This expands a 4 bit color into two longs for two movel operations * (4 planes). */ -static __inline__ void expand4dl(u_char c, u_long *ret1, u_long *ret2) +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) { - u_long rv1, rv2; - -#ifdef __mc68000__ - __asm__ __volatile__ ("lsrb #1,%3\n\t" - "scs %0\n\t" - "extw %0\n\t" - "swap %0\n\t" - "lsrb #1,%3\n\t" - "scs %0\n\t" - "extw %0\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "extw %1\n\t" - "swap %1\n\t" - "lsrb #1,%3\n\t" - "scs %1\n\t" - "extw %1" - : "=&d" (rv1), "=&d" (rv2), "=d" (c) - : "2" (c)); -#endif /* !m68k */ - *ret1 = rv1; - *ret2 = rv2; + *ret1 = two2word[c & 3]; + *ret2 = two2word[c >> 2]; } /* This duplicates a byte 4 times into a long. */ -static __inline__ u_long dup4l(u_char c) +static __inline__ u32 dup4l(u8 c) { - ushort tmp; - ulong rv; - -#ifdef __mc68000__ - __asm__ __volatile__ ("moveb %2,%0\n\t" - "lslw #8,%0\n\t" - "moveb %2,%0\n\t" - "movew %0,%1\n\t" - "swap %0\n\t" - "movew %1,%0" - : "=&d" (rv), "=d" (tmp) - : "d" (c)); -#endif /* !m68k */ - return(rv); + u32 rv; + + rv = c; + rv |= rv << 8; + rv |= rv << 16; + return rv; } -static int open_iplan2p4(struct display *p) +void fbcon_iplan2p4_setup(struct display *p) { - if (p->type != FB_TYPE_INTERLEAVED_PLANES || p->type_aux != 2 || - p->var.bits_per_pixel != 4) - return -EINVAL; - p->next_line = p->var.xres_virtual>>1; p->next_plane = 2; - MOD_INC_USE_COUNT; - return 0; } -static void release_iplan2p4(void) -{ - MOD_DEC_USE_COUNT; -} - -static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) +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 @@ -231,7 +173,7 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, * all movements by memmove_col(). */ - if (sx == 0 && dx == 0 && width == p->next_line/4) { + if (sx == 0 && dx == 0 && width * 4 == p->next_line) { /* Special (but often used) case: Moving whole lines can be *done with memmove() */ @@ -240,8 +182,8 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, p->next_line * height * p->fontheight); } else { int rows, cols; - u_char *src; - u_char *dst; + u8 *src; + u8 *dst; int bytes = p->next_line; int linesize = bytes * p->fontheight; u_int colsize = height * p->fontheight; @@ -320,20 +262,20 @@ static void bmove_iplan2p4(struct display *p, int sy, int sx, int dy, int dx, } } -static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, - int sx, int height, int width) +void fbcon_iplan2p4_clear(struct vc_data *conp, struct display *p, int sy, + int sx, int height, int width) { - ulong offset; - u_char *start; + u32 offset; + u8 *start; int rows; int bytes = p->next_line; int lines = height * p->fontheight; - ulong size; - u_long cval1, cval2, pcval; + u32 size; + u32 cval1, cval2, pcval; expand4dl(attr_bgcol_ec(p,conp), &cval1, &cval2); - if (sx == 0 && width == bytes/4) { + if (sx == 0 && width * 4 == bytes) { offset = sy * bytes * p->fontheight; size = lines * bytes; memset_even_4p(p->screen_base+offset, size, cval1, cval2); @@ -365,14 +307,14 @@ static void clear_iplan2p4(struct vc_data *conp, struct display *p, int sy, } } -static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, - int yy, int xx) +void fbcon_iplan2p4_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) { - u_char *dest; - u_char *cdat; + u8 *dest; + u8 *cdat; int rows; int bytes = p->next_line; - ulong eorx, fgx, bgx, fdx; + u32 eorx, fgx, bgx, fdx; c &= 0xff; @@ -385,22 +327,18 @@ static void putc_iplan2p4(struct vc_data *conp, struct display *p, int c, for(rows = p->fontheight ; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepl(dest, (fdx & eorx) ^ bgx); } } -static void putcs_iplan2p4(struct vc_data *conp, struct display *p, - const char *s, int count, int yy, int xx) +void fbcon_iplan2p4_putcs(struct vc_data *conp, struct display *p, + const char *s, int count, int yy, int xx) { - u_char *dest, *dest0; - u_char *cdat, c; + u8 *dest, *dest0; + u8 *cdat, c; int rows; int bytes; - ulong eorx, fgx, bgx, fdx; + u32 eorx, fgx, bgx, fdx; bytes = p->next_line; dest0 = p->screen_base + yy * p->fontheight * bytes + (xx>>1)*8 + (xx & 1); @@ -421,19 +359,15 @@ static void putcs_iplan2p4(struct vc_data *conp, struct display *p, for(rows = p->fontheight, dest = dest0; rows-- ; dest += bytes) { fdx = dup4l(*cdat++); -#ifdef __mc68000__ - __asm__ __volatile__ ("movepl %1,%0@(0)" - : /* no outputs */ - : "a" (dest), "d" ((fdx & eorx) ^ bgx)); -#endif /* !m68k */ + movepl(dest, (fdx & eorx) ^ bgx); } INC_4P(dest0); } } -static void rev_char_iplan2p4(struct display *p, int xx, int yy) +void fbcon_iplan2p4_revc(struct display *p, int xx, int yy) { - u_char *dest; + u8 *dest; int j; int bytes; @@ -456,18 +390,24 @@ static void rev_char_iplan2p4(struct display *p, int xx, int yy) } -#ifdef MODULE -int init_module(void) -#else -int fbcon_init_iplan2p4(void) -#endif -{ - return(fbcon_register_driver(&dispsw_iplan2p4, 0)); -} + /* + * `switch' for the low level operations + */ -#ifdef MODULE -void cleanup_module(void) -{ - fbcon_unregister_driver(&dispsw_iplan2p4); -} -#endif /* MODULE */ +struct display_switch fbcon_iplan2p4 = { + fbcon_iplan2p4_setup, fbcon_iplan2p4_bmove, fbcon_iplan2p4_clear, + fbcon_iplan2p4_putc, fbcon_iplan2p4_putcs, fbcon_iplan2p4_revc +}; + + + /* + * 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); |