1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43#include <linux/module.h>
44#include <linux/kernel.h>
45#include <linux/errno.h>
46#include <linux/string.h>
47#include <linux/mm.h>
48#include <linux/delay.h>
49#include <linux/interrupt.h>
50#include <linux/fb.h>
51#include <linux/init.h>
52#include <linux/ioport.h>
53
54#include <linux/uaccess.h>
55#include <asm/system.h>
56#include <asm/irq.h>
57#include <asm/amigahw.h>
58#include <asm/amigaints.h>
59#include <asm/setup.h>
60
61#include "c2p.h"
62
63
64#define DEBUG
65
66#if !defined(CONFIG_FB_AMIGA_OCS) && !defined(CONFIG_FB_AMIGA_ECS) && !defined(CONFIG_FB_AMIGA_AGA)
67#define CONFIG_FB_AMIGA_OCS
68#endif
69
70#if !defined(CONFIG_FB_AMIGA_OCS)
71# define IS_OCS (0)
72#elif defined(CONFIG_FB_AMIGA_ECS) || defined(CONFIG_FB_AMIGA_AGA)
73# define IS_OCS (chipset == TAG_OCS)
74#else
75# define CONFIG_FB_AMIGA_OCS_ONLY
76# define IS_OCS (1)
77#endif
78
79#if !defined(CONFIG_FB_AMIGA_ECS)
80# define IS_ECS (0)
81#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_AGA)
82# define IS_ECS (chipset == TAG_ECS)
83#else
84# define CONFIG_FB_AMIGA_ECS_ONLY
85# define IS_ECS (1)
86#endif
87
88#if !defined(CONFIG_FB_AMIGA_AGA)
89# define IS_AGA (0)
90#elif defined(CONFIG_FB_AMIGA_OCS) || defined(CONFIG_FB_AMIGA_ECS)
91# define IS_AGA (chipset == TAG_AGA)
92#else
93# define CONFIG_FB_AMIGA_AGA_ONLY
94# define IS_AGA (1)
95#endif
96
97#ifdef DEBUG
98# define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
99#else
100# define DPRINTK(fmt, args...)
101#endif
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372#define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
373
374
375
376
377
378#define BPC0_HIRES (0x8000)
379#define BPC0_BPU2 (0x4000)
380#define BPC0_BPU1 (0x2000)
381#define BPC0_BPU0 (0x1000)
382#define BPC0_HAM (0x0800)
383#define BPC0_DPF (0x0400)
384#define BPC0_COLOR (0x0200)
385#define BPC0_GAUD (0x0100)
386#define BPC0_UHRES (0x0080)
387#define BPC0_SHRES (0x0040)
388#define BPC0_BYPASS (0x0020)
389#define BPC0_BPU3 (0x0010)
390#define BPC0_LPEN (0x0008)
391#define BPC0_LACE (0x0004)
392#define BPC0_ERSY (0x0002)
393#define BPC0_ECSENA (0x0001)
394
395
396
397
398
399#define BPC2_ZDBPSEL2 (0x4000)
400#define BPC2_ZDBPSEL1 (0x2000)
401#define BPC2_ZDBPSEL0 (0x1000)
402#define BPC2_ZDBPEN (0x0800)
403#define BPC2_ZDCTEN (0x0400)
404#define BPC2_KILLEHB (0x0200)
405#define BPC2_RDRAM (0x0100)
406#define BPC2_SOGEN (0x0080)
407#define BPC2_PF2PRI (0x0040)
408#define BPC2_PF2P2 (0x0020)
409#define BPC2_PF2P1 (0x0010)
410#define BPC2_PF2P0 (0x0008)
411#define BPC2_PF1P2 (0x0004)
412#define BPC2_PF1P1 (0x0002)
413#define BPC2_PF1P0 (0x0001)
414
415
416
417
418
419#define BPC3_BANK2 (0x8000)
420#define BPC3_BANK1 (0x4000)
421#define BPC3_BANK0 (0x2000)
422#define BPC3_PF2OF2 (0x1000)
423#define BPC3_PF2OF1 (0x0800)
424#define BPC3_PF2OF0 (0x0400)
425#define BPC3_LOCT (0x0200)
426#define BPC3_SPRES1 (0x0080)
427#define BPC3_SPRES0 (0x0040)
428#define BPC3_BRDRBLNK (0x0020)
429#define BPC3_BRDRTRAN (0x0010)
430#define BPC3_ZDCLKEN (0x0004)
431#define BPC3_BRDRSPRT (0x0002)
432#define BPC3_EXTBLKEN (0x0001)
433
434
435
436
437
438#define BPC4_BPLAM7 (0x8000)
439#define BPC4_BPLAM6 (0x4000)
440#define BPC4_BPLAM5 (0x2000)
441#define BPC4_BPLAM4 (0x1000)
442#define BPC4_BPLAM3 (0x0800)
443#define BPC4_BPLAM2 (0x0400)
444#define BPC4_BPLAM1 (0x0200)
445#define BPC4_BPLAM0 (0x0100)
446#define BPC4_ESPRM7 (0x0080)
447#define BPC4_ESPRM6 (0x0040)
448#define BPC4_ESPRM5 (0x0020)
449#define BPC4_ESPRM4 (0x0010)
450#define BPC4_OSPRM7 (0x0008)
451#define BPC4_OSPRM6 (0x0004)
452#define BPC4_OSPRM5 (0x0002)
453#define BPC4_OSPRM4 (0x0001)
454
455
456
457
458
459#define BMC0_HARDDIS (0x4000)
460#define BMC0_LPENDIS (0x2000)
461#define BMC0_VARVBEN (0x1000)
462#define BMC0_LOLDIS (0x0800)
463#define BMC0_CSCBEN (0x0400)
464#define BMC0_VARVSYEN (0x0200)
465#define BMC0_VARHSYEN (0x0100)
466#define BMC0_VARBEAMEN (0x0080)
467#define BMC0_DUAL (0x0040)
468#define BMC0_PAL (0x0020)
469#define BMC0_VARCSYEN (0x0010)
470#define BMC0_BLANKEN (0x0008)
471#define BMC0_CSYTRUE (0x0004)
472#define BMC0_VSYTRUE (0x0002)
473#define BMC0_HSYTRUE (0x0001)
474
475
476
477
478
479
480#define FMODE_SSCAN2 (0x8000)
481#define FMODE_BSCAN2 (0x4000)
482#define FMODE_SPAGEM (0x0008)
483#define FMODE_SPR32 (0x0004)
484#define FMODE_BPAGEM (0x0002)
485#define FMODE_BPL32 (0x0001)
486
487
488
489
490
491
492
493enum { TAG_SHRES, TAG_HIRES, TAG_LORES };
494
495
496
497
498
499enum { TAG_OCS, TAG_ECS, TAG_AGA };
500
501
502
503
504
505enum { TAG_FMODE_1, TAG_FMODE_2, TAG_FMODE_4 };
506
507
508
509
510
511
512
513
514
515static u_long pixclock[3];
516static u_short maxdepth[3];
517static u_short maxfmode, chipset;
518
519
520
521
522
523
524
525
526
527#define PAL_DIWSTRT_H (360)
528#define PAL_DIWSTRT_V (48)
529#define PAL_HTOTAL (1816)
530#define PAL_VTOTAL (625)
531
532#define NTSC_DIWSTRT_H (360)
533#define NTSC_DIWSTRT_V (40)
534#define NTSC_HTOTAL (1816)
535#define NTSC_VTOTAL (525)
536
537
538
539
540
541
542#define up2(v) (((v)+1) & -2)
543#define down2(v) ((v) & -2)
544#define div2(v) ((v)>>1)
545#define mod2(v) ((v) & 1)
546
547#define up4(v) (((v)+3) & -4)
548#define down4(v) ((v) & -4)
549#define mul4(v) ((v)<<2)
550#define div4(v) ((v)>>2)
551#define mod4(v) ((v) & 3)
552
553#define up8(v) (((v)+7) & -8)
554#define down8(v) ((v) & -8)
555#define div8(v) ((v)>>3)
556#define mod8(v) ((v) & 7)
557
558#define up16(v) (((v)+15) & -16)
559#define down16(v) ((v) & -16)
560#define div16(v) ((v)>>4)
561#define mod16(v) ((v) & 15)
562
563#define up32(v) (((v)+31) & -32)
564#define down32(v) ((v) & -32)
565#define div32(v) ((v)>>5)
566#define mod32(v) ((v) & 31)
567
568#define up64(v) (((v)+63) & -64)
569#define down64(v) ((v) & -64)
570#define div64(v) ((v)>>6)
571#define mod64(v) ((v) & 63)
572
573#define upx(x,v) (((v)+(x)-1) & -(x))
574#define downx(x,v) ((v) & -(x))
575#define modx(x,v) ((v) & ((x)-1))
576
577
578#ifdef __mc68000__
579#define DIVUL(x1, x2) ({int res; asm("divul %1,%2,%3": "=d" (res): \
580 "d" (x2), "d" ((long)((x1)/0x100000000ULL)), "0" ((long)(x1))); res;})
581#else
582
583#define DIVUL(x1, x2) ((((long)((unsigned long long)x1 >> 8) / x2) << 8) + \
584 ((((long)((unsigned long long)x1 >> 8) % x2) << 8) / x2))
585#endif
586
587#define highw(x) ((u_long)(x)>>16 & 0xffff)
588#define loww(x) ((u_long)(x) & 0xffff)
589
590#define custom amiga_custom
591
592#define VBlankOn() custom.intena = IF_SETCLR|IF_COPER
593#define VBlankOff() custom.intena = IF_COPER
594
595
596
597
598
599
600
601
602
603#define VIDEOMEMSIZE_AGA_2M (1310720)
604#define VIDEOMEMSIZE_AGA_1M (786432)
605#define VIDEOMEMSIZE_ECS_2M (655360)
606#define VIDEOMEMSIZE_ECS_1M (393216)
607#define VIDEOMEMSIZE_OCS (262144)
608
609#define SPRITEMEMSIZE (64*64/4)
610#define DUMMYSPRITEMEMSIZE (8)
611static u_long spritememory;
612
613#define CHIPRAM_SAFETY_LIMIT (16384)
614
615static u_long videomemory;
616
617
618
619
620
621
622
623static u_long min_fstrt = 192;
624
625#define assignchunk(name, type, ptr, size) \
626{ \
627 (name) = (type)(ptr); \
628 ptr += size; \
629}
630
631
632
633
634
635
636#define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val))
637#define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val))
638#define CWAIT(x, y) (((y) & 0x1fe)<<23 | ((x) & 0x7f0)<<13 | 0x0001fffe)
639#define CEND (0xfffffffe)
640
641
642typedef union {
643 u_long l;
644 u_short w[2];
645} copins;
646
647static struct copdisplay {
648 copins *init;
649 copins *wait;
650 copins *list[2][2];
651 copins *rebuild[2];
652} copdisplay;
653
654static u_short currentcop = 0;
655
656
657
658
659
660
661
662#define FBIOGET_FCURSORINFO 0x4607
663#define FBIOGET_VCURSORINFO 0x4608
664#define FBIOPUT_VCURSORINFO 0x4609
665#define FBIOGET_CURSORSTATE 0x460A
666#define FBIOPUT_CURSORSTATE 0x460B
667
668
669struct fb_fix_cursorinfo {
670 __u16 crsr_width;
671 __u16 crsr_height;
672 __u16 crsr_xsize;
673 __u16 crsr_ysize;
674 __u16 crsr_color1;
675 __u16 crsr_color2;
676};
677
678struct fb_var_cursorinfo {
679 __u16 width;
680 __u16 height;
681 __u16 xspot;
682 __u16 yspot;
683 __u8 data[1];
684};
685
686struct fb_cursorstate {
687 __s16 xoffset;
688 __s16 yoffset;
689 __u16 mode;
690};
691
692#define FB_CURSOR_OFF 0
693#define FB_CURSOR_ON 1
694#define FB_CURSOR_FLASH 2
695
696
697
698
699
700
701static int cursorrate = 20;
702static u_short cursorstate = -1;
703static u_short cursormode = FB_CURSOR_OFF;
704
705static u_short *lofsprite, *shfsprite, *dummysprite;
706
707
708
709
710
711static struct amifb_par {
712
713
714
715 int xres;
716 int yres;
717 int vxres;
718 int vyres;
719 int xoffset;
720 int yoffset;
721 u_short bpp;
722 u_short clk_shift;
723 u_short line_shift;
724 int vmode;
725 u_short diwstrt_h;
726 u_short diwstop_h;
727 u_short diwstrt_v;
728 u_short diwstop_v;
729 u_long next_line;
730 u_long next_plane;
731
732
733
734 struct {
735 short crsr_x;
736 short crsr_y;
737 short spot_x;
738 short spot_y;
739 u_short height;
740 u_short width;
741 u_short fmode;
742 } crsr;
743
744
745
746 u_long bplpt0;
747 u_long bplpt0wrap;
748 u_short ddfstrt;
749 u_short ddfstop;
750 u_short bpl1mod;
751 u_short bpl2mod;
752 u_short bplcon0;
753 u_short bplcon1;
754 u_short htotal;
755 u_short vtotal;
756
757
758
759 u_short bplcon3;
760 u_short beamcon0;
761 u_short hsstrt;
762 u_short hsstop;
763 u_short hbstrt;
764 u_short hbstop;
765 u_short vsstrt;
766 u_short vsstop;
767 u_short vbstrt;
768 u_short vbstop;
769 u_short hcenter;
770
771
772
773 u_short fmode;
774} currentpar;
775
776
777static struct fb_info fb_info = {
778 .fix = {
779 .id = "Amiga ",
780 .visual = FB_VISUAL_PSEUDOCOLOR,
781 .accel = FB_ACCEL_AMIGABLITT
782 }
783};
784
785
786
787
788
789
790static u_char red0, green0, blue0;
791
792
793#if defined(CONFIG_FB_AMIGA_ECS)
794static u_short ecs_palette[32];
795#endif
796
797
798
799
800
801
802static u_short do_vmode_full = 0;
803static u_short do_vmode_pan = 0;
804static short do_blank = 0;
805static u_short do_cursor = 0;
806
807
808
809
810
811
812static u_short is_blanked = 0;
813static u_short is_lace = 0;
814
815
816
817
818
819
820static struct fb_videomode ami_modedb[] __initdata = {
821
822
823
824
825
826
827
828 {
829
830 "ntsc", 60, 640, 200, TAG_HIRES, 106, 86, 44, 16, 76, 2,
831 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
832 }, {
833
834 "ntsc-lace", 60, 640, 400, TAG_HIRES, 106, 86, 88, 33, 76, 4,
835 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
836 }, {
837
838 "pal", 50, 640, 256, TAG_HIRES, 106, 86, 40, 14, 76, 2,
839 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
840 }, {
841
842 "pal-lace", 50, 640, 512, TAG_HIRES, 106, 86, 80, 29, 76, 4,
843 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
844 }, {
845
846 "multiscan", 57, 640, 480, TAG_SHRES, 96, 112, 29, 8, 72, 8,
847 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
848 }, {
849
850 "multiscan-lace", 57, 640, 960, TAG_SHRES, 96, 112, 58, 16, 72, 16,
851 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
852 }, {
853
854 "euro36", 72, 640, 200, TAG_HIRES, 92, 124, 6, 6, 52, 5,
855 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
856 }, {
857
858 "euro36-lace", 72, 640, 400, TAG_HIRES, 92, 124, 12, 12, 52, 10,
859 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
860 }, {
861
862 "euro72", 68, 640, 400, TAG_SHRES, 164, 92, 9, 9, 80, 8,
863 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
864 }, {
865
866 "euro72-lace", 68, 640, 800, TAG_SHRES, 164, 92, 18, 18, 80, 16,
867 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
868 }, {
869
870 "super72", 70, 800, 300, TAG_SHRES, 212, 140, 10, 11, 80, 7,
871 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
872 }, {
873
874 "super72-lace", 70, 800, 600, TAG_SHRES, 212, 140, 20, 22, 80, 14,
875 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
876 }, {
877
878 "dblntsc", 57, 640, 200, TAG_SHRES, 196, 124, 18, 17, 80, 4,
879 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
880 }, {
881
882 "dblntsc-ff", 57, 640, 400, TAG_SHRES, 196, 124, 36, 35, 80, 7,
883 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
884 }, {
885
886 "dblntsc-lace", 57, 640, 800, TAG_SHRES, 196, 124, 72, 70, 80, 14,
887 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
888 }, {
889
890 "dblpal", 47, 640, 256, TAG_SHRES, 196, 124, 14, 13, 80, 4,
891 0, FB_VMODE_DOUBLE | FB_VMODE_YWRAP
892 }, {
893
894 "dblpal-ff", 47, 640, 512, TAG_SHRES, 196, 124, 28, 27, 80, 7,
895 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
896 }, {
897
898 "dblpal-lace", 47, 640, 1024, TAG_SHRES, 196, 124, 56, 54, 80, 14,
899 0, FB_VMODE_INTERLACED | FB_VMODE_YWRAP
900 },
901
902
903
904
905
906 {
907
908 "vga", 60, 640, 480, TAG_SHRES, 64, 96, 30, 9, 112, 2,
909 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
910 }, {
911
912 "vga70", 70, 640, 400, TAG_SHRES, 64, 96, 35, 12, 112, 2,
913 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
914 },
915
916#if 0
917
918
919
920
921
922
923 {
924
925 "a2024-10", 10, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
926 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
927 }, {
928
929 "a2024-15", 15, 1024, 800, TAG_HIRES, 0, 0, 0, 0, 0, 0,
930 0, FB_VMODE_NONINTERLACED | FB_VMODE_YWRAP
931 }
932#endif
933};
934
935#define NUM_TOTAL_MODES ARRAY_SIZE(ami_modedb)
936
937static char *mode_option __initdata = NULL;
938static int round_down_bpp = 1;
939
940
941
942
943
944
945#define DEFMODE_PAL 2
946#define DEFMODE_NTSC 0
947#define DEFMODE_AMBER_PAL 3
948#define DEFMODE_AMBER_NTSC 1
949#define DEFMODE_AGA 19
950
951
952static int amifb_ilbm = 0;
953static int amifb_inverse = 0;
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993#define hscroll2hw(hscroll) \
994 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
995 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
996
997
998
999#define diwstrt2hw(diwstrt_h, diwstrt_v) \
1000 (((diwstrt_v)<<7 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
1001#define diwstop2hw(diwstop_h, diwstop_v) \
1002 (((diwstop_v)<<7 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
1003#define diwhigh2hw(diwstrt_h, diwstrt_v, diwstop_h, diwstop_v) \
1004 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
1005 ((diwstop_v)>>1 & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
1006 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>9 & 0x0007))
1007
1008
1009
1010#define ddfstrt2hw(ddfstrt) div8(ddfstrt)
1011#define ddfstop2hw(ddfstop) div8(ddfstop)
1012
1013
1014
1015#define hsstrt2hw(hsstrt) (div8(hsstrt))
1016#define hsstop2hw(hsstop) (div8(hsstop))
1017#define htotal2hw(htotal) (div8(htotal)-1)
1018#define vsstrt2hw(vsstrt) (div2(vsstrt))
1019#define vsstop2hw(vsstop) (div2(vsstop))
1020#define vtotal2hw(vtotal) (div2(vtotal)-1)
1021#define hcenter2hw(htotal) (div8(htotal))
1022
1023
1024
1025#define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
1026#define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
1027#define vbstrt2hw(vbstrt) (div2(vbstrt))
1028#define vbstop2hw(vbstop) (div2(vbstop))
1029
1030
1031
1032#define rgb2hw8_high(red, green, blue) \
1033 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1034#define rgb2hw8_low(red, green, blue) \
1035 (((red & 0x0f)<<8) | ((green & 0x0f)<<4) | (blue & 0x0f))
1036#define rgb2hw4(red, green, blue) \
1037 (((red & 0xf0)<<4) | (green & 0xf0) | ((blue & 0xf0)>>4))
1038#define rgb2hw2(red, green, blue) \
1039 (((red & 0xc0)<<4) | (green & 0xc0) | ((blue & 0xc0)>>4))
1040
1041
1042
1043#define spr2hw_pos(start_v, start_h) \
1044 (((start_v)<<7&0xff00) | ((start_h)>>3&0x00ff))
1045#define spr2hw_ctl(start_v, start_h, stop_v) \
1046 (((stop_v)<<7&0xff00) | ((start_v)>>4&0x0040) | ((stop_v)>>5&0x0020) | \
1047 ((start_h)<<3&0x0018) | ((start_v)>>7&0x0004) | ((stop_v)>>8&0x0002) | \
1048 ((start_h)>>2&0x0001))
1049
1050
1051#define get_vbpos() ((u_short)((*(u_long volatile *)&custom.vposr >> 7) & 0xffe))
1052
1053
1054
1055
1056
1057#define COPINITSIZE (sizeof(copins)*40)
1058
1059enum {
1060 cip_bplcon0
1061};
1062
1063
1064
1065
1066
1067
1068#define COPLISTSIZE (sizeof(copins)*64)
1069
1070enum {
1071 cop_wait, cop_bplcon0,
1072 cop_spr0ptrh, cop_spr0ptrl,
1073 cop_diwstrt, cop_diwstop,
1074 cop_diwhigh,
1075};
1076
1077
1078
1079
1080
1081static u_short bplpixmode[3] = {
1082 BPC0_SHRES,
1083 BPC0_HIRES,
1084 0
1085};
1086
1087static u_short sprpixmode[3] = {
1088 BPC3_SPRES1 | BPC3_SPRES0,
1089 BPC3_SPRES1,
1090 BPC3_SPRES0
1091};
1092
1093
1094
1095
1096
1097static u_short bplfetchmode[3] = {
1098 0,
1099 FMODE_BPL32,
1100 FMODE_BPAGEM | FMODE_BPL32
1101};
1102
1103static u_short sprfetchmode[3] = {
1104 0,
1105 FMODE_SPR32,
1106 FMODE_SPAGEM | FMODE_SPR32
1107};
1108
1109
1110
1111
1112
1113
1114int amifb_setup(char*);
1115
1116static int amifb_check_var(struct fb_var_screeninfo *var,
1117 struct fb_info *info);
1118static int amifb_set_par(struct fb_info *info);
1119static int amifb_setcolreg(unsigned regno, unsigned red, unsigned green,
1120 unsigned blue, unsigned transp,
1121 struct fb_info *info);
1122static int amifb_blank(int blank, struct fb_info *info);
1123static int amifb_pan_display(struct fb_var_screeninfo *var,
1124 struct fb_info *info);
1125static void amifb_fillrect(struct fb_info *info,
1126 const struct fb_fillrect *rect);
1127static void amifb_copyarea(struct fb_info *info,
1128 const struct fb_copyarea *region);
1129static void amifb_imageblit(struct fb_info *info,
1130 const struct fb_image *image);
1131static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
1132
1133
1134
1135
1136
1137
1138static void amifb_deinit(void);
1139
1140
1141
1142
1143
1144static int flash_cursor(void);
1145static irqreturn_t amifb_interrupt(int irq, void *dev_id);
1146static u_long chipalloc(u_long size);
1147static void chipfree(void);
1148
1149
1150
1151
1152
1153static int ami_decode_var(struct fb_var_screeninfo *var,
1154 struct amifb_par *par);
1155static int ami_encode_var(struct fb_var_screeninfo *var,
1156 struct amifb_par *par);
1157static void ami_pan_var(struct fb_var_screeninfo *var);
1158static int ami_update_par(void);
1159static void ami_update_display(void);
1160static void ami_init_display(void);
1161static void ami_do_blank(void);
1162static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix);
1163static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1164static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data);
1165static int ami_get_cursorstate(struct fb_cursorstate *state);
1166static int ami_set_cursorstate(struct fb_cursorstate *state);
1167static void ami_set_sprite(void);
1168static void ami_init_copper(void);
1169static void ami_reinit_copper(void);
1170static void ami_build_copper(void);
1171static void ami_rebuild_copper(void);
1172
1173
1174static struct fb_ops amifb_ops = {
1175 .owner = THIS_MODULE,
1176 .fb_check_var = amifb_check_var,
1177 .fb_set_par = amifb_set_par,
1178 .fb_setcolreg = amifb_setcolreg,
1179 .fb_blank = amifb_blank,
1180 .fb_pan_display = amifb_pan_display,
1181 .fb_fillrect = amifb_fillrect,
1182 .fb_copyarea = amifb_copyarea,
1183 .fb_imageblit = amifb_imageblit,
1184 .fb_ioctl = amifb_ioctl,
1185};
1186
1187static void __init amifb_setup_mcap(char *spec)
1188{
1189 char *p;
1190 int vmin, vmax, hmin, hmax;
1191
1192
1193
1194
1195
1196
1197 if (!(p = strsep(&spec, ";")) || !*p)
1198 return;
1199 vmin = simple_strtoul(p, NULL, 10);
1200 if (vmin <= 0)
1201 return;
1202 if (!(p = strsep(&spec, ";")) || !*p)
1203 return;
1204 vmax = simple_strtoul(p, NULL, 10);
1205 if (vmax <= 0 || vmax <= vmin)
1206 return;
1207 if (!(p = strsep(&spec, ";")) || !*p)
1208 return;
1209 hmin = 1000 * simple_strtoul(p, NULL, 10);
1210 if (hmin <= 0)
1211 return;
1212 if (!(p = strsep(&spec, "")) || !*p)
1213 return;
1214 hmax = 1000 * simple_strtoul(p, NULL, 10);
1215 if (hmax <= 0 || hmax <= hmin)
1216 return;
1217
1218 fb_info.monspecs.vfmin = vmin;
1219 fb_info.monspecs.vfmax = vmax;
1220 fb_info.monspecs.hfmin = hmin;
1221 fb_info.monspecs.hfmax = hmax;
1222}
1223
1224int __init amifb_setup(char *options)
1225{
1226 char *this_opt;
1227
1228 if (!options || !*options)
1229 return 0;
1230
1231 while ((this_opt = strsep(&options, ",")) != NULL) {
1232 if (!*this_opt)
1233 continue;
1234 if (!strcmp(this_opt, "inverse")) {
1235 amifb_inverse = 1;
1236 fb_invert_cmaps();
1237 } else if (!strcmp(this_opt, "ilbm"))
1238 amifb_ilbm = 1;
1239 else if (!strncmp(this_opt, "monitorcap:", 11))
1240 amifb_setup_mcap(this_opt+11);
1241 else if (!strncmp(this_opt, "fstart:", 7))
1242 min_fstrt = simple_strtoul(this_opt+7, NULL, 0);
1243 else
1244 mode_option = this_opt;
1245 }
1246
1247 if (min_fstrt < 48)
1248 min_fstrt = 48;
1249
1250 return 0;
1251}
1252
1253
1254static int amifb_check_var(struct fb_var_screeninfo *var,
1255 struct fb_info *info)
1256{
1257 int err;
1258 struct amifb_par par;
1259
1260
1261 if ((err = ami_decode_var(var, &par)))
1262 return err;
1263
1264
1265 ami_encode_var(var, &par);
1266 return 0;
1267}
1268
1269
1270static int amifb_set_par(struct fb_info *info)
1271{
1272 struct amifb_par *par = (struct amifb_par *)info->par;
1273
1274 do_vmode_pan = 0;
1275 do_vmode_full = 0;
1276
1277
1278 ami_decode_var(&info->var, par);
1279
1280
1281 ami_build_copper();
1282
1283
1284 do_vmode_full = 1;
1285
1286
1287 if (par->bpp == 1) {
1288 info->fix.type = FB_TYPE_PACKED_PIXELS;
1289 info->fix.type_aux = 0;
1290 } else if (amifb_ilbm) {
1291 info->fix.type = FB_TYPE_INTERLEAVED_PLANES;
1292 info->fix.type_aux = par->next_line;
1293 } else {
1294 info->fix.type = FB_TYPE_PLANES;
1295 info->fix.type_aux = 0;
1296 }
1297 info->fix.line_length = div8(upx(16<<maxfmode, par->vxres));
1298
1299 if (par->vmode & FB_VMODE_YWRAP) {
1300 info->fix.ywrapstep = 1;
1301 info->fix.xpanstep = 0;
1302 info->fix.ypanstep = 0;
1303 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YWRAP |
1304 FBINFO_READS_FAST;
1305 } else {
1306 info->fix.ywrapstep = 0;
1307 if (par->vmode & FB_VMODE_SMOOTH_XPAN)
1308 info->fix.xpanstep = 1;
1309 else
1310 info->fix.xpanstep = 16<<maxfmode;
1311 info->fix.ypanstep = 1;
1312 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1313 }
1314 return 0;
1315}
1316
1317
1318
1319
1320
1321
1322
1323
1324static int amifb_pan_display(struct fb_var_screeninfo *var,
1325 struct fb_info *info)
1326{
1327 if (var->vmode & FB_VMODE_YWRAP) {
1328 if (var->yoffset < 0 ||
1329 var->yoffset >= info->var.yres_virtual || var->xoffset)
1330 return -EINVAL;
1331 } else {
1332
1333
1334
1335
1336 if (var->xoffset+info->var.xres > upx(16<<maxfmode, info->var.xres_virtual) ||
1337 var->yoffset+info->var.yres > info->var.yres_virtual)
1338 return -EINVAL;
1339 }
1340 ami_pan_var(var);
1341 info->var.xoffset = var->xoffset;
1342 info->var.yoffset = var->yoffset;
1343 if (var->vmode & FB_VMODE_YWRAP)
1344 info->var.vmode |= FB_VMODE_YWRAP;
1345 else
1346 info->var.vmode &= ~FB_VMODE_YWRAP;
1347 return 0;
1348}
1349
1350
1351#if BITS_PER_LONG == 32
1352#define BYTES_PER_LONG 4
1353#define SHIFT_PER_LONG 5
1354#elif BITS_PER_LONG == 64
1355#define BYTES_PER_LONG 8
1356#define SHIFT_PER_LONG 6
1357#else
1358#define Please update me
1359#endif
1360
1361
1362
1363
1364
1365
1366
1367static inline unsigned long comp(unsigned long a, unsigned long b,
1368 unsigned long mask)
1369{
1370 return ((a ^ b) & mask) ^ b;
1371}
1372
1373
1374static inline unsigned long xor(unsigned long a, unsigned long b,
1375 unsigned long mask)
1376{
1377 return (a & mask) ^ b;
1378}
1379
1380
1381
1382
1383
1384
1385static void bitcpy(unsigned long *dst, int dst_idx, const unsigned long *src,
1386 int src_idx, u32 n)
1387{
1388 unsigned long first, last;
1389 int shift = dst_idx-src_idx, left, right;
1390 unsigned long d0, d1;
1391 int m;
1392
1393 if (!n)
1394 return;
1395
1396 shift = dst_idx-src_idx;
1397 first = ~0UL >> dst_idx;
1398 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1399
1400 if (!shift) {
1401
1402
1403 if (dst_idx+n <= BITS_PER_LONG) {
1404
1405 if (last)
1406 first &= last;
1407 *dst = comp(*src, *dst, first);
1408 } else {
1409
1410
1411 if (first) {
1412 *dst = comp(*src, *dst, first);
1413 dst++;
1414 src++;
1415 n -= BITS_PER_LONG-dst_idx;
1416 }
1417
1418
1419 n /= BITS_PER_LONG;
1420 while (n >= 8) {
1421 *dst++ = *src++;
1422 *dst++ = *src++;
1423 *dst++ = *src++;
1424 *dst++ = *src++;
1425 *dst++ = *src++;
1426 *dst++ = *src++;
1427 *dst++ = *src++;
1428 *dst++ = *src++;
1429 n -= 8;
1430 }
1431 while (n--)
1432 *dst++ = *src++;
1433
1434
1435 if (last)
1436 *dst = comp(*src, *dst, last);
1437 }
1438 } else {
1439
1440
1441 right = shift & (BITS_PER_LONG-1);
1442 left = -shift & (BITS_PER_LONG-1);
1443
1444 if (dst_idx+n <= BITS_PER_LONG) {
1445
1446 if (last)
1447 first &= last;
1448 if (shift > 0) {
1449
1450 *dst = comp(*src >> right, *dst, first);
1451 } else if (src_idx+n <= BITS_PER_LONG) {
1452
1453 *dst = comp(*src << left, *dst, first);
1454 } else {
1455
1456 d0 = *src++;
1457 d1 = *src;
1458 *dst = comp(d0 << left | d1 >> right, *dst,
1459 first);
1460 }
1461 } else {
1462
1463 d0 = *src++;
1464
1465 if (shift > 0) {
1466
1467 *dst = comp(d0 >> right, *dst, first);
1468 dst++;
1469 n -= BITS_PER_LONG-dst_idx;
1470 } else {
1471
1472 d1 = *src++;
1473 *dst = comp(d0 << left | d1 >> right, *dst,
1474 first);
1475 d0 = d1;
1476 dst++;
1477 n -= BITS_PER_LONG-dst_idx;
1478 }
1479
1480
1481 m = n % BITS_PER_LONG;
1482 n /= BITS_PER_LONG;
1483 while (n >= 4) {
1484 d1 = *src++;
1485 *dst++ = d0 << left | d1 >> right;
1486 d0 = d1;
1487 d1 = *src++;
1488 *dst++ = d0 << left | d1 >> right;
1489 d0 = d1;
1490 d1 = *src++;
1491 *dst++ = d0 << left | d1 >> right;
1492 d0 = d1;
1493 d1 = *src++;
1494 *dst++ = d0 << left | d1 >> right;
1495 d0 = d1;
1496 n -= 4;
1497 }
1498 while (n--) {
1499 d1 = *src++;
1500 *dst++ = d0 << left | d1 >> right;
1501 d0 = d1;
1502 }
1503
1504
1505 if (last) {
1506 if (m <= right) {
1507
1508 *dst = comp(d0 << left, *dst, last);
1509 } else {
1510
1511 d1 = *src;
1512 *dst = comp(d0 << left | d1 >> right,
1513 *dst, last);
1514 }
1515 }
1516 }
1517 }
1518}
1519
1520
1521
1522
1523
1524
1525static void bitcpy_rev(unsigned long *dst, int dst_idx,
1526 const unsigned long *src, int src_idx, u32 n)
1527{
1528 unsigned long first, last;
1529 int shift = dst_idx-src_idx, left, right;
1530 unsigned long d0, d1;
1531 int m;
1532
1533 if (!n)
1534 return;
1535
1536 dst += (n-1)/BITS_PER_LONG;
1537 src += (n-1)/BITS_PER_LONG;
1538 if ((n-1) % BITS_PER_LONG) {
1539 dst_idx += (n-1) % BITS_PER_LONG;
1540 dst += dst_idx >> SHIFT_PER_LONG;
1541 dst_idx &= BITS_PER_LONG-1;
1542 src_idx += (n-1) % BITS_PER_LONG;
1543 src += src_idx >> SHIFT_PER_LONG;
1544 src_idx &= BITS_PER_LONG-1;
1545 }
1546
1547 shift = dst_idx-src_idx;
1548 first = ~0UL << (BITS_PER_LONG-1-dst_idx);
1549 last = ~(~0UL << (BITS_PER_LONG-1-((dst_idx-n) % BITS_PER_LONG)));
1550
1551 if (!shift) {
1552
1553
1554 if ((unsigned long)dst_idx+1 >= n) {
1555
1556 if (last)
1557 first &= last;
1558 *dst = comp(*src, *dst, first);
1559 } else {
1560
1561
1562 if (first) {
1563 *dst = comp(*src, *dst, first);
1564 dst--;
1565 src--;
1566 n -= dst_idx+1;
1567 }
1568
1569
1570 n /= BITS_PER_LONG;
1571 while (n >= 8) {
1572 *dst-- = *src--;
1573 *dst-- = *src--;
1574 *dst-- = *src--;
1575 *dst-- = *src--;
1576 *dst-- = *src--;
1577 *dst-- = *src--;
1578 *dst-- = *src--;
1579 *dst-- = *src--;
1580 n -= 8;
1581 }
1582 while (n--)
1583 *dst-- = *src--;
1584
1585
1586 if (last)
1587 *dst = comp(*src, *dst, last);
1588 }
1589 } else {
1590
1591
1592 right = shift & (BITS_PER_LONG-1);
1593 left = -shift & (BITS_PER_LONG-1);
1594
1595 if ((unsigned long)dst_idx+1 >= n) {
1596
1597 if (last)
1598 first &= last;
1599 if (shift < 0) {
1600
1601 *dst = comp(*src << left, *dst, first);
1602 } else if (1+(unsigned long)src_idx >= n) {
1603
1604 *dst = comp(*src >> right, *dst, first);
1605 } else {
1606
1607 d0 = *src--;
1608 d1 = *src;
1609 *dst = comp(d0 >> right | d1 << left, *dst,
1610 first);
1611 }
1612 } else {
1613
1614 d0 = *src--;
1615
1616 if (shift < 0) {
1617
1618 *dst = comp(d0 << left, *dst, first);
1619 dst--;
1620 n -= dst_idx+1;
1621 } else {
1622
1623 d1 = *src--;
1624 *dst = comp(d0 >> right | d1 << left, *dst,
1625 first);
1626 d0 = d1;
1627 dst--;
1628 n -= dst_idx+1;
1629 }
1630
1631
1632 m = n % BITS_PER_LONG;
1633 n /= BITS_PER_LONG;
1634 while (n >= 4) {
1635 d1 = *src--;
1636 *dst-- = d0 >> right | d1 << left;
1637 d0 = d1;
1638 d1 = *src--;
1639 *dst-- = d0 >> right | d1 << left;
1640 d0 = d1;
1641 d1 = *src--;
1642 *dst-- = d0 >> right | d1 << left;
1643 d0 = d1;
1644 d1 = *src--;
1645 *dst-- = d0 >> right | d1 << left;
1646 d0 = d1;
1647 n -= 4;
1648 }
1649 while (n--) {
1650 d1 = *src--;
1651 *dst-- = d0 >> right | d1 << left;
1652 d0 = d1;
1653 }
1654
1655
1656 if (last) {
1657 if (m <= left) {
1658
1659 *dst = comp(d0 >> right, *dst, last);
1660 } else {
1661
1662 d1 = *src;
1663 *dst = comp(d0 >> right | d1 << left,
1664 *dst, last);
1665 }
1666 }
1667 }
1668 }
1669}
1670
1671
1672
1673
1674
1675
1676
1677static void bitcpy_not(unsigned long *dst, int dst_idx,
1678 const unsigned long *src, int src_idx, u32 n)
1679{
1680 unsigned long first, last;
1681 int shift = dst_idx-src_idx, left, right;
1682 unsigned long d0, d1;
1683 int m;
1684
1685 if (!n)
1686 return;
1687
1688 shift = dst_idx-src_idx;
1689 first = ~0UL >> dst_idx;
1690 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1691
1692 if (!shift) {
1693
1694
1695 if (dst_idx+n <= BITS_PER_LONG) {
1696
1697 if (last)
1698 first &= last;
1699 *dst = comp(~*src, *dst, first);
1700 } else {
1701
1702
1703 if (first) {
1704 *dst = comp(~*src, *dst, first);
1705 dst++;
1706 src++;
1707 n -= BITS_PER_LONG-dst_idx;
1708 }
1709
1710
1711 n /= BITS_PER_LONG;
1712 while (n >= 8) {
1713 *dst++ = ~*src++;
1714 *dst++ = ~*src++;
1715 *dst++ = ~*src++;
1716 *dst++ = ~*src++;
1717 *dst++ = ~*src++;
1718 *dst++ = ~*src++;
1719 *dst++ = ~*src++;
1720 *dst++ = ~*src++;
1721 n -= 8;
1722 }
1723 while (n--)
1724 *dst++ = ~*src++;
1725
1726
1727 if (last)
1728 *dst = comp(~*src, *dst, last);
1729 }
1730 } else {
1731
1732
1733 right = shift & (BITS_PER_LONG-1);
1734 left = -shift & (BITS_PER_LONG-1);
1735
1736 if (dst_idx+n <= BITS_PER_LONG) {
1737
1738 if (last)
1739 first &= last;
1740 if (shift > 0) {
1741
1742 *dst = comp(~*src >> right, *dst, first);
1743 } else if (src_idx+n <= BITS_PER_LONG) {
1744
1745 *dst = comp(~*src << left, *dst, first);
1746 } else {
1747
1748 d0 = ~*src++;
1749 d1 = ~*src;
1750 *dst = comp(d0 << left | d1 >> right, *dst,
1751 first);
1752 }
1753 } else {
1754
1755 d0 = ~*src++;
1756
1757 if (shift > 0) {
1758
1759 *dst = comp(d0 >> right, *dst, first);
1760 dst++;
1761 n -= BITS_PER_LONG-dst_idx;
1762 } else {
1763
1764 d1 = ~*src++;
1765 *dst = comp(d0 << left | d1 >> right, *dst,
1766 first);
1767 d0 = d1;
1768 dst++;
1769 n -= BITS_PER_LONG-dst_idx;
1770 }
1771
1772
1773 m = n % BITS_PER_LONG;
1774 n /= BITS_PER_LONG;
1775 while (n >= 4) {
1776 d1 = ~*src++;
1777 *dst++ = d0 << left | d1 >> right;
1778 d0 = d1;
1779 d1 = ~*src++;
1780 *dst++ = d0 << left | d1 >> right;
1781 d0 = d1;
1782 d1 = ~*src++;
1783 *dst++ = d0 << left | d1 >> right;
1784 d0 = d1;
1785 d1 = ~*src++;
1786 *dst++ = d0 << left | d1 >> right;
1787 d0 = d1;
1788 n -= 4;
1789 }
1790 while (n--) {
1791 d1 = ~*src++;
1792 *dst++ = d0 << left | d1 >> right;
1793 d0 = d1;
1794 }
1795
1796
1797 if (last) {
1798 if (m <= right) {
1799
1800 *dst = comp(d0 << left, *dst, last);
1801 } else {
1802
1803 d1 = ~*src;
1804 *dst = comp(d0 << left | d1 >> right,
1805 *dst, last);
1806 }
1807 }
1808 }
1809 }
1810}
1811
1812
1813
1814
1815
1816
1817static void bitfill32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1818{
1819 unsigned long val = pat;
1820 unsigned long first, last;
1821
1822 if (!n)
1823 return;
1824
1825#if BITS_PER_LONG == 64
1826 val |= val << 32;
1827#endif
1828
1829 first = ~0UL >> dst_idx;
1830 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1831
1832 if (dst_idx+n <= BITS_PER_LONG) {
1833
1834 if (last)
1835 first &= last;
1836 *dst = comp(val, *dst, first);
1837 } else {
1838
1839
1840 if (first) {
1841 *dst = comp(val, *dst, first);
1842 dst++;
1843 n -= BITS_PER_LONG-dst_idx;
1844 }
1845
1846
1847 n /= BITS_PER_LONG;
1848 while (n >= 8) {
1849 *dst++ = val;
1850 *dst++ = val;
1851 *dst++ = val;
1852 *dst++ = val;
1853 *dst++ = val;
1854 *dst++ = val;
1855 *dst++ = val;
1856 *dst++ = val;
1857 n -= 8;
1858 }
1859 while (n--)
1860 *dst++ = val;
1861
1862
1863 if (last)
1864 *dst = comp(val, *dst, last);
1865 }
1866}
1867
1868
1869
1870
1871
1872
1873static void bitxor32(unsigned long *dst, int dst_idx, u32 pat, u32 n)
1874{
1875 unsigned long val = pat;
1876 unsigned long first, last;
1877
1878 if (!n)
1879 return;
1880
1881#if BITS_PER_LONG == 64
1882 val |= val << 32;
1883#endif
1884
1885 first = ~0UL >> dst_idx;
1886 last = ~(~0UL >> ((dst_idx+n) % BITS_PER_LONG));
1887
1888 if (dst_idx+n <= BITS_PER_LONG) {
1889
1890 if (last)
1891 first &= last;
1892 *dst = xor(val, *dst, first);
1893 } else {
1894
1895
1896 if (first) {
1897 *dst = xor(val, *dst, first);
1898 dst++;
1899 n -= BITS_PER_LONG-dst_idx;
1900 }
1901
1902
1903 n /= BITS_PER_LONG;
1904 while (n >= 4) {
1905 *dst++ ^= val;
1906 *dst++ ^= val;
1907 *dst++ ^= val;
1908 *dst++ ^= val;
1909 n -= 4;
1910 }
1911 while (n--)
1912 *dst++ ^= val;
1913
1914
1915 if (last)
1916 *dst = xor(val, *dst, last);
1917 }
1918}
1919
1920static inline void fill_one_line(int bpp, unsigned long next_plane,
1921 unsigned long *dst, int dst_idx, u32 n,
1922 u32 color)
1923{
1924 while (1) {
1925 dst += dst_idx >> SHIFT_PER_LONG;
1926 dst_idx &= (BITS_PER_LONG-1);
1927 bitfill32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1928 if (!--bpp)
1929 break;
1930 color >>= 1;
1931 dst_idx += next_plane*8;
1932 }
1933}
1934
1935static inline void xor_one_line(int bpp, unsigned long next_plane,
1936 unsigned long *dst, int dst_idx, u32 n,
1937 u32 color)
1938{
1939 while (color) {
1940 dst += dst_idx >> SHIFT_PER_LONG;
1941 dst_idx &= (BITS_PER_LONG-1);
1942 bitxor32(dst, dst_idx, color & 1 ? ~0 : 0, n);
1943 if (!--bpp)
1944 break;
1945 color >>= 1;
1946 dst_idx += next_plane*8;
1947 }
1948}
1949
1950
1951static void amifb_fillrect(struct fb_info *info,
1952 const struct fb_fillrect *rect)
1953{
1954 struct amifb_par *par = (struct amifb_par *)info->par;
1955 int dst_idx, x2, y2;
1956 unsigned long *dst;
1957 u32 width, height;
1958
1959 if (!rect->width || !rect->height)
1960 return;
1961
1962
1963
1964
1965
1966 x2 = rect->dx + rect->width;
1967 y2 = rect->dy + rect->height;
1968 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
1969 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
1970 width = x2 - rect->dx;
1971 height = y2 - rect->dy;
1972
1973 dst = (unsigned long *)
1974 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
1975 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
1976 dst_idx += rect->dy*par->next_line*8+rect->dx;
1977 while (height--) {
1978 switch (rect->rop) {
1979 case ROP_COPY:
1980 fill_one_line(info->var.bits_per_pixel,
1981 par->next_plane, dst, dst_idx, width,
1982 rect->color);
1983 break;
1984
1985 case ROP_XOR:
1986 xor_one_line(info->var.bits_per_pixel, par->next_plane,
1987 dst, dst_idx, width, rect->color);
1988 break;
1989 }
1990 dst_idx += par->next_line*8;
1991 }
1992}
1993
1994static inline void copy_one_line(int bpp, unsigned long next_plane,
1995 unsigned long *dst, int dst_idx,
1996 unsigned long *src, int src_idx, u32 n)
1997{
1998 while (1) {
1999 dst += dst_idx >> SHIFT_PER_LONG;
2000 dst_idx &= (BITS_PER_LONG-1);
2001 src += src_idx >> SHIFT_PER_LONG;
2002 src_idx &= (BITS_PER_LONG-1);
2003 bitcpy(dst, dst_idx, src, src_idx, n);
2004 if (!--bpp)
2005 break;
2006 dst_idx += next_plane*8;
2007 src_idx += next_plane*8;
2008 }
2009}
2010
2011static inline void copy_one_line_rev(int bpp, unsigned long next_plane,
2012 unsigned long *dst, int dst_idx,
2013 unsigned long *src, int src_idx, u32 n)
2014{
2015 while (1) {
2016 dst += dst_idx >> SHIFT_PER_LONG;
2017 dst_idx &= (BITS_PER_LONG-1);
2018 src += src_idx >> SHIFT_PER_LONG;
2019 src_idx &= (BITS_PER_LONG-1);
2020 bitcpy_rev(dst, dst_idx, src, src_idx, n);
2021 if (!--bpp)
2022 break;
2023 dst_idx += next_plane*8;
2024 src_idx += next_plane*8;
2025 }
2026}
2027
2028
2029static void amifb_copyarea(struct fb_info *info,
2030 const struct fb_copyarea *area)
2031{
2032 struct amifb_par *par = (struct amifb_par *)info->par;
2033 int x2, y2;
2034 u32 dx, dy, sx, sy, width, height;
2035 unsigned long *dst, *src;
2036 int dst_idx, src_idx;
2037 int rev_copy = 0;
2038
2039
2040 x2 = area->dx + area->width;
2041 y2 = area->dy + area->height;
2042 dx = area->dx > 0 ? area->dx : 0;
2043 dy = area->dy > 0 ? area->dy : 0;
2044 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2045 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2046 width = x2 - dx;
2047 height = y2 - dy;
2048
2049 if (area->sx + dx < area->dx || area->sy + dy < area->dy)
2050 return;
2051
2052
2053 sx = area->sx + (dx - area->dx);
2054 sy = area->sy + (dy - area->dy);
2055
2056
2057 if (sx + width > info->var.xres_virtual ||
2058 sy + height > info->var.yres_virtual)
2059 return;
2060
2061 if (dy > sy || (dy == sy && dx > sx)) {
2062 dy += height;
2063 sy += height;
2064 rev_copy = 1;
2065 }
2066 dst = (unsigned long *)
2067 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2068 src = dst;
2069 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2070 src_idx = dst_idx;
2071 dst_idx += dy*par->next_line*8+dx;
2072 src_idx += sy*par->next_line*8+sx;
2073 if (rev_copy) {
2074 while (height--) {
2075 dst_idx -= par->next_line*8;
2076 src_idx -= par->next_line*8;
2077 copy_one_line_rev(info->var.bits_per_pixel,
2078 par->next_plane, dst, dst_idx, src,
2079 src_idx, width);
2080 }
2081 } else {
2082 while (height--) {
2083 copy_one_line(info->var.bits_per_pixel,
2084 par->next_plane, dst, dst_idx, src,
2085 src_idx, width);
2086 dst_idx += par->next_line*8;
2087 src_idx += par->next_line*8;
2088 }
2089 }
2090}
2091
2092
2093static inline void expand_one_line(int bpp, unsigned long next_plane,
2094 unsigned long *dst, int dst_idx, u32 n,
2095 const u8 *data, u32 bgcolor, u32 fgcolor)
2096{
2097 const unsigned long *src;
2098 int src_idx;
2099
2100 while (1) {
2101 dst += dst_idx >> SHIFT_PER_LONG;
2102 dst_idx &= (BITS_PER_LONG-1);
2103 if ((bgcolor ^ fgcolor) & 1) {
2104 src = (unsigned long *)((unsigned long)data & ~(BYTES_PER_LONG-1));
2105 src_idx = ((unsigned long)data & (BYTES_PER_LONG-1))*8;
2106 if (fgcolor & 1)
2107 bitcpy(dst, dst_idx, src, src_idx, n);
2108 else
2109 bitcpy_not(dst, dst_idx, src, src_idx, n);
2110
2111 } else
2112 bitfill32(dst, dst_idx, fgcolor & 1 ? ~0 : 0, n);
2113 if (!--bpp)
2114 break;
2115 bgcolor >>= 1;
2116 fgcolor >>= 1;
2117 dst_idx += next_plane*8;
2118 }
2119}
2120
2121
2122static void amifb_imageblit(struct fb_info *info, const struct fb_image *image)
2123{
2124 struct amifb_par *par = (struct amifb_par *)info->par;
2125 int x2, y2;
2126 unsigned long *dst;
2127 int dst_idx;
2128 const char *src;
2129 u32 dx, dy, width, height, pitch;
2130
2131
2132
2133
2134
2135
2136 x2 = image->dx + image->width;
2137 y2 = image->dy + image->height;
2138 dx = image->dx;
2139 dy = image->dy;
2140 x2 = x2 < info->var.xres_virtual ? x2 : info->var.xres_virtual;
2141 y2 = y2 < info->var.yres_virtual ? y2 : info->var.yres_virtual;
2142 width = x2 - dx;
2143 height = y2 - dy;
2144
2145 if (image->depth == 1) {
2146 dst = (unsigned long *)
2147 ((unsigned long)info->screen_base & ~(BYTES_PER_LONG-1));
2148 dst_idx = ((unsigned long)info->screen_base & (BYTES_PER_LONG-1))*8;
2149 dst_idx += dy*par->next_line*8+dx;
2150 src = image->data;
2151 pitch = (image->width+7)/8;
2152 while (height--) {
2153 expand_one_line(info->var.bits_per_pixel,
2154 par->next_plane, dst, dst_idx, width,
2155 src, image->bg_color,
2156 image->fg_color);
2157 dst_idx += par->next_line*8;
2158 src += pitch;
2159 }
2160 } else {
2161 c2p_planar(info->screen_base, image->data, dx, dy, width,
2162 height, par->next_line, par->next_plane,
2163 image->width, info->var.bits_per_pixel);
2164 }
2165}
2166
2167
2168
2169
2170
2171
2172static int amifb_ioctl(struct fb_info *info,
2173 unsigned int cmd, unsigned long arg)
2174{
2175 union {
2176 struct fb_fix_cursorinfo fix;
2177 struct fb_var_cursorinfo var;
2178 struct fb_cursorstate state;
2179 } crsr;
2180 void __user *argp = (void __user *)arg;
2181 int i;
2182
2183 switch (cmd) {
2184 case FBIOGET_FCURSORINFO:
2185 i = ami_get_fix_cursorinfo(&crsr.fix);
2186 if (i)
2187 return i;
2188 return copy_to_user(argp, &crsr.fix,
2189 sizeof(crsr.fix)) ? -EFAULT : 0;
2190
2191 case FBIOGET_VCURSORINFO:
2192 i = ami_get_var_cursorinfo(&crsr.var,
2193 ((struct fb_var_cursorinfo __user *)arg)->data);
2194 if (i)
2195 return i;
2196 return copy_to_user(argp, &crsr.var,
2197 sizeof(crsr.var)) ? -EFAULT : 0;
2198
2199 case FBIOPUT_VCURSORINFO:
2200 if (copy_from_user(&crsr.var, argp, sizeof(crsr.var)))
2201 return -EFAULT;
2202 return ami_set_var_cursorinfo(&crsr.var,
2203 ((struct fb_var_cursorinfo __user *)arg)->data);
2204
2205 case FBIOGET_CURSORSTATE:
2206 i = ami_get_cursorstate(&crsr.state);
2207 if (i)
2208 return i;
2209 return copy_to_user(argp, &crsr.state,
2210 sizeof(crsr.state)) ? -EFAULT : 0;
2211
2212 case FBIOPUT_CURSORSTATE:
2213 if (copy_from_user(&crsr.state, argp,
2214 sizeof(crsr.state)))
2215 return -EFAULT;
2216 return ami_set_cursorstate(&crsr.state);
2217 }
2218 return -EINVAL;
2219}
2220
2221
2222
2223
2224
2225
2226static u_long unaligned_chipptr = 0;
2227
2228static inline u_long __init chipalloc(u_long size)
2229{
2230 size += PAGE_SIZE-1;
2231 if (!(unaligned_chipptr = (u_long)amiga_chip_alloc(size,
2232 "amifb [RAM]")))
2233 panic("No Chip RAM for frame buffer");
2234 memset((void *)unaligned_chipptr, 0, size);
2235 return PAGE_ALIGN(unaligned_chipptr);
2236}
2237
2238static inline void chipfree(void)
2239{
2240 if (unaligned_chipptr)
2241 amiga_chip_free((void *)unaligned_chipptr);
2242}
2243
2244
2245
2246
2247
2248
2249static int __init amifb_init(void)
2250{
2251 int tag, i, err = 0;
2252 u_long chipptr;
2253 u_int defmode;
2254
2255#ifndef MODULE
2256 char *option = NULL;
2257
2258 if (fb_get_options("amifb", &option)) {
2259 amifb_video_off();
2260 return -ENODEV;
2261 }
2262 amifb_setup(option);
2263#endif
2264 if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO))
2265 return -ENODEV;
2266
2267
2268
2269
2270 if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120,
2271 "amifb [Denise/Lisa]"))
2272 return -EBUSY;
2273
2274 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2275
2276 switch (amiga_chipset) {
2277#ifdef CONFIG_FB_AMIGA_OCS
2278 case CS_OCS:
2279 strcat(fb_info.fix.id, "OCS");
2280default_chipset:
2281 chipset = TAG_OCS;
2282 maxdepth[TAG_SHRES] = 0;
2283 maxdepth[TAG_HIRES] = 4;
2284 maxdepth[TAG_LORES] = 6;
2285 maxfmode = TAG_FMODE_1;
2286 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2287 : DEFMODE_NTSC;
2288 fb_info.fix.smem_len = VIDEOMEMSIZE_OCS;
2289 break;
2290#endif
2291
2292#ifdef CONFIG_FB_AMIGA_ECS
2293 case CS_ECS:
2294 strcat(fb_info.fix.id, "ECS");
2295 chipset = TAG_ECS;
2296 maxdepth[TAG_SHRES] = 2;
2297 maxdepth[TAG_HIRES] = 4;
2298 maxdepth[TAG_LORES] = 6;
2299 maxfmode = TAG_FMODE_1;
2300 if (AMIGAHW_PRESENT(AMBER_FF))
2301 defmode = amiga_vblank == 50 ? DEFMODE_AMBER_PAL
2302 : DEFMODE_AMBER_NTSC;
2303 else
2304 defmode = amiga_vblank == 50 ? DEFMODE_PAL
2305 : DEFMODE_NTSC;
2306 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2307 VIDEOMEMSIZE_ECS_1M)
2308 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_2M;
2309 else
2310 fb_info.fix.smem_len = VIDEOMEMSIZE_ECS_1M;
2311 break;
2312#endif
2313
2314#ifdef CONFIG_FB_AMIGA_AGA
2315 case CS_AGA:
2316 strcat(fb_info.fix.id, "AGA");
2317 chipset = TAG_AGA;
2318 maxdepth[TAG_SHRES] = 8;
2319 maxdepth[TAG_HIRES] = 8;
2320 maxdepth[TAG_LORES] = 8;
2321 maxfmode = TAG_FMODE_4;
2322 defmode = DEFMODE_AGA;
2323 if (amiga_chip_avail()-CHIPRAM_SAFETY_LIMIT >
2324 VIDEOMEMSIZE_AGA_1M)
2325 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_2M;
2326 else
2327 fb_info.fix.smem_len = VIDEOMEMSIZE_AGA_1M;
2328 break;
2329#endif
2330
2331 default:
2332#ifdef CONFIG_FB_AMIGA_OCS
2333 printk("Unknown graphics chipset, defaulting to OCS\n");
2334 strcat(fb_info.fix.id, "Unknown");
2335 goto default_chipset;
2336#else
2337 err = -ENODEV;
2338 goto amifb_error;
2339#endif
2340 break;
2341 }
2342
2343
2344
2345
2346
2347 {
2348 u_long tmp = DIVUL(200000000000ULL, amiga_eclock);
2349
2350 pixclock[TAG_SHRES] = (tmp + 4) / 8;
2351 pixclock[TAG_HIRES] = (tmp + 2) / 4;
2352 pixclock[TAG_LORES] = (tmp + 1) / 2;
2353 }
2354
2355
2356
2357
2358
2359 for (i = 0; i < NUM_TOTAL_MODES; i++) {
2360 struct fb_videomode *mode = &ami_modedb[i];
2361 tag = mode->pixclock;
2362 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
2363 mode->pixclock = pixclock[tag];
2364 }
2365 }
2366
2367
2368
2369
2370 if (fb_info.monspecs.hfmin == 0) {
2371 fb_info.monspecs.hfmin = 15000;
2372 fb_info.monspecs.hfmax = 38000;
2373 fb_info.monspecs.vfmin = 49;
2374 fb_info.monspecs.vfmax = 90;
2375 }
2376
2377 fb_info.fbops = &amifb_ops;
2378 fb_info.par = ¤tpar;
2379 fb_info.flags = FBINFO_DEFAULT;
2380
2381 if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb,
2382 NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) {
2383 err = -EINVAL;
2384 goto amifb_error;
2385 }
2386
2387 fb_videomode_to_modelist(ami_modedb, NUM_TOTAL_MODES,
2388 &fb_info.modelist);
2389
2390 round_down_bpp = 0;
2391 chipptr = chipalloc(fb_info.fix.smem_len+
2392 SPRITEMEMSIZE+
2393 DUMMYSPRITEMEMSIZE+
2394 COPINITSIZE+
2395 4*COPLISTSIZE);
2396
2397 assignchunk(videomemory, u_long, chipptr, fb_info.fix.smem_len);
2398 assignchunk(spritememory, u_long, chipptr, SPRITEMEMSIZE);
2399 assignchunk(dummysprite, u_short *, chipptr, DUMMYSPRITEMEMSIZE);
2400 assignchunk(copdisplay.init, copins *, chipptr, COPINITSIZE);
2401 assignchunk(copdisplay.list[0][0], copins *, chipptr, COPLISTSIZE);
2402 assignchunk(copdisplay.list[0][1], copins *, chipptr, COPLISTSIZE);
2403 assignchunk(copdisplay.list[1][0], copins *, chipptr, COPLISTSIZE);
2404 assignchunk(copdisplay.list[1][1], copins *, chipptr, COPLISTSIZE);
2405
2406
2407
2408
2409 fb_info.fix.smem_start = (u_long)ZTWO_PADDR(videomemory);
2410 videomemory = (u_long)ioremap_writethrough(fb_info.fix.smem_start,
2411 fb_info.fix.smem_len);
2412 if (!videomemory) {
2413 printk("amifb: WARNING! unable to map videomem cached writethrough\n");
2414 fb_info.screen_base = (char *)ZTWO_VADDR(fb_info.fix.smem_start);
2415 } else
2416 fb_info.screen_base = (char *)videomemory;
2417
2418 memset(dummysprite, 0, DUMMYSPRITEMEMSIZE);
2419
2420
2421
2422
2423
2424 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2425 DMAF_BLITTER | DMAF_SPRITE;
2426
2427
2428
2429
2430
2431 ami_init_copper();
2432
2433 if (request_irq(IRQ_AMIGA_COPPER, amifb_interrupt, 0,
2434 "fb vertb handler", ¤tpar)) {
2435 err = -EBUSY;
2436 goto amifb_error;
2437 }
2438
2439 err = fb_alloc_cmap(&fb_info.cmap, 1<<fb_info.var.bits_per_pixel, 0);
2440 if (err)
2441 goto amifb_error;
2442
2443 if (register_framebuffer(&fb_info) < 0) {
2444 err = -EINVAL;
2445 goto amifb_error;
2446 }
2447
2448 printk("fb%d: %s frame buffer device, using %dK of video memory\n",
2449 fb_info.node, fb_info.fix.id, fb_info.fix.smem_len>>10);
2450
2451 return 0;
2452
2453amifb_error:
2454 amifb_deinit();
2455 return err;
2456}
2457
2458static void amifb_deinit(void)
2459{
2460 if (fb_info.cmap.len)
2461 fb_dealloc_cmap(&fb_info.cmap);
2462 chipfree();
2463 if (videomemory)
2464 iounmap((void*)videomemory);
2465 release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120);
2466 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2467}
2468
2469
2470
2471
2472
2473
2474static int amifb_blank(int blank, struct fb_info *info)
2475{
2476 do_blank = blank ? blank : -1;
2477
2478 return 0;
2479}
2480
2481
2482
2483
2484
2485static int flash_cursor(void)
2486{
2487 static int cursorcount = 1;
2488
2489 if (cursormode == FB_CURSOR_FLASH) {
2490 if (!--cursorcount) {
2491 cursorstate = -cursorstate;
2492 cursorcount = cursorrate;
2493 if (!is_blanked)
2494 return 1;
2495 }
2496 }
2497 return 0;
2498}
2499
2500
2501
2502
2503
2504static irqreturn_t amifb_interrupt(int irq, void *dev_id)
2505{
2506 if (do_vmode_pan || do_vmode_full)
2507 ami_update_display();
2508
2509 if (do_vmode_full)
2510 ami_init_display();
2511
2512 if (do_vmode_pan) {
2513 flash_cursor();
2514 ami_rebuild_copper();
2515 do_cursor = do_vmode_pan = 0;
2516 } else if (do_cursor) {
2517 flash_cursor();
2518 ami_set_sprite();
2519 do_cursor = 0;
2520 } else {
2521 if (flash_cursor())
2522 ami_set_sprite();
2523 }
2524
2525 if (do_blank) {
2526 ami_do_blank();
2527 do_blank = 0;
2528 }
2529
2530 if (do_vmode_full) {
2531 ami_reinit_copper();
2532 do_vmode_full = 0;
2533 }
2534 return IRQ_HANDLED;
2535}
2536
2537
2538
2539
2540
2541
2542
2543
2544static int ami_decode_var(struct fb_var_screeninfo *var,
2545 struct amifb_par *par)
2546{
2547 u_short clk_shift, line_shift;
2548 u_long maxfetchstop, fstrt, fsize, fconst, xres_n, yres_n;
2549 u_int htotal, vtotal;
2550
2551
2552
2553
2554
2555 for (clk_shift = TAG_SHRES; clk_shift <= TAG_LORES; clk_shift++)
2556 if (var->pixclock <= pixclock[clk_shift])
2557 break;
2558 if (clk_shift > TAG_LORES) {
2559 DPRINTK("pixclock too high\n");
2560 return -EINVAL;
2561 }
2562 par->clk_shift = clk_shift;
2563
2564
2565
2566
2567
2568 if ((par->xres = var->xres) < 64)
2569 par->xres = 64;
2570 if ((par->yres = var->yres) < 64)
2571 par->yres = 64;
2572 if ((par->vxres = var->xres_virtual) < par->xres)
2573 par->vxres = par->xres;
2574 if ((par->vyres = var->yres_virtual) < par->yres)
2575 par->vyres = par->yres;
2576
2577 par->bpp = var->bits_per_pixel;
2578 if (!var->nonstd) {
2579 if (par->bpp < 1)
2580 par->bpp = 1;
2581 if (par->bpp > maxdepth[clk_shift]) {
2582 if (round_down_bpp && maxdepth[clk_shift])
2583 par->bpp = maxdepth[clk_shift];
2584 else {
2585 DPRINTK("invalid bpp\n");
2586 return -EINVAL;
2587 }
2588 }
2589 } else if (var->nonstd == FB_NONSTD_HAM) {
2590 if (par->bpp < 6)
2591 par->bpp = 6;
2592 if (par->bpp != 6) {
2593 if (par->bpp < 8)
2594 par->bpp = 8;
2595 if (par->bpp != 8 || !IS_AGA) {
2596 DPRINTK("invalid bpp for ham mode\n");
2597 return -EINVAL;
2598 }
2599 }
2600 } else {
2601 DPRINTK("unknown nonstd mode\n");
2602 return -EINVAL;
2603 }
2604
2605
2606
2607
2608
2609
2610 par->vmode = var->vmode | FB_VMODE_SMOOTH_XPAN;
2611 switch (par->vmode & FB_VMODE_MASK) {
2612 case FB_VMODE_INTERLACED:
2613 line_shift = 0;
2614 break;
2615 case FB_VMODE_NONINTERLACED:
2616 line_shift = 1;
2617 break;
2618 case FB_VMODE_DOUBLE:
2619 if (!IS_AGA) {
2620 DPRINTK("double mode only possible with aga\n");
2621 return -EINVAL;
2622 }
2623 line_shift = 2;
2624 break;
2625 default:
2626 DPRINTK("unknown video mode\n");
2627 return -EINVAL;
2628 break;
2629 }
2630 par->line_shift = line_shift;
2631
2632
2633
2634
2635
2636 xres_n = par->xres<<clk_shift;
2637 yres_n = par->yres<<line_shift;
2638 par->htotal = down8((var->left_margin+par->xres+var->right_margin+var->hsync_len)<<clk_shift);
2639 par->vtotal = down2(((var->upper_margin+par->yres+var->lower_margin+var->vsync_len)<<line_shift)+1);
2640
2641 if (IS_AGA)
2642 par->bplcon3 = sprpixmode[clk_shift];
2643 else
2644 par->bplcon3 = 0;
2645 if (var->sync & FB_SYNC_BROADCAST) {
2646 par->diwstop_h = par->htotal-((var->right_margin-var->hsync_len)<<clk_shift);
2647 if (IS_AGA)
2648 par->diwstop_h += mod4(var->hsync_len);
2649 else
2650 par->diwstop_h = down4(par->diwstop_h);
2651
2652 par->diwstrt_h = par->diwstop_h - xres_n;
2653 par->diwstop_v = par->vtotal-((var->lower_margin-var->vsync_len)<<line_shift);
2654 par->diwstrt_v = par->diwstop_v - yres_n;
2655 if (par->diwstop_h >= par->htotal+8) {
2656 DPRINTK("invalid diwstop_h\n");
2657 return -EINVAL;
2658 }
2659 if (par->diwstop_v > par->vtotal) {
2660 DPRINTK("invalid diwstop_v\n");
2661 return -EINVAL;
2662 }
2663
2664 if (!IS_OCS) {
2665
2666 par->hsstrt = 160;
2667 par->hsstop = 320;
2668 par->vsstrt = 30;
2669 par->vsstop = 34;
2670 } else {
2671 par->hsstrt = 0;
2672 par->hsstop = 0;
2673 par->vsstrt = 0;
2674 par->vsstop = 0;
2675 }
2676 if (par->vtotal > (PAL_VTOTAL+NTSC_VTOTAL)/2) {
2677
2678 if (par->htotal != PAL_HTOTAL) {
2679 DPRINTK("htotal invalid for pal\n");
2680 return -EINVAL;
2681 }
2682 if (par->diwstrt_h < PAL_DIWSTRT_H) {
2683 DPRINTK("diwstrt_h too low for pal\n");
2684 return -EINVAL;
2685 }
2686 if (par->diwstrt_v < PAL_DIWSTRT_V) {
2687 DPRINTK("diwstrt_v too low for pal\n");
2688 return -EINVAL;
2689 }
2690 htotal = PAL_HTOTAL>>clk_shift;
2691 vtotal = PAL_VTOTAL>>1;
2692 if (!IS_OCS) {
2693 par->beamcon0 = BMC0_PAL;
2694 par->bplcon3 |= BPC3_BRDRBLNK;
2695 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2696 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2697 par->beamcon0 = BMC0_PAL;
2698 par->hsstop = 1;
2699 } else if (amiga_vblank != 50) {
2700 DPRINTK("pal not supported by this chipset\n");
2701 return -EINVAL;
2702 }
2703 } else {
2704
2705
2706
2707
2708 if (par->htotal != NTSC_HTOTAL) {
2709 DPRINTK("htotal invalid for ntsc\n");
2710 return -EINVAL;
2711 }
2712 if (par->diwstrt_h < NTSC_DIWSTRT_H) {
2713 DPRINTK("diwstrt_h too low for ntsc\n");
2714 return -EINVAL;
2715 }
2716 if (par->diwstrt_v < NTSC_DIWSTRT_V) {
2717 DPRINTK("diwstrt_v too low for ntsc\n");
2718 return -EINVAL;
2719 }
2720 htotal = NTSC_HTOTAL>>clk_shift;
2721 vtotal = NTSC_VTOTAL>>1;
2722 if (!IS_OCS) {
2723 par->beamcon0 = 0;
2724 par->bplcon3 |= BPC3_BRDRBLNK;
2725 } else if (AMIGAHW_PRESENT(AGNUS_HR_PAL) ||
2726 AMIGAHW_PRESENT(AGNUS_HR_NTSC)) {
2727 par->beamcon0 = 0;
2728 par->hsstop = 1;
2729 } else if (amiga_vblank != 60) {
2730 DPRINTK("ntsc not supported by this chipset\n");
2731 return -EINVAL;
2732 }
2733 }
2734 if (IS_OCS) {
2735 if (par->diwstrt_h >= 1024 || par->diwstop_h < 1024 ||
2736 par->diwstrt_v >= 512 || par->diwstop_v < 256) {
2737 DPRINTK("invalid position for display on ocs\n");
2738 return -EINVAL;
2739 }
2740 }
2741 } else if (!IS_OCS) {
2742
2743 par->hsstrt = var->right_margin<<clk_shift;
2744 par->hsstop = (var->right_margin+var->hsync_len)<<clk_shift;
2745 par->diwstop_h = par->htotal - mod8(par->hsstrt) + 8 - (1 << clk_shift);
2746 if (!IS_AGA)
2747 par->diwstop_h = down4(par->diwstop_h) - 16;
2748 par->diwstrt_h = par->diwstop_h - xres_n;
2749 par->hbstop = par->diwstrt_h + 4;
2750 par->hbstrt = par->diwstop_h + 4;
2751 if (par->hbstrt >= par->htotal + 8)
2752 par->hbstrt -= par->htotal;
2753 par->hcenter = par->hsstrt + (par->htotal >> 1);
2754 par->vsstrt = var->lower_margin<<line_shift;
2755 par->vsstop = (var->lower_margin+var->vsync_len)<<line_shift;
2756 par->diwstop_v = par->vtotal;
2757 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED)
2758 par->diwstop_v -= 2;
2759 par->diwstrt_v = par->diwstop_v - yres_n;
2760 par->vbstop = par->diwstrt_v - 2;
2761 par->vbstrt = par->diwstop_v - 2;
2762 if (par->vtotal > 2048) {
2763 DPRINTK("vtotal too high\n");
2764 return -EINVAL;
2765 }
2766 if (par->htotal > 2048) {
2767 DPRINTK("htotal too high\n");
2768 return -EINVAL;
2769 }
2770 par->bplcon3 |= BPC3_EXTBLKEN;
2771 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
2772 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
2773 BMC0_PAL | BMC0_VARCSYEN;
2774 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
2775 par->beamcon0 |= BMC0_HSYTRUE;
2776 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
2777 par->beamcon0 |= BMC0_VSYTRUE;
2778 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
2779 par->beamcon0 |= BMC0_CSYTRUE;
2780 htotal = par->htotal>>clk_shift;
2781 vtotal = par->vtotal>>1;
2782 } else {
2783 DPRINTK("only broadcast modes possible for ocs\n");
2784 return -EINVAL;
2785 }
2786
2787
2788
2789
2790
2791 fconst = 16<<maxfmode<<clk_shift;
2792
2793
2794
2795
2796
2797
2798
2799 fsize = ((maxfmode+clk_shift <= 1) ? fconst : 64);
2800 fstrt = downx(fconst, par->diwstrt_h-4) - fsize;
2801 if (fstrt < min_fstrt) {
2802 DPRINTK("fetch start too low\n");
2803 return -EINVAL;
2804 }
2805
2806
2807
2808
2809
2810 fstrt = downx(fconst, par->diwstrt_h-fconst+(1<<clk_shift)-4) - fsize;
2811 if (fstrt < min_fstrt)
2812 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2813
2814 maxfetchstop = down16(par->htotal - 80);
2815
2816 fstrt = downx(fconst, par->diwstrt_h-4) - 64 - fconst;
2817 fsize = upx(fconst, xres_n + modx(fconst, downx(1<<clk_shift, par->diwstrt_h-4)));
2818 if (fstrt + fsize > maxfetchstop)
2819 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2820
2821 fsize = upx(fconst, xres_n);
2822 if (fstrt + fsize > maxfetchstop) {
2823 DPRINTK("fetch stop too high\n");
2824 return -EINVAL;
2825 }
2826
2827 if (maxfmode + clk_shift <= 1) {
2828 fsize = up64(xres_n + fconst - 1);
2829 if (min_fstrt + fsize - 64 > maxfetchstop)
2830 par->vmode &= ~FB_VMODE_SMOOTH_XPAN;
2831
2832 fsize = up64(xres_n);
2833 if (min_fstrt + fsize - 64 > maxfetchstop) {
2834 DPRINTK("fetch size too high\n");
2835 return -EINVAL;
2836 }
2837
2838 fsize -= 64;
2839 } else
2840 fsize -= fconst;
2841
2842
2843
2844
2845
2846 if (par->htotal-fsize-64 < par->bpp*64)
2847 par->vmode &= ~FB_VMODE_YWRAP;
2848
2849
2850
2851
2852
2853 if (amifb_ilbm) {
2854 par->next_plane = div8(upx(16<<maxfmode, par->vxres));
2855 par->next_line = par->bpp*par->next_plane;
2856 if (par->next_line * par->vyres > fb_info.fix.smem_len) {
2857 DPRINTK("too few video mem\n");
2858 return -EINVAL;
2859 }
2860 } else {
2861 par->next_line = div8(upx(16<<maxfmode, par->vxres));
2862 par->next_plane = par->vyres*par->next_line;
2863 if (par->next_plane * par->bpp > fb_info.fix.smem_len) {
2864 DPRINTK("too few video mem\n");
2865 return -EINVAL;
2866 }
2867 }
2868
2869
2870
2871
2872
2873 par->bplcon0 = BPC0_COLOR | bplpixmode[clk_shift];
2874 if (!IS_OCS)
2875 par->bplcon0 |= BPC0_ECSENA;
2876 if (par->bpp == 8)
2877 par->bplcon0 |= BPC0_BPU3;
2878 else
2879 par->bplcon0 |= par->bpp<<12;
2880 if (var->nonstd == FB_NONSTD_HAM)
2881 par->bplcon0 |= BPC0_HAM;
2882 if (var->sync & FB_SYNC_EXT)
2883 par->bplcon0 |= BPC0_ERSY;
2884
2885 if (IS_AGA)
2886 par->fmode = bplfetchmode[maxfmode];
2887
2888 switch (par->vmode & FB_VMODE_MASK) {
2889 case FB_VMODE_INTERLACED:
2890 par->bplcon0 |= BPC0_LACE;
2891 break;
2892 case FB_VMODE_DOUBLE:
2893 if (IS_AGA)
2894 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
2895 break;
2896 }
2897
2898 if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) {
2899 par->xoffset = var->xoffset;
2900 par->yoffset = var->yoffset;
2901 if (par->vmode & FB_VMODE_YWRAP) {
2902 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres)
2903 par->xoffset = par->yoffset = 0;
2904 } else {
2905 if (par->xoffset < 0 || par->xoffset > upx(16<<maxfmode, par->vxres-par->xres) ||
2906 par->yoffset < 0 || par->yoffset > par->vyres-par->yres)
2907 par->xoffset = par->yoffset = 0;
2908 }
2909 } else
2910 par->xoffset = par->yoffset = 0;
2911
2912 par->crsr.crsr_x = par->crsr.crsr_y = 0;
2913 par->crsr.spot_x = par->crsr.spot_y = 0;
2914 par->crsr.height = par->crsr.width = 0;
2915
2916 return 0;
2917}
2918
2919
2920
2921
2922
2923
2924static int ami_encode_var(struct fb_var_screeninfo *var,
2925 struct amifb_par *par)
2926{
2927 u_short clk_shift, line_shift;
2928
2929 memset(var, 0, sizeof(struct fb_var_screeninfo));
2930
2931 clk_shift = par->clk_shift;
2932 line_shift = par->line_shift;
2933
2934 var->xres = par->xres;
2935 var->yres = par->yres;
2936 var->xres_virtual = par->vxres;
2937 var->yres_virtual = par->vyres;
2938 var->xoffset = par->xoffset;
2939 var->yoffset = par->yoffset;
2940
2941 var->bits_per_pixel = par->bpp;
2942 var->grayscale = 0;
2943
2944 var->red.offset = 0;
2945 var->red.msb_right = 0;
2946 var->red.length = par->bpp;
2947 if (par->bplcon0 & BPC0_HAM)
2948 var->red.length -= 2;
2949 var->blue = var->green = var->red;
2950 var->transp.offset = 0;
2951 var->transp.length = 0;
2952 var->transp.msb_right = 0;
2953
2954 if (par->bplcon0 & BPC0_HAM)
2955 var->nonstd = FB_NONSTD_HAM;
2956 else
2957 var->nonstd = 0;
2958 var->activate = 0;
2959
2960 var->height = -1;
2961 var->width = -1;
2962
2963 var->pixclock = pixclock[clk_shift];
2964
2965 if (IS_AGA && par->fmode & FMODE_BSCAN2)
2966 var->vmode = FB_VMODE_DOUBLE;
2967 else if (par->bplcon0 & BPC0_LACE)
2968 var->vmode = FB_VMODE_INTERLACED;
2969 else
2970 var->vmode = FB_VMODE_NONINTERLACED;
2971
2972 if (!IS_OCS && par->beamcon0 & BMC0_VARBEAMEN) {
2973 var->hsync_len = (par->hsstop-par->hsstrt)>>clk_shift;
2974 var->right_margin = par->hsstrt>>clk_shift;
2975 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2976 var->vsync_len = (par->vsstop-par->vsstrt)>>line_shift;
2977 var->lower_margin = par->vsstrt>>line_shift;
2978 var->upper_margin = (par->vtotal>>line_shift) - var->yres - var->lower_margin - var->vsync_len;
2979 var->sync = 0;
2980 if (par->beamcon0 & BMC0_HSYTRUE)
2981 var->sync |= FB_SYNC_HOR_HIGH_ACT;
2982 if (par->beamcon0 & BMC0_VSYTRUE)
2983 var->sync |= FB_SYNC_VERT_HIGH_ACT;
2984 if (par->beamcon0 & BMC0_CSYTRUE)
2985 var->sync |= FB_SYNC_COMP_HIGH_ACT;
2986 } else {
2987 var->sync = FB_SYNC_BROADCAST;
2988 var->hsync_len = (152>>clk_shift) + mod4(par->diwstop_h);
2989 var->right_margin = ((par->htotal - down4(par->diwstop_h))>>clk_shift) + var->hsync_len;
2990 var->left_margin = (par->htotal>>clk_shift) - var->xres - var->right_margin - var->hsync_len;
2991 var->vsync_len = 4>>line_shift;
2992 var->lower_margin = ((par->vtotal - par->diwstop_v)>>line_shift) + var->vsync_len;
2993 var->upper_margin = (((par->vtotal - 2)>>line_shift) + 1) - var->yres -
2994 var->lower_margin - var->vsync_len;
2995 }
2996
2997 if (par->bplcon0 & BPC0_ERSY)
2998 var->sync |= FB_SYNC_EXT;
2999 if (par->vmode & FB_VMODE_YWRAP)
3000 var->vmode |= FB_VMODE_YWRAP;
3001
3002 return 0;
3003}
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013static void ami_pan_var(struct fb_var_screeninfo *var)
3014{
3015 struct amifb_par *par = ¤tpar;
3016
3017 par->xoffset = var->xoffset;
3018 par->yoffset = var->yoffset;
3019 if (var->vmode & FB_VMODE_YWRAP)
3020 par->vmode |= FB_VMODE_YWRAP;
3021 else
3022 par->vmode &= ~FB_VMODE_YWRAP;
3023
3024 do_vmode_pan = 0;
3025 ami_update_par();
3026 do_vmode_pan = 1;
3027}
3028
3029
3030
3031
3032
3033static int ami_update_par(void)
3034{
3035 struct amifb_par *par = ¤tpar;
3036 short clk_shift, vshift, fstrt, fsize, fstop, fconst, shift, move, mod;
3037
3038 clk_shift = par->clk_shift;
3039
3040 if (!(par->vmode & FB_VMODE_SMOOTH_XPAN))
3041 par->xoffset = upx(16<<maxfmode, par->xoffset);
3042
3043 fconst = 16<<maxfmode<<clk_shift;
3044 vshift = modx(16<<maxfmode, par->xoffset);
3045 fstrt = par->diwstrt_h - (vshift<<clk_shift) - 4;
3046 fsize = (par->xres+vshift)<<clk_shift;
3047 shift = modx(fconst, fstrt);
3048 move = downx(2<<maxfmode, div8(par->xoffset));
3049 if (maxfmode + clk_shift > 1) {
3050 fstrt = downx(fconst, fstrt) - 64;
3051 fsize = upx(fconst, fsize);
3052 fstop = fstrt + fsize - fconst;
3053 } else {
3054 mod = fstrt = downx(fconst, fstrt) - fconst;
3055 fstop = fstrt + upx(fconst, fsize) - 64;
3056 fsize = up64(fsize);
3057 fstrt = fstop - fsize + 64;
3058 if (fstrt < min_fstrt) {
3059 fstop += min_fstrt - fstrt;
3060 fstrt = min_fstrt;
3061 }
3062 move = move - div8((mod-fstrt)>>clk_shift);
3063 }
3064 mod = par->next_line - div8(fsize>>clk_shift);
3065 par->ddfstrt = fstrt;
3066 par->ddfstop = fstop;
3067 par->bplcon1 = hscroll2hw(shift);
3068 par->bpl2mod = mod;
3069 if (par->bplcon0 & BPC0_LACE)
3070 par->bpl2mod += par->next_line;
3071 if (IS_AGA && (par->fmode & FMODE_BSCAN2))
3072 par->bpl1mod = -div8(fsize>>clk_shift);
3073 else
3074 par->bpl1mod = par->bpl2mod;
3075
3076 if (par->yoffset) {
3077 par->bplpt0 = fb_info.fix.smem_start + par->next_line*par->yoffset + move;
3078 if (par->vmode & FB_VMODE_YWRAP) {
3079 if (par->yoffset > par->vyres-par->yres) {
3080 par->bplpt0wrap = fb_info.fix.smem_start + move;
3081 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v+par->vyres-par->yoffset))
3082 par->bplpt0wrap += par->next_line;
3083 }
3084 }
3085 } else
3086 par->bplpt0 = fb_info.fix.smem_start + move;
3087
3088 if (par->bplcon0 & BPC0_LACE && mod2(par->diwstrt_v))
3089 par->bplpt0 += par->next_line;
3090
3091 return 0;
3092}
3093
3094
3095
3096
3097
3098
3099
3100
3101static int amifb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3102 u_int transp, struct fb_info *info)
3103{
3104 if (IS_AGA) {
3105 if (regno > 255)
3106 return 1;
3107 } else if (currentpar.bplcon0 & BPC0_SHRES) {
3108 if (regno > 3)
3109 return 1;
3110 } else {
3111 if (regno > 31)
3112 return 1;
3113 }
3114 red >>= 8;
3115 green >>= 8;
3116 blue >>= 8;
3117 if (!regno) {
3118 red0 = red;
3119 green0 = green;
3120 blue0 = blue;
3121 }
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131 if (regno || !is_blanked) {
3132#if defined(CONFIG_FB_AMIGA_AGA)
3133 if (IS_AGA) {
3134 u_short bplcon3 = currentpar.bplcon3;
3135 VBlankOff();
3136 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3137 custom.color[regno&31] = rgb2hw8_high(red, green, blue);
3138 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3139 custom.color[regno&31] = rgb2hw8_low(red, green, blue);
3140 custom.bplcon3 = bplcon3;
3141 VBlankOn();
3142 } else
3143#endif
3144#if defined(CONFIG_FB_AMIGA_ECS)
3145 if (currentpar.bplcon0 & BPC0_SHRES) {
3146 u_short color, mask;
3147 int i;
3148
3149 mask = 0x3333;
3150 color = rgb2hw2(red, green, blue);
3151 VBlankOff();
3152 for (i = regno+12; i >= (int)regno; i -= 4)
3153 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3154 mask <<=2; color >>= 2;
3155 regno = down16(regno)+mul4(mod4(regno));
3156 for (i = regno+3; i >= (int)regno; i--)
3157 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3158 VBlankOn();
3159 } else
3160#endif
3161 custom.color[regno] = rgb2hw4(red, green, blue);
3162 }
3163 return 0;
3164}
3165
3166static void ami_update_display(void)
3167{
3168 struct amifb_par *par = ¤tpar;
3169
3170 custom.bplcon1 = par->bplcon1;
3171 custom.bpl1mod = par->bpl1mod;
3172 custom.bpl2mod = par->bpl2mod;
3173 custom.ddfstrt = ddfstrt2hw(par->ddfstrt);
3174 custom.ddfstop = ddfstop2hw(par->ddfstop);
3175}
3176
3177
3178
3179
3180
3181static void ami_init_display(void)
3182{
3183 struct amifb_par *par = ¤tpar;
3184 int i;
3185
3186 custom.bplcon0 = par->bplcon0 & ~BPC0_LACE;
3187 custom.bplcon2 = (IS_OCS ? 0 : BPC2_KILLEHB) | BPC2_PF2P2 | BPC2_PF1P2;
3188 if (!IS_OCS) {
3189 custom.bplcon3 = par->bplcon3;
3190 if (IS_AGA)
3191 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3192 if (par->beamcon0 & BMC0_VARBEAMEN) {
3193 custom.htotal = htotal2hw(par->htotal);
3194 custom.hbstrt = hbstrt2hw(par->hbstrt);
3195 custom.hbstop = hbstop2hw(par->hbstop);
3196 custom.hsstrt = hsstrt2hw(par->hsstrt);
3197 custom.hsstop = hsstop2hw(par->hsstop);
3198 custom.hcenter = hcenter2hw(par->hcenter);
3199 custom.vtotal = vtotal2hw(par->vtotal);
3200 custom.vbstrt = vbstrt2hw(par->vbstrt);
3201 custom.vbstop = vbstop2hw(par->vbstop);
3202 custom.vsstrt = vsstrt2hw(par->vsstrt);
3203 custom.vsstop = vsstop2hw(par->vsstop);
3204 }
3205 }
3206 if (!IS_OCS || par->hsstop)
3207 custom.beamcon0 = par->beamcon0;
3208 if (IS_AGA)
3209 custom.fmode = par->fmode;
3210
3211
3212
3213
3214
3215 amiga_audio_min_period = div16(par->htotal);
3216
3217 is_lace = par->bplcon0 & BPC0_LACE ? 1 : 0;
3218#if 1
3219 if (is_lace) {
3220 i = custom.vposr >> 15;
3221 } else {
3222 custom.vposw = custom.vposr | 0x8000;
3223 i = 1;
3224 }
3225#else
3226 i = 1;
3227 custom.vposw = custom.vposr | 0x8000;
3228#endif
3229 custom.cop2lc = (u_short *)ZTWO_PADDR(copdisplay.list[currentcop][i]);
3230}
3231
3232
3233
3234
3235
3236static void ami_do_blank(void)
3237{
3238 struct amifb_par *par = ¤tpar;
3239#if defined(CONFIG_FB_AMIGA_AGA)
3240 u_short bplcon3 = par->bplcon3;
3241#endif
3242 u_char red, green, blue;
3243
3244 if (do_blank > 0) {
3245 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3246 red = green = blue = 0;
3247 if (!IS_OCS && do_blank > 1) {
3248 switch (do_blank) {
3249 case FB_BLANK_VSYNC_SUSPEND:
3250 custom.hsstrt = hsstrt2hw(par->hsstrt);
3251 custom.hsstop = hsstop2hw(par->hsstop);
3252 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3253 custom.vsstop = vsstop2hw(par->vtotal+4);
3254 break;
3255 case FB_BLANK_HSYNC_SUSPEND:
3256 custom.hsstrt = hsstrt2hw(par->htotal+16);
3257 custom.hsstop = hsstop2hw(par->htotal+16);
3258 custom.vsstrt = vsstrt2hw(par->vsstrt);
3259 custom.vsstop = vsstrt2hw(par->vsstop);
3260 break;
3261 case FB_BLANK_POWERDOWN:
3262 custom.hsstrt = hsstrt2hw(par->htotal+16);
3263 custom.hsstop = hsstop2hw(par->htotal+16);
3264 custom.vsstrt = vsstrt2hw(par->vtotal+4);
3265 custom.vsstop = vsstop2hw(par->vtotal+4);
3266 break;
3267 }
3268 if (!(par->beamcon0 & BMC0_VARBEAMEN)) {
3269 custom.htotal = htotal2hw(par->htotal);
3270 custom.vtotal = vtotal2hw(par->vtotal);
3271 custom.beamcon0 = BMC0_HARDDIS | BMC0_VARBEAMEN |
3272 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARCSYEN;
3273 }
3274 }
3275 } else {
3276 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
3277 red = red0;
3278 green = green0;
3279 blue = blue0;
3280 if (!IS_OCS) {
3281 custom.hsstrt = hsstrt2hw(par->hsstrt);
3282 custom.hsstop = hsstop2hw(par->hsstop);
3283 custom.vsstrt = vsstrt2hw(par->vsstrt);
3284 custom.vsstop = vsstop2hw(par->vsstop);
3285 custom.beamcon0 = par->beamcon0;
3286 }
3287 }
3288#if defined(CONFIG_FB_AMIGA_AGA)
3289 if (IS_AGA) {
3290 custom.bplcon3 = bplcon3;
3291 custom.color[0] = rgb2hw8_high(red, green, blue);
3292 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3293 custom.color[0] = rgb2hw8_low(red, green, blue);
3294 custom.bplcon3 = bplcon3;
3295 } else
3296#endif
3297#if defined(CONFIG_FB_AMIGA_ECS)
3298 if (par->bplcon0 & BPC0_SHRES) {
3299 u_short color, mask;
3300 int i;
3301
3302 mask = 0x3333;
3303 color = rgb2hw2(red, green, blue);
3304 for (i = 12; i >= 0; i -= 4)
3305 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3306 mask <<=2; color >>= 2;
3307 for (i = 3; i >= 0; i--)
3308 custom.color[i] = ecs_palette[i] = (ecs_palette[i] & mask) | color;
3309 } else
3310#endif
3311 custom.color[0] = rgb2hw4(red, green, blue);
3312 is_blanked = do_blank > 0 ? do_blank : 0;
3313}
3314
3315static int ami_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix)
3316{
3317 struct amifb_par *par = ¤tpar;
3318
3319 fix->crsr_width = fix->crsr_xsize = par->crsr.width;
3320 fix->crsr_height = fix->crsr_ysize = par->crsr.height;
3321 fix->crsr_color1 = 17;
3322 fix->crsr_color2 = 18;
3323 return 0;
3324}
3325
3326static int ami_get_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3327{
3328 struct amifb_par *par = ¤tpar;
3329 register u_short *lspr, *sspr;
3330#ifdef __mc68000__
3331 register u_long datawords asm ("d2");
3332#else
3333 register u_long datawords;
3334#endif
3335 register short delta;
3336 register u_char color;
3337 short height, width, bits, words;
3338 int size, alloc;
3339
3340 size = par->crsr.height*par->crsr.width;
3341 alloc = var->height*var->width;
3342 var->height = par->crsr.height;
3343 var->width = par->crsr.width;
3344 var->xspot = par->crsr.spot_x;
3345 var->yspot = par->crsr.spot_y;
3346 if (size > var->height*var->width)
3347 return -ENAMETOOLONG;
3348 if (!access_ok(VERIFY_WRITE, data, size))
3349 return -EFAULT;
3350 delta = 1<<par->crsr.fmode;
3351 lspr = lofsprite + (delta<<1);
3352 if (par->bplcon0 & BPC0_LACE)
3353 sspr = shfsprite + (delta<<1);
3354 else
3355 sspr = NULL;
3356 for (height = (short)var->height-1; height >= 0; height--) {
3357 bits = 0; words = delta; datawords = 0;
3358 for (width = (short)var->width-1; width >= 0; width--) {
3359 if (bits == 0) {
3360 bits = 16; --words;
3361#ifdef __mc68000__
3362 asm volatile ("movew %1@(%3:w:2),%0 ; swap %0 ; movew %1@+,%0"
3363 : "=d" (datawords), "=a" (lspr) : "1" (lspr), "d" (delta));
3364#else
3365 datawords = (*(lspr+delta) << 16) | (*lspr++);
3366#endif
3367 }
3368 --bits;
3369#ifdef __mc68000__
3370 asm volatile (
3371 "clrb %0 ; swap %1 ; lslw #1,%1 ; roxlb #1,%0 ; "
3372 "swap %1 ; lslw #1,%1 ; roxlb #1,%0"
3373 : "=d" (color), "=d" (datawords) : "1" (datawords));
3374#else
3375 color = (((datawords >> 30) & 2)
3376 | ((datawords >> 15) & 1));
3377 datawords <<= 1;
3378#endif
3379 put_user(color, data++);
3380 }
3381 if (bits > 0) {
3382 --words; ++lspr;
3383 }
3384 while (--words >= 0)
3385 ++lspr;
3386#ifdef __mc68000__
3387 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3388 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3389#else
3390 lspr += delta;
3391 if (sspr) {
3392 u_short *tmp = lspr;
3393 lspr = sspr;
3394 sspr = tmp;
3395 }
3396#endif
3397 }
3398 return 0;
3399}
3400
3401static int ami_set_var_cursorinfo(struct fb_var_cursorinfo *var, u_char __user *data)
3402{
3403 struct amifb_par *par = ¤tpar;
3404 register u_short *lspr, *sspr;
3405#ifdef __mc68000__
3406 register u_long datawords asm ("d2");
3407#else
3408 register u_long datawords;
3409#endif
3410 register short delta;
3411 u_short fmode;
3412 short height, width, bits, words;
3413
3414 if (!var->width)
3415 return -EINVAL;
3416 else if (var->width <= 16)
3417 fmode = TAG_FMODE_1;
3418 else if (var->width <= 32)
3419 fmode = TAG_FMODE_2;
3420 else if (var->width <= 64)
3421 fmode = TAG_FMODE_4;
3422 else
3423 return -EINVAL;
3424 if (fmode > maxfmode)
3425 return -EINVAL;
3426 if (!var->height)
3427 return -EINVAL;
3428 if (!access_ok(VERIFY_READ, data, var->width*var->height))
3429 return -EFAULT;
3430 delta = 1<<fmode;
3431 lofsprite = shfsprite = (u_short *)spritememory;
3432 lspr = lofsprite + (delta<<1);
3433 if (par->bplcon0 & BPC0_LACE) {
3434 if (((var->height+4)<<fmode<<2) > SPRITEMEMSIZE)
3435 return -EINVAL;
3436 memset(lspr, 0, (var->height+4)<<fmode<<2);
3437 shfsprite += ((var->height+5)&-2)<<fmode;
3438 sspr = shfsprite + (delta<<1);
3439 } else {
3440 if (((var->height+2)<<fmode<<2) > SPRITEMEMSIZE)
3441 return -EINVAL;
3442 memset(lspr, 0, (var->height+2)<<fmode<<2);
3443 sspr = NULL;
3444 }
3445 for (height = (short)var->height-1; height >= 0; height--) {
3446 bits = 16; words = delta; datawords = 0;
3447 for (width = (short)var->width-1; width >= 0; width--) {
3448 unsigned long tdata = 0;
3449 get_user(tdata, data);
3450 data++;
3451#ifdef __mc68000__
3452 asm volatile (
3453 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0 ; "
3454 "lsrb #1,%2 ; roxlw #1,%0 ; swap %0"
3455 : "=d" (datawords)
3456 : "0" (datawords), "d" (tdata));
3457#else
3458 datawords = ((datawords << 1) & 0xfffefffe);
3459 datawords |= tdata & 1;
3460 datawords |= (tdata & 2) << (16-1);
3461#endif
3462 if (--bits == 0) {
3463 bits = 16; --words;
3464#ifdef __mc68000__
3465 asm volatile ("swap %2 ; movew %2,%0@(%3:w:2) ; swap %2 ; movew %2,%0@+"
3466 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta));
3467#else
3468 *(lspr+delta) = (u_short) (datawords >> 16);
3469 *lspr++ = (u_short) (datawords & 0xffff);
3470#endif
3471 }
3472 }
3473 if (bits < 16) {
3474 --words;
3475#ifdef __mc68000__
3476 asm volatile (
3477 "swap %2 ; lslw %4,%2 ; movew %2,%0@(%3:w:2) ; "
3478 "swap %2 ; lslw %4,%2 ; movew %2,%0@+"
3479 : "=a" (lspr) : "0" (lspr), "d" (datawords), "d" (delta), "d" (bits));
3480#else
3481 *(lspr+delta) = (u_short) (datawords >> (16+bits));
3482 *lspr++ = (u_short) ((datawords & 0x0000ffff) >> bits);
3483#endif
3484 }
3485 while (--words >= 0) {
3486#ifdef __mc68000__
3487 asm volatile ("moveql #0,%%d0 ; movew %%d0,%0@(%2:w:2) ; movew %%d0,%0@+"
3488 : "=a" (lspr) : "0" (lspr), "d" (delta) : "d0");
3489#else
3490 *(lspr+delta) = 0;
3491 *lspr++ = 0;
3492#endif
3493 }
3494#ifdef __mc68000__
3495 asm volatile ("lea %0@(%4:w:2),%0 ; tstl %1 ; jeq 1f ; exg %0,%1\n1:"
3496 : "=a" (lspr), "=a" (sspr) : "0" (lspr), "1" (sspr), "d" (delta));
3497#else
3498 lspr += delta;
3499 if (sspr) {
3500 u_short *tmp = lspr;
3501 lspr = sspr;
3502 sspr = tmp;
3503 }
3504#endif
3505 }
3506 par->crsr.height = var->height;
3507 par->crsr.width = var->width;
3508 par->crsr.spot_x = var->xspot;
3509 par->crsr.spot_y = var->yspot;
3510 par->crsr.fmode = fmode;
3511 if (IS_AGA) {
3512 par->fmode &= ~(FMODE_SPAGEM | FMODE_SPR32);
3513 par->fmode |= sprfetchmode[fmode];
3514 custom.fmode = par->fmode;
3515 }
3516 return 0;
3517}
3518
3519static int ami_get_cursorstate(struct fb_cursorstate *state)
3520{
3521 struct amifb_par *par = ¤tpar;
3522
3523 state->xoffset = par->crsr.crsr_x;
3524 state->yoffset = par->crsr.crsr_y;
3525 state->mode = cursormode;
3526 return 0;
3527}
3528
3529static int ami_set_cursorstate(struct fb_cursorstate *state)
3530{
3531 struct amifb_par *par = ¤tpar;
3532
3533 par->crsr.crsr_x = state->xoffset;
3534 par->crsr.crsr_y = state->yoffset;
3535 if ((cursormode = state->mode) == FB_CURSOR_OFF)
3536 cursorstate = -1;
3537 do_cursor = 1;
3538 return 0;
3539}
3540
3541static void ami_set_sprite(void)
3542{
3543 struct amifb_par *par = ¤tpar;
3544 copins *copl, *cops;
3545 u_short hs, vs, ve;
3546 u_long pl, ps, pt;
3547 short mx, my;
3548
3549 cops = copdisplay.list[currentcop][0];
3550 copl = copdisplay.list[currentcop][1];
3551 ps = pl = ZTWO_PADDR(dummysprite);
3552 mx = par->crsr.crsr_x-par->crsr.spot_x;
3553 my = par->crsr.crsr_y-par->crsr.spot_y;
3554 if (!(par->vmode & FB_VMODE_YWRAP)) {
3555 mx -= par->xoffset;
3556 my -= par->yoffset;
3557 }
3558 if (!is_blanked && cursorstate > 0 && par->crsr.height > 0 &&
3559 mx > -(short)par->crsr.width && mx < par->xres &&
3560 my > -(short)par->crsr.height && my < par->yres) {
3561 pl = ZTWO_PADDR(lofsprite);
3562 hs = par->diwstrt_h + (mx<<par->clk_shift) - 4;
3563 vs = par->diwstrt_v + (my<<par->line_shift);
3564 ve = vs + (par->crsr.height<<par->line_shift);
3565 if (par->bplcon0 & BPC0_LACE) {
3566 ps = ZTWO_PADDR(shfsprite);
3567 lofsprite[0] = spr2hw_pos(vs, hs);
3568 shfsprite[0] = spr2hw_pos(vs+1, hs);
3569 if (mod2(vs)) {
3570 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3571 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve+1);
3572 pt = pl; pl = ps; ps = pt;
3573 } else {
3574 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve+1);
3575 shfsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs+1, hs, ve);
3576 }
3577 } else {
3578 lofsprite[0] = spr2hw_pos(vs, hs) | (IS_AGA && (par->fmode & FMODE_BSCAN2) ? 0x80 : 0);
3579 lofsprite[1<<par->crsr.fmode] = spr2hw_ctl(vs, hs, ve);
3580 }
3581 }
3582 copl[cop_spr0ptrh].w[1] = highw(pl);
3583 copl[cop_spr0ptrl].w[1] = loww(pl);
3584 if (par->bplcon0 & BPC0_LACE) {
3585 cops[cop_spr0ptrh].w[1] = highw(ps);
3586 cops[cop_spr0ptrl].w[1] = loww(ps);
3587 }
3588}
3589
3590
3591
3592
3593
3594
3595static void __init ami_init_copper(void)
3596{
3597 copins *cop = copdisplay.init;
3598 u_long p;
3599 int i;
3600
3601 if (!IS_OCS) {
3602 (cop++)->l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3603 (cop++)->l = CMOVE(0x0181, diwstrt);
3604 (cop++)->l = CMOVE(0x0281, diwstop);
3605 (cop++)->l = CMOVE(0x0000, diwhigh);
3606 } else
3607 (cop++)->l = CMOVE(BPC0_COLOR, bplcon0);
3608 p = ZTWO_PADDR(dummysprite);
3609 for (i = 0; i < 8; i++) {
3610 (cop++)->l = CMOVE(0, spr[i].pos);
3611 (cop++)->l = CMOVE(highw(p), sprpt[i]);
3612 (cop++)->l = CMOVE2(loww(p), sprpt[i]);
3613 }
3614
3615 (cop++)->l = CMOVE(IF_SETCLR | IF_COPER, intreq);
3616 copdisplay.wait = cop;
3617 (cop++)->l = CEND;
3618 (cop++)->l = CMOVE(0, copjmp2);
3619 cop->l = CEND;
3620
3621 custom.cop1lc = (u_short *)ZTWO_PADDR(copdisplay.init);
3622 custom.copjmp1 = 0;
3623}
3624
3625static void ami_reinit_copper(void)
3626{
3627 struct amifb_par *par = ¤tpar;
3628
3629 copdisplay.init[cip_bplcon0].w[1] = ~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) & par->bplcon0;
3630 copdisplay.wait->l = CWAIT(32, par->diwstrt_v-4);
3631}
3632
3633
3634
3635
3636
3637static void ami_build_copper(void)
3638{
3639 struct amifb_par *par = ¤tpar;
3640 copins *copl, *cops;
3641 u_long p;
3642
3643 currentcop = 1 - currentcop;
3644
3645 copl = copdisplay.list[currentcop][1];
3646
3647 (copl++)->l = CWAIT(0, 10);
3648 (copl++)->l = CMOVE(par->bplcon0, bplcon0);
3649 (copl++)->l = CMOVE(0, sprpt[0]);
3650 (copl++)->l = CMOVE2(0, sprpt[0]);
3651
3652 if (par->bplcon0 & BPC0_LACE) {
3653 cops = copdisplay.list[currentcop][0];
3654
3655 (cops++)->l = CWAIT(0, 10);
3656 (cops++)->l = CMOVE(par->bplcon0, bplcon0);
3657 (cops++)->l = CMOVE(0, sprpt[0]);
3658 (cops++)->l = CMOVE2(0, sprpt[0]);
3659
3660 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v+1), diwstrt);
3661 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v+1), diwstop);
3662 (cops++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3663 (cops++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3664 if (!IS_OCS) {
3665 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v+1,
3666 par->diwstop_h, par->diwstop_v+1), diwhigh);
3667 (cops++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3668 par->diwstop_h, par->diwstop_v), diwhigh);
3669#if 0
3670 if (par->beamcon0 & BMC0_VARBEAMEN) {
3671 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3672 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt+1), vbstrt);
3673 (copl++)->l = CMOVE(vbstop2hw(par->vbstop+1), vbstop);
3674 (cops++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3675 (cops++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3676 (cops++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3677 }
3678#endif
3679 }
3680 p = ZTWO_PADDR(copdisplay.list[currentcop][0]);
3681 (copl++)->l = CMOVE(highw(p), cop2lc);
3682 (copl++)->l = CMOVE2(loww(p), cop2lc);
3683 p = ZTWO_PADDR(copdisplay.list[currentcop][1]);
3684 (cops++)->l = CMOVE(highw(p), cop2lc);
3685 (cops++)->l = CMOVE2(loww(p), cop2lc);
3686 copdisplay.rebuild[0] = cops;
3687 } else {
3688 (copl++)->l = CMOVE(diwstrt2hw(par->diwstrt_h, par->diwstrt_v), diwstrt);
3689 (copl++)->l = CMOVE(diwstop2hw(par->diwstop_h, par->diwstop_v), diwstop);
3690 if (!IS_OCS) {
3691 (copl++)->l = CMOVE(diwhigh2hw(par->diwstrt_h, par->diwstrt_v,
3692 par->diwstop_h, par->diwstop_v), diwhigh);
3693#if 0
3694 if (par->beamcon0 & BMC0_VARBEAMEN) {
3695 (copl++)->l = CMOVE(vtotal2hw(par->vtotal), vtotal);
3696 (copl++)->l = CMOVE(vbstrt2hw(par->vbstrt), vbstrt);
3697 (copl++)->l = CMOVE(vbstop2hw(par->vbstop), vbstop);
3698 }
3699#endif
3700 }
3701 }
3702 copdisplay.rebuild[1] = copl;
3703
3704 ami_update_par();
3705 ami_rebuild_copper();
3706}
3707
3708
3709
3710
3711
3712
3713
3714static void ami_rebuild_copper(void)
3715{
3716 struct amifb_par *par = ¤tpar;
3717 copins *copl, *cops;
3718 u_short line, h_end1, h_end2;
3719 short i;
3720 u_long p;
3721
3722 if (IS_AGA && maxfmode + par->clk_shift == 0)
3723 h_end1 = par->diwstrt_h-64;
3724 else
3725 h_end1 = par->htotal-32;
3726 h_end2 = par->ddfstop+64;
3727
3728 ami_set_sprite();
3729
3730 copl = copdisplay.rebuild[1];
3731 p = par->bplpt0;
3732 if (par->vmode & FB_VMODE_YWRAP) {
3733 if ((par->vyres-par->yoffset) != 1 || !mod2(par->diwstrt_v)) {
3734 if (par->yoffset > par->vyres-par->yres) {
3735 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3736 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3737 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3738 }
3739 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 1;
3740 while (line >= 512) {
3741 (copl++)->l = CWAIT(h_end1, 510);
3742 line -= 512;
3743 }
3744 if (line >= 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3745 (copl++)->l = CWAIT(h_end1, line);
3746 else
3747 (copl++)->l = CWAIT(h_end2, line);
3748 p = par->bplpt0wrap;
3749 }
3750 } else p = par->bplpt0wrap;
3751 }
3752 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3753 (copl++)->l = CMOVE(highw(p), bplpt[i]);
3754 (copl++)->l = CMOVE2(loww(p), bplpt[i]);
3755 }
3756 copl->l = CEND;
3757
3758 if (par->bplcon0 & BPC0_LACE) {
3759 cops = copdisplay.rebuild[0];
3760 p = par->bplpt0;
3761 if (mod2(par->diwstrt_v))
3762 p -= par->next_line;
3763 else
3764 p += par->next_line;
3765 if (par->vmode & FB_VMODE_YWRAP) {
3766 if ((par->vyres-par->yoffset) != 1 || mod2(par->diwstrt_v)) {
3767 if (par->yoffset > par->vyres-par->yres+1) {
3768 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3769 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3770 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3771 }
3772 line = par->diwstrt_v + ((par->vyres-par->yoffset)<<par->line_shift) - 2;
3773 while (line >= 512) {
3774 (cops++)->l = CWAIT(h_end1, 510);
3775 line -= 512;
3776 }
3777 if (line > 510 && IS_AGA && maxfmode + par->clk_shift == 0)
3778 (cops++)->l = CWAIT(h_end1, line);
3779 else
3780 (cops++)->l = CWAIT(h_end2, line);
3781 p = par->bplpt0wrap;
3782 if (mod2(par->diwstrt_v+par->vyres-par->yoffset))
3783 p -= par->next_line;
3784 else
3785 p += par->next_line;
3786 }
3787 } else p = par->bplpt0wrap - par->next_line;
3788 }
3789 for (i = 0; i < (short)par->bpp; i++, p += par->next_plane) {
3790 (cops++)->l = CMOVE(highw(p), bplpt[i]);
3791 (cops++)->l = CMOVE2(loww(p), bplpt[i]);
3792 }
3793 cops->l = CEND;
3794 }
3795}
3796
3797static void __exit amifb_exit(void)
3798{
3799 unregister_framebuffer(&fb_info);
3800 amifb_deinit();
3801 amifb_video_off();
3802}
3803
3804module_init(amifb_init);
3805module_exit(amifb_exit);
3806
3807MODULE_LICENSE("GPL");
3808