43 #include <linux/module.h>
44 #include <linux/kernel.h>
45 #include <linux/errno.h>
46 #include <linux/string.h>
59 #include <asm/setup.h>
66 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
67 #define CONFIG_FB_AMIGA_OCS
70 #if !defined(CONFIG_FB_AMIGA_OCS)
72 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
73 # define IS_OCS (chipset == TAG_OCS)
75 # define CONFIG_FB_AMIGA_OCS_ONLY
79 #if !defined(CONFIG_FB_AMIGA_ECS)
81 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
82 # define IS_ECS (chipset == TAG_ECS)
84 # define CONFIG_FB_AMIGA_ECS_ONLY
88 #if !defined(CONFIG_FB_AMIGA_AGA)
90 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
91 # define IS_AGA (chipset == TAG_AGA)
93 # define CONFIG_FB_AMIGA_AGA_ONLY
98 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
100 # define DPRINTK(fmt, args...)
373 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
379 #define BPC0_HIRES (0x8000)
380 #define BPC0_BPU2 (0x4000)
381 #define BPC0_BPU1 (0x2000)
382 #define BPC0_BPU0 (0x1000)
383 #define BPC0_HAM (0x0800)
384 #define BPC0_DPF (0x0400)
385 #define BPC0_COLOR (0x0200)
386 #define BPC0_GAUD (0x0100)
387 #define BPC0_UHRES (0x0080)
388 #define BPC0_SHRES (0x0040)
389 #define BPC0_BYPASS (0x0020)
390 #define BPC0_BPU3 (0x0010)
391 #define BPC0_LPEN (0x0008)
392 #define BPC0_LACE (0x0004)
393 #define BPC0_ERSY (0x0002)
394 #define BPC0_ECSENA (0x0001)
400 #define BPC2_ZDBPSEL2 (0x4000)
401 #define BPC2_ZDBPSEL1 (0x2000)
402 #define BPC2_ZDBPSEL0 (0x1000)
403 #define BPC2_ZDBPEN (0x0800)
404 #define BPC2_ZDCTEN (0x0400)
405 #define BPC2_KILLEHB (0x0200)
406 #define BPC2_RDRAM (0x0100)
407 #define BPC2_SOGEN (0x0080)
408 #define BPC2_PF2PRI (0x0040)
409 #define BPC2_PF2P2 (0x0020)
410 #define BPC2_PF2P1 (0x0010)
411 #define BPC2_PF2P0 (0x0008)
412 #define BPC2_PF1P2 (0x0004)
413 #define BPC2_PF1P1 (0x0002)
414 #define BPC2_PF1P0 (0x0001)
420 #define BPC3_BANK2 (0x8000)
421 #define BPC3_BANK1 (0x4000)
422 #define BPC3_BANK0 (0x2000)
423 #define BPC3_PF2OF2 (0x1000)
424 #define BPC3_PF2OF1 (0x0800)
425 #define BPC3_PF2OF0 (0x0400)
426 #define BPC3_LOCT (0x0200)
427 #define BPC3_SPRES1 (0x0080)
428 #define BPC3_SPRES0 (0x0040)
429 #define BPC3_BRDRBLNK (0x0020)
430 #define BPC3_BRDRTRAN (0x0010)
431 #define BPC3_ZDCLKEN (0x0004)
432 #define BPC3_BRDRSPRT (0x0002)
433 #define BPC3_EXTBLKEN (0x0001)
439 #define BPC4_BPLAM7 (0x8000)
440 #define BPC4_BPLAM6 (0x4000)
441 #define BPC4_BPLAM5 (0x2000)
442 #define BPC4_BPLAM4 (0x1000)
443 #define BPC4_BPLAM3 (0x0800)
444 #define BPC4_BPLAM2 (0x0400)
445 #define BPC4_BPLAM1 (0x0200)
446 #define BPC4_BPLAM0 (0x0100)
447 #define BPC4_ESPRM7 (0x0080)
448 #define BPC4_ESPRM6 (0x0040)
449 #define BPC4_ESPRM5 (0x0020)
450 #define BPC4_ESPRM4 (0x0010)
451 #define BPC4_OSPRM7 (0x0008)
452 #define BPC4_OSPRM6 (0x0004)
453 #define BPC4_OSPRM5 (0x0002)
454 #define BPC4_OSPRM4 (0x0001)
460 #define BMC0_HARDDIS (0x4000)
461 #define BMC0_LPENDIS (0x2000)
462 #define BMC0_VARVBEN (0x1000)
463 #define BMC0_LOLDIS (0x0800)
464 #define BMC0_CSCBEN (0x0400)
465 #define BMC0_VARVSYEN (0x0200)
466 #define BMC0_VARHSYEN (0x0100)
467 #define BMC0_VARBEAMEN (0x0080)
468 #define BMC0_DUAL (0x0040)
469 #define BMC0_PAL (0x0020)
470 #define BMC0_VARCSYEN (0x0010)
471 #define BMC0_BLANKEN (0x0008)
472 #define BMC0_CSYTRUE (0x0004)
473 #define BMC0_VSYTRUE (0x0002)
474 #define BMC0_HSYTRUE (0x0001)
481 #define FMODE_SSCAN2 (0x8000)
482 #define FMODE_BSCAN2 (0x4000)
483 #define FMODE_SPAGEM (0x0008)
484 #define FMODE_SPR32 (0x0004)
485 #define FMODE_BPAGEM (0x0002)
486 #define FMODE_BPL32 (0x0001)
516 static u_long pixclock[3];
528 #define PAL_DIWSTRT_H (360)
529 #define PAL_DIWSTRT_V (48)
530 #define PAL_HTOTAL (1816)
531 #define PAL_VTOTAL (625)
533 #define NTSC_DIWSTRT_H (360)
534 #define NTSC_DIWSTRT_V (40)
535 #define NTSC_HTOTAL (1816)
536 #define NTSC_VTOTAL (525)
543 #define up2(v) (((v) + 1) & -2)
544 #define down2(v) ((v) & -2)
545 #define div2(v) ((v)>>1)
546 #define mod2(v) ((v) & 1)
548 #define up4(v) (((v) + 3) & -4)
549 #define down4(v) ((v) & -4)
550 #define mul4(v) ((v) << 2)
551 #define div4(v) ((v)>>2)
552 #define mod4(v) ((v) & 3)
554 #define up8(v) (((v) + 7) & -8)
555 #define down8(v) ((v) & -8)
556 #define div8(v) ((v)>>3)
557 #define mod8(v) ((v) & 7)
559 #define up16(v) (((v) + 15) & -16)
560 #define down16(v) ((v) & -16)
561 #define div16(v) ((v)>>4)
562 #define mod16(v) ((v) & 15)
564 #define up32(v) (((v) + 31) & -32)
565 #define down32(v) ((v) & -32)
566 #define div32(v) ((v)>>5)
567 #define mod32(v) ((v) & 31)
569 #define up64(v) (((v) + 63) & -64)
570 #define down64(v) ((v) & -64)
571 #define div64(v) ((v)>>6)
572 #define mod64(v) ((v) & 63)
574 #define upx(x, v) (((v) + (x) - 1) & -(x))
575 #define downx(x, v) ((v) & -(x))
576 #define modx(x, v) ((v) & ((x) - 1))
580 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
581 "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
584 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
585 ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
588 #define highw(x) ((u_long)(x)>>16 & 0xffff)
589 #define loww(x) ((u_long)(x) & 0xffff)
591 #define custom amiga_custom
593 #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
594 #define VBlankOff() custom.intena = IF_COPER
604 #define VIDEOMEMSIZE_AGA_2M (1310720)
605 #define VIDEOMEMSIZE_AGA_1M (786432)
606 #define VIDEOMEMSIZE_ECS_2M (655360)
607 #define VIDEOMEMSIZE_ECS_1M (393216)
608 #define VIDEOMEMSIZE_OCS (262144)
610 #define SPRITEMEMSIZE (64 * 64 / 4)
611 #define DUMMYSPRITEMEMSIZE (8)
612 static u_long spritememory;
614 #define CHIPRAM_SAFETY_LIMIT (16384)
616 static u_long videomemory;
624 static u_long min_fstrt = 192;
626 #define assignchunk(name, type, ptr, size) \
628 (name) = (type)(ptr); \
637 #define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
638 #define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
639 #define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
640 #define CEND (0xfffffffe)
648 static struct copdisplay {
663 #define FBIOGET_FCURSORINFO 0x4607
664 #define FBIOGET_VCURSORINFO 0x4608
665 #define FBIOPUT_VCURSORINFO 0x4609
666 #define FBIOGET_CURSORSTATE 0x460A
667 #define FBIOPUT_CURSORSTATE 0x460B
693 #define FB_CURSOR_OFF 0
694 #define FB_CURSOR_ON 1
695 #define FB_CURSOR_FLASH 2
702 static int cursorrate = 20;
703 static u_short cursorstate = -1;
706 static u_short *lofsprite, *shfsprite, *dummysprite;
782 static u_char red0, green0, blue0;
785 #if defined(CONFIG_FB_AMIGA_ECS)
786 static u_short ecs_palette[32];
794 static u_short do_vmode_full = 0;
795 static u_short do_vmode_pan = 0;
796 static short do_blank = 0;
822 "ntsc", 60, 640, 200,
TAG_HIRES, 106, 86, 44, 16, 76, 2,
826 "ntsc-lace", 60, 640, 400,
TAG_HIRES, 106, 86, 88, 33, 76, 4,
830 "pal", 50, 640, 256,
TAG_HIRES, 106, 86, 40, 14, 76, 2,
834 "pal-lace", 50, 640, 512,
TAG_HIRES, 106, 86, 80, 29, 76, 4,
838 "multiscan", 57, 640, 480,
TAG_SHRES, 96, 112, 29, 8, 72, 8,
842 "multiscan-lace", 57, 640, 960,
TAG_SHRES, 96, 112, 58, 16, 72,
847 "euro36", 72, 640, 200,
TAG_HIRES, 92, 124, 6, 6, 52, 5,
851 "euro36-lace", 72, 640, 400,
TAG_HIRES, 92, 124, 12, 12, 52,
856 "euro72", 68, 640, 400,
TAG_SHRES, 164, 92, 9, 9, 80, 8,
860 "euro72-lace", 68, 640, 800,
TAG_SHRES, 164, 92, 18, 18, 80,
865 "super72", 70, 800, 300,
TAG_SHRES, 212, 140, 10, 11, 80, 7,
869 "super72-lace", 70, 800, 600,
TAG_SHRES, 212, 140, 20, 22, 80,
874 "dblntsc", 57, 640, 200,
TAG_SHRES, 196, 124, 18, 17, 80, 4,
878 "dblntsc-ff", 57, 640, 400,
TAG_SHRES, 196, 124, 36, 35, 80, 7,
882 "dblntsc-lace", 57, 640, 800,
TAG_SHRES, 196, 124, 72, 70, 80,
887 "dblpal", 47, 640, 256,
TAG_SHRES, 196, 124, 14, 13, 80, 4,
891 "dblpal-ff", 47, 640, 512,
TAG_SHRES, 196, 124, 28, 27, 80, 7,
895 "dblpal-lace", 47, 640, 1024,
TAG_SHRES, 196, 124, 56, 54, 80,
906 "vga", 60, 640, 480,
TAG_SHRES, 64, 96, 30, 9, 112, 2,
910 "vga70", 70, 640, 400,
TAG_SHRES, 64, 96, 35, 12, 112, 2,
924 "a2024-10", 10, 1024, 800,
TAG_HIRES, 0, 0, 0, 0, 0, 0,
928 "a2024-15", 15, 1024, 800,
TAG_HIRES, 0, 0, 0, 0, 0, 0,
934 #define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
936 static char *mode_option __initdata =
NULL;
937 static int round_down_bpp = 1;
944 #define DEFMODE_PAL 2
945 #define DEFMODE_NTSC 0
946 #define DEFMODE_AMBER_PAL 3
947 #define DEFMODE_AMBER_NTSC 1
948 #define DEFMODE_AGA 19
951 static int amifb_ilbm = 0;
996 #define hscroll2hw(hscroll) \
997 (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
998 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
999 ((hscroll)>>2 & 0x000f))
1003 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
1004 (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1005 #define diwstop2hw(diwstop_h, diwstop_v) \
1006 (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1007 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1008 (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
1009 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1010 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1014 #define ddfstrt2hw(ddfstrt) div8(ddfstrt)
1015 #define ddfstop2hw(ddfstop) div8(ddfstop)
1019 #define hsstrt2hw(hsstrt) (div8(hsstrt))
1020 #define hsstop2hw(hsstop) (div8(hsstop))
1021 #define htotal2hw(htotal) (div8(htotal) - 1)
1022 #define vsstrt2hw(vsstrt) (div2(vsstrt))
1023 #define vsstop2hw(vsstop) (div2(vsstop))
1024 #define vtotal2hw(vtotal) (div2(vtotal) - 1)
1025 #define hcenter2hw(htotal) (div8(htotal))
1029 #define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1030 #define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1031 #define vbstrt2hw(vbstrt) (div2(vbstrt))
1032 #define vbstop2hw(vbstop) (div2(vbstop))
1036 #define rgb2hw8_high(red, green, blue) \
1037 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1038 #define rgb2hw8_low(red, green, blue) \
1039 (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
1040 #define rgb2hw4(red, green, blue) \
1041 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1042 #define rgb2hw2(red, green, blue) \
1043 (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1047 #define spr2hw_pos(start_v, start_h) \
1048 (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
1049 #define spr2hw_ctl(start_v, start_h, stop_v) \
1050 (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
1051 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
1052 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
1053 ((start_h)>>2 & 0x0001))
1056 #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
1062 #define COPINITSIZE (sizeof(copins) * 40)
1073 #define COPLISTSIZE (sizeof(copins) * 64)
1086 static u_short bplpixmode[3] = {
1092 static u_short sprpixmode[3] = {
1102 static u_short bplfetchmode[3] = {
1108 static u_short sprfetchmode[3] = {
1125 u_short clk_shift, line_shift;
1126 u_long maxfetchstop, fstrt, fsize,
fconst, xres_n, yres_n;
1127 u_int htotal, vtotal;
1137 DPRINTK(
"pixclock too high\n");
1159 if (par->
bpp > maxdepth[clk_shift]) {
1160 if (round_down_bpp && maxdepth[clk_shift])
1161 par->
bpp = maxdepth[clk_shift];
1170 if (par->
bpp != 6) {
1174 DPRINTK(
"invalid bpp for ham mode\n");
1179 DPRINTK(
"unknown nonstd mode\n");
1198 DPRINTK(
"double mode only possible with aga\n");
1204 DPRINTK(
"unknown video mode\n");
1214 xres_n = par->
xres << clk_shift;
1215 yres_n = par->
yres << line_shift;
1223 par->
bplcon3 = sprpixmode[clk_shift];
1239 DPRINTK(
"invalid diwstop_h\n");
1243 DPRINTK(
"invalid diwstop_v\n");
1262 DPRINTK(
"htotal invalid for pal\n");
1266 DPRINTK(
"diwstrt_h too low for pal\n");
1270 DPRINTK(
"diwstrt_v too low for pal\n");
1283 DPRINTK(
"pal not supported by this chipset\n");
1292 DPRINTK(
"htotal invalid for ntsc\n");
1296 DPRINTK(
"diwstrt_h too low for ntsc\n");
1300 DPRINTK(
"diwstrt_v too low for ntsc\n");
1313 DPRINTK(
"ntsc not supported by this chipset\n");
1320 DPRINTK(
"invalid position for display on ocs\n");
1349 if (par->
htotal > 2048) {
1363 htotal = par->
htotal>>clk_shift;
1366 DPRINTK(
"only broadcast modes possible for ocs\n");
1374 fconst = 16 << maxfmode << clk_shift;
1382 fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
1384 if (fstrt < min_fstrt) {
1385 DPRINTK(
"fetch start too low\n");
1393 fstrt =
downx(fconst, par->
diwstrt_h - fconst + (1 << clk_shift) - 4) -
1395 if (fstrt < min_fstrt)
1401 fsize =
upx(fconst, xres_n +
1403 if (fstrt + fsize > maxfetchstop)
1406 fsize =
upx(fconst, xres_n);
1407 if (fstrt + fsize > maxfetchstop) {
1408 DPRINTK(
"fetch stop too high\n");
1412 if (maxfmode + clk_shift <= 1) {
1413 fsize =
up64(xres_n + fconst - 1);
1414 if (min_fstrt + fsize - 64 > maxfetchstop)
1417 fsize =
up64(xres_n);
1418 if (min_fstrt + fsize - 64 > maxfetchstop) {
1419 DPRINTK(
"fetch size too high\n");
1431 if (par->
htotal - fsize - 64 < par->
bpp * 64)
1442 DPRINTK(
"too few video mem\n");
1449 DPRINTK(
"too few video mem\n");
1471 par->
fmode = bplfetchmode[maxfmode];
1499 par->
crsr.crsr_x = par->
crsr.crsr_y = 0;
1500 par->
crsr.spot_x = par->
crsr.spot_y = 0;
1501 par->
crsr.height = par->
crsr.width = 0;
1514 u_short clk_shift, line_shift;
1531 var->
red.offset = 0;
1532 var->
red.msb_right = 0;
1533 var->
red.length = par->
bpp;
1535 var->
red.length -= 2;
1539 var->
transp.msb_right = 0;
1595 static void ami_update_par(
struct fb_info *info)
1608 fsize = (par->
xres + vshift) << clk_shift;
1609 shift =
modx(fconst, fstrt);
1611 if (maxfmode + clk_shift > 1) {
1612 fstrt =
downx(fconst, fstrt) - 64;
1613 fsize =
upx(fconst, fsize);
1614 fstop = fstrt + fsize -
fconst;
1617 fstop = fstrt +
upx(fconst, fsize) - 64;
1618 fsize =
up64(fsize);
1619 fstrt = fstop - fsize + 64;
1620 if (fstrt < min_fstrt) {
1621 fstop += min_fstrt - fstrt;
1624 move = move -
div8((mod - fstrt)>>clk_shift);
1651 par->
bplpt0 = info->
fix.smem_start + move;
1677 ami_update_par(info);
1682 static void ami_update_display(
const struct amifb_par *par)
1695 static void ami_init_display(
const struct amifb_par *par)
1749 static void ami_do_blank(
const struct amifb_par *par)
1751 #if defined(CONFIG_FB_AMIGA_AGA)
1758 red = green = blue = 0;
1759 if (!
IS_OCS && do_blank > 1) {
1800 #if defined(CONFIG_FB_AMIGA_AGA)
1809 #if defined(CONFIG_FB_AMIGA_ECS)
1815 color =
rgb2hw2(red, green, blue);
1816 for (i = 12; i >= 0; i -= 4)
1817 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) |
color;
1818 mask <<= 2; color >>= 2;
1819 for (i = 3; i >= 0; i--)
1820 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) |
color;
1824 is_blanked = do_blank > 0 ? do_blank : 0;
1841 register u_short *lspr, *sspr;
1843 register u_long datawords
asm (
"d2");
1845 register u_long datawords;
1847 register short delta;
1852 size = par->
crsr.height * par->
crsr.width;
1862 delta = 1 << par->
crsr.fmode;
1863 lspr = lofsprite + (delta << 1);
1865 sspr = shfsprite + (delta << 1);
1868 for (height = (
short)var->
height - 1; height >= 0; height--) {
1869 bits = 0; words =
delta; datawords = 0;
1870 for (width = (
short)var->
width - 1; width >= 0; width--) {
1874 asm volatile (
"movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1875 :
"=d" (datawords),
"=a" (lspr) :
"1" (lspr),
"d" (delta));
1877 datawords = (*(lspr +
delta) << 16) | (*lspr++);
1883 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1884 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1885 :
"=d" (
color),
"=d" (datawords) :
"1" (datawords));
1887 color = (((datawords >> 30) & 2)
1888 | ((datawords >> 15) & 1));
1896 while (--words >= 0)
1899 asm volatile (
"lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1900 :
"=a" (lspr),
"=a" (sspr) :
"0" (lspr),
"1" (sspr),
"d" (
delta));
1916 register u_short *lspr, *sspr;
1918 register u_long datawords
asm (
"d2");
1920 register u_long datawords;
1922 register short delta;
1928 else if (var->
width <= 16)
1930 else if (var->
width <= 32)
1932 else if (var->
width <= 64)
1936 if (fmode > maxfmode)
1943 lofsprite = shfsprite = (
u_short *)spritememory;
1944 lspr = lofsprite + (delta << 1);
1950 sspr = shfsprite + (delta << 1);
1957 for (height = (
short)var->
height - 1; height >= 0; height--) {
1958 bits = 16; words =
delta; datawords = 0;
1959 for (width = (
short)var->
width - 1; width >= 0; width--) {
1960 unsigned long tdata = 0;
1965 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1966 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1968 :
"0" (datawords),
"d" (tdata));
1970 datawords = ((datawords << 1) & 0xfffefffe);
1971 datawords |= tdata & 1;
1972 datawords |= (tdata & 2) << (16 - 1);
1977 asm volatile (
"swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1978 :
"=a" (lspr) :
"0" (lspr),
"d" (datawords),
"d" (delta));
1981 *lspr++ = (
u_short) (datawords & 0xffff);
1989 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1990 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1991 :
"=a" (lspr) :
"0" (lspr),
"d" (datawords),
"d" (delta),
"d" (
bits));
1994 *lspr++ = (
u_short) ((datawords & 0x0000ffff) >>
bits);
1997 while (--words >= 0) {
1999 asm volatile (
"moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
2000 :
"=a" (lspr) :
"0" (lspr),
"d" (
delta) :
"d0");
2002 *(lspr +
delta) = 0;
2007 asm volatile (
"lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2008 :
"=a" (lspr),
"=a" (sspr) :
"0" (lspr),
"1" (sspr),
"d" (
delta));
2036 state->
mode = cursormode;
2051 static void ami_set_sprite(
const struct amifb_par *par)
2058 cops = copdisplay.list[currentcop][0];
2059 copl = copdisplay.list[currentcop][1];
2061 mx = par->
crsr.crsr_x - par->
crsr.spot_x;
2062 my = par->
crsr.crsr_y - par->
crsr.spot_y;
2067 if (!is_blanked && cursorstate > 0 && par->
crsr.height > 0 &&
2068 mx > -(
short)par->
crsr.width && mx < par->
xres &&
2069 my > -(
short)par->
crsr.height && my < par->
yres) {
2080 shfsprite[1 << par->
crsr.fmode] =
spr2hw_ctl(vs + 1, hs, ve + 1);
2081 pt =
pl; pl =
ps; ps = pt;
2104 static void __init ami_init_copper(
void)
2106 copins *cop = copdisplay.init;
2112 (cop++)->
l =
CMOVE(0x0181, diwstrt);
2113 (cop++)->
l =
CMOVE(0x0281, diwstop);
2114 (cop++)->
l =
CMOVE(0x0000, diwhigh);
2118 for (i = 0; i < 8; i++) {
2125 copdisplay.wait = cop;
2127 (cop++)->
l =
CMOVE(0, copjmp2);
2134 static void ami_reinit_copper(
const struct amifb_par *par)
2147 static void ami_rebuild_copper(
const struct amifb_par *par)
2157 h_end1 = par->
htotal - 32;
2160 ami_set_sprite(par);
2162 copl = copdisplay.rebuild[1];
2172 while (line >= 512) {
2173 (copl++)->
l =
CWAIT(h_end1, 510);
2177 (copl++)->
l =
CWAIT(h_end1, line);
2179 (copl++)->l =
CWAIT(h_end2, line);
2192 cops = copdisplay.rebuild[0];
2206 while (line >= 512) {
2207 (cops++)->
l =
CWAIT(h_end1, 510);
2211 (cops++)->
l =
CWAIT(h_end1, line);
2213 (cops++)->l =
CWAIT(h_end2, line);
2237 static void ami_build_copper(
struct fb_info *info)
2243 currentcop = 1 - currentcop;
2245 copl = copdisplay.list[currentcop][1];
2247 (copl++)->
l =
CWAIT(0, 10);
2249 (copl++)->
l =
CMOVE(0, sprpt[0]);
2250 (copl++)->
l =
CMOVE2(0, sprpt[0]);
2253 cops = copdisplay.list[currentcop][0];
2255 (cops++)->
l =
CWAIT(0, 10);
2257 (cops++)->
l =
CMOVE(0, sprpt[0]);
2258 (cops++)->
l =
CMOVE2(0, sprpt[0]);
2280 p =
ZTWO_PADDR(copdisplay.list[currentcop][0]);
2283 p =
ZTWO_PADDR(copdisplay.list[currentcop][1]);
2286 copdisplay.rebuild[0] = cops;
2302 copdisplay.rebuild[1] = copl;
2304 ami_update_par(info);
2305 ami_rebuild_copper(info->
par);
2309 static void __init amifb_setup_mcap(
char *spec)
2312 int vmin, vmax, hmin, hmax;
2319 if (!(p =
strsep(&spec,
";")) || !*p)
2324 if (!(p =
strsep(&spec,
";")) || !*p)
2327 if (vmax <= 0 || vmax <= vmin)
2329 if (!(p =
strsep(&spec,
";")) || !*p)
2334 if (!(p =
strsep(&spec,
"")) || !*p)
2337 if (hmax <= 0 || hmax <= hmin)
2350 if (!options || !*options)
2353 while ((this_opt =
strsep(&options,
",")) !=
NULL) {
2356 if (!
strcmp(this_opt,
"inverse")) {
2358 }
else if (!
strcmp(this_opt,
"ilbm"))
2360 else if (!
strncmp(this_opt,
"monitorcap:", 11))
2361 amifb_setup_mcap(this_opt + 11);
2362 else if (!
strncmp(this_opt,
"fstart:", 7))
2365 mode_option = this_opt;
2382 err = ami_decode_var(var, &par, info);
2387 ami_encode_var(var, &par);
2392 static int amifb_set_par(
struct fb_info *info)
2401 error = ami_decode_var(&info->
var, par, info);
2406 ami_build_copper(info);
2412 if (par->
bpp == 1) {
2414 info->
fix.type_aux = 0;
2415 }
else if (amifb_ilbm) {
2420 info->
fix.type_aux = 0;
2425 info->
fix.ywrapstep = 1;
2426 info->
fix.xpanstep = 0;
2427 info->
fix.ypanstep = 0;
2431 info->
fix.ywrapstep = 0;
2433 info->
fix.xpanstep = 1;
2435 info->
fix.xpanstep = 16 << maxfmode;
2436 info->
fix.ypanstep = 1;
2481 if (regno || !is_blanked) {
2482 #if defined(CONFIG_FB_AMIGA_AGA)
2486 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2489 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2497 #if defined(CONFIG_FB_AMIGA_ECS)
2503 color =
rgb2hw2(red, green, blue);
2505 for (i = regno + 12; i >= (
int)regno; i -= 4)
2506 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) |
color;
2507 mask <<= 2; color >>= 2;
2509 for (i = regno + 3; i >= (
int)regno; i--)
2510 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) |
color;
2524 static int amifb_blank(
int blank,
struct fb_info *info)
2526 do_blank = blank ? blank : -1;
2551 upx(16 << maxfmode, info->
var.xres_virtual) ||
2555 ami_pan_var(var, info);
2566 #if BITS_PER_LONG == 32
2567 #define BYTES_PER_LONG 4
2568 #define SHIFT_PER_LONG 5
2569 #elif BITS_PER_LONG == 64
2570 #define BYTES_PER_LONG 8
2571 #define SHIFT_PER_LONG 6
2573 #define Please update me
2582 static inline unsigned long comp(
unsigned long a,
unsigned long b,
2585 return ((a ^ b) & mask) ^
b;
2589 static inline unsigned long xor(
unsigned long a,
unsigned long b,
2592 return (a & mask) ^
b;
2600 static void bitcpy(
unsigned long *
dst,
int dst_idx,
const unsigned long *
src,
2604 int shift = dst_idx - src_idx,
left,
right;
2605 unsigned long d0,
d1;
2611 shift = dst_idx - src_idx;
2612 first = ~0
UL >> dst_idx;
2622 *dst = comp(*src, *dst, first);
2627 *dst = comp(*src, *dst, first);
2651 *dst = comp(*src, *dst, last);
2665 *dst = comp(*src >> right, *dst, first);
2668 *dst = comp(*src << left, *dst, first);
2673 *dst = comp(d0 << left | d1 >> right, *dst,
2682 *dst = comp(d0 >> right, *dst, first);
2688 *dst = comp(d0 << left | d1 >> right, *dst,
2700 *dst++ = d0 << left | d1 >>
right;
2703 *dst++ = d0 << left | d1 >>
right;
2706 *dst++ = d0 << left | d1 >>
right;
2709 *dst++ = d0 << left | d1 >>
right;
2715 *dst++ = d0 << left | d1 >>
right;
2723 *dst = comp(d0 << left, *dst, last);
2727 *dst = comp(d0 << left | d1 >> right,
2740 static void bitcpy_rev(
unsigned long *dst,
int dst_idx,
2741 const unsigned long *src,
int src_idx,
u32 n)
2743 unsigned long first, last;
2744 int shift = dst_idx - src_idx,
left,
right;
2745 unsigned long d0,
d1;
2762 shift = dst_idx - src_idx;
2769 if ((
unsigned long)dst_idx + 1 >=
n) {
2773 *dst = comp(*src, *dst, first);
2778 *dst = comp(*src, *dst, first);
2802 *dst = comp(*src, *dst, last);
2810 if ((
unsigned long)dst_idx + 1 >=
n) {
2816 *dst = comp(*src << left, *dst, first);
2817 }
else if (1 + (
unsigned long)src_idx >= n) {
2819 *dst = comp(*src >> right, *dst, first);
2824 *dst = comp(d0 >> right | d1 << left, *dst,
2833 *dst = comp(d0 << left, *dst, first);
2839 *dst = comp(d0 >> right | d1 << left, *dst,
2851 *dst-- = d0 >> right | d1 <<
left;
2854 *dst-- = d0 >> right | d1 <<
left;
2857 *dst-- = d0 >> right | d1 <<
left;
2860 *dst-- = d0 >> right | d1 <<
left;
2866 *dst-- = d0 >> right | d1 <<
left;
2874 *dst = comp(d0 >> right, *dst, last);
2878 *dst = comp(d0 >> right | d1 << left,
2892 static void bitcpy_not(
unsigned long *dst,
int dst_idx,
2893 const unsigned long *src,
int src_idx,
u32 n)
2895 unsigned long first, last;
2896 int shift = dst_idx - src_idx,
left,
right;
2897 unsigned long d0,
d1;
2903 shift = dst_idx - src_idx;
2904 first = ~0
UL >> dst_idx;
2914 *dst = comp(~*src, *dst, first);
2919 *dst = comp(~*src, *dst, first);
2943 *dst = comp(~*src, *dst, last);
2957 *dst = comp(~*src >> right, *dst, first);
2960 *dst = comp(~*src << left, *dst, first);
2965 *dst = comp(d0 << left | d1 >> right, *dst,
2974 *dst = comp(d0 >> right, *dst, first);
2980 *dst = comp(d0 << left | d1 >> right, *dst,
2992 *dst++ = d0 << left | d1 >>
right;
2995 *dst++ = d0 << left | d1 >>
right;
2998 *dst++ = d0 << left | d1 >>
right;
3001 *dst++ = d0 << left | d1 >>
right;
3007 *dst++ = d0 << left | d1 >>
right;
3015 *dst = comp(d0 << left, *dst, last);
3019 *dst = comp(d0 << left | d1 >> right,
3032 static void bitfill32(
unsigned long *dst,
int dst_idx,
u32 pat,
u32 n)
3034 unsigned long val = pat;
3035 unsigned long first, last;
3040 #if BITS_PER_LONG == 64
3044 first = ~0
UL >> dst_idx;
3051 *dst = comp(val, *dst, first);
3056 *dst = comp(val, *dst, first);
3079 *dst = comp(val, *dst, last);
3088 static void bitxor32(
unsigned long *dst,
int dst_idx,
u32 pat,
u32 n)
3090 unsigned long val = pat;
3091 unsigned long first, last;
3096 #if BITS_PER_LONG == 64
3100 first = ~0
UL >> dst_idx;
3107 *dst =
xor(val, *dst, first);
3112 *dst =
xor(val, *dst, first);
3131 *dst =
xor(val, *dst, last);
3135 static inline void fill_one_line(
int bpp,
unsigned long next_plane,
3136 unsigned long *dst,
int dst_idx,
u32 n,
3142 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3146 dst_idx += next_plane * 8;
3150 static inline void xor_one_line(
int bpp,
unsigned long next_plane,
3151 unsigned long *dst,
int dst_idx,
u32 n,
3157 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3161 dst_idx += next_plane * 8;
3166 static void amifb_fillrect(
struct fb_info *info,
3170 int dst_idx, x2, y2;
3183 x2 = x2 < info->
var.xres_virtual ? x2 : info->
var.xres_virtual;
3184 y2 = y2 < info->
var.yres_virtual ? y2 : info->
var.yres_virtual;
3185 width = x2 - rect->
dx;
3186 height = y2 - rect->
dy;
3188 dst = (
unsigned long *)
3190 dst_idx = ((
unsigned long)info->
screen_base & (BYTES_PER_LONG - 1)) * 8;
3193 switch (rect->
rop) {
3195 fill_one_line(info->
var.bits_per_pixel,
3202 dst, dst_idx, width, rect->
color);
3209 static inline void copy_one_line(
int bpp,
unsigned long next_plane,
3210 unsigned long *dst,
int dst_idx,
3211 unsigned long *src,
int src_idx,
u32 n)
3218 bitcpy(dst, dst_idx, src, src_idx, n);
3221 dst_idx += next_plane * 8;
3222 src_idx += next_plane * 8;
3226 static inline void copy_one_line_rev(
int bpp,
unsigned long next_plane,
3227 unsigned long *dst,
int dst_idx,
3228 unsigned long *src,
int src_idx,
u32 n)
3235 bitcpy_rev(dst, dst_idx, src, src_idx, n);
3238 dst_idx += next_plane * 8;
3239 src_idx += next_plane * 8;
3244 static void amifb_copyarea(
struct fb_info *info,
3250 unsigned long *
dst, *
src;
3251 int dst_idx, src_idx;
3257 dx = area->
dx > 0 ? area->
dx : 0;
3258 dy = area->
dy > 0 ? area->
dy : 0;
3259 x2 = x2 < info->
var.xres_virtual ? x2 : info->
var.xres_virtual;
3260 y2 = y2 < info->
var.yres_virtual ? y2 : info->
var.yres_virtual;
3264 if (area->
sx + dx < area->dx || area->
sy + dy < area->dy)
3268 sx = area->
sx + (dx - area->
dx);
3269 sy = area->
sy + (dy - area->
dy);
3272 if (sx + width > info->
var.xres_virtual ||
3273 sy + height > info->
var.yres_virtual)
3276 if (dy > sy || (dy == sy && dx > sx)) {
3281 dst = (
unsigned long *)
3284 dst_idx = ((
unsigned long)info->
screen_base & (BYTES_PER_LONG - 1)) * 8;
3286 dst_idx += dy * par->
next_line * 8 + dx;
3292 copy_one_line_rev(info->
var.bits_per_pixel,
3298 copy_one_line(info->
var.bits_per_pixel,
3308 static inline void expand_one_line(
int bpp,
unsigned long next_plane,
3309 unsigned long *dst,
int dst_idx,
u32 n,
3310 const u8 *data,
u32 bgcolor,
u32 fgcolor)
3312 const unsigned long *
src;
3318 if ((bgcolor ^ fgcolor) & 1) {
3319 src = (
unsigned long *)
3321 src_idx = ((
unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
3323 bitcpy(dst, dst_idx, src, src_idx, n);
3325 bitcpy_not(dst, dst_idx, src, src_idx, n);
3328 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
3333 dst_idx += next_plane * 8;
3352 x2 = image->
dx + image->
width;
3356 x2 = x2 < info->
var.xres_virtual ? x2 : info->
var.xres_virtual;
3357 y2 = y2 < info->
var.yres_virtual ? y2 : info->
var.yres_virtual;
3361 if (image->
depth == 1) {
3362 dst = (
unsigned long *)
3364 dst_idx = ((
unsigned long)info->
screen_base & (BYTES_PER_LONG - 1)) * 8;
3365 dst_idx += dy * par->
next_line * 8 + dx;
3367 pitch = (image->
width + 7) / 8;
3369 expand_one_line(info->
var.bits_per_pixel,
3379 image->
width, info->
var.bits_per_pixel);
3388 static int amifb_ioctl(
struct fb_info *info,
3389 unsigned int cmd,
unsigned long arg)
3401 i = ami_get_fix_cursorinfo(&crsr.fix, info->
par);
3405 sizeof(crsr.fix)) ? -
EFAULT : 0;
3408 i = ami_get_var_cursorinfo(&crsr.var,
3414 sizeof(crsr.var)) ? -
EFAULT : 0;
3419 return ami_set_var_cursorinfo(&crsr.var,
3424 i = ami_get_cursorstate(&crsr.state, info->
par);
3428 sizeof(crsr.state)) ? -
EFAULT : 0;
3433 return ami_set_cursorstate(&crsr.state, info->
par);
3443 static int flash_cursor(
void)
3445 static int cursorcount = 1;
3448 if (!--cursorcount) {
3449 cursorstate = -cursorstate;
3450 cursorcount = cursorrate;
3466 if (do_vmode_pan || do_vmode_full)
3467 ami_update_display(par);
3470 ami_init_display(par);
3474 ami_rebuild_copper(par);
3475 do_cursor = do_vmode_pan = 0;
3476 }
else if (do_cursor) {
3478 ami_set_sprite(par);
3482 ami_set_sprite(par);
3490 if (do_vmode_full) {
3491 ami_reinit_copper(par);
3498 static struct fb_ops amifb_ops = {
3500 .fb_check_var = amifb_check_var,
3501 .fb_set_par = amifb_set_par,
3502 .fb_setcolreg = amifb_setcolreg,
3503 .fb_blank = amifb_blank,
3504 .fb_pan_display = amifb_pan_display,
3505 .fb_fillrect = amifb_fillrect,
3506 .fb_copyarea = amifb_copyarea,
3507 .fb_imageblit = amifb_imageblit,
3508 .fb_ioctl = amifb_ioctl,
3516 static void *aligned_chipptr;
3521 if (!aligned_chipptr) {
3522 pr_err(
"amifb: No Chip RAM for frame buffer");
3525 memset(aligned_chipptr, 0, size);
3526 return (
u_long)aligned_chipptr;
3529 static inline void chipfree(
void)
3531 if (aligned_chipptr)
3543 int tag,
i, err = 0;
3554 amifb_setup(option);
3560 dev_err(&pdev->
dev,
"framebuffer_alloc failed\n");
3569 #ifdef CONFIG_FB_AMIGA_OCS
3583 #ifdef CONFIG_FB_AMIGA_ECS
3605 #ifdef CONFIG_FB_AMIGA_AGA
3623 #ifdef CONFIG_FB_AMIGA_OCS
3624 printk(
"Unknown graphics chipset, defaulting to OCS\n");
3626 goto default_chipset;
3659 info->
monspecs.hfmin = amifb_hfmin;
3660 info->
monspecs.hfmax = amifb_hfmax;
3661 info->
monspecs.vfmin = amifb_vfmin;
3662 info->
monspecs.vfmax = amifb_vfmax;
3673 info->
fbops = &amifb_ops;
3678 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
3709 info->
fix.smem_len);
3712 "Unable to map videomem cached writethrough\n");
3731 "fb vertb handler", info->
par);
3745 printk(
"fb%d: %s frame buffer device, using %dK of video memory\n",
3746 info->
node, info->
fix.id, info->
fix.smem_len>>10);
3786 .name =
"amiga-video",
3791 static int __init amifb_init(
void)
3798 static void __exit amifb_exit(
void)