Commit 0458af5e authored by James Simmons's avatar James Simmons

Moved VESA framebuffer driver over to new fbdev api

parent 4cc4c697
......@@ -69,7 +69,7 @@ obj-$(CONFIG_FB_RETINAZ3) += retz3fb.o
obj-$(CONFIG_FB_CLGEN) += clgenfb.o
obj-$(CONFIG_FB_S3TRIO) += S3triofb.o
obj-$(CONFIG_FB_TGA) += tgafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o
obj-$(CONFIG_FB_VESA) += vesafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
obj-$(CONFIG_FB_VGA16) += vga16fb.o fbcon-vga-planes.o
obj-$(CONFIG_FB_VIRGE) += virgefb.o
obj-$(CONFIG_FB_G364) += g364fb.o
......@@ -138,6 +138,7 @@ obj-$(CONFIG_FBCON_MFB) += fbcon-mfb.o
obj-$(CONFIG_FBCON_VGA) += fbcon-vga.o
obj-$(CONFIG_FBCON_HGA) += fbcon-hga.o
obj-$(CONFIG_FBCON_STI) += fbcon-sti.o
obj-$(CONFIG_FBCON_ACCEL) += fbcon-accel.o
include $(TOPDIR)/Rules.make
......
/*
* Generic function for frame buffer with packed pixels of any depth.
*
* Copyright (C) June 1999 James Simmons
*
* 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.
*
* NOTES:
*
* This is for cfb packed pixels. Iplan and such are incorporated in the
* drivers that need them.
*
* FIXME
* The code for 24 bit is horrible. It copies byte by byte size instead of
* longs like the other sizes. Needs to be optimized.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/fb.h>
#include <linux/slab.h>
#include <asm/types.h>
#include <asm/io.h>
#include <video/fbcon.h>
void cfb_copyarea(struct fb_info *p, struct fb_copyarea *area)
{
int x2, y2, lineincr, shift, shift_right, shift_left, old_dx, old_dy;
int n, j, linesize = p->fix.line_length, bpl = sizeof(unsigned long);
unsigned long start_index, end_index, start_mask, end_mask, last;
unsigned long *dst = NULL, *src = NULL;
char *src1, *dst1;
int tmp, height;
/* clip the destination */
old_dx = area->dx;
old_dy = area->dy;
/*
* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly.
*/
x2 = area->dx + area->width;
y2 = area->dy + area->height;
area->dx = area->dx > 0 ? area->dx : 0;
area->dy = area->dy > 0 ? area->dy : 0;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
area->width = x2 - area->dx;
area->height = y2 - area->dy;
/* update sx1,sy1 */
area->sx += (area->dx - old_dx);
area->sy += (area->dy - old_dy);
height = area->height;
/* the source must be completely inside the virtual screen */
if (area->sx < 0 || area->sy < 0 ||
(area->sx + area->width) > p->var.xres_virtual ||
(area->sy + area->height) > p->var.yres_virtual)
return;
if (area->dy < area->sy
|| (area->dy == area->sy && area->dx < area->sx)) {
/* start at the top */
src1 = p->screen_base + area->sy * linesize +
((area->sx * p->var.bits_per_pixel) >> 3);
dst1 = p->screen_base + area->dy * linesize +
((area->dx * p->var.bits_per_pixel) >> 3);
lineincr = linesize;
} else {
/* start at the bottom */
src1 = p->screen_base + (area->sy + area->height-1) * linesize
+ (((area->sx + area->width - 1) * p->var.bits_per_pixel) >> 3);
dst1 = p->screen_base + (area->dy + area->height-1) * linesize
+ (((area->dx + area->width - 1) * p->var.bits_per_pixel) >> 3);
lineincr = -linesize;
}
if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) {
int ppw = BITS_PER_LONG / p->var.bits_per_pixel;
int n = ((area->width * p->var.bits_per_pixel) >> 3);
start_index = ((unsigned long) src1 & (bpl - 1));
end_index = ((unsigned long) (src1 + n) & (bpl - 1));
shift = ((unsigned long) dst1 & (bpl - 1)) -
((unsigned long) src1 & (bpl - 1));
start_mask = end_mask = 0;
if (start_index) {
start_mask = -1 >> (start_index << 3);
n -= (bpl - start_index);
}
if (end_index) {
end_mask = -1 << ((bpl - end_index) << 3);
n -= end_index;
}
n = n / bpl;
if (n <= 0) {
if (start_mask) {
if (end_mask)
end_mask &= start_mask;
else
end_mask = start_mask;
start_mask = 0;
}
n = 0;
}
if (shift) {
if (shift > 0) {
/* dest is over to right more */
shift_right =
shift * p->var.bits_per_pixel;
shift_left =
(ppw - shift) * p->var.bits_per_pixel;
} else {
/* source is to the right more */
shift_right =
(ppw + shift) * p->var.bits_per_pixel;
shift_left =
-shift * p->var.bits_per_pixel;
}
/* general case, positive increment */
if (lineincr > 0) {
if (shift < 0)
n++;
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
last = (fb_readl(src) & start_mask);
if (shift > 0)
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
for (j = 0; j < n; j++) {
dst++;
tmp = fb_readl(src);
src++;
fb_writel((last << shift_left) | (tmp >> shift_right), dst);
last = tmp;
src++;
}
fb_writel(fb_readl(dst) | (last << shift_left), dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
} else {
/* general case, negative increment */
if (shift > 0)
n++;
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
last = (fb_readl(src) & end_mask);
if (shift < 0)
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
for (j = 0; j < n; j++) {
dst--;
tmp = fb_readl(src);
src--;
fb_writel((tmp << shift_left) | (last >> shift_right), dst);
last = tmp;
src--;
}
fb_writel(fb_readl(dst) | (last >> shift_right), dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
}
} else {
/* no shift needed */
if (lineincr > 0) {
/* positive increment */
do {
dst = (unsigned long *) (dst1 - start_index);
src = (unsigned long *) (src1 - start_index);
if (start_mask)
fb_writel(fb_readl(src) | start_mask, dst);
for (j = 0; j < n; j++) {
fb_writel(fb_readl(src), dst);
dst++;
src++;
}
if (end_mask)
fb_writel(fb_readl(src) | end_mask, dst);
src1 += lineincr;
dst1 += lineincr;
} while (--height);
} else {
/* negative increment */
do {
dst = (unsigned long *) dst1;
src = (unsigned long *) src1;
if (start_mask)
fb_writel(fb_readl(src) | start_mask, dst);
for (j = 0; j < n; j++) {
fb_writel(fb_readl(src), dst);
dst--;
src--;
}
src1 += lineincr;
dst1 += lineincr;
} while (--height);
}
}
}
}
/*
* Generic fillrect for frame buffers with packed pixels of any depth.
*
* Copyright (C) 2000 James Simmons (jsimmons@linux-fbdev.org)
*
* 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.
*
* NOTES:
*
* The code for depths like 24 that don't have integer number of pixels per
* long is broken and needs to be fixed. For now I turned these types of
* mode off.
*
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
*/
#include <linux/string.h>
#include <linux/fb.h>
#include <asm/types.h>
#include <video/fbcon.h>
void cfb_fillrect(struct fb_info *p, struct fb_fillrect *rect)
{
unsigned long start_index, end_index, start_mask = 0, end_mask = 0;
unsigned long height, ppw, fg, fgcolor;
int i, n, x2, y2, linesize = p->fix.line_length;
int bpl = sizeof(unsigned long);
unsigned long *dst;
char *dst1;
if (!rect->width || !rect->height)
return;
/* We could use hardware clipping but on many cards you get around
* hardware clipping by writing to framebuffer directly. */
x2 = rect->dx + rect->width;
y2 = rect->dy + rect->height;
x2 = x2 < p->var.xres_virtual ? x2 : p->var.xres_virtual;
y2 = y2 < p->var.yres_virtual ? y2 : p->var.yres_virtual;
rect->width = x2 - rect->dx;
height = y2 - rect->dy;
/* Size of the scanline in bytes */
n = (rect->width * (p->var.bits_per_pixel >> 3));
ppw = BITS_PER_LONG / p->var.bits_per_pixel;
dst1 = p->screen_base + (rect->dy * linesize) +
(rect->dx * (p->var.bits_per_pixel >> 3));
start_index = ((unsigned long) dst1 & (bpl - 1));
end_index = ((unsigned long) (dst1 + n) & (bpl - 1));
if (p->fix.visual == FB_VISUAL_TRUECOLOR)
fg = fgcolor = ((u32 *) (p->pseudo_palette))[rect->color];
else
fg = fgcolor = rect->color;
for (i = 0; i < ppw - 1; i++) {
fg <<= p->var.bits_per_pixel;
fg |= fgcolor;
}
if (start_index) {
start_mask = fg << (start_index << 3);
n -= (bpl - start_index);
}
if (end_index) {
end_mask = fg >> ((bpl - end_index) << 3);
n -= end_index;
}
n = n / bpl;
if (n <= 0) {
if (start_mask) {
if (end_mask)
end_mask &= start_mask;
else
end_mask = start_mask;
start_mask = 0;
}
n = 0;
}
if ((BITS_PER_LONG % p->var.bits_per_pixel) == 0) {
switch (rect->rop) {
case ROP_COPY:
do {
/* Word align to increases performace :-) */
dst = (unsigned long *) (dst1 - start_index);
if (start_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) |
start_mask, dst);
#else
fb_writeq(fb_readq(dst) |
start_mask, dst);
#endif
dst++;
}
for (i = 0; i < n; i++) {
#if BITS_PER_LONG == 32
fb_writel(fg, dst);
#else
fb_writeq(fg, dst);
#endif
dst++;
}
if (end_mask)
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) | end_mask,
dst);
#else
fb_writeq(fb_readq(dst) | end_mask,
dst);
#endif
dst1 += linesize;
} while (--height);
break;
case ROP_XOR:
do {
dst = (unsigned long *) (dst1 - start_index);
if (start_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^
start_mask, dst);
#else
fb_writeq(fb_readq(dst) ^
start_mask, dst);
#endif
dst++;
}
for (i = 0; i < n; i++) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^ fg, dst);
#else
fb_writeq(fb_readq(dst) ^ fg, dst);
#endif
dst++;
}
if (end_mask) {
#if BITS_PER_LONG == 32
fb_writel(fb_readl(dst) ^ end_mask,
dst);
#else
fb_writeq(fb_readq(dst) ^ end_mask,
dst);
#endif
}
dst1 += linesize;
} while (--height);
break;
}
} else {
/* Odd modes like 24 or 80 bits per pixel */
start_mask = fg >> (start_index * p->var.bits_per_pixel);
end_mask = fg << (end_index * p->var.bits_per_pixel);
/* start_mask =& PFILL24(x1,fg);
end_mask_or = end_mask & PFILL24(x1+width-1,fg); */
n = (rect->width - start_index - end_index) / ppw;
switch (rect->rop) {
case ROP_COPY:
do {
dst = (unsigned long *) dst1;
if (start_mask)
*dst |= start_mask;
if ((start_index + rect->width) > ppw)
dst++;
/* XXX: slow */
for (i = 0; i < n; i++) {
*dst++ = fg;
}
if (end_mask)
*dst |= end_mask;
dst1 += linesize;
} while (--height);
break;
case ROP_XOR:
do {
dst = (unsigned long *) dst1;
if (start_mask)
*dst ^= start_mask;
if ((start_mask + rect->width) > ppw)
dst++;
for (i = 0; i < n; i++) {
*dst++ ^= fg; /* PFILL24(fg,x1+i); */
}
if (end_mask)
*dst ^= end_mask;
dst1 += linesize;
} while (--height);
break;
}
}
return;
}
This diff is collapsed.
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