13 #include <linux/module.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
23 #include <linux/screen_info.h>
28 #define VGA_FB_PHYS 0xA0000
29 #define VGA_FB_PHYS_LEN 65536
97 .line_length = 640 / 8,
112 static inline void rmw(
volatile char __iomem *
p)
130 static inline int selectmask(
void)
137 static inline void setmask(
int mask)
145 static inline int setop(
int op)
156 static inline int setsr(
int sr)
166 static inline int setcolor(
int color)
176 static inline int getindex(
void)
182 static inline void setindex(
int index)
194 if (info->
var.bits_per_pixel == 8) {
195 pos = (info->
var.xres_virtual * var->
yoffset + xoffset) >> 2;
198 pos = (info->
var.xres_virtual * (var->
yoffset / fh) + xoffset) >> 3;
200 if (info->
var.nonstd)
202 pos = (info->
var.xres_virtual * var->
yoffset + xoffset) >> 3;
210 if (info->
var.bits_per_pixel == 8)
218 static void vga16fb_update_fix(
struct fb_info *info)
220 if (info->
var.bits_per_pixel == 4) {
221 if (info->
var.nonstd) {
223 info->
fix.line_length = info->
var.xres_virtual / 2;
227 info->
fix.line_length = info->
var.xres_virtual / 8;
229 }
else if (info->
var.bits_per_pixel == 0) {
232 info->
fix.line_length = info->
var.xres_virtual / 4;
234 if (info->
var.nonstd) {
237 info->
fix.line_length = info->
var.xres_virtual / 4;
240 info->
fix.line_length = info->
var.xres_virtual;
245 static void vga16fb_clock_chip(
struct vga16fb_par *par,
246 unsigned int pixclock,
250 static const struct {
254 } *
ptr, *best, vgaclocks[] = {
255 { 79442 , 0x00, 0x08},
256 { 70616 , 0x04, 0x08},
257 { 39721 , 0x00, 0x00},
258 { 35308 , 0x04, 0x00},
262 pixclock = (pixclock * mul) / div;
264 err = pixclock - best->pixclock;
265 if (err < 0) err = -
err;
266 for (
ptr = vgaclocks + 1;
ptr->pixclock;
ptr++) {
269 tmp = pixclock -
ptr->pixclock;
270 if (tmp < 0) tmp = -
tmp;
276 par->
misc |= best->misc;
277 par->
clkdiv = best->seq_clock_mode;
278 pixclock = (best->pixclock *
div) / mul;
281 #define FAIL(X) return -EINVAL
283 static int vga16fb_open(
struct fb_info *info,
int user)
298 static int vga16fb_release(
struct fb_info *info,
int user)
317 u32 yres, lower, vslen, upper, ytotal;
318 u32 vxres, xoffset, vyres, yoffset;
354 xres = (var->
xres + 7) & ~7;
356 xoffset = (var->
xoffset + 7) & ~7;
363 if (xres + xoffset > vxres)
364 xoffset = vxres - xres;
378 xtotal = xres + right + hslen +
left;
380 FAIL(
"xtotal too big");
382 FAIL(
"hslen too big");
383 if (right + hslen + left > 64)
384 FAIL(
"hblank too big");
406 if (vxres * vyres > maxmem) {
407 vyres = maxmem / vxres;
411 if (yoffset + yres > vyres)
412 yoffset = vyres - yres;
426 ytotal = yres + lower + vslen + upper;
437 FAIL(
"ytotal too big");
439 FAIL(
"vslen too big");
442 if (ytotal & 0x100) r7 |= 0x01;
443 if (ytotal & 0x200) r7 |= 0x20;
452 pos = yoffset * vxres + (xoffset >> shift);
478 FAIL(
"vxres too long");
500 vga16fb_clock_chip(par, var->
pixclock, info, 1, 2);
503 vga16fb_clock_chip(par, var->
pixclock, info, 1, 1);
505 var->
red.offset = var->
green.offset = var->
blue.offset =
507 var->
red.length = var->
green.length = var->
blue.length =
508 (par->
isVGA) ? 6 : 2;
518 static int vga16fb_set_par(
struct fb_info *info)
534 else if (par->
mode & MODE_SKIP4)
557 for (i = 0x00; i < 0x10; i++)
591 vga_io_wseq(0x00, 0x01);
599 vga_io_wseq(i, seq[i]);
603 vga_io_wseq(0x00, 0x03);
610 vga_io_wcrt(i, par->
crtc[i]);
615 vga_io_wgfx(i, gdc[i]);
621 vga_io_wattr(i, atc[i]);
632 vga16fb_update_fix(info);
636 static void ega16_setpalette(
int regno,
unsigned red,
unsigned green,
unsigned blue)
638 static const unsigned char map[] = { 000, 001, 010, 011 };
643 val = map[red>>14] | ((map[green>>14]) << 1) | ((map[blue>>14]) << 2);
645 vga_io_wattr(regno, val);
650 static void vga16_setpalette(
int regno,
unsigned red,
unsigned green,
unsigned blue)
658 static int vga16fb_setcolreg(
unsigned regno,
unsigned red,
unsigned green,
659 unsigned blue,
unsigned transp,
675 gray = info->
var.grayscale;
679 red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
682 vga16_setpalette(regno,red,green,blue);
684 ega16_setpalette(regno,red,green,blue);
691 vga16fb_pan_var(info, var);
700 static void vga_vesa_blank(
struct vga16fb_par *par,
int mode)
710 par->
vga_state.HorizontalTotal = vga_io_rcrt(0x00);
711 par->
vga_state.HorizDisplayEnd = vga_io_rcrt(0x01);
712 par->
vga_state.StartHorizRetrace = vga_io_rcrt(0x04);
713 par->
vga_state.EndHorizRetrace = vga_io_rcrt(0x05);
714 par->
vga_state.Overflow = vga_io_rcrt(0x07);
715 par->
vga_state.StartVertRetrace = vga_io_rcrt(0x10);
716 par->
vga_state.EndVertRetrace = vga_io_rcrt(0x11);
717 par->
vga_state.ModeControl = vga_io_rcrt(0x17);
718 par->
vga_state.ClockingMode = vga_io_rseq(0x01);
723 vga_io_wseq(0x01, par->
vga_state.ClockingMode | 0x20);
726 if ((par->
vga_state.CrtMiscIO & 0x80) == 0x80)
756 static void vga_vesa_unblank(
struct vga16fb_par *par)
758 unsigned char SeqCtrlIndex = vga_io_r(
VGA_SEQ_I);
759 unsigned char CrtCtrlIndex = vga_io_r(
VGA_CRT_IC);
765 vga_io_wcrt(0x00, par->
vga_state.HorizontalTotal);
767 vga_io_wcrt(0x01, par->
vga_state.HorizDisplayEnd);
769 vga_io_wcrt(0x04, par->
vga_state.StartHorizRetrace);
771 vga_io_wcrt(0x05, par->
vga_state.EndHorizRetrace);
773 vga_io_wcrt(0x07, par->
vga_state.Overflow);
775 vga_io_wcrt(0x10, par->
vga_state.StartVertRetrace);
777 vga_io_wcrt(0x11, par->
vga_state.EndVertRetrace);
779 vga_io_wcrt(0x17, par->
vga_state.ModeControl);
781 vga_io_wseq(0x01, par->
vga_state.ClockingMode);
788 static void vga_pal_blank(
void)
792 for (i=0; i<16; i++) {
801 static int vga16fb_blank(
int blank,
struct fb_info *info)
808 vga_vesa_unblank(par);
820 vga_vesa_blank(par, blank);
827 static void vga_8planes_fillrect(
struct fb_info *info,
const struct fb_fillrect *rect)
830 char oldindex = getindex();
832 char oldmask = selectmask();
845 line_ofs = info->
fix.line_length -
width;
854 for (x =
width; x > 0; --
x) {
861 char oldcolor = setcolor(0xf);
867 for (y = 0; y < rect->
height; y++) {
870 where += info->
fix.line_length;
886 vxres = info->
var.xres_virtual;
887 vyres = info->
var.yres_virtual;
889 if (!rect->
width || !rect->
height || rect->
dx > vxres || rect->
dy > vyres)
897 x2 = x2 < vxres ? x2 : vxres;
898 y2 = y2 < vyres ? y2 : vyres;
899 width = x2 - rect->
dx;
901 switch (info->
fix.type) {
905 height = y2 - rect->
dy;
906 width = rect->
width/8;
908 line_ofs = info->
fix.line_length -
width;
916 setcolor(rect->
color);
922 for (x = 0; x <
width; x++) {
938 for (x = 0; x <
width; x++) {
947 vga_8planes_fillrect(info, rect);
956 static void vga_8planes_copyarea(
struct fb_info *info,
const struct fb_copyarea *area)
958 char oldindex = getindex();
960 char oldop = setop(0);
961 char oldsr = setsr(0xf);
971 width = area->
width / 4;
973 if (area->
dy < area->
sy || (area->
dy == area->
sy && dx < sx)) {
974 line_ofs = info->
fix.line_length -
width;
978 for (x = 0; x <
width; x++) {
988 line_ofs = info->
fix.line_length -
width;
990 (area->
dy + height - 1) * info->
fix.line_length;
992 (area->
sy + height - 1) * info->
fix.line_length;
994 for (x = 0; x <
width; x++) {
1013 u32 dx = area->
dx, dy = area->
dy, sx = area->
sx, sy = area->
sy;
1014 int x, x2, y2, old_dx, old_dy, vxres, vyres;
1019 vxres = info->
var.xres_virtual;
1020 vyres = info->
var.yres_virtual;
1022 if (area->
dx > vxres || area->
sx > vxres || area->
dy > vyres ||
1036 dx = area->
dx > 0 ? area->
dx : 0;
1037 dy = area->
dy > 0 ? area->
dy : 0;
1038 x2 = x2 < vxres ? x2 : vxres;
1039 y2 = y2 < vyres ? y2 : vyres;
1043 if (sx + dx < old_dx || sy + dy < old_dy)
1047 sx += (dx - old_dx);
1048 sy += (dy - old_dy);
1051 if (sx + width > vxres || sy + height > vyres)
1054 switch (info->
fix.type) {
1059 line_ofs = info->
fix.line_length -
width;
1065 if (dy < sy || (dy == sy && dx < sx)) {
1069 for (x = 0; x <
width; x++) {
1080 (dy + height - 1) * info->
fix.line_length;
1082 (sy + height - 1) * info->
fix.line_length;
1084 for (x = 0; x <
width; x++) {
1095 vga_8planes_copyarea(info, area);
1104 #define TRANS_MASK_LOW {0x0,0x8,0x4,0xC,0x2,0xA,0x6,0xE,0x1,0x9,0x5,0xD,0x3,0xB,0x7,0xF}
1105 #define TRANS_MASK_HIGH {0x000, 0x800, 0x400, 0xC00, 0x200, 0xA00, 0x600, 0xE00, \
1106 0x100, 0x900, 0x500, 0xD00, 0x300, 0xB00, 0x700, 0xF00}
1108 #if defined(__LITTLE_ENDIAN)
1111 #elif defined(__BIG_ENDIAN)
1115 #error "Only __BIG_ENDIAN and __LITTLE_ENDIAN are supported in vga-planes"
1120 char oldindex = getindex();
1122 char oldop = setop(0);
1123 char oldsr = setsr(0);
1124 char oldmask = selectmask();
1125 const char *cdat = image->
data;
1140 for (y = 0; y < image->
height; y++, where += info->
fix.line_length)
1141 writew(transl_h[cdat[y]&0xF] | transl_l[cdat[y] >> 4], where);
1152 image->
dy * info->
fix.line_length;
1154 char *cdat = (
char *) image->
data;
1158 switch (info->
fix.type) {
1174 for (y = 0; y < image->
height; y++) {
1176 for (x = image->
width/8; x--;)
1178 where += info->
fix.line_length;
1189 for (y = 0; y < image->
height; y++) {
1191 for (x=image->
width/8; x--;){
1200 where += info->
fix.line_length;
1204 vga_8planes_imageblit(info, image);
1213 static void vga_imageblit_color(
struct fb_info *info,
const struct fb_image *image)
1222 const char *cdat = image->
data;
1226 switch (info->
fix.type) {
1234 for (y = 0; y < image->
height; y++) {
1235 for (x = 0; x < image->
width; x++) {
1240 setmask(1 << (7 - (x % 8)));
1246 where += info->
fix.line_length;
1258 static void vga16fb_imageblit(
struct fb_info *info,
const struct fb_image *image)
1260 if (image->
depth == 1)
1261 vga_imageblit_expand(info, image);
1263 vga_imageblit_color(info, image);
1266 static void vga16fb_destroy(
struct fb_info *info)
1272 platform_set_drvdata(dev,
NULL);
1276 static struct fb_ops vga16fb_ops = {
1278 .fb_open = vga16fb_open,
1279 .fb_release = vga16fb_release,
1280 .fb_destroy = vga16fb_destroy,
1281 .fb_check_var = vga16fb_check_var,
1282 .fb_set_par = vga16fb_set_par,
1283 .fb_setcolreg = vga16fb_setcolreg,
1284 .fb_pan_display = vga16fb_pan_display,
1285 .fb_blank = vga16fb_blank,
1286 .fb_fillrect = vga16fb_fillrect,
1287 .fb_copyarea = vga16fb_copyarea,
1288 .fb_imageblit = vga16fb_imageblit,
1296 if (!options || !*options)
1299 while ((this_opt =
strsep(&options,
",")) !=
NULL) {
1300 if (!*this_opt)
continue;
1342 i = par->
isVGA? 6 : 2;
1344 vga16fb_defined.red.length =
i;
1345 vga16fb_defined.green.length =
i;
1346 vga16fb_defined.blue.length =
i;
1349 info->
fbops = &vga16fb_ops;
1350 info->
var = vga16fb_defined;
1351 info->
fix = vga16fb_fix;
1353 info->
pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31;
1357 i = (info->
var.bits_per_pixel == 8) ? 256 : 16;
1362 goto err_alloc_cmap;
1365 if (vga16fb_check_var(&info->
var, info)) {
1371 vga16fb_update_fix(info);
1384 platform_set_drvdata(dev, info);
1400 struct fb_info *info = platform_get_drvdata(dev);
1409 .probe = vga16fb_probe,
1418 static int __init vga16fb_init(
void)
1427 vga16fb_setup(option);
1448 static void __exit vga16fb_exit(
void)