57 #include <linux/module.h>
58 #include <linux/kernel.h>
59 #include <linux/errno.h>
60 #include <linux/string.h>
62 #include <linux/slab.h>
65 #include <linux/pci.h>
68 #include <linux/toshiba.h>
73 #include <asm/pgtable.h>
82 #define NEOFB_VERSION "0.4.2"
89 static bool nostretch;
90 static bool nopciburst;
106 "Disable stretching of modes smaller than LCD.");
110 MODULE_PARM_DESC(mode_option,
"Preferred video mode ('640x480-8@60', etc)");
117 static biosMode bios8[] = {
126 static biosMode bios16[] = {
135 static biosMode bios24[] = {
141 #ifdef NO_32BIT_SUPPORT_YET
143 static biosMode
bios32[] = {
150 static inline void write_le32(
int regindex,
u32 val,
const struct neofb_par *par)
152 writel(val, par->neo2200 + par->cursorOff + regindex);
155 static int neoFindMode(
int xres,
int yres,
int depth)
174 #ifdef NO_32BIT_SUPPORT_YET
184 for (i = 0; i <
size; i++) {
185 if (xres <= mode[i].
x_res) {
186 xres_s = mode[
i].x_res;
187 for (; i <
size; i++) {
188 if (mode[i].x_res != xres_s)
189 return mode[i - 1].mode;
190 if (yres <= mode[i].
y_res)
195 return mode[size - 1].mode;
207 static void neoCalcVCLK(
const struct fb_info *
info,
208 struct neofb_par *par,
long freq)
211 int n_best = 0, d_best = 0, f_best = 0;
212 long f_best_diff = 0x7ffff;
214 for (f = 0; f <=
MAX_F; f++)
215 for (d = 0; d <=
MAX_D; d++)
216 for (n = 0; n <=
MAX_N; n++) {
220 f_out = ((14318 * (n + 1)) / (d + 1)) >>
f;
221 f_diff =
abs(f_out - freq);
222 if (f_diff <= f_best_diff) {
223 f_best_diff = f_diff;
238 par->VCLK3NumeratorLow = n_best;
239 par->VCLK3NumeratorHigh = (f_best << 7);
241 par->VCLK3NumeratorLow = n_best | (f_best << 7);
243 par->VCLK3Denominator = d_best;
248 par->VCLK3NumeratorLow,
249 par->VCLK3NumeratorHigh,
250 par->VCLK3Denominator, f_best_diff);
261 struct neofb_par *par)
266 int vsync_end = vsync_start + var->
vsync_len;
269 par->MiscOutReg = 0x23;
272 par->MiscOutReg |= 0x40;
275 par->MiscOutReg |= 0x80;
280 par->Sequencer[0] = 0x00;
281 par->Sequencer[1] = 0x01;
282 par->Sequencer[2] = 0x0F;
283 par->Sequencer[3] = 0x00;
284 par->Sequencer[4] = 0x0E;
289 par->CRTC[0] = htotal - 5;
290 par->CRTC[1] = (var->
xres >> 3) - 1;
291 par->CRTC[2] = (var->
xres >> 3) - 1;
292 par->CRTC[3] = ((htotal - 1) & 0x1F) | 0x80;
294 par->CRTC[5] = (((htotal - 1) & 0x20) << 2)
295 | (((hsync_end >> 3)) & 0x1F);
296 par->CRTC[6] = (vtotal - 2) & 0xFF;
297 par->CRTC[7] = (((vtotal - 2) & 0x100) >> 8)
298 | (((var->
yres - 1) & 0x100) >> 7)
299 | ((vsync_start & 0x100) >> 6)
300 | (((var->
yres - 1) & 0x100) >> 5)
301 | 0x10 | (((vtotal - 2) & 0x200) >> 4)
302 | (((var->
yres - 1) & 0x200) >> 3)
303 | ((vsync_start & 0x200) >> 2);
305 par->CRTC[9] = (((var->
yres - 1) & 0x200) >> 4) | 0x40;
308 par->CRTC[9] |= 0x80;
310 par->CRTC[10] = 0x00;
311 par->CRTC[11] = 0x00;
312 par->CRTC[12] = 0x00;
313 par->CRTC[13] = 0x00;
314 par->CRTC[14] = 0x00;
315 par->CRTC[15] = 0x00;
316 par->CRTC[16] = vsync_start & 0xFF;
317 par->CRTC[17] = (vsync_end & 0x0F) | 0x20;
318 par->CRTC[18] = (var->
yres - 1) & 0xFF;
320 par->CRTC[20] = 0x00;
321 par->CRTC[21] = (var->
yres - 1) & 0xFF;
322 par->CRTC[22] = (vtotal - 1) & 0xFF;
323 par->CRTC[23] = 0xC3;
324 par->CRTC[24] = 0xFF;
335 par->Graphics[0] = 0x00;
336 par->Graphics[1] = 0x00;
337 par->Graphics[2] = 0x00;
338 par->Graphics[3] = 0x00;
339 par->Graphics[4] = 0x00;
340 par->Graphics[5] = 0x40;
341 par->Graphics[6] = 0x05;
342 par->Graphics[7] = 0x0F;
343 par->Graphics[8] = 0xFF;
346 par->Attribute[0] = 0x00;
347 par->Attribute[1] = 0x01;
348 par->Attribute[2] = 0x02;
349 par->Attribute[3] = 0x03;
350 par->Attribute[4] = 0x04;
351 par->Attribute[5] = 0x05;
352 par->Attribute[6] = 0x06;
353 par->Attribute[7] = 0x07;
354 par->Attribute[8] = 0x08;
355 par->Attribute[9] = 0x09;
356 par->Attribute[10] = 0x0A;
357 par->Attribute[11] = 0x0B;
358 par->Attribute[12] = 0x0C;
359 par->Attribute[13] = 0x0D;
360 par->Attribute[14] = 0x0E;
361 par->Attribute[15] = 0x0F;
362 par->Attribute[16] = 0x41;
363 par->Attribute[17] = 0xFF;
364 par->Attribute[18] = 0x0F;
365 par->Attribute[19] = 0x00;
366 par->Attribute[20] = 0x00;
373 vga_wcrt(state->
vgabase, 0x11, vga_rcrt(state->
vgabase, 0x11) | 0x80);
376 static void vgaHWUnlock(
void)
379 vga_wcrt(
NULL, 0x11, vga_rcrt(
NULL, 0x11) & ~0x80);
382 static void neoLock(
struct vgastate *state)
384 vga_wgfx(state->
vgabase, 0x09, 0x00);
388 static void neoUnlock(
void)
391 vga_wgfx(
NULL, 0x09, 0x26);
397 static int paletteEnabled = 0;
399 static inline void VGAenablePalette(
void)
406 static inline void VGAdisablePalette(
void)
421 vga_wattr(
NULL, index, value);
424 static void vgaHWProtect(
int on)
428 tmp = vga_rseq(
NULL, 0x01);
433 vga_wseq(
NULL, 0x00, 0x01);
434 vga_wseq(
NULL, 0x01, tmp | 0x20);
441 vga_wseq(
NULL, 0x01, tmp & ~0x20);
442 vga_wseq(
NULL, 0x00, 0x03);
448 static void vgaHWRestore(
const struct fb_info *
info,
449 const struct neofb_par *par)
455 for (i = 1; i < 5; i++)
456 vga_wseq(
NULL, i, par->Sequencer[i]);
459 vga_wcrt(
NULL, 17, par->CRTC[17] & ~0x80);
461 for (i = 0; i < 25; i++)
462 vga_wcrt(
NULL, i, par->CRTC[i]);
464 for (i = 0; i < 9; i++)
465 vga_wgfx(
NULL, i, par->Graphics[i]);
469 for (i = 0; i < 21; i++)
470 VGAwATTR(i, par->Attribute[i]);
481 static inline int neo2200_sync(
struct fb_info *info)
483 struct neofb_par *par = info->
par;
485 while (
readl(&par->neo2200->bltStat) & 1)
490 static inline void neo2200_wait_fifo(
struct fb_info *info,
491 int requested_fifo_space)
519 static inline void neo2200_accel_init(
struct fb_info *info,
522 struct neofb_par *par = info->
par;
523 Neo2200
__iomem *neo2200 = par->neo2200;
544 "neofb: neo2200_accel_init: unexpected bits per pixel!\n");
548 writel(bltMod << 16, &neo2200->bltStat);
549 writel((pitch << 16) | pitch, &neo2200->pitch);
557 struct neofb_par *par = info->
par;
559 if (!par->ref_count) {
570 neofb_release(
struct fb_info *info,
int user)
572 struct neofb_par *par = info->
par;
577 if (par->ref_count == 1) {
588 struct neofb_par *par = info->
par;
592 DBG(
"neofb_check_var");
598 if (par->internal_display &&
599 ((var->
xres > par->NeoPanelWidth) ||
600 (var->
yres > par->NeoPanelHeight))) {
602 "Mode (%dx%d) larger than the LCD panel (%dx%d)\n",
603 var->
xres, var->
yres, par->NeoPanelWidth,
604 par->NeoPanelHeight);
609 if (!par->internal_display)
614 if (var->
yres == 1024)
618 if (var->
yres == 768)
622 if (var->
yres == (par->libretto ? 480 : 600))
626 if (var->
yres == 480)
634 "Mode (%dx%d) won't display properly on LCD\n",
639 var->
red.msb_right = 0;
640 var->
green.msb_right = 0;
641 var->
blue.msb_right = 0;
642 var->
transp.msb_right = 0;
650 var->
green.offset = 0;
651 var->
green.length = 8;
652 var->
blue.offset = 0;
653 var->
blue.length = 8;
657 var->
red.offset = 11;
659 var->
green.offset = 5;
660 var->
green.length = 6;
661 var->
blue.offset = 0;
662 var->
blue.length = 5;
666 var->
red.offset = 16;
668 var->
green.offset = 8;
669 var->
green.length = 8;
670 var->
blue.offset = 0;
671 var->
blue.length = 8;
674 #ifdef NO_32BIT_SUPPORT_YET
678 var->
red.offset = 16;
680 var->
green.offset = 8;
681 var->
green.length = 8;
682 var->
blue.offset = 0;
683 var->
blue.length = 8;
692 vramlen = info->
fix.smem_len;
693 if (vramlen > 4 * 1024 * 1024)
694 vramlen = 4 * 1024 * 1024;
701 if (memlen > vramlen) {
726 static int neofb_set_par(
struct fb_info *info)
728 struct neofb_par *par = info->
par;
732 int hoffset, voffset;
733 int vsync_start, vtotal;
735 DBG(
"neofb_set_par");
741 vsync_start = info->
var.yres + info->
var.lower_margin;
742 vtotal = vsync_start + info->
var.vsync_len + info->
var.upper_margin;
749 if (vgaHWInit(&info->
var, par))
756 par->Attribute[16] = 0x01;
758 switch (info->
var.bits_per_pixel) {
760 par->CRTC[0x13] = info->
var.xres_virtual >> 3;
761 par->ExtCRTOffset = info->
var.xres_virtual >> 11;
762 par->ExtColorModeSelect = 0x11;
765 par->CRTC[0x13] = info->
var.xres_virtual >> 2;
766 par->ExtCRTOffset = info->
var.xres_virtual >> 10;
767 par->ExtColorModeSelect = 0x13;
770 par->CRTC[0x13] = (info->
var.xres_virtual * 3) >> 3;
771 par->ExtCRTOffset = (info->
var.xres_virtual * 3) >> 11;
772 par->ExtColorModeSelect = 0x14;
774 #ifdef NO_32BIT_SUPPORT_YET
776 par->CRTC[0x13] = info->
var.xres_virtual >> 1;
777 par->ExtCRTOffset = info->
var.xres_virtual >> 9;
778 par->ExtColorModeSelect = 0x15;
785 par->ExtCRTDispAddr = 0x10;
788 par->VerticalExt = (((vtotal - 2) & 0x400) >> 10)
789 | (((info->
var.yres - 1) & 0x400) >> 9)
790 | (((vsync_start) & 0x400) >> 8)
791 | (((vsync_start) & 0x400) >> 7);
795 par->SysIfaceCntl1 = 0x30;
797 par->SysIfaceCntl1 = 0x00;
799 par->SysIfaceCntl2 = 0xc0;
802 par->PanelDispCntlRegRead = 1;
805 par->PanelDispCntlReg1 = 0x00;
806 if (par->internal_display)
807 par->PanelDispCntlReg1 |= 0x02;
808 if (par->external_display)
809 par->PanelDispCntlReg1 |= 0x01;
812 if (par->PanelDispCntlReg1 == 0x00) {
814 par->PanelDispCntlReg1 = vga_rgfx(
NULL, 0x20) & 0x03;
818 switch (info->
var.xres) {
820 par->PanelDispCntlReg1 |= 0x60;
823 par->PanelDispCntlReg1 |= 0x40;
826 par->PanelDispCntlReg1 |= 0x20;
834 switch (par->PanelDispCntlReg1 & 0x03) {
836 par->GeneralLockReg = 0x00;
838 par->ProgramVCLK = 1;
842 par->GeneralLockReg = 0x01;
844 par->ProgramVCLK = 0;
854 par->PanelDispCntlReg2 = 0x00;
855 par->PanelDispCntlReg3 = 0x00;
857 if (par->lcd_stretch && (par->PanelDispCntlReg1 == 0x02) &&
858 (info->
var.xres != par->NeoPanelWidth)) {
859 switch (info->
var.xres) {
866 par->PanelDispCntlReg2 |= 0xC6;
879 par->PanelVertCenterReg1 = 0x00;
880 par->PanelVertCenterReg2 = 0x00;
881 par->PanelVertCenterReg3 = 0x00;
882 par->PanelVertCenterReg4 = 0x00;
883 par->PanelVertCenterReg5 = 0x00;
884 par->PanelHorizCenterReg1 = 0x00;
885 par->PanelHorizCenterReg2 = 0x00;
886 par->PanelHorizCenterReg3 = 0x00;
887 par->PanelHorizCenterReg4 = 0x00;
888 par->PanelHorizCenterReg5 = 0x00;
891 if (par->PanelDispCntlReg1 & 0x02) {
892 if (info->
var.xres == par->NeoPanelWidth) {
898 par->PanelDispCntlReg2 |= 0x01;
899 par->PanelDispCntlReg3 |= 0x10;
904 ((par->NeoPanelWidth -
905 info->
var.xres) >> 4) - 1;
907 ((par->NeoPanelHeight -
908 info->
var.yres) >> 1) - 2;
915 switch (info->
var.xres) {
917 par->PanelHorizCenterReg3 = hoffset;
918 par->PanelVertCenterReg2 = voffset;
921 par->PanelHorizCenterReg4 = hoffset;
922 par->PanelVertCenterReg1 = voffset;
925 par->PanelHorizCenterReg1 = hoffset;
926 par->PanelVertCenterReg3 = voffset;
929 par->PanelHorizCenterReg2 = hoffset;
930 par->PanelVertCenterReg4 = voffset;
933 par->PanelHorizCenterReg5 = hoffset;
934 par->PanelVertCenterReg5 = voffset;
945 neoFindMode(info->
var.xres, info->
var.yres,
946 info->
var.bits_per_pixel);
955 par->MiscOutReg |= 0x0C;
961 vga_wgfx(
NULL, 0x15, 0x00);
964 vga_wgfx(
NULL, 0x0A, par->GeneralLockReg);
973 temp = vga_rgfx(
NULL, 0x90);
974 switch (info->
fix.accel) {
977 temp |= (par->ExtColorModeSelect & ~0xF0);
988 temp |= (par->ExtColorModeSelect & ~0x70);
992 vga_wgfx(
NULL, 0x90, temp);
1004 temp = vga_rgfx(
NULL, 0x25);
1006 vga_wgfx(
NULL, 0x25, temp);
1016 vgaHWRestore(info, par);
1019 switch (info->
var.bits_per_pixel) {
1028 for (i = 0; i < 64; i++) {
1031 outb(i << 1, 0x3c9);
1033 outb(i << 1, 0x3c9);
1037 #ifdef NO_32BIT_SUPPORT_YET
1043 for (i = 0; i < 256; i++) {
1053 vga_wgfx(
NULL, 0x0E, par->ExtCRTDispAddr);
1054 vga_wgfx(
NULL, 0x0F, par->ExtCRTOffset);
1055 temp = vga_rgfx(
NULL, 0x10);
1057 temp |= (par->SysIfaceCntl1 & ~0x0F);
1058 vga_wgfx(
NULL, 0x10, temp);
1060 vga_wgfx(
NULL, 0x11, par->SysIfaceCntl2);
1061 vga_wgfx(
NULL, 0x15, 0 );
1062 vga_wgfx(
NULL, 0x16, 0 );
1064 temp = vga_rgfx(
NULL, 0x20);
1065 switch (info->
fix.accel) {
1068 temp |= (par->PanelDispCntlReg1 & ~0xFC);
1075 temp |= (par->PanelDispCntlReg1 & ~0xDC);
1082 temp |= (par->PanelDispCntlReg1 & ~0x98);
1085 vga_wgfx(
NULL, 0x20, temp);
1087 temp = vga_rgfx(
NULL, 0x25);
1089 temp |= (par->PanelDispCntlReg2 & ~0x38);
1090 vga_wgfx(
NULL, 0x25, temp);
1093 temp = vga_rgfx(
NULL, 0x30);
1095 temp |= (par->PanelDispCntlReg3 & ~0xEF);
1096 vga_wgfx(
NULL, 0x30, temp);
1099 vga_wgfx(
NULL, 0x28, par->PanelVertCenterReg1);
1100 vga_wgfx(
NULL, 0x29, par->PanelVertCenterReg2);
1101 vga_wgfx(
NULL, 0x2a, par->PanelVertCenterReg3);
1104 vga_wgfx(
NULL, 0x32, par->PanelVertCenterReg4);
1105 vga_wgfx(
NULL, 0x33, par->PanelHorizCenterReg1);
1106 vga_wgfx(
NULL, 0x34, par->PanelHorizCenterReg2);
1107 vga_wgfx(
NULL, 0x35, par->PanelHorizCenterReg3);
1111 vga_wgfx(
NULL, 0x36, par->PanelHorizCenterReg4);
1117 vga_wgfx(
NULL, 0x36, par->PanelHorizCenterReg4);
1118 vga_wgfx(
NULL, 0x37, par->PanelVertCenterReg5);
1119 vga_wgfx(
NULL, 0x38, par->PanelHorizCenterReg5);
1125 if (par->ProgramVCLK && ((vga_rgfx(
NULL, 0x9B) != par->VCLK3NumeratorLow)
1126 || (vga_rgfx(
NULL, 0x9F) != par->VCLK3Denominator)
1127 || (clock_hi && ((vga_rgfx(
NULL, 0x8F) & ~0x0f)
1128 != (par->VCLK3NumeratorHigh &
1130 vga_wgfx(
NULL, 0x9B, par->VCLK3NumeratorLow);
1132 temp = vga_rgfx(
NULL, 0x8F);
1134 temp |= (par->VCLK3NumeratorHigh & ~0x0F);
1135 vga_wgfx(
NULL, 0x8F, temp);
1137 vga_wgfx(
NULL, 0x9F, par->VCLK3Denominator);
1141 vga_wcrt(
NULL, 0x23, par->biosMode);
1143 vga_wgfx(
NULL, 0x93, 0xc0);
1150 vga_wcrt(
NULL, 0x70, par->VerticalExt);
1156 neoLock(&par->state);
1158 info->
fix.line_length =
1159 info->
var.xres_virtual * (info->
var.bits_per_pixel >> 3);
1161 switch (info->
fix.accel) {
1166 neo2200_accel_init(info, &info->
var);
1180 struct neofb_par *par = info->
par;
1181 struct vgastate *state = &par->state;
1182 int oldExtCRTDispAddr;
1185 DBG(
"neofb_update_start");
1188 Base *= (info->
var.bits_per_pixel + 7) / 8;
1195 vga_wcrt(state->
vgabase, 0x0C, (Base & 0x00FF00) >> 8);
1196 vga_wcrt(state->
vgabase, 0x0D, (Base & 0x00FF));
1203 oldExtCRTDispAddr = vga_rgfx(
NULL, 0x0E);
1204 vga_wgfx(state->
vgabase, 0x0E, (((Base >> 16) & 0x0f) | (oldExtCRTDispAddr & 0xf0)));
1214 if (regno >= fb->
cmap.len || regno > 255)
1217 if (fb->
var.bits_per_pixel <= 8) {
1220 outb(red >> 10, 0x3c9);
1221 outb(green >> 10, 0x3c9);
1222 outb(blue >> 10, 0x3c9);
1223 }
else if (regno < 16) {
1224 switch (fb->
var.bits_per_pixel) {
1227 ((red & 0xf800)) | ((green & 0xfc00) >> 5) |
1228 ((blue & 0xf800) >> 11);
1232 ((red & 0xff00) << 8) | ((green & 0xff00)) |
1233 ((blue & 0xff00) >> 8);
1235 #ifdef NO_32BIT_SUPPORT_YET
1238 ((transp & 0xff00) << 16) | ((red & 0xff00) << 8) |
1239 ((green & 0xff00)) | ((blue & 0xff00) >> 8);
1253 static int neofb_blank(
int blank_mode,
struct fb_info *info)
1269 struct neofb_par *par = info->
par;
1270 int seqflags, lcdflags, dpmsflags,
reg, tmpdisp;
1277 tmpdisp = vga_rgfx(
NULL, 0x20) & 0x03;
1278 neoLock(&par->state);
1284 if (par->PanelDispCntlRegRead) {
1285 par->PanelDispCntlReg1 = tmpdisp;
1287 par->PanelDispCntlRegRead = !blank_mode;
1289 switch (blank_mode) {
1295 #ifdef CONFIG_TOSHIBA
1329 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02);
1334 lcdflags = ((par->PanelDispCntlReg1 | tmpdisp) & 0x02);
1336 #ifdef CONFIG_TOSHIBA
1355 reg = (vga_rseq(
NULL, 0x01) & ~0x20) | seqflags;
1356 vga_wseq(
NULL, 0x01, reg);
1357 reg = (vga_rgfx(
NULL, 0x20) & ~0x02) | lcdflags;
1358 vga_wgfx(
NULL, 0x20, reg);
1359 reg = (vga_rgfx(
NULL, 0x01) & ~0xF0) | 0x80 | dpmsflags;
1360 vga_wgfx(
NULL, 0x01, reg);
1361 neoLock(&par->state);
1368 struct neofb_par *par = info->
par;
1371 dst = rect->
dx + rect->
dy * info->
var.xres_virtual;
1372 rop = rect->
rop ? 0x060000 : 0x0c0000;
1374 neo2200_wait_fifo(info, 4);
1381 rop, &par->neo2200->bltCntl);
1383 switch (info->
var.bits_per_pixel) {
1390 &par->neo2200->fgColor);
1394 writel(dst * ((info->
var.bits_per_pixel + 7) >> 3),
1395 &par->neo2200->dstStart);
1397 &par->neo2200->xyExt);
1403 u32 sx = area->
sx, sy = area->
sy, dx = area->
dx, dy = area->
dy;
1404 struct neofb_par *par = info->
par;
1409 if ((dy > sy) || ((dy == sy) && (dx > sx))) {
1411 sy += (area->
height - 1);
1412 dy += (area->
height - 1);
1413 sx += (area->
width - 1);
1414 dx += (area->
width - 1);
1419 src = sx * (info->
var.bits_per_pixel >> 3) + sy*info->
fix.line_length;
1420 dst = dx * (info->
var.bits_per_pixel >> 3) + dy*info->
fix.line_length;
1422 neo2200_wait_fifo(info, 4);
1425 writel(bltCntl, &par->neo2200->bltCntl);
1427 writel(src, &par->neo2200->srcStart);
1428 writel(dst, &par->neo2200->dstStart);
1430 &par->neo2200->xyExt);
1436 struct neofb_par *par = info->
par;
1437 int s_pitch = (image->
width * image->
depth + 7) >> 3;
1438 int scan_align = info->
pixmap.scan_align - 1;
1439 int buf_align = info->
pixmap.buf_align - 1;
1440 int bltCntl_flags, d_pitch,
data_len;
1443 d_pitch = (s_pitch + scan_align) & ~scan_align;
1444 data_len = ((d_pitch * image->
height) + buf_align) & ~buf_align;
1448 if (image->
depth == 1) {
1449 if (info->
var.bits_per_pixel == 24 && image->
width < 16) {
1459 }
else if (image->
depth == info->
var.bits_per_pixel) {
1468 switch (info->
var.bits_per_pixel) {
1476 &par->neo2200->fgColor);
1478 &par->neo2200->bgColor);
1485 0x0c0000, &par->neo2200->bltCntl);
1487 writel(0, &par->neo2200->srcStart);
1489 writel(((image->
dx & 0xffff) * (info->
var.bits_per_pixel >> 3) +
1490 image->
dy * info->
fix.line_length), &par->neo2200->dstStart);
1492 &par->neo2200->xyExt);
1500 switch (info->
fix.accel) {
1505 neo2200_fillrect(info, rect);
1516 switch (info->
fix.accel) {
1521 neo2200_copyarea(info, area);
1532 switch (info->
fix.accel) {
1537 neo2200_imageblit(info, image);
1546 neofb_sync(
struct fb_info *info)
1548 switch (info->
fix.accel) {
1618 static struct fb_ops neofb_ops = {
1620 .fb_open = neofb_open,
1621 .fb_release = neofb_release,
1622 .fb_check_var = neofb_check_var,
1623 .fb_set_par = neofb_set_par,
1624 .fb_setcolreg = neofb_setcolreg,
1625 .fb_pan_display = neofb_pan_display,
1626 .fb_blank = neofb_blank,
1627 .fb_sync = neofb_sync,
1628 .fb_fillrect = neofb_fillrect,
1629 .fb_copyarea = neofb_copyarea,
1630 .fb_imageblit = neofb_imageblit,
1652 struct neofb_par *par = info->
par;
1654 DBG(
"neo_map_mmio");
1656 switch (info->
fix.accel) {
1680 (info->
fix.mmio_start,
MMIO_SIZE,
"memory mapped I/O")) {
1681 printk(
"neofb: memory mapped IO in use\n");
1686 if (!par->mmio_vbase) {
1687 printk(
"neofb: unable to map memory mapped IO\n");
1689 info->
fix.mmio_len);
1697 static void neo_unmap_mmio(
struct fb_info *info)
1699 struct neofb_par *par = info->
par;
1701 DBG(
"neo_unmap_mmio");
1704 par->mmio_vbase =
NULL;
1707 info->
fix.mmio_len);
1711 struct pci_dev *dev,
int video_len)
1715 DBG(
"neo_map_video");
1718 info->
fix.smem_len = video_len;
1722 printk(
"neofb: frame buffer in use\n");
1729 printk(
"neofb: unable to map screen memory\n");
1731 info->
fix.smem_len);
1738 ((
struct neofb_par *)(info->
par))->mtrr =
1756 static void neo_unmap_video(
struct fb_info *info)
1758 DBG(
"neo_unmap_video");
1762 struct neofb_par *par = info->
par;
1765 info->
fix.smem_len);
1772 info->
fix.smem_len);
1777 struct neofb_par *par = info->
par;
1788 vga_wgfx(
NULL, 0x09, 0x26);
1789 type = vga_rgfx(
NULL, 0x21);
1790 display = vga_rgfx(
NULL, 0x20);
1791 if (!par->internal_display && !par->external_display) {
1792 par->internal_display = display & 2 || !(display & 3) ? 1 : 0;
1793 par->external_display = display & 1;
1795 par->internal_display && par->external_display ?
"simultaneous" :
1796 par->internal_display ?
"internal" :
"external");
1800 w = vga_rgfx(
NULL, 0x20);
1801 vga_wgfx(
NULL, 0x09, 0x00);
1802 switch ((w & 0x18) >> 3) {
1805 par->NeoPanelWidth = 640;
1806 par->NeoPanelHeight = 480;
1810 par->NeoPanelWidth = 800;
1811 if (par->libretto) {
1812 par->NeoPanelHeight = 480;
1816 par->NeoPanelHeight = 600;
1822 par->NeoPanelWidth = 1024;
1823 par->NeoPanelHeight = 768;
1829 par->NeoPanelWidth = 1280;
1830 par->NeoPanelHeight = 1024;
1835 "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n");
1840 par->NeoPanelWidth = 640;
1841 par->NeoPanelHeight = 480;
1848 par->NeoPanelHeight,
1849 (type & 0x02) ?
"color" :
"monochrome",
1850 (type & 0x10) ?
"TFT" :
"dual scan");
1856 struct neofb_par *par = info->
par;
1858 int maxClock = 65000;
1859 int CursorMem = 1024;
1860 int CursorOff = 0x100;
1868 for (
int w = 0; w < 0x85; w++)
1870 (
void *) vga_rcrt(
NULL, w));
1871 for (
int w = 0; w < 0xC7; w++)
1873 (
void *) vga_rgfx(
NULL, w));
1875 switch (info->
fix.accel) {
1907 switch (info->
fix.accel) {
1926 par->neo2200 = (Neo2200
__iomem *) par->mmio_vbase;
1936 par->maxClock = maxClock;
1937 par->cursorOff = CursorOff;
1938 return videoRam * 1024;
1946 struct neofb_par *par;
1955 info->
fix.accel =
id->driver_data;
1957 par->pci_burst = !nopciburst;
1958 par->lcd_stretch = !nostretch;
1959 par->libretto = libretto;
1961 par->internal_display =
internal;
1965 switch (info->
fix.accel) {
1976 "MagicGraph 128ZV");
1980 "MagicGraph 128ZV+");
1984 "MagicGraph 128XD");
1988 "MagicGraph 256AV");
1995 "MagicGraph 256AV+");
2002 "MagicGraph 256ZX");
2009 "MagicGraph 256XL+");
2017 info->
fix.type_aux = 0;
2018 info->
fix.xpanstep = 0;
2019 info->
fix.ypanstep = 4;
2020 info->
fix.ywrapstep = 0;
2021 info->
fix.accel =
id->driver_data;
2023 info->
fbops = &neofb_ops;
2028 static void neo_free_fb_info(
struct fb_info *info)
2045 u_int h_sync, v_sync;
2055 info = neo_alloc_fb_info(dev,
id);
2059 err = neo_map_mmio(info, dev);
2063 err = neo_scan_monitor(info);
2065 goto err_scan_monitor;
2067 video_len = neo_init_hw(info);
2068 if (video_len < 0) {
2073 err = neo_map_video(info, dev, video_len);
2089 h_sync = 1953125000 / info->
var.pixclock;
2091 h_sync * 512 / (info->
var.xres + info->
var.left_margin +
2092 info->
var.right_margin + info->
var.hsync_len);
2094 h_sync / (info->
var.yres + info->
var.upper_margin +
2095 info->
var.lower_margin + info->
var.vsync_len);
2098 ": %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n",
2099 info->
fix.smem_len >> 10, info->
var.xres,
2100 info->
var.yres, h_sync / 1000, h_sync % 1000, v_sync);
2115 pci_set_drvdata(dev, info);
2121 neo_unmap_video(info);
2125 neo_unmap_mmio(info);
2127 neo_free_fb_info(info);
2133 struct fb_info *info = pci_get_drvdata(dev);
2135 DBG(
"neofb_remove");
2145 "neofb: danger danger! Oopsen imminent!\n");
2147 neo_unmap_video(info);
2149 neo_unmap_mmio(info);
2150 neo_free_fb_info(info);
2156 pci_set_drvdata(dev,
NULL);
2188 {0, 0, 0, 0, 0, 0, 0}
2195 .id_table = neofb_devices,
2196 .probe = neofb_probe,
2209 if (!options || !*options)
2212 while ((this_opt =
strsep(&options,
",")) !=
NULL) {
2216 if (!
strncmp(this_opt,
"internal", 8))
2218 else if (!
strncmp(this_opt,
"external", 8))
2220 else if (!
strncmp(this_opt,
"nostretch", 9))
2222 else if (!
strncmp(this_opt,
"nopciburst", 10))
2224 else if (!
strncmp(this_opt,
"libretto", 8))
2227 mode_option = this_opt;
2233 static int __init neofb_init(
void)
2240 neofb_setup(option);
2242 return pci_register_driver(&neofb_driver);
2248 static void __exit neofb_exit(
void)