0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043 #include <linux/module.h>
0044 #include <linux/kernel.h>
0045 #include <linux/errno.h>
0046 #include <linux/string.h>
0047 #include <linux/mm.h>
0048 #include <linux/delay.h>
0049 #include <linux/interrupt.h>
0050 #include <linux/fb.h>
0051 #include <linux/init.h>
0052 #include <linux/ioport.h>
0053 #include <linux/platform_device.h>
0054 #include <linux/uaccess.h>
0055
0056 #include <asm/irq.h>
0057 #include <asm/amigahw.h>
0058 #include <asm/amigaints.h>
0059 #include <asm/setup.h>
0060
0061 #include "c2p.h"
0062
0063
0064 #define DEBUG
0065
0066 #if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
0067 #define CONFIG_FB_AMIGA_OCS
0068 #endif
0069
0070 #if !defined(CONFIG_FB_AMIGA_OCS)
0071 # define IS_OCS (0)
0072 #elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
0073 # define IS_OCS (chipset == TAG_OCS)
0074 #else
0075 # define CONFIG_FB_AMIGA_OCS_ONLY
0076 # define IS_OCS (1)
0077 #endif
0078
0079 #if !defined(CONFIG_FB_AMIGA_ECS)
0080 # define IS_ECS (0)
0081 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
0082 # define IS_ECS (chipset == TAG_ECS)
0083 #else
0084 # define CONFIG_FB_AMIGA_ECS_ONLY
0085 # define IS_ECS (1)
0086 #endif
0087
0088 #if !defined(CONFIG_FB_AMIGA_AGA)
0089 # define IS_AGA (0)
0090 #elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
0091 # define IS_AGA (chipset == TAG_AGA)
0092 #else
0093 # define CONFIG_FB_AMIGA_AGA_ONLY
0094 # define IS_AGA (1)
0095 #endif
0096
0097 #ifdef DEBUG
0098 # define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
0099 #else
0100 # define DPRINTK(fmt, args...)
0101 #endif
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145
0146
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
0374
0375
0376
0377
0378
0379 #define BPC0_HIRES (0x8000)
0380 #define BPC0_BPU2 (0x4000)
0381 #define BPC0_BPU1 (0x2000)
0382 #define BPC0_BPU0 (0x1000)
0383 #define BPC0_HAM (0x0800)
0384 #define BPC0_DPF (0x0400)
0385 #define BPC0_COLOR (0x0200)
0386 #define BPC0_GAUD (0x0100)
0387 #define BPC0_UHRES (0x0080)
0388 #define BPC0_SHRES (0x0040)
0389 #define BPC0_BYPASS (0x0020)
0390 #define BPC0_BPU3 (0x0010)
0391 #define BPC0_LPEN (0x0008)
0392 #define BPC0_LACE (0x0004)
0393 #define BPC0_ERSY (0x0002)
0394 #define BPC0_ECSENA (0x0001)
0395
0396
0397
0398
0399
0400 #define BPC2_ZDBPSEL2 (0x4000)
0401 #define BPC2_ZDBPSEL1 (0x2000)
0402 #define BPC2_ZDBPSEL0 (0x1000)
0403 #define BPC2_ZDBPEN (0x0800)
0404 #define BPC2_ZDCTEN (0x0400)
0405 #define BPC2_KILLEHB (0x0200)
0406 #define BPC2_RDRAM (0x0100)
0407 #define BPC2_SOGEN (0x0080)
0408 #define BPC2_PF2PRI (0x0040)
0409 #define BPC2_PF2P2 (0x0020)
0410 #define BPC2_PF2P1 (0x0010)
0411 #define BPC2_PF2P0 (0x0008)
0412 #define BPC2_PF1P2 (0x0004)
0413 #define BPC2_PF1P1 (0x0002)
0414 #define BPC2_PF1P0 (0x0001)
0415
0416
0417
0418
0419
0420 #define BPC3_BANK2 (0x8000)
0421 #define BPC3_BANK1 (0x4000)
0422 #define BPC3_BANK0 (0x2000)
0423 #define BPC3_PF2OF2 (0x1000)
0424 #define BPC3_PF2OF1 (0x0800)
0425 #define BPC3_PF2OF0 (0x0400)
0426 #define BPC3_LOCT (0x0200)
0427 #define BPC3_SPRES1 (0x0080)
0428 #define BPC3_SPRES0 (0x0040)
0429 #define BPC3_BRDRBLNK (0x0020)
0430 #define BPC3_BRDRTRAN (0x0010)
0431 #define BPC3_ZDCLKEN (0x0004)
0432 #define BPC3_BRDRSPRT (0x0002)
0433 #define BPC3_EXTBLKEN (0x0001)
0434
0435
0436
0437
0438
0439 #define BPC4_BPLAM7 (0x8000)
0440 #define BPC4_BPLAM6 (0x4000)
0441 #define BPC4_BPLAM5 (0x2000)
0442 #define BPC4_BPLAM4 (0x1000)
0443 #define BPC4_BPLAM3 (0x0800)
0444 #define BPC4_BPLAM2 (0x0400)
0445 #define BPC4_BPLAM1 (0x0200)
0446 #define BPC4_BPLAM0 (0x0100)
0447 #define BPC4_ESPRM7 (0x0080)
0448 #define BPC4_ESPRM6 (0x0040)
0449 #define BPC4_ESPRM5 (0x0020)
0450 #define BPC4_ESPRM4 (0x0010)
0451 #define BPC4_OSPRM7 (0x0008)
0452 #define BPC4_OSPRM6 (0x0004)
0453 #define BPC4_OSPRM5 (0x0002)
0454 #define BPC4_OSPRM4 (0x0001)
0455
0456
0457
0458
0459
0460 #define BMC0_HARDDIS (0x4000)
0461 #define BMC0_LPENDIS (0x2000)
0462 #define BMC0_VARVBEN (0x1000)
0463 #define BMC0_LOLDIS (0x0800)
0464 #define BMC0_CSCBEN (0x0400)
0465 #define BMC0_VARVSYEN (0x0200)
0466 #define BMC0_VARHSYEN (0x0100)
0467 #define BMC0_VARBEAMEN (0x0080)
0468 #define BMC0_DUAL (0x0040)
0469 #define BMC0_PAL (0x0020)
0470 #define BMC0_VARCSYEN (0x0010)
0471 #define BMC0_BLANKEN (0x0008)
0472 #define BMC0_CSYTRUE (0x0004)
0473 #define BMC0_VSYTRUE (0x0002)
0474 #define BMC0_HSYTRUE (0x0001)
0475
0476
0477
0478
0479
0480
0481 #define FMODE_SSCAN2 (0x8000)
0482 #define FMODE_BSCAN2 (0x4000)
0483 #define FMODE_SPAGEM (0x0008)
0484 #define FMODE_SPR32 (0x0004)
0485 #define FMODE_BPAGEM (0x0002)
0486 #define FMODE_BPL32 (0x0001)
0487
0488
0489
0490
0491
0492
0493
0494 enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
0495
0496
0497
0498
0499
0500 enum { TAG_OCS, TAG_ECS, TAG_AGA };
0501
0502
0503
0504
0505
0506 enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516 static u_long pixclock[3];
0517 static u_short maxdepth[3];
0518 static u_short maxfmode, chipset;
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528 #define PAL_DIWSTRT_H (360)
0529 #define PAL_DIWSTRT_V (48)
0530 #define PAL_HTOTAL (1816)
0531 #define PAL_VTOTAL (625)
0532
0533 #define NTSC_DIWSTRT_H (360)
0534 #define NTSC_DIWSTRT_V (40)
0535 #define NTSC_HTOTAL (1816)
0536 #define NTSC_VTOTAL (525)
0537
0538
0539
0540
0541
0542
0543 #define up2(v) (((v) + 1) & -2)
0544 #define down2(v) ((v) & -2)
0545 #define div2(v) ((v)>>1)
0546 #define mod2(v) ((v) & 1)
0547
0548 #define up4(v) (((v) + 3) & -4)
0549 #define down4(v) ((v) & -4)
0550 #define mul4(v) ((v) << 2)
0551 #define div4(v) ((v)>>2)
0552 #define mod4(v) ((v) & 3)
0553
0554 #define up8(v) (((v) + 7) & -8)
0555 #define down8(v) ((v) & -8)
0556 #define div8(v) ((v)>>3)
0557 #define mod8(v) ((v) & 7)
0558
0559 #define up16(v) (((v) + 15) & -16)
0560 #define down16(v) ((v) & -16)
0561 #define div16(v) ((v)>>4)
0562 #define mod16(v) ((v) & 15)
0563
0564 #define up32(v) (((v) + 31) & -32)
0565 #define down32(v) ((v) & -32)
0566 #define div32(v) ((v)>>5)
0567 #define mod32(v) ((v) & 31)
0568
0569 #define up64(v) (((v) + 63) & -64)
0570 #define down64(v) ((v) & -64)
0571 #define div64(v) ((v)>>6)
0572 #define mod64(v) ((v) & 63)
0573
0574 #define upx(x, v) (((v) + (x) - 1) & -(x))
0575 #define downx(x, v) ((v) & -(x))
0576 #define modx(x, v) ((v) & ((x) - 1))
0577
0578
0579
0580
0581
0582
0583
0584
0585 #ifdef __mc68000__
0586 #define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
0587 "d" (x2), "d" ((long)((x1) / 0x100000000ULL)), "0" ((long)(x1))); res;})
0588 #else
0589
0590 #define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
0591 ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
0592 #endif
0593
0594 #define highw(x) ((u_long)(x)>>16 & 0xffff)
0595 #define loww(x) ((u_long)(x) & 0xffff)
0596
0597 #define custom amiga_custom
0598
0599 #define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
0600 #define VBlankOff() custom.intena = IF_COPER
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610 #define VIDEOMEMSIZE_AGA_2M (1310720)
0611 #define VIDEOMEMSIZE_AGA_1M (786432)
0612 #define VIDEOMEMSIZE_ECS_2M (655360)
0613 #define VIDEOMEMSIZE_ECS_1M (393216)
0614 #define VIDEOMEMSIZE_OCS (262144)
0615
0616 #define SPRITEMEMSIZE (64 * 64 / 4)
0617 #define DUMMYSPRITEMEMSIZE (8)
0618 static u_long spritememory;
0619
0620 #define CHIPRAM_SAFETY_LIMIT (16384)
0621
0622 static u_long videomemory;
0623
0624
0625
0626
0627
0628
0629
0630 static u_long min_fstrt = 192;
0631
0632 #define assignchunk(name, type, ptr, size) \
0633 { \
0634 (name) = (type)(ptr); \
0635 ptr += size; \
0636 }
0637
0638
0639
0640
0641
0642
0643 #define CMOVE(val, reg) (CUSTOM_OFS(reg) << 16 | (val))
0644 #define CMOVE2(val, reg) ((CUSTOM_OFS(reg) + 2) << 16 | (val))
0645 #define CWAIT(x, y) (((y) & 0x1fe) << 23 | ((x) & 0x7f0) << 13 | 0x0001fffe)
0646 #define CEND (0xfffffffe)
0647
0648
0649 typedef union {
0650 u_long l;
0651 u_short w[2];
0652 } copins;
0653
0654 static struct copdisplay {
0655 copins *init;
0656 copins *wait;
0657 copins *list[2][2];
0658 copins *rebuild[2];
0659 } copdisplay;
0660
0661 static u_short currentcop = 0;
0662
0663
0664
0665
0666
0667
0668
0669 #define FBIOGET_FCURSORINFO 0x4607
0670 #define FBIOGET_VCURSORINFO 0x4608
0671 #define FBIOPUT_VCURSORINFO 0x4609
0672 #define FBIOGET_CURSORSTATE 0x460A
0673 #define FBIOPUT_CURSORSTATE 0x460B
0674
0675
0676 struct fb_fix_cursorinfo {
0677 __u16 crsr_width;
0678 __u16 crsr_height;
0679 __u16 crsr_xsize;
0680 __u16 crsr_ysize;
0681 __u16 crsr_color1;
0682 __u16 crsr_color2;
0683 };
0684
0685 struct fb_var_cursorinfo {
0686 __u16 width;
0687 __u16 height;
0688 __u16 xspot;
0689 __u16 yspot;
0690 __u8 data[1];
0691 };
0692
0693 struct fb_cursorstate {
0694 __s16 xoffset;
0695 __s16 yoffset;
0696 __u16 mode;
0697 };
0698
0699 #define FB_CURSOR_OFF 0
0700 #define FB_CURSOR_ON 1
0701 #define FB_CURSOR_FLASH 2
0702
0703
0704
0705
0706
0707
0708 static int cursorrate = 20;
0709 static u_short cursorstate = -1;
0710 static u_short cursormode = FB_CURSOR_OFF;
0711
0712 static u_short *lofsprite, *shfsprite, *dummysprite;
0713
0714
0715
0716
0717
0718 struct amifb_par {
0719
0720
0721
0722 int xres;
0723 int yres;
0724 int vxres;
0725 int vyres;
0726 int xoffset;
0727 int yoffset;
0728 u_short bpp;
0729 u_short clk_shift;
0730 u_short line_shift;
0731 int vmode;
0732 u_short diwstrt_h;
0733 u_short diwstop_h;
0734 u_short diwstrt_v;
0735 u_short diwstop_v;
0736 u_long next_line;
0737 u_long next_plane;
0738
0739
0740
0741 struct {
0742 short crsr_x;
0743 short crsr_y;
0744 short spot_x;
0745 short spot_y;
0746 u_short height;
0747 u_short width;
0748 u_short fmode;
0749 } crsr;
0750
0751
0752
0753 u_long bplpt0;
0754 u_long bplpt0wrap;
0755 u_short ddfstrt;
0756 u_short ddfstop;
0757 u_short bpl1mod;
0758 u_short bpl2mod;
0759 u_short bplcon0;
0760 u_short bplcon1;
0761 u_short htotal;
0762 u_short vtotal;
0763
0764
0765
0766 u_short bplcon3;
0767 u_short beamcon0;
0768 u_short hsstrt;
0769 u_short hsstop;
0770 u_short hbstrt;
0771 u_short hbstop;
0772 u_short vsstrt;
0773 u_short vsstop;
0774 u_short vbstrt;
0775 u_short vbstop;
0776 u_short hcenter;
0777
0778
0779
0780 u_short fmode;
0781 };
0782
0783
0784
0785
0786
0787
0788 static u_char red0, green0, blue0;
0789
0790
0791 #if defined(CONFIG_FB_AMIGA_ECS)
0792 static u_short ecs_palette[32];
0793 #endif
0794
0795
0796
0797
0798
0799
0800 static u_short do_vmode_full = 0;
0801 static u_short do_vmode_pan = 0;
0802 static short do_blank = 0;
0803 static u_short do_cursor = 0;
0804
0805
0806
0807
0808
0809
0810 static u_short is_blanked = 0;
0811 static u_short is_lace = 0;
0812
0813
0814
0815
0816
0817
0818 static struct fb_videomode ami_modedb[] __initdata = {
0819
0820
0821
0822
0823
0824
0825
0826 {
0827
0828 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
0829 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0830 }, {
0831
0832 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
0833 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0834 }, {
0835
0836 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
0837 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0838 }, {
0839
0840 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
0841 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0842 }, {
0843
0844 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
0845 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0846 }, {
0847
0848 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72,
0849 16,
0850 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0851 }, {
0852
0853 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
0854 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0855 }, {
0856
0857 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52,
0858 10,
0859 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0860 }, {
0861
0862 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
0863 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0864 }, {
0865
0866 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80,
0867 16,
0868 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0869 }, {
0870
0871 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
0872 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0873 }, {
0874
0875 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80,
0876 14,
0877 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0878 }, {
0879
0880 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
0881 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
0882 }, {
0883
0884 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
0885 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0886 }, {
0887
0888 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80,
0889 14,
0890 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0891 }, {
0892
0893 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
0894 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
0895 }, {
0896
0897 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
0898 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0899 }, {
0900
0901 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80,
0902 14,
0903 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
0904 },
0905
0906
0907
0908
0909
0910 {
0911
0912 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
0913 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0914 }, {
0915
0916 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
0917 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT,
0918 FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0919 },
0920
0921 #if 0
0922
0923
0924
0925
0926
0927
0928 {
0929
0930 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
0931 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0932 }, {
0933
0934 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
0935 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
0936 }
0937 #endif
0938 };
0939
0940 #define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
0941
0942 static char *mode_option __initdata = NULL;
0943 static int round_down_bpp = 1;
0944
0945
0946
0947
0948
0949
0950 #define DEFMODE_PAL 2
0951 #define DEFMODE_NTSC 0
0952 #define DEFMODE_AMBER_PAL 3
0953 #define DEFMODE_AMBER_NTSC 1
0954 #define DEFMODE_AGA 19
0955
0956
0957 static int amifb_ilbm = 0;
0958
0959 static u32 amifb_hfmin __initdata;
0960 static u32 amifb_hfmax __initdata;
0961 static u16 amifb_vfmin __initdata;
0962 static u16 amifb_vfmax __initdata;
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002 #define hscroll2hw(hscroll) \
1003 (((hscroll) << 12 & 0x3000) | ((hscroll) << 8 & 0xc300) | \
1004 ((hscroll) << 4 & 0x0c00) | ((hscroll) << 2 & 0x00f0) | \
1005 ((hscroll)>>2 & 0x000f))
1006
1007
1008
1009 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
1010 (((diwstrt_v) << 7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1011 #define diwstop2hw(diwstop_h, diwstop_v) \
1012 (((diwstop_v) << 7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1013 #define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1014 (((diwstop_h) << 3 & 0x2000) | ((diwstop_h) << 11 & 0x1800) | \
1015 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1016 ((diwstrt_h) << 3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1017
1018
1019
1020 #define ddfstrt2hw(ddfstrt) div8(ddfstrt)
1021 #define ddfstop2hw(ddfstop) div8(ddfstop)
1022
1023
1024
1025 #define hsstrt2hw(hsstrt) (div8(hsstrt))
1026 #define hsstop2hw(hsstop) (div8(hsstop))
1027 #define htotal2hw(htotal) (div8(htotal) - 1)
1028 #define vsstrt2hw(vsstrt) (div2(vsstrt))
1029 #define vsstop2hw(vsstop) (div2(vsstop))
1030 #define vtotal2hw(vtotal) (div2(vtotal) - 1)
1031 #define hcenter2hw(htotal) (div8(htotal))
1032
1033
1034
1035 #define hbstrt2hw(hbstrt) (((hbstrt) << 8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1036 #define hbstop2hw(hbstop) (((hbstop) << 8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1037 #define vbstrt2hw(vbstrt) (div2(vbstrt))
1038 #define vbstop2hw(vbstop) (div2(vbstop))
1039
1040
1041
1042 #define rgb2hw8_high(red, green, blue) \
1043 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1044 #define rgb2hw8_low(red, green, blue) \
1045 (((red & 0x0f) << 8) | ((green & 0x0f) << 4) | (blue & 0x0f))
1046 #define rgb2hw4(red, green, blue) \
1047 (((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1048 #define rgb2hw2(red, green, blue) \
1049 (((red & 0xc0) << 4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1050
1051
1052
1053 #define spr2hw_pos(start_v, start_h) \
1054 (((start_v) << 7 & 0xff00) | ((start_h)>>3 & 0x00ff))
1055 #define spr2hw_ctl(start_v, start_h, stop_v) \
1056 (((stop_v) << 7 & 0xff00) | ((start_v)>>4 & 0x0040) | \
1057 ((stop_v)>>5 & 0x0020) | ((start_h) << 3 & 0x0018) | \
1058 ((start_v)>>7 & 0x0004) | ((stop_v)>>8 & 0x0002) | \
1059 ((start_h)>>2 & 0x0001))
1060
1061
1062 #define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
1063
1064
1065
1066
1067
1068 #define COPINITSIZE (sizeof(copins) * 40)
1069
1070 enum {
1071 cip_bplcon0
1072 };
1073
1074
1075
1076
1077
1078
1079 #define COPLISTSIZE (sizeof(copins) * 64)
1080
1081 enum {
1082 cop_wait, cop_bplcon0,
1083 cop_spr0ptrh, cop_spr0ptrl,
1084 cop_diwstrt, cop_diwstop,
1085 cop_diwhigh,
1086 };
1087
1088
1089
1090
1091
1092 static u_short bplpixmode[3] = {
1093 BPC0_SHRES,
1094 BPC0_HIRES,
1095 0
1096 };
1097
1098 static u_short sprpixmode[3] = {
1099 BPC3_SPRES1 | BPC3_SPRES0,
1100 BPC3_SPRES1,
1101 BPC3_SPRES0
1102 };
1103
1104
1105
1106
1107
1108 static u_short bplfetchmode[3] = {
1109 0,
1110 FMODE_BPL32,
1111 FMODE_BPAGEM | FMODE_BPL32
1112 };
1113
1114 static u_short sprfetchmode[3] = {
1115 0,
1116 FMODE_SPR32,
1117 FMODE_SPAGEM | FMODE_SPR32
1118 };
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128 static int ami_decode_var(struct fb_var_screeninfo *var, struct amifb_par *par,
1129 const struct fb_info *info)
1130 {
1131 u_short clk_shift, line_shift;
1132 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
1133 u_int htotal, vtotal;
1134
1135
1136
1137
1138
1139 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
1140 if (var->pixclock <= pixclock[clk_shift])
1141 break;
1142 if (clk_shift > TAG_LORES) {
1143 DPRINTK("pixclock too high\n");
1144 return -EINVAL;
1145 }
1146 par->clk_shift = clk_shift;
1147
1148
1149
1150
1151
1152 if ((par->xres = var->xres) < 64)
1153 par->xres = 64;
1154 if ((par->yres = var->yres) < 64)
1155 par->yres = 64;
1156 if ((par->vxres = var->xres_virtual) < par->xres)
1157 par->vxres = par->xres;
1158 if ((par->vyres = var->yres_virtual) < par->yres)
1159 par->vyres = par->yres;
1160
1161 par->bpp = var->bits_per_pixel;
1162 if (!var->nonstd) {
1163 if (par->bpp < 1)
1164 par->bpp = 1;
1165 if (par->bpp > maxdepth[clk_shift]) {
1166 if (round_down_bpp && maxdepth[clk_shift])
1167 par->bpp = maxdepth[clk_shift];
1168 else {
1169 DPRINTK("invalid bpp\n");
1170 return -EINVAL;
1171 }
1172 }
1173 } else if (var->nonstd == FB_NONSTD_HAM) {
1174 if (par->bpp < 6)
1175 par->bpp = 6;
1176 if (par->bpp != 6) {
1177 if (par->bpp < 8)
1178 par->bpp = 8;
1179 if (par->bpp != 8 || !IS_AGA) {
1180 DPRINTK("invalid bpp for ham mode\n");
1181 return -EINVAL;
1182 }
1183 }
1184 } else {
1185 DPRINTK("unknown nonstd mode\n");
1186 return -EINVAL;
1187 }
1188
1189
1190
1191
1192
1193
1194 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
1195 switch (par->vmode & FB_VMODE_MASK) {
1196 case FB_VMODE_INTERLACED:
1197 line_shift = 0;
1198 break;
1199 case FB_VMODE_NONINTERLACED:
1200 line_shift = 1;
1201 break;
1202 case FB_VMODE_DOUBLE:
1203 if (!IS_AGA) {
1204 DPRINTK("double mode only possible with aga\n");
1205 return -EINVAL;
1206 }
1207 line_shift = 2;
1208 break;
1209 default:
1210 DPRINTK("unknown video mode\n");
1211 return -EINVAL;
1212 break;
1213 }
1214 par->line_shift = line_shift;
1215
1216
1217
1218
1219
1220 xres_n = par->xres << clk_shift;
1221 yres_n = par->yres << line_shift;
1222 par->htotal = down8((var->left_margin + par->xres + var->right_margin +
1223 var->hsync_len) << clk_shift);
1224 par->vtotal =
1225 down2(((var->upper_margin + par->yres + var->lower_margin +
1226 var->vsync_len) << line_shift) + 1);
1227
1228 if (IS_AGA)
1229 par->bplcon3 = sprpixmode[clk_shift];
1230 else
1231 par->bplcon3 = 0;
1232 if (var->sync & FB_SYNC_BROADCAST) {
1233 par->diwstop_h = par->htotal -
1234 ((var->right_margin - var->hsync_len) << clk_shift);
1235 if (IS_AGA)
1236 par->diwstop_h += mod4(var->hsync_len);
1237 else
1238 par->diwstop_h = down4(par->diwstop_h);
1239
1240 par->diwstrt_h = par->diwstop_h - xres_n;
1241 par->diwstop_v = par->vtotal -
1242 ((var->lower_margin - var->vsync_len) << line_shift);
1243 par->diwstrt_v = par->diwstop_v - yres_n;
1244 if (par->diwstop_h >= par->htotal + 8) {
1245 DPRINTK("invalid diwstop_h\n");
1246 return -EINVAL;
1247 }
1248 if (par->diwstop_v > par->vtotal) {
1249 DPRINTK("invalid diwstop_v\n");
1250 return -EINVAL;
1251 }
1252
1253 if (!IS_OCS) {
1254
1255 par->hsstrt = 160;
1256 par->hsstop = 320;
1257 par->vsstrt = 30;
1258 par->vsstop = 34;
1259 } else {
1260 par->hsstrt = 0;
1261 par->hsstop = 0;
1262 par->vsstrt = 0;
1263 par->vsstop = 0;
1264 }
1265 if (par->vtotal > (PAL_VTOTAL + NTSC_VTOTAL) / 2) {
1266
1267 if (par->htotal != PAL_HTOTAL) {
1268 DPRINTK("htotal invalid for pal\n");
1269 return -EINVAL;
1270 }
1271 if (par->diwstrt_h < PAL_DIWSTRT_H) {
1272 DPRINTK("diwstrt_h too low for pal\n");
1273 return -EINVAL;
1274 }
1275 if (par->diwstrt_v < PAL_DIWSTRT_V) {
1276 DPRINTK("diwstrt_v too low for pal\n");
1277 return -EINVAL;
1278 }
1279 htotal = PAL_HTOTAL>>clk_shift;
1280 vtotal = PAL_VTOTAL>>1;
1281 if (!IS_OCS) {
1282 par->beamcon0 = BMC0_PAL;
1283 par->bplcon3 |= BPC3_BRDRBLNK;
1284 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1285 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1286 par->beamcon0 = BMC0_PAL;
1287 par->hsstop = 1;
1288 } else if (amiga_vblank != 50) {
1289 DPRINTK("pal not supported by this chipset\n");
1290 return -EINVAL;
1291 }
1292 } else {
1293
1294
1295
1296
1297 if (par->htotal != NTSC_HTOTAL) {
1298 DPRINTK("htotal invalid for ntsc\n");
1299 return -EINVAL;
1300 }
1301 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
1302 DPRINTK("diwstrt_h too low for ntsc\n");
1303 return -EINVAL;
1304 }
1305 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
1306 DPRINTK("diwstrt_v too low for ntsc\n");
1307 return -EINVAL;
1308 }
1309 htotal = NTSC_HTOTAL>>clk_shift;
1310 vtotal = NTSC_VTOTAL>>1;
1311 if (!IS_OCS) {
1312 par->beamcon0 = 0;
1313 par->bplcon3 |= BPC3_BRDRBLNK;
1314 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
1315 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
1316 par->beamcon0 = 0;
1317 par->hsstop = 1;
1318 } else if (amiga_vblank != 60) {
1319 DPRINTK("ntsc not supported by this chipset\n");
1320 return -EINVAL;
1321 }
1322 }
1323 if (IS_OCS) {
1324 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
1325 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
1326 DPRINTK("invalid position for display on ocs\n");
1327 return -EINVAL;
1328 }
1329 }
1330 } else if (!IS_OCS) {
1331
1332 par->hsstrt = var->right_margin << clk_shift;
1333 par->hsstop = (var->right_margin + var->hsync_len) << clk_shift;
1334 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
1335 if (!IS_AGA)
1336 par->diwstop_h = down4(par->diwstop_h) - 16;
1337 par->diwstrt_h = par->diwstop_h - xres_n;
1338 par->hbstop = par->diwstrt_h + 4;
1339 par->hbstrt = par->diwstop_h + 4;
1340 if (par->hbstrt >= par->htotal + 8)
1341 par->hbstrt -= par->htotal;
1342 par->hcenter = par->hsstrt + (par->htotal >> 1);
1343 par->vsstrt = var->lower_margin << line_shift;
1344 par->vsstop = (var->lower_margin + var->vsync_len) << line_shift;
1345 par->diwstop_v = par->vtotal;
1346 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
1347 par->diwstop_v -= 2;
1348 par->diwstrt_v = par->diwstop_v - yres_n;
1349 par->vbstop = par->diwstrt_v - 2;
1350 par->vbstrt = par->diwstop_v - 2;
1351 if (par->vtotal > 2048) {
1352 DPRINTK("vtotal too high\n");
1353 return -EINVAL;
1354 }
1355 if (par->htotal > 2048) {
1356 DPRINTK("htotal too high\n");
1357 return -EINVAL;
1358 }
1359 par->bplcon3 |= BPC3_EXTBLKEN;
1360 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
1361 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
1362 BMC0_PAL | BMC0_VARCSYEN;
1363 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
1364 par->beamcon0 |= BMC0_HSYTRUE;
1365 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
1366 par->beamcon0 |= BMC0_VSYTRUE;
1367 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
1368 par->beamcon0 |= BMC0_CSYTRUE;
1369 htotal = par->htotal>>clk_shift;
1370 vtotal = par->vtotal>>1;
1371 } else {
1372 DPRINTK("only broadcast modes possible for ocs\n");
1373 return -EINVAL;
1374 }
1375
1376
1377
1378
1379
1380 fconst = 16 << maxfmode << clk_shift;
1381
1382
1383
1384
1385
1386
1387
1388 fsize = ((maxfmode + clk_shift <= 1) ? fconst : 64);
1389 fstrt = downx(fconst, par->diwstrt_h - 4) - fsize;
1390 if (fstrt < min_fstrt) {
1391 DPRINTK("fetch start too low\n");
1392 return -EINVAL;
1393 }
1394
1395
1396
1397
1398
1399 fstrt = downx(fconst, par->diwstrt_h - fconst + (1 << clk_shift) - 4) -
1400 fsize;
1401 if (fstrt < min_fstrt)
1402 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1403
1404 maxfetchstop = down16(par->htotal - 80);
1405
1406 fstrt = downx(fconst, par->diwstrt_h - 4) - 64 - fconst;
1407 fsize = upx(fconst, xres_n +
1408 modx(fconst, downx(1 << clk_shift, par->diwstrt_h - 4)));
1409 if (fstrt + fsize > maxfetchstop)
1410 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1411
1412 fsize = upx(fconst, xres_n);
1413 if (fstrt + fsize > maxfetchstop) {
1414 DPRINTK("fetch stop too high\n");
1415 return -EINVAL;
1416 }
1417
1418 if (maxfmode + clk_shift <= 1) {
1419 fsize = up64(xres_n + fconst - 1);
1420 if (min_fstrt + fsize - 64 > maxfetchstop)
1421 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
1422
1423 fsize = up64(xres_n);
1424 if (min_fstrt + fsize - 64 > maxfetchstop) {
1425 DPRINTK("fetch size too high\n");
1426 return -EINVAL;
1427 }
1428
1429 fsize -= 64;
1430 } else
1431 fsize -= fconst;
1432
1433
1434
1435
1436
1437 if (par->htotal - fsize - 64 < par->bpp * 64)
1438 par->vmode &= ~FB_VMODE_YWRAP;
1439
1440
1441
1442
1443
1444 if (amifb_ilbm) {
1445 par->next_plane = div8(upx(16 << maxfmode, par->vxres));
1446 par->next_line = par->bpp * par->next_plane;
1447 if (par->next_line * par->vyres > info->fix.smem_len) {
1448 DPRINTK("too few video mem\n");
1449 return -EINVAL;
1450 }
1451 } else {
1452 par->next_line = div8(upx(16 << maxfmode, par->vxres));
1453 par->next_plane = par->vyres * par->next_line;
1454 if (par->next_plane * par->bpp > info->fix.smem_len) {
1455 DPRINTK("too few video mem\n");
1456 return -EINVAL;
1457 }
1458 }
1459
1460
1461
1462
1463
1464 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
1465 if (!IS_OCS)
1466 par->bplcon0 |= BPC0_ECSENA;
1467 if (par->bpp == 8)
1468 par->bplcon0 |= BPC0_BPU3;
1469 else
1470 par->bplcon0 |= par->bpp << 12;
1471 if (var->nonstd == FB_NONSTD_HAM)
1472 par->bplcon0 |= BPC0_HAM;
1473 if (var->sync & FB_SYNC_EXT)
1474 par->bplcon0 |= BPC0_ERSY;
1475
1476 if (IS_AGA)
1477 par->fmode = bplfetchmode[maxfmode];
1478
1479 switch (par->vmode & FB_VMODE_MASK) {
1480 case FB_VMODE_INTERLACED:
1481 par->bplcon0 |= BPC0_LACE;
1482 break;
1483 case FB_VMODE_DOUBLE:
1484 if (IS_AGA)
1485 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
1486 break;
1487 }
1488
1489 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
1490 par->xoffset = var->xoffset;
1491 par->yoffset = var->yoffset;
1492 if (par->vmode & FB_VMODE_YWRAP) {
1493 if (par->yoffset >= par->vyres)
1494 par->xoffset = par->yoffset = 0;
1495 } else {
1496 if (par->xoffset > upx(16 << maxfmode, par->vxres - par->xres) ||
1497 par->yoffset > par->vyres - par->yres)
1498 par->xoffset = par->yoffset = 0;
1499 }
1500 } else
1501 par->xoffset = par->yoffset = 0;
1502
1503 par->crsr.crsr_x = par->crsr.crsr_y = 0;
1504 par->crsr.spot_x = par->crsr.spot_y = 0;
1505 par->crsr.height = par->crsr.width = 0;
1506
1507 return 0;
1508 }
1509
1510
1511
1512
1513
1514
1515 static void ami_encode_var(struct fb_var_screeninfo *var,
1516 struct amifb_par *par)
1517 {
1518 u_short clk_shift, line_shift;
1519
1520 memset(var, 0, sizeof(struct fb_var_screeninfo));
1521
1522 clk_shift = par->clk_shift;
1523 line_shift = par->line_shift;
1524
1525 var->xres = par->xres;
1526 var->yres = par->yres;
1527 var->xres_virtual = par->vxres;
1528 var->yres_virtual = par->vyres;
1529 var->xoffset = par->xoffset;
1530 var->yoffset = par->yoffset;
1531
1532 var->bits_per_pixel = par->bpp;
1533 var->grayscale = 0;
1534
1535 var->red.offset = 0;
1536 var->red.msb_right = 0;
1537 var->red.length = par->bpp;
1538 if (par->bplcon0 & BPC0_HAM)
1539 var->red.length -= 2;
1540 var->blue = var->green = var->red;
1541 var->transp.offset = 0;
1542 var->transp.length = 0;
1543 var->transp.msb_right = 0;
1544
1545 if (par->bplcon0 & BPC0_HAM)
1546 var->nonstd = FB_NONSTD_HAM;
1547 else
1548 var->nonstd = 0;
1549 var->activate = 0;
1550
1551 var->height = -1;
1552 var->width = -1;
1553
1554 var->pixclock = pixclock[clk_shift];
1555
1556 if (IS_AGA && par->fmode & FMODE_BSCAN2)
1557 var->vmode = FB_VMODE_DOUBLE;
1558 else if (par->bplcon0 & BPC0_LACE)
1559 var->vmode = FB_VMODE_INTERLACED;
1560 else
1561 var->vmode = FB_VMODE_NONINTERLACED;
1562
1563 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
1564 var->hsync_len = (par->hsstop - par->hsstrt)>>clk_shift;
1565 var->right_margin = par->hsstrt>>clk_shift;
1566 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1567 var->vsync_len = (par->vsstop - par->vsstrt)>>line_shift;
1568 var->lower_margin = par->vsstrt>>line_shift;
1569 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
1570 var->sync = 0;
1571 if (par->beamcon0 & BMC0_HSYTRUE)
1572 var->sync |= FB_SYNC_HOR_HIGH_ACT;
1573 if (par->beamcon0 & BMC0_VSYTRUE)
1574 var->sync |= FB_SYNC_VERT_HIGH_ACT;
1575 if (par->beamcon0 & BMC0_CSYTRUE)
1576 var->sync |= FB_SYNC_COMP_HIGH_ACT;
1577 } else {
1578 var->sync = FB_SYNC_BROADCAST;
1579 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
1580 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
1581 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
1582 var->vsync_len = 4>>line_shift;
1583 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
1584 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
1585 var->lower_margin - var->vsync_len;
1586 }
1587
1588 if (par->bplcon0 & BPC0_ERSY)
1589 var->sync |= FB_SYNC_EXT;
1590 if (par->vmode & FB_VMODE_YWRAP)
1591 var->vmode |= FB_VMODE_YWRAP;
1592 }
1593
1594
1595
1596
1597
1598
1599 static void ami_update_par(struct fb_info *info)
1600 {
1601 struct amifb_par *par = info->par;
1602 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
1603
1604 clk_shift = par->clk_shift;
1605
1606 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
1607 par->xoffset = upx(16 << maxfmode, par->xoffset);
1608
1609 fconst = 16 << maxfmode << clk_shift;
1610 vshift = modx(16 << maxfmode, par->xoffset);
1611 fstrt = par->diwstrt_h - (vshift << clk_shift) - 4;
1612 fsize = (par->xres + vshift) << clk_shift;
1613 shift = modx(fconst, fstrt);
1614 move = downx(2 << maxfmode, div8(par->xoffset));
1615 if (maxfmode + clk_shift > 1) {
1616 fstrt = downx(fconst, fstrt) - 64;
1617 fsize = upx(fconst, fsize);
1618 fstop = fstrt + fsize - fconst;
1619 } else {
1620 mod = fstrt = downx(fconst, fstrt) - fconst;
1621 fstop = fstrt + upx(fconst, fsize) - 64;
1622 fsize = up64(fsize);
1623 fstrt = fstop - fsize + 64;
1624 if (fstrt < min_fstrt) {
1625 fstop += min_fstrt - fstrt;
1626 fstrt = min_fstrt;
1627 }
1628 move = move - div8((mod - fstrt)>>clk_shift);
1629 }
1630 mod = par->next_line - div8(fsize>>clk_shift);
1631 par->ddfstrt = fstrt;
1632 par->ddfstop = fstop;
1633 par->bplcon1 = hscroll2hw(shift);
1634 par->bpl2mod = mod;
1635 if (par->bplcon0 & BPC0_LACE)
1636 par->bpl2mod += par->next_line;
1637 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
1638 par->bpl1mod = -div8(fsize>>clk_shift);
1639 else
1640 par->bpl1mod = par->bpl2mod;
1641
1642 if (par->yoffset) {
1643 par->bplpt0 = info->fix.smem_start +
1644 par->next_line * par->yoffset + move;
1645 if (par->vmode & FB_VMODE_YWRAP) {
1646 if (par->yoffset > par->vyres - par->yres) {
1647 par->bplpt0wrap = info->fix.smem_start + move;
1648 if (par->bplcon0 & BPC0_LACE &&
1649 mod2(par->diwstrt_v + par->vyres -
1650 par->yoffset))
1651 par->bplpt0wrap += par->next_line;
1652 }
1653 }
1654 } else
1655 par->bplpt0 = info->fix.smem_start + move;
1656
1657 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
1658 par->bplpt0 += par->next_line;
1659 }
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669 static void ami_pan_var(struct fb_var_screeninfo *var, struct fb_info *info)
1670 {
1671 struct amifb_par *par = info->par;
1672
1673 par->xoffset = var->xoffset;
1674 par->yoffset = var->yoffset;
1675 if (var->vmode & FB_VMODE_YWRAP)
1676 par->vmode |= FB_VMODE_YWRAP;
1677 else
1678 par->vmode &= ~FB_VMODE_YWRAP;
1679
1680 do_vmode_pan = 0;
1681 ami_update_par(info);
1682 do_vmode_pan = 1;
1683 }
1684
1685
1686 static void ami_update_display(const struct amifb_par *par)
1687 {
1688 custom.bplcon1 = par->bplcon1;
1689 custom.bpl1mod = par->bpl1mod;
1690 custom.bpl2mod = par->bpl2mod;
1691 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
1692 custom.ddfstop = ddfstop2hw(par->ddfstop);
1693 }
1694
1695
1696
1697
1698
1699 static void ami_init_display(const struct amifb_par *par)
1700 {
1701 int i;
1702
1703 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
1704 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
1705 if (!IS_OCS) {
1706 custom.bplcon3 = par->bplcon3;
1707 if (IS_AGA)
1708 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
1709 if (par->beamcon0 & BMC0_VARBEAMEN) {
1710 custom.htotal = htotal2hw(par->htotal);
1711 custom.hbstrt = hbstrt2hw(par->hbstrt);
1712 custom.hbstop = hbstop2hw(par->hbstop);
1713 custom.hsstrt = hsstrt2hw(par->hsstrt);
1714 custom.hsstop = hsstop2hw(par->hsstop);
1715 custom.hcenter = hcenter2hw(par->hcenter);
1716 custom.vtotal = vtotal2hw(par->vtotal);
1717 custom.vbstrt = vbstrt2hw(par->vbstrt);
1718 custom.vbstop = vbstop2hw(par->vbstop);
1719 custom.vsstrt = vsstrt2hw(par->vsstrt);
1720 custom.vsstop = vsstop2hw(par->vsstop);
1721 }
1722 }
1723 if (!IS_OCS || par->hsstop)
1724 custom.beamcon0 = par->beamcon0;
1725 if (IS_AGA)
1726 custom.fmode = par->fmode;
1727
1728
1729
1730
1731
1732 amiga_audio_min_period = div16(par->htotal);
1733
1734 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
1735 #if 1
1736 if (is_lace) {
1737 i = custom.vposr >> 15;
1738 } else {
1739 custom.vposw = custom.vposr | 0x8000;
1740 i = 1;
1741 }
1742 #else
1743 i = 1;
1744 custom.vposw = custom.vposr | 0x8000;
1745 #endif
1746 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
1747 }
1748
1749
1750
1751
1752
1753 static void ami_do_blank(const struct amifb_par *par)
1754 {
1755 #if defined(CONFIG_FB_AMIGA_AGA)
1756 u_short bplcon3 = par->bplcon3;
1757 #endif
1758 u_char red, green, blue;
1759
1760 if (do_blank > 0) {
1761 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
1762 red = green = blue = 0;
1763 if (!IS_OCS && do_blank > 1) {
1764 switch (do_blank) {
1765 case FB_BLANK_VSYNC_SUSPEND:
1766 custom.hsstrt = hsstrt2hw(par->hsstrt);
1767 custom.hsstop = hsstop2hw(par->hsstop);
1768 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1769 custom.vsstop = vsstop2hw(par->vtotal + 4);
1770 break;
1771 case FB_BLANK_HSYNC_SUSPEND:
1772 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1773 custom.hsstop = hsstop2hw(par->htotal + 16);
1774 custom.vsstrt = vsstrt2hw(par->vsstrt);
1775 custom.vsstop = vsstrt2hw(par->vsstop);
1776 break;
1777 case FB_BLANK_POWERDOWN:
1778 custom.hsstrt = hsstrt2hw(par->htotal + 16);
1779 custom.hsstop = hsstop2hw(par->htotal + 16);
1780 custom.vsstrt = vsstrt2hw(par->vtotal + 4);
1781 custom.vsstop = vsstop2hw(par->vtotal + 4);
1782 break;
1783 }
1784 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
1785 custom.htotal = htotal2hw(par->htotal);
1786 custom.vtotal = vtotal2hw(par->vtotal);
1787 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
1788 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
1789 }
1790 }
1791 } else {
1792 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
1793 red = red0;
1794 green = green0;
1795 blue = blue0;
1796 if (!IS_OCS) {
1797 custom.hsstrt = hsstrt2hw(par->hsstrt);
1798 custom.hsstop = hsstop2hw(par->hsstop);
1799 custom.vsstrt = vsstrt2hw(par->vsstrt);
1800 custom.vsstop = vsstop2hw(par->vsstop);
1801 custom.beamcon0 = par->beamcon0;
1802 }
1803 }
1804 #if defined(CONFIG_FB_AMIGA_AGA)
1805 if (IS_AGA) {
1806 custom.bplcon3 = bplcon3;
1807 custom.color[0] = rgb2hw8_high(red, green, blue);
1808 custom.bplcon3 = bplcon3 | BPC3_LOCT;
1809 custom.color[0] = rgb2hw8_low(red, green, blue);
1810 custom.bplcon3 = bplcon3;
1811 } else
1812 #endif
1813 #if defined(CONFIG_FB_AMIGA_ECS)
1814 if (par->bplcon0 & BPC0_SHRES) {
1815 u_short color, mask;
1816 int i;
1817
1818 mask = 0x3333;
1819 color = rgb2hw2(red, green, blue);
1820 for (i = 12; i >= 0; i -= 4)
1821 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1822 mask <<= 2; color >>= 2;
1823 for (i = 3; i >= 0; i--)
1824 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
1825 } else
1826 #endif
1827 custom.color[0] = rgb2hw4(red, green, blue);
1828 is_blanked = do_blank > 0 ? do_blank : 0;
1829 }
1830
1831 static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix,
1832 const struct amifb_par *par)
1833 {
1834 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
1835 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
1836 fix->crsr_color1 = 17;
1837 fix->crsr_color2 = 18;
1838 return 0;
1839 }
1840
1841 static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var,
1842 u_char __user *data,
1843 const struct amifb_par *par)
1844 {
1845 register u_short *lspr, *sspr;
1846 #ifdef __mc68000__
1847 register u_long datawords asm ("d2");
1848 #else
1849 register u_long datawords;
1850 #endif
1851 register short delta;
1852 register u_char color;
1853 short height, width, bits, words;
1854 int size, alloc;
1855
1856 size = par->crsr.height * par->crsr.width;
1857 alloc = var->height * var->width;
1858 var->height = par->crsr.height;
1859 var->width = par->crsr.width;
1860 var->xspot = par->crsr.spot_x;
1861 var->yspot = par->crsr.spot_y;
1862 if (size > var->height * var->width)
1863 return -ENAMETOOLONG;
1864 delta = 1 << par->crsr.fmode;
1865 lspr = lofsprite + (delta << 1);
1866 if (par->bplcon0 & BPC0_LACE)
1867 sspr = shfsprite + (delta << 1);
1868 else
1869 sspr = NULL;
1870 for (height = (short)var->height - 1; height >= 0; height--) {
1871 bits = 0; words = delta; datawords = 0;
1872 for (width = (short)var->width - 1; width >= 0; width--) {
1873 if (bits == 0) {
1874 bits = 16; --words;
1875 #ifdef __mc68000__
1876 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
1877 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
1878 #else
1879 datawords = (*(lspr + delta) << 16) | (*lspr++);
1880 #endif
1881 }
1882 --bits;
1883 #ifdef __mc68000__
1884 asm volatile (
1885 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
1886 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
1887 : "=d" (color), "=d" (datawords) : "1" (datawords));
1888 #else
1889 color = (((datawords >> 30) & 2)
1890 | ((datawords >> 15) & 1));
1891 datawords <<= 1;
1892 #endif
1893
1894 put_user(color, data++);
1895 }
1896 if (bits > 0) {
1897 --words; ++lspr;
1898 }
1899 while (--words >= 0)
1900 ++lspr;
1901 #ifdef __mc68000__
1902 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
1903 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
1904 #else
1905 lspr += delta;
1906 if (sspr) {
1907 u_short *tmp = lspr;
1908 lspr = sspr;
1909 sspr = tmp;
1910 }
1911 #endif
1912 }
1913 return 0;
1914 }
1915
1916 static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var,
1917 u_char __user *data, struct amifb_par *par)
1918 {
1919 register u_short *lspr, *sspr;
1920 #ifdef __mc68000__
1921 register u_long datawords asm ("d2");
1922 #else
1923 register u_long datawords;
1924 #endif
1925 register short delta;
1926 u_short fmode;
1927 short height, width, bits, words;
1928
1929 if (!var->width)
1930 return -EINVAL;
1931 else if (var->width <= 16)
1932 fmode = TAG_FMODE_1;
1933 else if (var->width <= 32)
1934 fmode = TAG_FMODE_2;
1935 else if (var->width <= 64)
1936 fmode = TAG_FMODE_4;
1937 else
1938 return -EINVAL;
1939 if (fmode > maxfmode)
1940 return -EINVAL;
1941 if (!var->height)
1942 return -EINVAL;
1943 delta = 1 << fmode;
1944 lofsprite = shfsprite = (u_short *)spritememory;
1945 lspr = lofsprite + (delta << 1);
1946 if (par->bplcon0 & BPC0_LACE) {
1947 if (((var->height + 4) << fmode << 2) > SPRITEMEMSIZE)
1948 return -EINVAL;
1949 memset(lspr, 0, (var->height + 4) << fmode << 2);
1950 shfsprite += ((var->height + 5)&-2) << fmode;
1951 sspr = shfsprite + (delta << 1);
1952 } else {
1953 if (((var->height + 2) << fmode << 2) > SPRITEMEMSIZE)
1954 return -EINVAL;
1955 memset(lspr, 0, (var->height + 2) << fmode << 2);
1956 sspr = NULL;
1957 }
1958 for (height = (short)var->height - 1; height >= 0; height--) {
1959 bits = 16; words = delta; datawords = 0;
1960 for (width = (short)var->width - 1; width >= 0; width--) {
1961 unsigned long tdata = 0;
1962
1963 get_user(tdata, data);
1964 data++;
1965 #ifdef __mc68000__
1966 asm volatile (
1967 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
1968 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
1969 : "=d" (datawords)
1970 : "0" (datawords), "d" (tdata));
1971 #else
1972 datawords = ((datawords << 1) & 0xfffefffe);
1973 datawords |= tdata & 1;
1974 datawords |= (tdata & 2) << (16 - 1);
1975 #endif
1976 if (--bits == 0) {
1977 bits = 16; --words;
1978 #ifdef __mc68000__
1979 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
1980 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
1981 #else
1982 *(lspr + delta) = (u_short) (datawords >> 16);
1983 *lspr++ = (u_short) (datawords & 0xffff);
1984 #endif
1985 }
1986 }
1987 if (bits < 16) {
1988 --words;
1989 #ifdef __mc68000__
1990 asm volatile (
1991 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
1992 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
1993 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
1994 #else
1995 *(lspr + delta) = (u_short) (datawords >> (16 + bits));
1996 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
1997 #endif
1998 }
1999 while (--words >= 0) {
2000 #ifdef __mc68000__
2001 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
2002 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
2003 #else
2004 *(lspr + delta) = 0;
2005 *lspr++ = 0;
2006 #endif
2007 }
2008 #ifdef __mc68000__
2009 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
2010 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
2011 #else
2012 lspr += delta;
2013 if (sspr) {
2014 u_short *tmp = lspr;
2015 lspr = sspr;
2016 sspr = tmp;
2017 }
2018 #endif
2019 }
2020 par->crsr.height = var->height;
2021 par->crsr.width = var->width;
2022 par->crsr.spot_x = var->xspot;
2023 par->crsr.spot_y = var->yspot;
2024 par->crsr.fmode = fmode;
2025 if (IS_AGA) {
2026 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
2027 par->fmode |= sprfetchmode[fmode];
2028 custom.fmode = par->fmode;
2029 }
2030 return 0;
2031 }
2032
2033 static int ami_get_cursorstate(struct fb_cursorstate *state,
2034 const struct amifb_par *par)
2035 {
2036 state->xoffset = par->crsr.crsr_x;
2037 state->yoffset = par->crsr.crsr_y;
2038 state->mode = cursormode;
2039 return 0;
2040 }
2041
2042 static int ami_set_cursorstate(struct fb_cursorstate *state,
2043 struct amifb_par *par)
2044 {
2045 par->crsr.crsr_x = state->xoffset;
2046 par->crsr.crsr_y = state->yoffset;
2047 if ((cursormode = state->mode) == FB_CURSOR_OFF)
2048 cursorstate = -1;
2049 do_cursor = 1;
2050 return 0;
2051 }
2052
2053 static void ami_set_sprite(const struct amifb_par *par)
2054 {
2055 copins *copl, *cops;
2056 u_short hs, vs, ve;
2057 u_long pl, ps;
2058 short mx, my;
2059
2060 cops = copdisplay.list[currentcop][0];
2061 copl = copdisplay.list[currentcop][1];
2062 ps = pl = ZTWO_PADDR(dummysprite);
2063 mx = par->crsr.crsr_x - par->crsr.spot_x;
2064 my = par->crsr.crsr_y - par->crsr.spot_y;
2065 if (!(par->vmode & FB_VMODE_YWRAP)) {
2066 mx -= par->xoffset;
2067 my -= par->yoffset;
2068 }
2069 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
2070 mx > -(short)par->crsr.width && mx < par->xres &&
2071 my > -(short)par->crsr.height && my < par->yres) {
2072 pl = ZTWO_PADDR(lofsprite);
2073 hs = par->diwstrt_h + (mx << par->clk_shift) - 4;
2074 vs = par->diwstrt_v + (my << par->line_shift);
2075 ve = vs + (par->crsr.height << par->line_shift);
2076 if (par->bplcon0 & BPC0_LACE) {
2077 ps = ZTWO_PADDR(shfsprite);
2078 lofsprite[0] = spr2hw_pos(vs, hs);
2079 shfsprite[0] = spr2hw_pos(vs + 1, hs);
2080 if (mod2(vs)) {
2081 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2082 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve + 1);
2083 swap(pl, ps);
2084 } else {
2085 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve + 1);
2086 shfsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs + 1, hs, ve);
2087 }
2088 } else {
2089 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
2090 lofsprite[1 << par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
2091 }
2092 }
2093 copl[cop_spr0ptrh].w[1] = highw(pl);
2094 copl[cop_spr0ptrl].w[1] = loww(pl);
2095 if (par->bplcon0 & BPC0_LACE) {
2096 cops[cop_spr0ptrh].w[1] = highw(ps);
2097 cops[cop_spr0ptrl].w[1] = loww(ps);
2098 }
2099 }
2100
2101
2102
2103
2104
2105
2106 static void __init ami_init_copper(void)
2107 {
2108 copins *cop = copdisplay.init;
2109 u_long p;
2110 int i;
2111
2112 if (!IS_OCS) {
2113 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
2114 (cop++)->l = CMOVE(0x0181, diwstrt);
2115 (cop++)->l = CMOVE(0x0281, diwstop);
2116 (cop++)->l = CMOVE(0x0000, diwhigh);
2117 } else
2118 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
2119 p = ZTWO_PADDR(dummysprite);
2120 for (i = 0; i < 8; i++) {
2121 (cop++)->l = CMOVE(0, spr[i].pos);
2122 (cop++)->l = CMOVE(highw(p), sprpt[i]);
2123 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
2124 }
2125
2126 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
2127 copdisplay.wait = cop;
2128 (cop++)->l = CEND;
2129 (cop++)->l = CMOVE(0, copjmp2);
2130 cop->l = CEND;
2131
2132 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
2133 custom.copjmp1 = 0;
2134 }
2135
2136 static void ami_reinit_copper(const struct amifb_par *par)
2137 {
2138 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
2139 copdisplay.wait->l = CWAIT(32, par->diwstrt_v - 4);
2140 }
2141
2142
2143
2144
2145
2146
2147
2148
2149 static void ami_rebuild_copper(const struct amifb_par *par)
2150 {
2151 copins *copl, *cops;
2152 u_short line, h_end1, h_end2;
2153 short i;
2154 u_long p;
2155
2156 if (IS_AGA && maxfmode + par->clk_shift == 0)
2157 h_end1 = par->diwstrt_h - 64;
2158 else
2159 h_end1 = par->htotal - 32;
2160 h_end2 = par->ddfstop + 64;
2161
2162 ami_set_sprite(par);
2163
2164 copl = copdisplay.rebuild[1];
2165 p = par->bplpt0;
2166 if (par->vmode & FB_VMODE_YWRAP) {
2167 if ((par->vyres - par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
2168 if (par->yoffset > par->vyres - par->yres) {
2169 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2170 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2171 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2172 }
2173 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 1;
2174 while (line >= 512) {
2175 (copl++)->l = CWAIT(h_end1, 510);
2176 line -= 512;
2177 }
2178 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2179 (copl++)->l = CWAIT(h_end1, line);
2180 else
2181 (copl++)->l = CWAIT(h_end2, line);
2182 p = par->bplpt0wrap;
2183 }
2184 } else
2185 p = par->bplpt0wrap;
2186 }
2187 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2188 (copl++)->l = CMOVE(highw(p), bplpt[i]);
2189 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
2190 }
2191 copl->l = CEND;
2192
2193 if (par->bplcon0 & BPC0_LACE) {
2194 cops = copdisplay.rebuild[0];
2195 p = par->bplpt0;
2196 if (mod2(par->diwstrt_v))
2197 p -= par->next_line;
2198 else
2199 p += par->next_line;
2200 if (par->vmode & FB_VMODE_YWRAP) {
2201 if ((par->vyres - par->yoffset) != 1 || mod2(par->diwstrt_v)) {
2202 if (par->yoffset > par->vyres - par->yres + 1) {
2203 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2204 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2205 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2206 }
2207 line = par->diwstrt_v + ((par->vyres - par->yoffset) << par->line_shift) - 2;
2208 while (line >= 512) {
2209 (cops++)->l = CWAIT(h_end1, 510);
2210 line -= 512;
2211 }
2212 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
2213 (cops++)->l = CWAIT(h_end1, line);
2214 else
2215 (cops++)->l = CWAIT(h_end2, line);
2216 p = par->bplpt0wrap;
2217 if (mod2(par->diwstrt_v + par->vyres -
2218 par->yoffset))
2219 p -= par->next_line;
2220 else
2221 p += par->next_line;
2222 }
2223 } else
2224 p = par->bplpt0wrap - par->next_line;
2225 }
2226 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
2227 (cops++)->l = CMOVE(highw(p), bplpt[i]);
2228 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
2229 }
2230 cops->l = CEND;
2231 }
2232 }
2233
2234
2235
2236
2237
2238
2239 static void ami_build_copper(struct fb_info *info)
2240 {
2241 struct amifb_par *par = info->par;
2242 copins *copl, *cops;
2243 u_long p;
2244
2245 currentcop = 1 - currentcop;
2246
2247 copl = copdisplay.list[currentcop][1];
2248
2249 (copl++)->l = CWAIT(0, 10);
2250 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
2251 (copl++)->l = CMOVE(0, sprpt[0]);
2252 (copl++)->l = CMOVE2(0, sprpt[0]);
2253
2254 if (par->bplcon0 & BPC0_LACE) {
2255 cops = copdisplay.list[currentcop][0];
2256
2257 (cops++)->l = CWAIT(0, 10);
2258 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
2259 (cops++)->l = CMOVE(0, sprpt[0]);
2260 (cops++)->l = CMOVE2(0, sprpt[0]);
2261
2262 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v + 1), diwstrt);
2263 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v + 1), diwstop);
2264 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2265 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2266 if (!IS_OCS) {
2267 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v + 1,
2268 par->diwstop_h, par->diwstop_v + 1), diwhigh);
2269 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2270 par->diwstop_h, par->diwstop_v), diwhigh);
2271 #if 0
2272 if (par->beamcon0 & BMC0_VARBEAMEN) {
2273 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2274 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt + 1), vbstrt);
2275 (copl++)->l = CMOVE(vbstop2hw(par->vbstop + 1), vbstop);
2276 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2277 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2278 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2279 }
2280 #endif
2281 }
2282 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
2283 (copl++)->l = CMOVE(highw(p), cop2lc);
2284 (copl++)->l = CMOVE2(loww(p), cop2lc);
2285 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
2286 (cops++)->l = CMOVE(highw(p), cop2lc);
2287 (cops++)->l = CMOVE2(loww(p), cop2lc);
2288 copdisplay.rebuild[0] = cops;
2289 } else {
2290 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
2291 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
2292 if (!IS_OCS) {
2293 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
2294 par->diwstop_h, par->diwstop_v), diwhigh);
2295 #if 0
2296 if (par->beamcon0 & BMC0_VARBEAMEN) {
2297 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
2298 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
2299 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
2300 }
2301 #endif
2302 }
2303 }
2304 copdisplay.rebuild[1] = copl;
2305
2306 ami_update_par(info);
2307 ami_rebuild_copper(info->par);
2308 }
2309
2310 #ifndef MODULE
2311 static void __init amifb_setup_mcap(char *spec)
2312 {
2313 char *p;
2314 int vmin, vmax, hmin, hmax;
2315
2316
2317
2318
2319
2320
2321 if (!(p = strsep(&spec, ";")) || !*p)
2322 return;
2323 vmin = simple_strtoul(p, NULL, 10);
2324 if (vmin <= 0)
2325 return;
2326 if (!(p = strsep(&spec, ";")) || !*p)
2327 return;
2328 vmax = simple_strtoul(p, NULL, 10);
2329 if (vmax <= 0 || vmax <= vmin)
2330 return;
2331 if (!(p = strsep(&spec, ";")) || !*p)
2332 return;
2333 hmin = 1000 * simple_strtoul(p, NULL, 10);
2334 if (hmin <= 0)
2335 return;
2336 if (!(p = strsep(&spec, "")) || !*p)
2337 return;
2338 hmax = 1000 * simple_strtoul(p, NULL, 10);
2339 if (hmax <= 0 || hmax <= hmin)
2340 return;
2341
2342 amifb_hfmin = hmin;
2343 amifb_hfmax = hmax;
2344 amifb_vfmin = vmin;
2345 amifb_vfmax = vmax;
2346 }
2347
2348 static int __init amifb_setup(char *options)
2349 {
2350 char *this_opt;
2351
2352 if (!options || !*options)
2353 return 0;
2354
2355 while ((this_opt = strsep(&options, ",")) != NULL) {
2356 if (!*this_opt)
2357 continue;
2358 if (!strcmp(this_opt, "inverse")) {
2359 fb_invert_cmaps();
2360 } else if (!strcmp(this_opt, "ilbm"))
2361 amifb_ilbm = 1;
2362 else if (!strncmp(this_opt, "monitorcap:", 11))
2363 amifb_setup_mcap(this_opt + 11);
2364 else if (!strncmp(this_opt, "fstart:", 7))
2365 min_fstrt = simple_strtoul(this_opt + 7, NULL, 0);
2366 else
2367 mode_option = this_opt;
2368 }
2369
2370 if (min_fstrt < 48)
2371 min_fstrt = 48;
2372
2373 return 0;
2374 }
2375 #endif
2376
2377 static int amifb_check_var(struct fb_var_screeninfo *var,
2378 struct fb_info *info)
2379 {
2380 int err;
2381 struct amifb_par par;
2382
2383
2384 err = ami_decode_var(var, &par, info);
2385 if (err)
2386 return err;
2387
2388
2389 ami_encode_var(var, &par);
2390 return 0;
2391 }
2392
2393
2394 static int amifb_set_par(struct fb_info *info)
2395 {
2396 struct amifb_par *par = info->par;
2397 int error;
2398
2399 do_vmode_pan = 0;
2400 do_vmode_full = 0;
2401
2402
2403 error = ami_decode_var(&info->var, par, info);
2404 if (error)
2405 return error;
2406
2407
2408 ami_build_copper(info);
2409
2410
2411 do_vmode_full = 1;
2412
2413
2414 if (par->bpp == 1) {
2415 info->fix.type = FB_TYPE_PACKED_PIXELS;
2416 info->fix.type_aux = 0;
2417 } else if (amifb_ilbm) {
2418 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
2419 info->fix.type_aux = par->next_line;
2420 } else {
2421 info->fix.type = FB_TYPE_PLANES;
2422 info->fix.type_aux = 0;
2423 }
2424 info->fix.line_length = div8(upx(16 << maxfmode, par->vxres));
2425
2426 if (par->vmode & FB_VMODE_YWRAP) {
2427 info->fix.ywrapstep = 1;
2428 info->fix.xpanstep = 0;
2429 info->fix.ypanstep = 0;
2430 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
2431 FBINFO_READS_FAST;
2432 } else {
2433 info->fix.ywrapstep = 0;
2434 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
2435 info->fix.xpanstep = 1;
2436 else
2437 info->fix.xpanstep = 16 << maxfmode;
2438 info->fix.ypanstep = 1;
2439 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
2440 }
2441 return 0;
2442 }
2443
2444
2445
2446
2447
2448
2449
2450
2451 static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
2452 u_int transp, struct fb_info *info)
2453 {
2454 const struct amifb_par *par = info->par;
2455
2456 if (IS_AGA) {
2457 if (regno > 255)
2458 return 1;
2459 } else if (par->bplcon0 & BPC0_SHRES) {
2460 if (regno > 3)
2461 return 1;
2462 } else {
2463 if (regno > 31)
2464 return 1;
2465 }
2466 red >>= 8;
2467 green >>= 8;
2468 blue >>= 8;
2469 if (!regno) {
2470 red0 = red;
2471 green0 = green;
2472 blue0 = blue;
2473 }
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483 if (regno || !is_blanked) {
2484 #if defined(CONFIG_FB_AMIGA_AGA)
2485 if (IS_AGA) {
2486 u_short bplcon3 = par->bplcon3;
2487 VBlankOff();
2488 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000);
2489 custom.color[regno & 31] = rgb2hw8_high(red, green,
2490 blue);
2491 custom.bplcon3 = bplcon3 | (regno << 8 & 0xe000) |
2492 BPC3_LOCT;
2493 custom.color[regno & 31] = rgb2hw8_low(red, green,
2494 blue);
2495 custom.bplcon3 = bplcon3;
2496 VBlankOn();
2497 } else
2498 #endif
2499 #if defined(CONFIG_FB_AMIGA_ECS)
2500 if (par->bplcon0 & BPC0_SHRES) {
2501 u_short color, mask;
2502 int i;
2503
2504 mask = 0x3333;
2505 color = rgb2hw2(red, green, blue);
2506 VBlankOff();
2507 for (i = regno + 12; i >= (int)regno; i -= 4)
2508 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2509 mask <<= 2; color >>= 2;
2510 regno = down16(regno) + mul4(mod4(regno));
2511 for (i = regno + 3; i >= (int)regno; i--)
2512 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
2513 VBlankOn();
2514 } else
2515 #endif
2516 custom.color[regno] = rgb2hw4(red, green, blue);
2517 }
2518 return 0;
2519 }
2520
2521
2522
2523
2524
2525
2526 static int amifb_blank(int blank, struct fb_info *info)
2527 {
2528 do_blank = blank ? blank : -1;
2529
2530 return 0;
2531 }
2532
2533
2534
2535
2536
2537
2538
2539
2540 static int amifb_pan_display(struct fb_var_screeninfo *var,
2541 struct fb_info *info)
2542 {
2543 if (!(var->vmode & FB_VMODE_YWRAP)) {
2544
2545
2546
2547
2548 if (var->xoffset + info->var.xres >
2549 upx(16 << maxfmode, info->var.xres_virtual))
2550 return -EINVAL;
2551 }
2552 ami_pan_var(var, info);
2553 return 0;
2554 }
2555
2556
2557 #if BITS_PER_LONG == 32
2558 #define BYTES_PER_LONG 4
2559 #define SHIFT_PER_LONG 5
2560 #elif BITS_PER_LONG == 64
2561 #define BYTES_PER_LONG 8
2562 #define SHIFT_PER_LONG 6
2563 #else
2564 #define Please update me
2565 #endif
2566
2567
2568
2569
2570
2571
2572
2573 static inline unsigned long comp(unsigned long a, unsigned long b,
2574 unsigned long mask)
2575 {
2576 return ((a ^ b) & mask) ^ b;
2577 }
2578
2579
2580 static inline unsigned long xor(unsigned long a, unsigned long b,
2581 unsigned long mask)
2582 {
2583 return (a & mask) ^ b;
2584 }
2585
2586
2587
2588
2589
2590
2591 static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
2592 int src_idx, u32 n)
2593 {
2594 unsigned long first, last;
2595 int shift = dst_idx - src_idx, left, right;
2596 unsigned long d0, d1;
2597 int m;
2598
2599 if (!n)
2600 return;
2601
2602 shift = dst_idx - src_idx;
2603 first = ~0UL >> dst_idx;
2604 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2605
2606 if (!shift) {
2607
2608
2609 if (dst_idx + n <= BITS_PER_LONG) {
2610
2611 if (last)
2612 first &= last;
2613 *dst = comp(*src, *dst, first);
2614 } else {
2615
2616
2617 if (first) {
2618 *dst = comp(*src, *dst, first);
2619 dst++;
2620 src++;
2621 n -= BITS_PER_LONG - dst_idx;
2622 }
2623
2624
2625 n /= BITS_PER_LONG;
2626 while (n >= 8) {
2627 *dst++ = *src++;
2628 *dst++ = *src++;
2629 *dst++ = *src++;
2630 *dst++ = *src++;
2631 *dst++ = *src++;
2632 *dst++ = *src++;
2633 *dst++ = *src++;
2634 *dst++ = *src++;
2635 n -= 8;
2636 }
2637 while (n--)
2638 *dst++ = *src++;
2639
2640
2641 if (last)
2642 *dst = comp(*src, *dst, last);
2643 }
2644 } else {
2645
2646
2647 right = shift & (BITS_PER_LONG - 1);
2648 left = -shift & (BITS_PER_LONG - 1);
2649
2650 if (dst_idx + n <= BITS_PER_LONG) {
2651
2652 if (last)
2653 first &= last;
2654 if (shift > 0) {
2655
2656 *dst = comp(*src >> right, *dst, first);
2657 } else if (src_idx + n <= BITS_PER_LONG) {
2658
2659 *dst = comp(*src << left, *dst, first);
2660 } else {
2661
2662 d0 = *src++;
2663 d1 = *src;
2664 *dst = comp(d0 << left | d1 >> right, *dst,
2665 first);
2666 }
2667 } else {
2668
2669 d0 = *src++;
2670
2671 if (shift > 0) {
2672
2673 *dst = comp(d0 >> right, *dst, first);
2674 dst++;
2675 n -= BITS_PER_LONG - dst_idx;
2676 } else {
2677
2678 d1 = *src++;
2679 *dst = comp(d0 << left | d1 >> right, *dst,
2680 first);
2681 d0 = d1;
2682 dst++;
2683 n -= BITS_PER_LONG - dst_idx;
2684 }
2685
2686
2687 m = n % BITS_PER_LONG;
2688 n /= BITS_PER_LONG;
2689 while (n >= 4) {
2690 d1 = *src++;
2691 *dst++ = d0 << left | d1 >> right;
2692 d0 = d1;
2693 d1 = *src++;
2694 *dst++ = d0 << left | d1 >> right;
2695 d0 = d1;
2696 d1 = *src++;
2697 *dst++ = d0 << left | d1 >> right;
2698 d0 = d1;
2699 d1 = *src++;
2700 *dst++ = d0 << left | d1 >> right;
2701 d0 = d1;
2702 n -= 4;
2703 }
2704 while (n--) {
2705 d1 = *src++;
2706 *dst++ = d0 << left | d1 >> right;
2707 d0 = d1;
2708 }
2709
2710
2711 if (last) {
2712 if (m <= right) {
2713
2714 *dst = comp(d0 << left, *dst, last);
2715 } else {
2716
2717 d1 = *src;
2718 *dst = comp(d0 << left | d1 >> right,
2719 *dst, last);
2720 }
2721 }
2722 }
2723 }
2724 }
2725
2726
2727
2728
2729
2730
2731 static void bitcpy_rev(unsigned long *dst, int dst_idx,
2732 const unsigned long *src, int src_idx, u32 n)
2733 {
2734 unsigned long first, last;
2735 int shift = dst_idx - src_idx, left, right;
2736 unsigned long d0, d1;
2737 int m;
2738
2739 if (!n)
2740 return;
2741
2742 dst += (n - 1) / BITS_PER_LONG;
2743 src += (n - 1) / BITS_PER_LONG;
2744 if ((n - 1) % BITS_PER_LONG) {
2745 dst_idx += (n - 1) % BITS_PER_LONG;
2746 dst += dst_idx >> SHIFT_PER_LONG;
2747 dst_idx &= BITS_PER_LONG - 1;
2748 src_idx += (n - 1) % BITS_PER_LONG;
2749 src += src_idx >> SHIFT_PER_LONG;
2750 src_idx &= BITS_PER_LONG - 1;
2751 }
2752
2753 shift = dst_idx - src_idx;
2754 first = ~0UL << (BITS_PER_LONG - 1 - dst_idx);
2755 last = ~(~0UL << (BITS_PER_LONG - 1 - ((dst_idx - n) % BITS_PER_LONG)));
2756
2757 if (!shift) {
2758
2759
2760 if ((unsigned long)dst_idx + 1 >= n) {
2761
2762 if (last)
2763 first &= last;
2764 *dst = comp(*src, *dst, first);
2765 } else {
2766
2767
2768 if (first) {
2769 *dst = comp(*src, *dst, first);
2770 dst--;
2771 src--;
2772 n -= dst_idx + 1;
2773 }
2774
2775
2776 n /= BITS_PER_LONG;
2777 while (n >= 8) {
2778 *dst-- = *src--;
2779 *dst-- = *src--;
2780 *dst-- = *src--;
2781 *dst-- = *src--;
2782 *dst-- = *src--;
2783 *dst-- = *src--;
2784 *dst-- = *src--;
2785 *dst-- = *src--;
2786 n -= 8;
2787 }
2788 while (n--)
2789 *dst-- = *src--;
2790
2791
2792 if (last)
2793 *dst = comp(*src, *dst, last);
2794 }
2795 } else {
2796
2797
2798 right = shift & (BITS_PER_LONG - 1);
2799 left = -shift & (BITS_PER_LONG - 1);
2800
2801 if ((unsigned long)dst_idx + 1 >= n) {
2802
2803 if (last)
2804 first &= last;
2805 if (shift < 0) {
2806
2807 *dst = comp(*src << left, *dst, first);
2808 } else if (1 + (unsigned long)src_idx >= n) {
2809
2810 *dst = comp(*src >> right, *dst, first);
2811 } else {
2812
2813 d0 = *src--;
2814 d1 = *src;
2815 *dst = comp(d0 >> right | d1 << left, *dst,
2816 first);
2817 }
2818 } else {
2819
2820 d0 = *src--;
2821
2822 if (shift < 0) {
2823
2824 *dst = comp(d0 << left, *dst, first);
2825 dst--;
2826 n -= dst_idx + 1;
2827 } else {
2828
2829 d1 = *src--;
2830 *dst = comp(d0 >> right | d1 << left, *dst,
2831 first);
2832 d0 = d1;
2833 dst--;
2834 n -= dst_idx + 1;
2835 }
2836
2837
2838 m = n % BITS_PER_LONG;
2839 n /= BITS_PER_LONG;
2840 while (n >= 4) {
2841 d1 = *src--;
2842 *dst-- = d0 >> right | d1 << left;
2843 d0 = d1;
2844 d1 = *src--;
2845 *dst-- = d0 >> right | d1 << left;
2846 d0 = d1;
2847 d1 = *src--;
2848 *dst-- = d0 >> right | d1 << left;
2849 d0 = d1;
2850 d1 = *src--;
2851 *dst-- = d0 >> right | d1 << left;
2852 d0 = d1;
2853 n -= 4;
2854 }
2855 while (n--) {
2856 d1 = *src--;
2857 *dst-- = d0 >> right | d1 << left;
2858 d0 = d1;
2859 }
2860
2861
2862 if (last) {
2863 if (m <= left) {
2864
2865 *dst = comp(d0 >> right, *dst, last);
2866 } else {
2867
2868 d1 = *src;
2869 *dst = comp(d0 >> right | d1 << left,
2870 *dst, last);
2871 }
2872 }
2873 }
2874 }
2875 }
2876
2877
2878
2879
2880
2881
2882
2883 static void bitcpy_not(unsigned long *dst, int dst_idx,
2884 const unsigned long *src, int src_idx, u32 n)
2885 {
2886 unsigned long first, last;
2887 int shift = dst_idx - src_idx, left, right;
2888 unsigned long d0, d1;
2889 int m;
2890
2891 if (!n)
2892 return;
2893
2894 shift = dst_idx - src_idx;
2895 first = ~0UL >> dst_idx;
2896 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
2897
2898 if (!shift) {
2899
2900
2901 if (dst_idx + n <= BITS_PER_LONG) {
2902
2903 if (last)
2904 first &= last;
2905 *dst = comp(~*src, *dst, first);
2906 } else {
2907
2908
2909 if (first) {
2910 *dst = comp(~*src, *dst, first);
2911 dst++;
2912 src++;
2913 n -= BITS_PER_LONG - dst_idx;
2914 }
2915
2916
2917 n /= BITS_PER_LONG;
2918 while (n >= 8) {
2919 *dst++ = ~*src++;
2920 *dst++ = ~*src++;
2921 *dst++ = ~*src++;
2922 *dst++ = ~*src++;
2923 *dst++ = ~*src++;
2924 *dst++ = ~*src++;
2925 *dst++ = ~*src++;
2926 *dst++ = ~*src++;
2927 n -= 8;
2928 }
2929 while (n--)
2930 *dst++ = ~*src++;
2931
2932
2933 if (last)
2934 *dst = comp(~*src, *dst, last);
2935 }
2936 } else {
2937
2938
2939 right = shift & (BITS_PER_LONG - 1);
2940 left = -shift & (BITS_PER_LONG - 1);
2941
2942 if (dst_idx + n <= BITS_PER_LONG) {
2943
2944 if (last)
2945 first &= last;
2946 if (shift > 0) {
2947
2948 *dst = comp(~*src >> right, *dst, first);
2949 } else if (src_idx + n <= BITS_PER_LONG) {
2950
2951 *dst = comp(~*src << left, *dst, first);
2952 } else {
2953
2954 d0 = ~*src++;
2955 d1 = ~*src;
2956 *dst = comp(d0 << left | d1 >> right, *dst,
2957 first);
2958 }
2959 } else {
2960
2961 d0 = ~*src++;
2962
2963 if (shift > 0) {
2964
2965 *dst = comp(d0 >> right, *dst, first);
2966 dst++;
2967 n -= BITS_PER_LONG - dst_idx;
2968 } else {
2969
2970 d1 = ~*src++;
2971 *dst = comp(d0 << left | d1 >> right, *dst,
2972 first);
2973 d0 = d1;
2974 dst++;
2975 n -= BITS_PER_LONG - dst_idx;
2976 }
2977
2978
2979 m = n % BITS_PER_LONG;
2980 n /= BITS_PER_LONG;
2981 while (n >= 4) {
2982 d1 = ~*src++;
2983 *dst++ = d0 << left | d1 >> right;
2984 d0 = d1;
2985 d1 = ~*src++;
2986 *dst++ = d0 << left | d1 >> right;
2987 d0 = d1;
2988 d1 = ~*src++;
2989 *dst++ = d0 << left | d1 >> right;
2990 d0 = d1;
2991 d1 = ~*src++;
2992 *dst++ = d0 << left | d1 >> right;
2993 d0 = d1;
2994 n -= 4;
2995 }
2996 while (n--) {
2997 d1 = ~*src++;
2998 *dst++ = d0 << left | d1 >> right;
2999 d0 = d1;
3000 }
3001
3002
3003 if (last) {
3004 if (m <= right) {
3005
3006 *dst = comp(d0 << left, *dst, last);
3007 } else {
3008
3009 d1 = ~*src;
3010 *dst = comp(d0 << left | d1 >> right,
3011 *dst, last);
3012 }
3013 }
3014 }
3015 }
3016 }
3017
3018
3019
3020
3021
3022
3023 static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3024 {
3025 unsigned long val = pat;
3026 unsigned long first, last;
3027
3028 if (!n)
3029 return;
3030
3031 #if BITS_PER_LONG == 64
3032 val |= val << 32;
3033 #endif
3034
3035 first = ~0UL >> dst_idx;
3036 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3037
3038 if (dst_idx + n <= BITS_PER_LONG) {
3039
3040 if (last)
3041 first &= last;
3042 *dst = comp(val, *dst, first);
3043 } else {
3044
3045
3046 if (first) {
3047 *dst = comp(val, *dst, first);
3048 dst++;
3049 n -= BITS_PER_LONG - dst_idx;
3050 }
3051
3052
3053 n /= BITS_PER_LONG;
3054 while (n >= 8) {
3055 *dst++ = val;
3056 *dst++ = val;
3057 *dst++ = val;
3058 *dst++ = val;
3059 *dst++ = val;
3060 *dst++ = val;
3061 *dst++ = val;
3062 *dst++ = val;
3063 n -= 8;
3064 }
3065 while (n--)
3066 *dst++ = val;
3067
3068
3069 if (last)
3070 *dst = comp(val, *dst, last);
3071 }
3072 }
3073
3074
3075
3076
3077
3078
3079 static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
3080 {
3081 unsigned long val = pat;
3082 unsigned long first, last;
3083
3084 if (!n)
3085 return;
3086
3087 #if BITS_PER_LONG == 64
3088 val |= val << 32;
3089 #endif
3090
3091 first = ~0UL >> dst_idx;
3092 last = ~(~0UL >> ((dst_idx + n) % BITS_PER_LONG));
3093
3094 if (dst_idx + n <= BITS_PER_LONG) {
3095
3096 if (last)
3097 first &= last;
3098 *dst = xor(val, *dst, first);
3099 } else {
3100
3101
3102 if (first) {
3103 *dst = xor(val, *dst, first);
3104 dst++;
3105 n -= BITS_PER_LONG - dst_idx;
3106 }
3107
3108
3109 n /= BITS_PER_LONG;
3110 while (n >= 4) {
3111 *dst++ ^= val;
3112 *dst++ ^= val;
3113 *dst++ ^= val;
3114 *dst++ ^= val;
3115 n -= 4;
3116 }
3117 while (n--)
3118 *dst++ ^= val;
3119
3120
3121 if (last)
3122 *dst = xor(val, *dst, last);
3123 }
3124 }
3125
3126 static inline void fill_one_line(int bpp, unsigned long next_plane,
3127 unsigned long *dst, int dst_idx, u32 n,
3128 u32 color)
3129 {
3130 while (1) {
3131 dst += dst_idx >> SHIFT_PER_LONG;
3132 dst_idx &= (BITS_PER_LONG - 1);
3133 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3134 if (!--bpp)
3135 break;
3136 color >>= 1;
3137 dst_idx += next_plane * 8;
3138 }
3139 }
3140
3141 static inline void xor_one_line(int bpp, unsigned long next_plane,
3142 unsigned long *dst, int dst_idx, u32 n,
3143 u32 color)
3144 {
3145 while (color) {
3146 dst += dst_idx >> SHIFT_PER_LONG;
3147 dst_idx &= (BITS_PER_LONG - 1);
3148 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
3149 if (!--bpp)
3150 break;
3151 color >>= 1;
3152 dst_idx += next_plane * 8;
3153 }
3154 }
3155
3156
3157 static void amifb_fillrect(struct fb_info *info,
3158 const struct fb_fillrect *rect)
3159 {
3160 struct amifb_par *par = info->par;
3161 int dst_idx, x2, y2;
3162 unsigned long *dst;
3163 u32 width, height;
3164
3165 if (!rect->width || !rect->height)
3166 return;
3167
3168
3169
3170
3171
3172 x2 = rect->dx + rect->width;
3173 y2 = rect->dy + rect->height;
3174 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3175 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3176 width = x2 - rect->dx;
3177 height = y2 - rect->dy;
3178
3179 dst = (unsigned long *)
3180 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3181 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3182 dst_idx += rect->dy * par->next_line * 8 + rect->dx;
3183 while (height--) {
3184 switch (rect->rop) {
3185 case ROP_COPY:
3186 fill_one_line(info->var.bits_per_pixel,
3187 par->next_plane, dst, dst_idx, width,
3188 rect->color);
3189 break;
3190
3191 case ROP_XOR:
3192 xor_one_line(info->var.bits_per_pixel, par->next_plane,
3193 dst, dst_idx, width, rect->color);
3194 break;
3195 }
3196 dst_idx += par->next_line * 8;
3197 }
3198 }
3199
3200 static inline void copy_one_line(int bpp, unsigned long next_plane,
3201 unsigned long *dst, int dst_idx,
3202 unsigned long *src, int src_idx, u32 n)
3203 {
3204 while (1) {
3205 dst += dst_idx >> SHIFT_PER_LONG;
3206 dst_idx &= (BITS_PER_LONG - 1);
3207 src += src_idx >> SHIFT_PER_LONG;
3208 src_idx &= (BITS_PER_LONG - 1);
3209 bitcpy(dst, dst_idx, src, src_idx, n);
3210 if (!--bpp)
3211 break;
3212 dst_idx += next_plane * 8;
3213 src_idx += next_plane * 8;
3214 }
3215 }
3216
3217 static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
3218 unsigned long *dst, int dst_idx,
3219 unsigned long *src, int src_idx, u32 n)
3220 {
3221 while (1) {
3222 dst += dst_idx >> SHIFT_PER_LONG;
3223 dst_idx &= (BITS_PER_LONG - 1);
3224 src += src_idx >> SHIFT_PER_LONG;
3225 src_idx &= (BITS_PER_LONG - 1);
3226 bitcpy_rev(dst, dst_idx, src, src_idx, n);
3227 if (!--bpp)
3228 break;
3229 dst_idx += next_plane * 8;
3230 src_idx += next_plane * 8;
3231 }
3232 }
3233
3234
3235 static void amifb_copyarea(struct fb_info *info,
3236 const struct fb_copyarea *area)
3237 {
3238 struct amifb_par *par = info->par;
3239 int x2, y2;
3240 u32 dx, dy, sx, sy, width, height;
3241 unsigned long *dst, *src;
3242 int dst_idx, src_idx;
3243 int rev_copy = 0;
3244
3245
3246 x2 = area->dx + area->width;
3247 y2 = area->dy + area->height;
3248 dx = area->dx > 0 ? area->dx : 0;
3249 dy = area->dy > 0 ? area->dy : 0;
3250 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3251 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3252 width = x2 - dx;
3253 height = y2 - dy;
3254
3255 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
3256 return;
3257
3258
3259 sx = area->sx + (dx - area->dx);
3260 sy = area->sy + (dy - area->dy);
3261
3262
3263 if (sx + width > info->var.xres_virtual ||
3264 sy + height > info->var.yres_virtual)
3265 return;
3266
3267 if (dy > sy || (dy == sy && dx > sx)) {
3268 dy += height;
3269 sy += height;
3270 rev_copy = 1;
3271 }
3272 dst = (unsigned long *)
3273 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3274 src = dst;
3275 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3276 src_idx = dst_idx;
3277 dst_idx += dy * par->next_line * 8 + dx;
3278 src_idx += sy * par->next_line * 8 + sx;
3279 if (rev_copy) {
3280 while (height--) {
3281 dst_idx -= par->next_line * 8;
3282 src_idx -= par->next_line * 8;
3283 copy_one_line_rev(info->var.bits_per_pixel,
3284 par->next_plane, dst, dst_idx, src,
3285 src_idx, width);
3286 }
3287 } else {
3288 while (height--) {
3289 copy_one_line(info->var.bits_per_pixel,
3290 par->next_plane, dst, dst_idx, src,
3291 src_idx, width);
3292 dst_idx += par->next_line * 8;
3293 src_idx += par->next_line * 8;
3294 }
3295 }
3296 }
3297
3298
3299 static inline void expand_one_line(int bpp, unsigned long next_plane,
3300 unsigned long *dst, int dst_idx, u32 n,
3301 const u8 *data, u32 bgcolor, u32 fgcolor)
3302 {
3303 const unsigned long *src;
3304 int src_idx;
3305
3306 while (1) {
3307 dst += dst_idx >> SHIFT_PER_LONG;
3308 dst_idx &= (BITS_PER_LONG - 1);
3309 if ((bgcolor ^ fgcolor) & 1) {
3310 src = (unsigned long *)
3311 ((unsigned long)data & ~(BYTES_PER_LONG - 1));
3312 src_idx = ((unsigned long)data & (BYTES_PER_LONG - 1)) * 8;
3313 if (fgcolor & 1)
3314 bitcpy(dst, dst_idx, src, src_idx, n);
3315 else
3316 bitcpy_not(dst, dst_idx, src, src_idx, n);
3317
3318 } else
3319 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
3320 if (!--bpp)
3321 break;
3322 bgcolor >>= 1;
3323 fgcolor >>= 1;
3324 dst_idx += next_plane * 8;
3325 }
3326 }
3327
3328
3329 static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
3330 {
3331 struct amifb_par *par = info->par;
3332 int x2, y2;
3333 unsigned long *dst;
3334 int dst_idx;
3335 const char *src;
3336 u32 dx, dy, width, height, pitch;
3337
3338
3339
3340
3341
3342
3343 x2 = image->dx + image->width;
3344 y2 = image->dy + image->height;
3345 dx = image->dx;
3346 dy = image->dy;
3347 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
3348 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
3349 width = x2 - dx;
3350 height = y2 - dy;
3351
3352 if (image->depth == 1) {
3353 dst = (unsigned long *)
3354 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG - 1));
3355 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG - 1)) * 8;
3356 dst_idx += dy * par->next_line * 8 + dx;
3357 src = image->data;
3358 pitch = (image->width + 7) / 8;
3359 while (height--) {
3360 expand_one_line(info->var.bits_per_pixel,
3361 par->next_plane, dst, dst_idx, width,
3362 src, image->bg_color,
3363 image->fg_color);
3364 dst_idx += par->next_line * 8;
3365 src += pitch;
3366 }
3367 } else {
3368 c2p_planar(info->screen_base, image->data, dx, dy, width,
3369 height, par->next_line, par->next_plane,
3370 image->width, info->var.bits_per_pixel);
3371 }
3372 }
3373
3374
3375
3376
3377
3378
3379 static int amifb_ioctl(struct fb_info *info,
3380 unsigned int cmd, unsigned long arg)
3381 {
3382 union {
3383 struct fb_fix_cursorinfo fix;
3384 struct fb_var_cursorinfo var;
3385 struct fb_cursorstate state;
3386 } crsr;
3387 void __user *argp = (void __user *)arg;
3388 int i;
3389
3390 switch (cmd) {
3391 case FBIOGET_FCURSORINFO:
3392 i = ami_get_fix_cursorinfo(&crsr.fix, info->par);
3393 if (i)
3394 return i;
3395 return copy_to_user(argp, &crsr.fix,
3396 sizeof(crsr.fix)) ? -EFAULT : 0;
3397
3398 case FBIOGET_VCURSORINFO:
3399 i = ami_get_var_cursorinfo(&crsr.var,
3400 ((struct fb_var_cursorinfo __user *)arg)->data,
3401 info->par);
3402 if (i)
3403 return i;
3404 return copy_to_user(argp, &crsr.var,
3405 sizeof(crsr.var)) ? -EFAULT : 0;
3406
3407 case FBIOPUT_VCURSORINFO:
3408 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
3409 return -EFAULT;
3410 return ami_set_var_cursorinfo(&crsr.var,
3411 ((struct fb_var_cursorinfo __user *)arg)->data,
3412 info->par);
3413
3414 case FBIOGET_CURSORSTATE:
3415 i = ami_get_cursorstate(&crsr.state, info->par);
3416 if (i)
3417 return i;
3418 return copy_to_user(argp, &crsr.state,
3419 sizeof(crsr.state)) ? -EFAULT : 0;
3420
3421 case FBIOPUT_CURSORSTATE:
3422 if (copy_from_user(&crsr.state, argp, sizeof(crsr.state)))
3423 return -EFAULT;
3424 return ami_set_cursorstate(&crsr.state, info->par);
3425 }
3426 return -EINVAL;
3427 }
3428
3429
3430
3431
3432
3433
3434 static int flash_cursor(void)
3435 {
3436 static int cursorcount = 1;
3437
3438 if (cursormode == FB_CURSOR_FLASH) {
3439 if (!--cursorcount) {
3440 cursorstate = -cursorstate;
3441 cursorcount = cursorrate;
3442 if (!is_blanked)
3443 return 1;
3444 }
3445 }
3446 return 0;
3447 }
3448
3449
3450
3451
3452
3453 static irqreturn_t amifb_interrupt(int irq, void *dev_id)
3454 {
3455 struct amifb_par *par = dev_id;
3456
3457 if (do_vmode_pan || do_vmode_full)
3458 ami_update_display(par);
3459
3460 if (do_vmode_full)
3461 ami_init_display(par);
3462
3463 if (do_vmode_pan) {
3464 flash_cursor();
3465 ami_rebuild_copper(par);
3466 do_cursor = do_vmode_pan = 0;
3467 } else if (do_cursor) {
3468 flash_cursor();
3469 ami_set_sprite(par);
3470 do_cursor = 0;
3471 } else {
3472 if (flash_cursor())
3473 ami_set_sprite(par);
3474 }
3475
3476 if (do_blank) {
3477 ami_do_blank(par);
3478 do_blank = 0;
3479 }
3480
3481 if (do_vmode_full) {
3482 ami_reinit_copper(par);
3483 do_vmode_full = 0;
3484 }
3485 return IRQ_HANDLED;
3486 }
3487
3488
3489 static const struct fb_ops amifb_ops = {
3490 .owner = THIS_MODULE,
3491 .fb_check_var = amifb_check_var,
3492 .fb_set_par = amifb_set_par,
3493 .fb_setcolreg = amifb_setcolreg,
3494 .fb_blank = amifb_blank,
3495 .fb_pan_display = amifb_pan_display,
3496 .fb_fillrect = amifb_fillrect,
3497 .fb_copyarea = amifb_copyarea,
3498 .fb_imageblit = amifb_imageblit,
3499 .fb_ioctl = amifb_ioctl,
3500 };
3501
3502
3503
3504
3505
3506
3507 static void *aligned_chipptr;
3508
3509 static inline u_long __init chipalloc(u_long size)
3510 {
3511 aligned_chipptr = amiga_chip_alloc(size, "amifb [RAM]");
3512 if (!aligned_chipptr) {
3513 pr_err("amifb: No Chip RAM for frame buffer");
3514 return 0;
3515 }
3516 memset(aligned_chipptr, 0, size);
3517 return (u_long)aligned_chipptr;
3518 }
3519
3520 static inline void chipfree(void)
3521 {
3522 if (aligned_chipptr)
3523 amiga_chip_free(aligned_chipptr);
3524 }
3525
3526
3527
3528
3529
3530
3531 static int __init amifb_probe(struct platform_device *pdev)
3532 {
3533 struct fb_info *info;
3534 int tag, i, err = 0;
3535 u_long chipptr;
3536 u_int defmode;
3537
3538 #ifndef MODULE
3539 char *option = NULL;
3540
3541 if (fb_get_options("amifb", &option)) {
3542 amifb_video_off();
3543 return -ENODEV;
3544 }
3545 amifb_setup(option);
3546 #endif
3547 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3548
3549 info = framebuffer_alloc(sizeof(struct amifb_par), &pdev->dev);
3550 if (!info)
3551 return -ENOMEM;
3552
3553 strcpy(info->fix.id, "Amiga ");
3554 info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
3555 info->fix.accel = FB_ACCEL_AMIGABLITT;
3556
3557 switch (amiga_chipset) {
3558 #ifdef CONFIG_FB_AMIGA_OCS
3559 case CS_OCS:
3560 strcat(info->fix.id, "OCS");
3561 default_chipset:
3562 chipset = TAG_OCS;
3563 maxdepth[TAG_SHRES] = 0;
3564 maxdepth[TAG_HIRES] = 4;
3565 maxdepth[TAG_LORES] = 6;
3566 maxfmode = TAG_FMODE_1;
3567 defmode = amiga_vblank == 50 ? DEFMODE_PAL : DEFMODE_NTSC;
3568 info->fix.smem_len = VIDEOMEMSIZE_OCS;
3569 break;
3570 #endif
3571
3572 #ifdef CONFIG_FB_AMIGA_ECS
3573 case CS_ECS:
3574 strcat(info->fix.id, "ECS");
3575 chipset = TAG_ECS;
3576 maxdepth[TAG_SHRES] = 2;
3577 maxdepth[TAG_HIRES] = 4;
3578 maxdepth[TAG_LORES] = 6;
3579 maxfmode = TAG_FMODE_1;
3580 if (AMIGAHW_PRESENT(AMBER_FF))
3581 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
3582 : DEFMODE_AMBER_NTSC;
3583 else
3584 defmode = amiga_vblank == 50 ? DEFMODE_PAL
3585 : DEFMODE_NTSC;
3586 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3587 VIDEOMEMSIZE_ECS_2M)
3588 info->fix.smem_len = VIDEOMEMSIZE_ECS_2M;
3589 else
3590 info->fix.smem_len = VIDEOMEMSIZE_ECS_1M;
3591 break;
3592 #endif
3593
3594 #ifdef CONFIG_FB_AMIGA_AGA
3595 case CS_AGA:
3596 strcat(info->fix.id, "AGA");
3597 chipset = TAG_AGA;
3598 maxdepth[TAG_SHRES] = 8;
3599 maxdepth[TAG_HIRES] = 8;
3600 maxdepth[TAG_LORES] = 8;
3601 maxfmode = TAG_FMODE_4;
3602 defmode = DEFMODE_AGA;
3603 if (amiga_chip_avail() - CHIPRAM_SAFETY_LIMIT >
3604 VIDEOMEMSIZE_AGA_2M)
3605 info->fix.smem_len = VIDEOMEMSIZE_AGA_2M;
3606 else
3607 info->fix.smem_len = VIDEOMEMSIZE_AGA_1M;
3608 break;
3609 #endif
3610
3611 default:
3612 #ifdef CONFIG_FB_AMIGA_OCS
3613 printk("Unknown graphics chipset, defaulting to OCS\n");
3614 strcat(info->fix.id, "Unknown");
3615 goto default_chipset;
3616 #else
3617 err = -ENODEV;
3618 goto release;
3619 #endif
3620 break;
3621 }
3622
3623
3624
3625
3626
3627 {
3628 u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
3629
3630 pixclock[TAG_SHRES] = (tmp + 4) / 8;
3631 pixclock[TAG_HIRES] = (tmp + 2) / 4;
3632 pixclock[TAG_LORES] = (tmp + 1) / 2;
3633 }
3634
3635
3636
3637
3638
3639 for (i = 0; i < NUM_TOTAL_MODES; i++) {
3640 struct fb_videomode *mode = &ami_modedb[i];
3641 tag = mode->pixclock;
3642 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
3643 mode->pixclock = pixclock[tag];
3644 }
3645 }
3646
3647 if (amifb_hfmin) {
3648 info->monspecs.hfmin = amifb_hfmin;
3649 info->monspecs.hfmax = amifb_hfmax;
3650 info->monspecs.vfmin = amifb_vfmin;
3651 info->monspecs.vfmax = amifb_vfmax;
3652 } else {
3653
3654
3655
3656 info->monspecs.hfmin = 15000;
3657 info->monspecs.hfmax = 38000;
3658 info->monspecs.vfmin = 49;
3659 info->monspecs.vfmax = 90;
3660 }
3661
3662 info->fbops = &amifb_ops;
3663 info->flags = FBINFO_DEFAULT;
3664 info->device = &pdev->dev;
3665
3666 if (!fb_find_mode(&info->var, info, mode_option, ami_modedb,
3667 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
3668 err = -EINVAL;
3669 goto release;
3670 }
3671
3672 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
3673 &info->modelist);
3674
3675 round_down_bpp = 0;
3676 chipptr = chipalloc(info->fix.smem_len + SPRITEMEMSIZE +
3677 DUMMYSPRITEMEMSIZE + COPINITSIZE +
3678 4 * COPLISTSIZE);
3679 if (!chipptr) {
3680 err = -ENOMEM;
3681 goto release;
3682 }
3683
3684 assignchunk(videomemory, u_long, chipptr, info->fix.smem_len);
3685 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
3686 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
3687 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
3688 assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
3689 assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
3690 assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
3691 assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
3692
3693
3694
3695
3696 info->fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
3697 videomemory = (u_long)ioremap_wt(info->fix.smem_start,
3698 info->fix.smem_len);
3699 if (!videomemory) {
3700 dev_warn(&pdev->dev,
3701 "Unable to map videomem cached writethrough\n");
3702 info->screen_base = ZTWO_VADDR(info->fix.smem_start);
3703 } else
3704 info->screen_base = (char *)videomemory;
3705
3706 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
3707
3708
3709
3710
3711 ami_init_copper();
3712
3713
3714
3715
3716 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3717 DMAF_BLITTER | DMAF_SPRITE;
3718
3719 err = request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
3720 "fb vertb handler", info->par);
3721 if (err)
3722 goto disable_dma;
3723
3724 err = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
3725 if (err)
3726 goto free_irq;
3727
3728 platform_set_drvdata(pdev, info);
3729
3730 err = register_framebuffer(info);
3731 if (err)
3732 goto unset_drvdata;
3733
3734 fb_info(info, "%s frame buffer device, using %dK of video memory\n",
3735 info->fix.id, info->fix.smem_len>>10);
3736
3737 return 0;
3738
3739 unset_drvdata:
3740 fb_dealloc_cmap(&info->cmap);
3741 free_irq:
3742 free_irq(IRQ_AMIGA_COPPER, info->par);
3743 disable_dma:
3744 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3745 if (videomemory)
3746 iounmap((void *)videomemory);
3747 chipfree();
3748 release:
3749 framebuffer_release(info);
3750 return err;
3751 }
3752
3753
3754 static int __exit amifb_remove(struct platform_device *pdev)
3755 {
3756 struct fb_info *info = platform_get_drvdata(pdev);
3757
3758 unregister_framebuffer(info);
3759 fb_dealloc_cmap(&info->cmap);
3760 free_irq(IRQ_AMIGA_COPPER, info->par);
3761 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3762 if (videomemory)
3763 iounmap((void *)videomemory);
3764 chipfree();
3765 framebuffer_release(info);
3766 amifb_video_off();
3767 return 0;
3768 }
3769
3770 static struct platform_driver amifb_driver = {
3771 .remove = __exit_p(amifb_remove),
3772 .driver = {
3773 .name = "amiga-video",
3774 },
3775 };
3776
3777 module_platform_driver_probe(amifb_driver, amifb_probe);
3778
3779 MODULE_LICENSE("GPL");
3780 MODULE_ALIAS("platform:amiga-video");