This source file includes following definitions.
- mono_init_vblank
- mono_video_setup
- mono_build_clist_hdr
- mono_build_clist_dyn
- mono_build_cursor
- mono_build_ecs_colors
- mono_display_init
- mono_amifb_interrupt
- mono_amiga_fb_get_fix
- mono_amiga_fb_get_var
- mono_amiga_fb_set_disp
- mono_amiga_fb_set_var
- mono_amiga_fb_get_cmap
- mono_amiga_fb_set_cmap
- mono_amiga_fb_pan_display
- mono_amiga_fb_ioctl
- mono_amifb_switch
- mono_amifb_updatevar
- mono_amifb_blank
- mono_amiga_fb_init
- ocs_init
- ecs_init
- aga_init
- aga_encode_fix
- aga_decode_var
- aga_encode_var
- aga_getcolreg
- aga_setcolreg
- aga_pan_display
- aga_do_vmode
- aga_do_blank
- aga_do_movecursor
- aga_do_flashcursor
- aga_get_fix_cursorinfo
- aga_get_var_cursorinfo
- aga_set_var_cursorinfo
- aga_get_cursorstate
- aga_set_cursorstate
- aga_build_clist_hdr
- aga_update_clist_hdr
- aga_build_clist_dyn
- chipalloc
- amiga_fb_get_par
- amiga_fb_set_par
- do_fb_set_var
- get_default_colormap
- do_fb_get_cmap
- do_fb_set_cmap
- do_install_cmap
- memcpy_fs
- copy_cmap
- alloc_cmap
- amiga_fb_get_fix
- amiga_fb_get_var
- amiga_fb_set_disp
- amiga_fb_set_var
- amiga_fb_get_cmap
- amiga_fb_set_cmap
- amiga_fb_pan_display
- amiga_fb_ioctl
- amiga_fb_get_fix_cursorinfo
- amiga_fb_get_var_cursorinfo
- amiga_fb_set_var_cursorinfo
- amiga_fb_get_cursorstate
- amiga_fb_set_cursorstate
- amiga_video_setup
- amiga_fb_init
- amifb_switch
- amifb_updatevar
- amifb_blank
- amifb_interrupt
- strtoke
- get_video_mode
- check_default_mode
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 #include <linux/kernel.h>
39 #include <linux/errno.h>
40 #include <linux/string.h>
41 #include <linux/mm.h>
42 #include <linux/tty.h>
43 #include <linux/malloc.h>
44 #include <linux/delay.h>
45 #include <linux/config.h>
46 #include <linux/interrupt.h>
47 #include <asm/segment.h>
48 #include <asm/system.h>
49 #include <asm/irq.h>
50 #include <asm/amigahw.h>
51 #include <asm/amigaints.h>
52 #include <asm/bootinfo.h>
53 #include <linux/fb.h>
54
55
56 #undef CONFIG_AMIFB_OCS
57 #undef CONFIG_AMIFB_ECS
58 #define CONFIG_AMIFB_AGA
59
60 #define USE_MONO_AMIFB_IF_NON_AGA
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
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 #define CUSTOM_OFS(fld) ((long)&((struct CUSTOM*)0)->fld)
322
323
324
325
326
327
328 #define BPC0_HIRES (0x8000)
329 #define BPC0_BPU2 (0x4000)
330 #define BPC0_BPU1 (0x2000)
331 #define BPC0_BPU0 (0x1000)
332 #define BPC0_HAM (0x0800)
333 #define BPC0_DPF (0x0400)
334 #define BPC0_COLOR (0x0200)
335 #define BPC0_GAUD (0x0100)
336 #define BPC0_UHRES (0x0080)
337 #define BPC0_SHRES (0x0040)
338 #define BPC0_BYPASS (0x0020)
339 #define BPC0_BPU3 (0x0010)
340 #define BPC0_LPEN (0x0008)
341 #define BPC0_LACE (0x0004)
342 #define BPC0_ERSY (0x0002)
343 #define BPC0_ECSENA (0x0001)
344
345
346
347
348
349
350 #define BPC2_ZDBPSEL2 (0x4000)
351 #define BPC2_ZDBPSEL1 (0x2000)
352 #define BPC2_ZDBPSEL0 (0x1000)
353 #define BPC2_ZDBPEN (0x0800)
354 #define BPC2_ZDCTEN (0x0400)
355 #define BPC2_KILLEHB (0x0200)
356 #define BPC2_RDRAM (0x0100)
357 #define BPC2_SOGEN (0x0080)
358 #define BPC2_PF2PRI (0x0040)
359 #define BPC2_PF2P2 (0x0020)
360 #define BPC2_PF2P1 (0x0010)
361 #define BPC2_PF2P0 (0x0008)
362 #define BPC2_PF1P2 (0x0004)
363 #define BPC2_PF1P1 (0x0002)
364 #define BPC2_PF1P0 (0x0001)
365
366
367
368
369
370
371 #define BPC3_BANK2 (0x8000)
372 #define BPC3_BANK1 (0x4000)
373 #define BPC3_BANK0 (0x2000)
374 #define BPC3_PF2OF2 (0x1000)
375 #define BPC3_PF2OF1 (0x0800)
376 #define BPC3_PF2OF0 (0x0400)
377 #define BPC3_LOCT (0x0200)
378 #define BPC3_SPRES1 (0x0080)
379 #define BPC3_SPRES0 (0x0040)
380 #define BPC3_BRDRBLNK (0x0020)
381 #define BPC3_BRDRTRAN (0x0010)
382 #define BPC3_ZDCLKEN (0x0004)
383 #define BPC3_BRDRSPRT (0x0002)
384 #define BPC3_EXTBLKEN (0x0001)
385
386
387
388
389
390
391 #define BPC4_BPLAM7 (0x8000)
392 #define BPC4_BPLAM6 (0x4000)
393 #define BPC4_BPLAM5 (0x2000)
394 #define BPC4_BPLAM4 (0x1000)
395 #define BPC4_BPLAM3 (0x0800)
396 #define BPC4_BPLAM2 (0x0400)
397 #define BPC4_BPLAM1 (0x0200)
398 #define BPC4_BPLAM0 (0x0100)
399 #define BPC4_ESPRM7 (0x0080)
400 #define BPC4_ESPRM6 (0x0040)
401 #define BPC4_ESPRM5 (0x0020)
402 #define BPC4_ESPRM4 (0x0010)
403 #define BPC4_OSPRM7 (0x0008)
404 #define BPC4_OSPRM6 (0x0004)
405 #define BPC4_OSPRM5 (0x0002)
406 #define BPC4_OSPRM4 (0x0001)
407
408
409
410
411
412
413 #define BMC0_HARDDIS (0x4000)
414 #define BMC0_LPENDIS (0x2000)
415 #define BMC0_VARVBEN (0x1000)
416 #define BMC0_LOLDIS (0x0800)
417 #define BMC0_CSCBEN (0x0400)
418 #define BMC0_VARVSYEN (0x0200)
419 #define BMC0_VARHSYEN (0x0100)
420 #define BMC0_VARBEAMEN (0x0080)
421 #define BMC0_DUAL (0x0080)
422 #define BMC0_PAL (0x0020)
423 #define BMC0_VARCSYEN (0x0010)
424 #define BMC0_BLANKEN (0x0008)
425 #define BMC0_CSYTRUE (0x0004)
426 #define BMC0_VSYTRUE (0x0002)
427 #define BMC0_HSYTRUE (0x0001)
428
429
430
431
432
433
434 #define FMODE_SSCAN2 (0x8000)
435 #define FMODE_BSCAN2 (0x4000)
436 #define FMODE_SPAGEM (0x0008)
437 #define FMODE_SPR32 (0x0004)
438 #define FMODE_BPAGEM (0x0002)
439 #define FMODE_BPL32 (0x0001)
440
441
442
443
444
445
446
447
448 #define TAG_SHRES (1)
449 #define TAG_HIRES (2)
450 #define TAG_LORES (3)
451
452
453
454
455
456
457
458
459
460 static u_long pixclock[3];
461 static u_short maxdepth[3];
462
463
464
465
466
467
468
469
470
471 #define PAL_WINDOW_H (1472)
472 #define PAL_WINDOW_V (288)
473 #define PAL_DIWSTRT_H (360)
474 #define PAL_DIWSTRT_V (24)
475
476 #define NTSC_WINDOW_H (1472)
477 #define NTSC_WINDOW_V (242)
478 #define NTSC_DIWSTRT_H (360)
479 #define NTSC_DIWSTRT_V (20)
480
481 #define PAL_HTOTAL (1816)
482 #define NTSC_HTOTAL (1816)
483
484
485
486
487
488
489
490
491 static long vfmin = 50, vfmax = 90, hfmin = 15000, hfmax = 38000;
492
493 static u_short pwrsave = 0;
494
495
496
497
498
499
500 #define up8(x) (((x)+7) & ~7)
501 #define down8(x) ((x) & ~7)
502 #define div8(x) ((x)>>3)
503 #define mod8(x) ((x) & 7)
504
505 #define up16(x) (((x)+15) & ~15)
506 #define down16(x) ((x) & ~15)
507 #define div16(x) ((x)>>4)
508 #define mod16(x) ((x) & 15)
509
510 #define up32(x) (((x)+31) & ~31)
511 #define down32(x) ((x) & ~31)
512 #define div32(x) ((x)>>5)
513 #define mod32(x) ((x) & 31)
514
515 #define up64(x) (((x)+63) & ~63)
516 #define down64(x) ((x) & ~63)
517 #define div64(x) ((x)>>6)
518 #define mod64(x) ((x) & 63)
519
520 #define min(a, b) ((a) < (b) ? (a) : (b))
521 #define max(a, b) ((a) > (b) ? (a) : (b))
522
523 #define highw(x) ((u_long)(x)>>16 & 0xffff)
524 #define loww(x) ((u_long)(x) & 0xffff)
525
526 #define arraysize(x) (sizeof(x)/sizeof(*(x)))
527
528
529
530
531
532
533
534
535 #define VIDEOMEMSIZE_AGA_2M (1280*1024)
536 #define VIDEOMEMSIZE_AGA_1M (1024*768)
537 #define VIDEOMEMSIZE_ECS_2M (1280*1024/2)
538 #define VIDEOMEMSIZE_ECS_1M (1024*768/2)
539 #define VIDEOMEMSIZE_OCS (800*600/2)
540
541
542 static u_long videomemory;
543 static u_long videomemorysize;
544
545 #define assignchunk(name, type, ptr, size) \
546 { \
547 (name) = (type)(ptr); \
548 ptr += size; \
549 }
550
551
552
553
554
555
556 #define CMOVE(val, reg) (CUSTOM_OFS(reg)<<16 | (val))
557 #define CMOVE2(val, reg) ((CUSTOM_OFS(reg)+2)<<16 | (val))
558 #define CWAIT(x, y) (((y) & 0xff)<<24 | ((x) & 0xfe)<<16 | 0x0001fffe)
559 #define CEND (0xfffffffe)
560
561
562 typedef union {
563 u_long l;
564 u_short w[2];
565 } copins;
566
567
568
569
570
571
572 struct clist_hdr {
573 copins bplcon0;
574 copins diwstrt;
575 copins diwstop;
576 copins diwhigh;
577 copins sprfix[8];
578 copins sprstrtup[16];
579 copins wait;
580 copins jump;
581 copins wait_forever;
582 };
583
584
585
586
587
588
589 struct clist_dyn {
590 copins diwstrt;
591 copins diwstop;
592 copins diwhigh;
593 copins bplcon0;
594 copins sprpt[2];
595 copins rest[64];
596 };
597
598
599 static struct clist_hdr *clist_hdr;
600 static struct clist_dyn *clist_lof;
601 static struct clist_dyn *clist_shf;
602
603
604
605
606
607
608 #define CRSR_RATE (20)
609
610 static u_long *lofsprite, *shfsprite, *dummysprite;
611 static u_short cursormode = FB_CURSOR_FLASH;
612
613
614
615
616
617
618 struct amiga_fb_par {
619
620
621
622 int xres;
623 int yres;
624 int vxres;
625 int vyres;
626 int xoffset;
627 int yoffset;
628 u_short bpp;
629 u_short clk_shift;
630 int vmode;
631 u_short diwstrt_h;
632 u_short diwstrt_v;
633 u_long next_line;
634 u_long next_plane;
635 short crsr_x;
636 short crsr_y;
637
638
639
640 u_long bplpt0;
641 u_short bplcon0;
642 u_short bplcon1;
643 u_short bpl1mod;
644 u_short bpl2mod;
645 u_short diwstrt;
646 u_short diwstop;
647 u_short ddfstrt;
648 u_short ddfstop;
649
650 #if defined(CONFIG_AMIFB_ECS) || defined(CONFIG_AMIFB_AGA)
651
652
653 u_short diwhigh;
654 u_short bplcon3;
655 u_short beamcon0;
656 u_short htotal;
657 u_short hsstrt;
658 u_short hsstop;
659 u_short vtotal;
660 u_short vsstrt;
661 u_short vsstop;
662 u_short hcenter;
663 #endif
664
665 #if defined(CONFIG_AMIFB_AGA)
666
667
668 u_short fmode;
669 #endif
670 };
671
672 static struct amiga_fb_par current_par;
673
674 static int current_par_valid = 0;
675 static int currcon = 0;
676
677 static struct display disp[MAX_NR_CONSOLES];
678 static struct fb_info fb_info;
679
680 static int node;
681
682
683
684
685
686
687 volatile u_short amiga_audio_min_period = 124;
688
689
690
691
692
693
694
695
696 #ifdef CONFIG_AMIFB_AGA
697 static struct { u_char red, green, blue, pad; } palette[256];
698 #else
699 static struct { u_char red, green, blue, pad; } palette[32];
700 #endif
701
702
703
704
705
706
707 static volatile u_short do_vmode = 0;
708 static volatile short do_blank = 0;
709 static volatile u_short do_movecursor = 0;
710 static volatile u_short full_vmode_change = 1;
711 static volatile u_short is_blanked = 0;
712
713
714
715
716
717
718 static struct fb_hwswitch {
719
720
721 int (*init)(void);
722
723
724 int (*encode_fix)(struct fb_fix_screeninfo *fix, struct amiga_fb_par *par);
725 int (*decode_var)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
726 int (*encode_var)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
727 int (*getcolreg)(u_int regno, u_int *red, u_int *green, u_int *blue,
728 u_int *transp);
729 int (*setcolreg)(u_int regno, u_int red, u_int green, u_int blue,
730 u_int transp);
731 int (*pan_display)(struct fb_var_screeninfo *var, struct amiga_fb_par *par);
732
733
734 void (*do_vmode)(void);
735 void (*do_blank)(int blank);
736 void (*do_movecursor)(void);
737 void (*do_flashcursor)(void);
738 } *fbhw;
739
740
741
742
743
744
745
746
747 static char amiga_fb_name[16] = "Amiga ";
748
749
750
751
752
753
754
755
756 static char *amiga_fb_modenames[] = {
757
758
759
760
761
762 "default",
763
764
765
766
767
768 "ntsc",
769 "ntsc-lace",
770 "pal",
771 "pal-lace",
772 "multiscan",
773 "multiscan-lace",
774 "a2024-10",
775 "a2024-15",
776 "euro36",
777 "euro36-lace",
778 "euro72",
779 "euro72-lace",
780 "super72",
781 "super72-lace",
782 "dblntsc",
783 "dblntsc-ff",
784 "dblntsc-lace",
785 "dblpal",
786 "dblpal-ff",
787 "dblpal-lace",
788
789
790
791
792
793 "vga",
794 "vga70",
795
796
797
798
799
800 "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7"
801 };
802
803
804
805
806
807
808
809
810
811
812 static struct fb_var_screeninfo amiga_fb_predefined[] = {
813
814
815
816
817
818 { 0, },
819
820
821
822
823
824 {
825
826 640, 200, 640, 200, 0, 0, 4, 0,
827 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
828 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 24, 18, 0, 0,
829 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
830 }, {
831
832 640, 400, 640, 400, 0, 0, 4, 0,
833 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
834 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 48, 36, 0, 0,
835 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
836 }, {
837
838 640, 256, 640, 256, 0, 0, 4, 0,
839 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
840 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 20, 12, 0, 0,
841 FB_SYNC_BROADCAST, FB_VMODE_NONINTERLACED
842 }, {
843
844 640, 512, 640, 512, 0, 0, 4, 0,
845 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
846 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 78, 18, 40, 24, 0, 0,
847 FB_SYNC_BROADCAST, FB_VMODE_INTERLACED
848 }, {
849
850 640, 480, 640, 480, 0, 0, 4, 0,
851 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
852 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 9, 9, 80, 8,
853 0, FB_VMODE_NONINTERLACED
854 }, {
855
856 640, 960, 640, 960, 0, 0, 4, 0,
857 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
858 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 18, 18, 80, 16,
859 0, FB_VMODE_INTERLACED
860 }, {
861
862 1024, 800, 1024, 800, 0, 0, 2, 0,
863 {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
864 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0,
865 0, FB_VMODE_NONINTERLACED
866 }, {
867
868 1024, 800, 1024, 800, 0, 0, 2, 0,
869 {0, 2, 0}, {0, 2, 0}, {0, 2, 0}, {0, 0, 0},
870 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 0, 0, 0, 0, 0, 0,
871 0, FB_VMODE_NONINTERLACED
872 }, {
873
874 640, 200, 640, 200, 0, 0, 4, 0,
875 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
876 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 6, 6, 52, 5,
877 0, FB_VMODE_NONINTERLACED
878 }, {
879
880 640, 400, 640, 400, 0, 0, 4, 0,
881 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
882 0, 0, -1, -1, FB_ACCEL_NONE, TAG_HIRES, 92, 124, 12, 12, 52, 10,
883 0, FB_VMODE_INTERLACED
884 }, {
885
886 640, 400, 640, 400, 0, 0, 4, 0,
887 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
888 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 9, 9, 80, 8,
889 0, FB_VMODE_NONINTERLACED
890 }, {
891
892 640, 800, 640, 800, 0, 0, 4, 0,
893 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
894 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 164, 92, 18, 18, 80, 16,
895 0, FB_VMODE_INTERLACED
896 }, {
897
898 800, 300, 800, 300, 0, 0, 4, 0,
899 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
900 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 10, 11, 80, 7,
901 0, FB_VMODE_NONINTERLACED
902 }, {
903
904 800, 600, 800, 600, 0, 0, 4, 0,
905 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
906 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 212, 140, 20, 22, 80, 14,
907 0, FB_VMODE_INTERLACED
908 }, {
909
910 640, 200, 640, 200, 0, 0, 4, 0,
911 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
912 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 18, 17, 80, 4,
913 0, FB_VMODE_DOUBLE
914 }, {
915
916 640, 400, 640, 400, 0, 0, 4, 0,
917 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
918 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 36, 35, 80, 7,
919 0, FB_VMODE_NONINTERLACED
920 }, {
921
922 640, 800, 640, 800, 0, 0, 4, 0,
923 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
924 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 72, 70, 80, 14,
925 0, FB_VMODE_INTERLACED
926 }, {
927
928 640, 256, 640, 256, 0, 0, 4, 0,
929 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
930 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 14, 13, 80, 4,
931 0, FB_VMODE_DOUBLE
932 }, {
933
934 640, 512, 640, 512, 0, 0, 4, 0,
935 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
936 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 28, 27, 80, 7,
937 0, FB_VMODE_NONINTERLACED
938 }, {
939
940 640, 1024, 640, 1024, 0, 0, 4, 0,
941 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
942 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 196, 124, 56, 54, 80, 14,
943 0, FB_VMODE_INTERLACED
944 },
945
946
947
948
949
950 {
951
952 640, 480, 640, 480, 0, 0, 4, 0,
953 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
954 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 30, 9, 112, 2,
955 0, FB_VMODE_NONINTERLACED
956 }, {
957
958 640, 400, 640, 400, 0, 0, 4, 0,
959 {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0},
960 0, 0, -1, -1, FB_ACCEL_NONE, TAG_SHRES, 64, 96, 35, 12, 112, 2,
961 FB_SYNC_VERT_HIGH_ACT | FB_SYNC_COMP_HIGH_ACT, FB_VMODE_NONINTERLACED
962 },
963
964
965
966
967
968 { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }, { 0, }
969 };
970
971
972 #define NUM_USER_MODES (8)
973 #define NUM_TOTAL_MODES arraysize(amiga_fb_predefined)
974 #define NUM_PREDEF_MODES (NUM_TOTAL_MODES-NUM_USER_MODES)
975
976
977 static int amifb_ilbm = 0;
978
979 static int amifb_inverse = 0;
980 static int amifb_mode = 0;
981
982
983
984
985
986
987 #ifdef CONFIG_FB_CYBER
988 extern int Cyber_probe(void);
989 extern void Cyber_video_setup(char *options, int *ints);
990 extern struct fb_info *Cyber_fb_init(long *mem_start);
991
992 static int amifb_Cyber = 0;
993 #endif
994
995
996
997
998
999
1000 #define DEFMODE_PAL "pal"
1001 #define DEFMODE_NTSC "ntsc"
1002 #define DEFMODE_AMBER_PAL "pal-lace"
1003 #define DEFMODE_AMBER_NTSC "ntsc-lace"
1004 #define DEFMODE_AGA "vga70"
1005
1006
1007
1008
1009
1010
1011 void amiga_video_setup(char *options, int *ints);
1012
1013 static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con);
1014 static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con);
1015 static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con);
1016 static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con);
1017 static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con);
1018 static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con);
1019
1020 static int amiga_fb_ioctl(struct inode *inode, struct file *file, u_int cmd,
1021 u_long arg, int con);
1022
1023 static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con);
1024 static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1025 static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1026 static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con);
1027 static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con);
1028
1029
1030
1031
1032
1033
1034 struct fb_info *amiga_fb_init(long *mem_start);
1035 static int amifb_switch(int con);
1036 static int amifb_updatevar(int con);
1037 static void amifb_blank(int blank);
1038
1039
1040
1041
1042
1043
1044 #ifdef CONFIG_AMIFB_OCS
1045 #error "OCS support: not yet implemented"
1046 #endif
1047
1048
1049
1050
1051
1052
1053 #ifdef CONFIG_AMIFB_ECS
1054 #error "ECS support: not yet implemented"
1055 #endif
1056
1057
1058
1059
1060
1061
1062 #ifdef CONFIG_AMIFB_AGA
1063 static int aga_init(void);
1064 static int aga_encode_fix(struct fb_fix_screeninfo *fix,
1065 struct amiga_fb_par *par);
1066 static int aga_decode_var(struct fb_var_screeninfo *var,
1067 struct amiga_fb_par *par);
1068 static int aga_encode_var(struct fb_var_screeninfo *var,
1069 struct amiga_fb_par *par);
1070 static int aga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
1071 u_int *transp);
1072 static int aga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
1073 u_int transp);
1074 static int aga_pan_display(struct fb_var_screeninfo *var,
1075 struct amiga_fb_par *par);
1076 static void aga_do_vmode(void);
1077 static void aga_do_blank(int blank);
1078 static void aga_do_movecursor(void);
1079 static void aga_do_flashcursor(void);
1080
1081 static int aga_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con);
1082 static int aga_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1083 static int aga_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con);
1084 static int aga_get_cursorstate(struct fb_cursorstate *state, int con);
1085 static int aga_set_cursorstate(struct fb_cursorstate *state, int con);
1086
1087 static __inline__ void aga_build_clist_hdr(struct clist_hdr *cop);
1088 static __inline__ void aga_update_clist_hdr(struct clist_hdr *cop,
1089 struct amiga_fb_par *par);
1090 static void aga_build_clist_dyn(struct clist_dyn *cop,
1091 struct clist_dyn *othercop, u_short shf,
1092 struct amiga_fb_par *par);
1093 #endif
1094
1095
1096
1097
1098
1099
1100 static u_long chipalloc(u_long size);
1101 static void amiga_fb_get_par(struct amiga_fb_par *par);
1102 static void amiga_fb_set_par(struct amiga_fb_par *par);
1103 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive);
1104 static struct fb_cmap *get_default_colormap(int bpp);
1105 static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
1106 int kspc);
1107 static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
1108 int kspc);
1109 static void do_install_cmap(int con);
1110 static void memcpy_fs(int fsfromto, void *to, void *from, int len);
1111 static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto);
1112 static int alloc_cmap(struct fb_cmap *cmap, int len, int transp);
1113 static void amiga_fb_set_disp(int con);
1114 static void amifb_interrupt(int irq, struct pt_regs *fp, void *dummy);
1115 static char * strtoke(char * s,const char * ct);
1116 static int get_video_mode(const char *name);
1117 static void check_default_mode(void);
1118
1119
1120 #ifdef USE_MONO_AMIFB_IF_NON_AGA
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155 static struct mono_mono_amiga_fb_par {
1156 u_long smem_start;
1157 u_long smem_len;
1158 struct geometry *geometry;
1159 ushort scr_max_height;
1160 ushort scr_max_width;
1161 ushort scr_height;
1162 ushort scr_width;
1163 ushort scr_depth;
1164 int bytes_per_row;
1165 ulong fgcol;
1166 ulong bgcol;
1167 ulong crsrcol;
1168 ushort scroll_latch;
1169 ushort y_wrap;
1170 ushort cursor_latch;
1171 ushort *cursor, *dummy;
1172 ushort cursor_flash;
1173 ushort cursor_visible;
1174 ushort diwstrt_v, diwstrt_h;
1175 ushort diwstop_v, diwstop_h;
1176 ushort bplcon0;
1177 ushort htotal;
1178 u_char *bitplane[8];
1179 ulong plane_size;
1180 ushort *coplist1hdr;
1181 ushort *coplist1dyn;
1182 ushort *coplist2hdr;
1183 ushort *coplist2dyn;
1184 } mono_current_par;
1185
1186
1187 static ushort mono_cursor_data[] =
1188 {
1189 0x2c81,0x2d00,
1190 0xf000,0x0000,
1191 0x0000,0x0000
1192 };
1193
1194
1195
1196
1197
1198
1199 #define FG_COLOR (0x000000)
1200 #define BG_COLOR (0xaaaaaa)
1201 #define CRSR_COLOR (0xff0000)
1202
1203 #define FG_COLOR_INV BG_COLOR
1204 #define BG_COLOR_INV FG_COLOR
1205 #define CRSR_COLOR_INV (0x6677aa)
1206
1207
1208
1209
1210
1211 #define COLOR_MSB(rgb) (((rgb>>12)&0xf00)|((rgb>>8)&0x0f0)|((rgb>>4)&0x00f))
1212 #define COLOR_LSB(rgb) (((rgb>>8) &0xf00)|((rgb>>4)&0x0f0)|((rgb) &0x00f))
1213
1214
1215
1216 #define CRSR_FLASH 1
1217 #define CRSR_BLOCK 1
1218
1219
1220
1221 static int mono_do_blank;
1222 static int mono_do_unblank;
1223 static unsigned short mono_save_bplcon3;
1224
1225
1226
1227
1228
1229
1230
1231 static ushort mono_ecs_color_zero;
1232
1233 static struct {
1234 int right_count;
1235 int done;
1236 } mono_vblank;
1237
1238
1239 static __inline__ void mono_init_vblank(void)
1240 {
1241 mono_vblank.right_count = 0;
1242 mono_vblank.done = 0;
1243 }
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262 struct geometry {
1263 char *modename;
1264 char isOCS;
1265 ushort bplcon0;
1266 ushort scr_width;
1267 ushort scr_height;
1268 ushort scr_depth;
1269 ushort scr_max_width;
1270 ushort scr_max_height;
1271 ushort diwstrt_h;
1272 ushort diwstrt_v;
1273 ushort alignment;
1274
1275 ushort bplcon2;
1276 ushort bplcon3;
1277
1278 ushort htotal;
1279 ushort hsstrt;
1280 ushort hsstop;
1281 ushort hbstrt;
1282 ushort hbstop;
1283 ushort vtotal;
1284 ushort vsstrt;
1285 ushort vsstop;
1286 ushort vbstrt;
1287 ushort vbstop;
1288 ushort hcenter;
1289 ushort beamcon0;
1290 ushort fmode;
1291 };
1292
1293 #define MAX_COP_LIST_ENTS 64
1294 #define COP_MEM_REQ (MAX_COP_LIST_ENTS*4*2)
1295 #define SPR_MEM_REQ (24)
1296
1297
1298 static struct geometry mono_modes[] = {
1299
1300 {
1301 "ntsc-lace", 1,
1302 BPC0_HIRES | BPC0_LACE,
1303 640, 400, 1,
1304 704, 480,
1305 0x71, 0x18,
1306 16
1307 }, {
1308 "ntsc", 1,
1309 BPC0_HIRES,
1310 640, 200, 1,
1311 704, 240,
1312 0x71, 0x18,
1313 16
1314 }, {
1315 "ntsc-lace-over", 1,
1316 BPC0_HIRES | BPC0_LACE,
1317 704, 480, 1,
1318 704, 480,
1319 0x71, 0x18,
1320 16
1321 }, {
1322 "ntsc-over", 1,
1323 BPC0_HIRES,
1324 704, 240, 1,
1325 704, 240,
1326 0x71, 0x18,
1327 16
1328 },
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339 {
1340 "pal-lace", 1,
1341 BPC0_HIRES | BPC0_LACE,
1342 640, 512, 1,
1343 704, 592,
1344 0x71, 0x18,
1345 16
1346 }, {
1347 "pal", 1,
1348 BPC0_HIRES,
1349 640, 256, 1,
1350 704, 296,
1351 0x71, 0x18,
1352 16
1353 }, {
1354 "pal-lace-over", 1,
1355 BPC0_HIRES | BPC0_LACE,
1356 704, 592, 1,
1357 704, 582,
1358 0x5b, 0x18,
1359 16
1360 }, {
1361 "pal-over", 1,
1362 BPC0_HIRES,
1363 704, 296, 1,
1364 704, 296,
1365 0x5b, 0x18,
1366 16
1367
1368 },
1369
1370 {
1371 "multiscan", 0,
1372 BPC0_SHRES | BPC0_ECSENA,
1373 640, 480, 1,
1374 640, 480,
1375 0x0041, 0x002c,
1376 64,
1377 BPC2_KILLEHB,
1378 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1379 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1380
1381 0x0072,
1382 0x000a,
1383 0x0013,
1384 0x0002,
1385 0x001c,
1386 0x020c,
1387 0x0008,
1388 0x0011,
1389 0x0000,
1390 0x001c,
1391 0x0043,
1392 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1393 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1394
1395 FMODE_BPAGEM | FMODE_BPL32
1396 },
1397 {
1398 "multiscan-lace", 0,
1399 BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,
1400 640, 960, 1,
1401 640, 960,
1402 0x0041, 0x002c,
1403 64,
1404 BPC2_KILLEHB,
1405 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1406 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1407
1408 0x0072,
1409 0x000a,
1410 0x0013,
1411 0x0002,
1412 0x001c,
1413 0x020c,
1414 0x0008,
1415 0x0011,
1416 0x0000,
1417 0x001c,
1418 0x0043,
1419 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1420 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1421
1422 FMODE_BPAGEM | FMODE_BPL32
1423 },
1424
1425 {
1426 "super72", 0,
1427 BPC0_SHRES | BPC0_ECSENA,
1428 800, 304, 1,
1429 800, 304,
1430 0x0051, 0x0021,
1431 64,
1432 BPC2_KILLEHB,
1433 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1434 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1435 0x0091,
1436 0x000a,
1437 0x0013,
1438 0x0001,
1439 0x001e,
1440 0x0156,
1441 0x0009,
1442 0x0012,
1443 0x0000,
1444 0x001c,
1445 0x0052,
1446 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1447 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1448
1449 FMODE_BPAGEM | FMODE_BPL32
1450 },
1451
1452 {
1453 "super72-lace", 0,
1454 BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,
1455 800, 600, 1,
1456 800, 600,
1457 0x0051, 0x0021,
1458 64,
1459 BPC2_KILLEHB,
1460 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1461 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1462
1463 0x0091,
1464 0x000a,
1465 0x0013,
1466 0x0001,
1467 0x001e,
1468 0x0150,
1469 0x0009,
1470 0x0012,
1471 0x0000,
1472 0x001c,
1473 0x0052,
1474 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1475 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1476
1477 FMODE_BPAGEM | FMODE_BPL32
1478 },
1479
1480 {
1481 "dblntsc", 0,
1482 BPC0_SHRES | BPC0_ECSENA,
1483 640, 400, 1,
1484 640, 400,
1485 0x0049, 0x0021,
1486 64,
1487 BPC2_KILLEHB,
1488 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1489 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1490
1491 0x0079,
1492 0x0007,
1493 0x0013,
1494 0x0001,
1495 0x001e,
1496 0x01ec,
1497 0x0008,
1498 0x0010,
1499 0x0000,
1500 0x0019,
1501 0x0046,
1502 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1503 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1504
1505 FMODE_BPAGEM | FMODE_BPL32
1506 },
1507
1508 {
1509 "dblpal", 0,
1510 BPC0_SHRES | BPC0_ECSENA,
1511 640, 512, 1,
1512 640, 512,
1513 0x0049, 0x0021,
1514 64,
1515 BPC2_KILLEHB,
1516 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1517 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1518
1519 0x0079,
1520 0x0007,
1521 0x0013,
1522 0x0001,
1523 0x001e,
1524 0x0234,
1525 0x0008,
1526 0x0010,
1527 0x0000,
1528 0x0019,
1529 0x0046,
1530 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1531 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1532
1533 FMODE_BPAGEM | FMODE_BPL32
1534 },
1535
1536 {
1537 "euro72", 0,
1538 BPC0_SHRES | BPC0_ECSENA,
1539 640, 400, 1,
1540 640, 400,
1541 0x0041, 0x0021,
1542 64,
1543 BPC2_KILLEHB,
1544 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1545 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1546
1547 0x0071,
1548 0x0009,
1549 0x0013,
1550 0x0001,
1551 0x001e,
1552 0x01be,
1553 0x0008,
1554 0x0016,
1555 0x0000,
1556 0x001f,
1557 0x0041,
1558 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1559 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1560
1561 FMODE_BPAGEM | FMODE_BPL32
1562 },
1563
1564 {
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578 "aga640x480", 0,
1579 BPC0_SHRES | BPC0_ECSENA,
1580 640, 480, 1,
1581 640, 480,
1582 0x0041, 0x002b,
1583 64,
1584 BPC2_KILLEHB,
1585 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1586 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1587 0x0071,
1588 0x000c,
1589 0x001c,
1590 0x0008,
1591 0x001e,
1592 0x020c,
1593 0x0001,
1594 0x0003,
1595 0x0000,
1596 0x000f,
1597 0x0046,
1598 BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1599 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1600 FMODE_BPAGEM | FMODE_BPL32
1601 }, {
1602
1603 "aga800x600", 0,
1604 BPC0_SHRES | BPC0_LACE | BPC0_ECSENA,
1605 896, 624, 1,
1606 896, 624,
1607 0x0041, 0x001e,
1608 64,
1609 BPC2_KILLEHB,
1610 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1611 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1612 0x0091,
1613 0x000e,
1614 0x001d,
1615 0x000a,
1616 0x001e,
1617 0x0156,
1618 0x0001,
1619 0x0003,
1620 0x0000,
1621 0x000f,
1622 0x0050,
1623 BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN |
1624 BMC0_VARHSYEN | BMC0_VARBEAMEN | BMC0_BLANKEN,
1625 FMODE_BPAGEM | FMODE_BPL32
1626 },
1627
1628
1629
1630 {
1631
1632
1633
1634 "aga720x400", 0,
1635 BPC0_SHRES | BPC0_ECSENA,
1636 720, 400, 1,
1637 720, 400,
1638 0x0041, 0x0013,
1639 64,
1640 BPC2_KILLEHB,
1641 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1642 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1643 0x0079,
1644 0x000e,
1645 0x0018,
1646 0x0001,
1647 0x0021,
1648 0x01a2,
1649 0x0003,
1650 0x0005,
1651 0x0000,
1652 0x0012,
1653 0x0046,
1654 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1655 BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1656 BMC0_VSYTRUE,
1657 FMODE_BPAGEM | FMODE_BPL32
1658 }, {
1659
1660
1661
1662 "aga640x400", 0,
1663 BPC0_SHRES | BPC0_ECSENA,
1664 640, 400, 1,
1665 640, 400,
1666 0x0041, 0x0015,
1667 64,
1668 BPC2_KILLEHB,
1669 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1670 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1671 0x006f,
1672 0x000d,
1673 0x0018,
1674 0x0001,
1675 0x0021,
1676 0x01a4,
1677 0x0003,
1678 0x0005,
1679 0x0000,
1680 0x0014,
1681 0x0046,
1682 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1683 BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1684 BMC0_VSYTRUE,
1685 FMODE_BPAGEM | FMODE_BPL32
1686 }, {
1687
1688
1689
1690 "aga640x480a", 0,
1691 BPC0_SHRES | BPC0_ECSENA,
1692 640, 480, 1,
1693 640, 480,
1694 0x0041, 0x0015,
1695 64,
1696 BPC2_KILLEHB,
1697 BPC3_PF2OF1 | BPC3_PF2OF0 | BPC3_SPRES1 | BPC3_SPRES0 |
1698 BPC3_BRDRBLNK | BPC3_EXTBLKEN,
1699 0x006f,
1700 0x000e,
1701 0x0018,
1702 0x0001,
1703 0x0021,
1704 0x01f4,
1705 0x0003,
1706 0x0005,
1707 0x0000,
1708 0x0014,
1709 0x0046,
1710 BMC0_VARVBEN | BMC0_LOLDIS | BMC0_VARVSYEN | BMC0_VARHSYEN |
1711 BMC0_VARBEAMEN | BMC0_PAL | BMC0_VARCSYEN | BMC0_CSYTRUE |
1712 BMC0_VSYTRUE,
1713 FMODE_BPAGEM | FMODE_BPL32
1714 }
1715 };
1716
1717 #define NMODES (sizeof(mono_modes) / sizeof(struct geometry))
1718
1719 static struct fb_var_screeninfo mono_mono_amiga_fb_predefined[] = {
1720 {
1721 0, 0, 0, 0, 0, 0, 0, 0,
1722 {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, {0, 0, 0},
1723 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0 }
1724 };
1725
1726 static int mono_num_mono_amiga_fb_predefined= sizeof(mono_mono_amiga_fb_predefined)/sizeof(struct fb_var_screeninfo);
1727
1728
1729
1730
1731 #define OCS_PAL_LOWEND_DEFMODE 5
1732 #define OCS_PAL_3000_DEFMODE 4
1733 #define OCS_NTSC_LOWEND_DEFMODE 1
1734 #define OCS_NTSC_3000_DEFMODE 0
1735 #define AGA_DEFMODE 8
1736
1737 static int mono_amifb_inverse = 0;
1738 static int mono_amifb_mode = -1;
1739
1740 static void mono_video_setup (char *options, int *ints)
1741 {
1742 char *this_opt;
1743 int i;
1744
1745 fb_info.fontname[0] = '\0';
1746
1747 if (!options || !*options)
1748 return;
1749
1750 for (this_opt = strtok(options,","); this_opt; this_opt = strtok(NULL,","))
1751 if (!strcmp (this_opt, "inverse"))
1752 mono_amifb_inverse = 1;
1753 else if (!strncmp(this_opt, "font:", 5))
1754 strcpy(fb_info.fontname, this_opt+5);
1755 else
1756 for (i = 0; i < NMODES; i++)
1757 if (!strcmp(this_opt, mono_modes[i].modename)) {
1758 mono_amifb_mode = i;
1759 break;
1760 }
1761 }
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815 static __inline__ ushort *mono_build_clist_hdr(register struct display *p,
1816 ushort *cop,
1817 ushort *othercop)
1818 {
1819 int i;
1820 ushort diwstrt_v = mono_current_par.diwstrt_v;
1821 ushort diwstop_h = mono_current_par.diwstop_h;
1822
1823 if (othercop) {
1824 *cop++ = CUSTOM_OFS(cop1lc);
1825 *cop++ = (long)othercop >> 16;
1826 *cop++ = CUSTOM_OFS(cop1lc) + 2;
1827 *cop++ = (long)othercop;
1828 }
1829
1830
1831 *cop++ = CUSTOM_OFS(sprpt[0]);
1832 *cop++ = (ushort)((long)mono_current_par.cursor >> 16);
1833 *cop++ = CUSTOM_OFS(sprpt[0]) + 2;
1834 *cop++ = (ushort)((long)mono_current_par.cursor & 0x0000ffff);
1835
1836
1837 for (i=1; i<8; i++) {
1838 *cop++ = CUSTOM_OFS(sprpt[i]);
1839 *cop++ = (ushort)((long)mono_current_par.dummy >> 16);
1840 *cop++ = CUSTOM_OFS(sprpt[i]) + 2;
1841 *cop++ = (ushort)((long)mono_current_par.dummy & 0x0000ffff);
1842 }
1843
1844
1845
1846 *cop++ = ((diwstrt_v - 2) << 8) | (diwstop_h >> 1) | 0x1;
1847 *cop++ = 0xfffe;
1848
1849 return(cop);
1850 }
1851
1852 static __inline__ ushort *mono_build_clist_dyn(register struct display *p,
1853 ushort *cop,
1854 int shf)
1855 {
1856 ushort diwstrt_v = mono_current_par.diwstrt_v;
1857 ushort diwstop_h = mono_current_par.diwstop_h;
1858 ushort y_wrap = mono_current_par.y_wrap;
1859 ulong offset = y_wrap * mono_current_par.bytes_per_row;
1860 long scrmem;
1861 int i;
1862
1863
1864
1865 for (i = 0 ; i < mono_current_par.scr_depth ; i++) {
1866 scrmem = ((long)mono_current_par.bitplane[i]) + offset;
1867
1868 if (shf)
1869 scrmem += mono_current_par.bytes_per_row;
1870
1871 *cop++ = CUSTOM_OFS(bplpt[i]);
1872 *cop++ = (long)scrmem >> 16;
1873 *cop++ = CUSTOM_OFS(bplpt[i]) + 2;
1874 *cop++ = (long)scrmem;
1875 }
1876
1877
1878
1879 if (y_wrap) {
1880 ushort line;
1881
1882 if (mono_current_par.bplcon0 & BPC0_LACE)
1883 line = diwstrt_v + (mono_current_par.scr_height - y_wrap)/2;
1884 else
1885 line = diwstrt_v + mono_current_par.scr_height - y_wrap;
1886
1887
1888 while (line > 256) {
1889
1890
1891 if (mono_current_par.bplcon0 & BPC0_SHRES)
1892
1893
1894
1895
1896
1897 *cop++ = 0xff00 | ((mono_current_par.htotal-4) | 1);
1898 else
1899 *cop++ = 0xff00 | ((diwstop_h-2) >> 1) | 0x1;
1900
1901 *cop++ = 0xfffe;
1902
1903 *cop++ = 0x0001;
1904 *cop++ = 0xfffe;
1905 line -= 256;
1906
1907
1908
1909
1910
1911 if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
1912 *cop++ = 0x0180;
1913 *cop++ = mono_ecs_color_zero;
1914 }
1915 }
1916
1917
1918 *cop++ = ((line - 1) << 8) | (diwstop_h >> 1) | 0x1;
1919 *cop++ = 0xfffe;
1920
1921 for (i = 0 ; i < mono_current_par.scr_depth ; i++) {
1922 scrmem = (long)mono_current_par.bitplane[i];
1923 if (shf)
1924 scrmem += mono_current_par.bytes_per_row;
1925
1926 *cop++ = CUSTOM_OFS(bplpt[i]);
1927 *cop++ = (long)scrmem >> 16;
1928 *cop++ = CUSTOM_OFS(bplpt[i]) + 2;
1929 *cop++ = (long)scrmem;
1930 }
1931 }
1932
1933
1934 *cop++ = 0xffff;
1935 *cop++ = 0xfffe;
1936
1937 return(cop);
1938 }
1939
1940
1941 static __inline__ void mono_build_cursor(register struct display *p)
1942 {
1943 int vs, hs, ve;
1944 ushort diwstrt_v = mono_current_par.diwstrt_v;
1945 ushort diwstrt_h = mono_current_par.diwstrt_h;
1946
1947 if (mono_current_par.bplcon0 & BPC0_LACE) {
1948 vs = diwstrt_v + (p->cursor_y * p->fontheight)/2;
1949 ve = vs + p->fontheight/2;
1950 } else {
1951 vs = diwstrt_v + (p->cursor_y * p->fontheight);
1952 ve = vs + p->fontheight;
1953 }
1954
1955 if (mono_current_par.bplcon0 & BPC0_ECSENA)
1956
1957
1958
1959
1960 hs = diwstrt_h * 4 + (p->cursor_x * p->fontwidth) - 4;
1961 else
1962 hs = diwstrt_h + (p->cursor_x * p->fontwidth) / 2 - 1;
1963
1964 if (mono_current_par.bplcon0 & BPC0_ECSENA) {
1965
1966 *((ulong *) mono_current_par.cursor) =
1967 ((((vs & 0xff) << 24) | ((vs & 0x100) >> 6) |
1968 ((vs & 0x200) >> 3)) |
1969 (((hs & 0x7f8) << 13) | ((hs & 0x4) >> 2) |
1970 ((hs & 0x3) << 3)) |
1971 (((ve & 0xff) << 8) | ((ve & 0x100) >> 7) |
1972 ((ve & 0x200) >> 4)));
1973 } else {
1974 *((ulong *) mono_current_par.cursor) =
1975 ((vs << 24) | ((vs & 0x00000100) >> 6) |
1976 ((hs & 0x000001fe) << 15) | (hs & 0x00000001) |
1977 ((ve & 0x000000ff) << 8) | ((ve & 0x00000100) >> 7));
1978 }
1979 }
1980
1981 static void mono_build_ecs_colors(ushort color1, ushort color2, ushort color3,
1982 ushort color4, ushort *table)
1983 {
1984
1985
1986
1987
1988
1989
1990 ushort t;
1991
1992 t = (color1 & 0x0ccc);
1993 table[0] = t;
1994 table[4] = t;
1995 table[8] = t;
1996 table[12] = t;
1997 t = t >> 2;
1998 table[0] = (table[0] | t);
1999 table[1] = t;
2000 table[2] = t;
2001 table[3] = t;
2002
2003 t = (color2 & 0x0ccc);
2004 table[1] = (table[1] | t);
2005 table[5] = t;
2006 table[9] = t;
2007 table[13] = t;
2008 t = t >> 2;
2009 table[4] = (table[4] | t);
2010 table[5] = (table[5] | t);
2011 table[6] = t;
2012 table[7] = t;
2013
2014 t = (color3 & 0x0ccc);
2015 table[2] = (table[2] | t);
2016 table[6] = (table[6] | t);
2017 table[10] = t;
2018 table[14] = t;
2019 t = t >> 2;
2020 table[8] = (table[8] | t);
2021 table[9] = (table[9] | t);
2022 table[10] = (table[10] | t);
2023 table[11] = t;
2024
2025 t = (color4 & 0x0ccc);
2026 table[3] = (table[3] | t);
2027 table[7] = (table[7] | t);
2028 table[11] = (table[11] | t);
2029 table[15] = t;
2030 t = t >> 2;
2031 table[12] = (table[12] | t);
2032 table[13] = (table[13] | t);
2033 table[14] = (table[14] | t);
2034 table[15] = (table[15] | t);
2035
2036 }
2037
2038
2039
2040
2041
2042
2043 static void mono_display_init(struct display *p,
2044 struct geometry *geom, ushort inverse)
2045 {
2046 ushort ecs_table[16];
2047 int i;
2048 char *chipptr;
2049 ushort diwstrt_v, diwstop_v;
2050 ushort diwstrt_h, diwstop_h;
2051 ushort diw_min_h, diw_min_v;
2052 ushort bplmod, diwstrt, diwstop, diwhigh, ddfstrt, ddfstop;
2053 ushort cursorheight, cursormask = 0;
2054 u_long size;
2055
2056
2057
2058 if (inverse) {
2059 mono_current_par.fgcol = FG_COLOR_INV;
2060 mono_current_par.bgcol = BG_COLOR_INV;
2061 mono_current_par.crsrcol = CRSR_COLOR_INV;
2062 } else {
2063 mono_current_par.fgcol = FG_COLOR;
2064 mono_current_par.bgcol = BG_COLOR;
2065 mono_current_par.crsrcol = CRSR_COLOR;
2066 }
2067
2068
2069
2070 mono_current_par.scr_max_height = geom->scr_max_height;
2071 mono_current_par.scr_max_width = geom->scr_max_width;
2072 mono_current_par.scr_height = geom->scr_height;
2073 mono_current_par.scr_width = geom->scr_width;
2074 mono_current_par.scr_depth = geom->scr_depth;
2075 mono_current_par.bplcon0 = geom->bplcon0 | BPC0_COLOR;
2076 mono_current_par.htotal = geom->htotal;
2077
2078
2079
2080 if (mono_current_par.scr_depth < 8)
2081 mono_current_par.bplcon0 |= (mono_current_par.scr_depth << 12);
2082 else {
2083
2084 mono_current_par.bplcon0 |= BPC0_BPU3;
2085 }
2086
2087 diw_min_v = geom->diwstrt_v;
2088 diw_min_h = geom->diwstrt_h;
2089
2090
2091
2092
2093
2094
2095
2096
2097 mono_current_par.bytes_per_row = ((mono_current_par.scr_width+geom->alignment-1)&~(geom->alignment-1)) >> 3;
2098 mono_current_par.plane_size = mono_current_par.bytes_per_row * mono_current_par.scr_height;
2099
2100
2101
2102
2103
2104
2105
2106
2107 mono_current_par.plane_size = PAGE_ALIGN(mono_current_par.plane_size);
2108
2109
2110 mono_current_par.y_wrap = 0; mono_current_par.scroll_latch = 1;
2111 p->cursor_x = 0; p->cursor_y = 0; mono_current_par.cursor_latch = 1;
2112
2113 if (mono_current_par.bplcon0 & BPC0_LACE) {
2114 bplmod = mono_current_par.bytes_per_row;
2115 diwstrt_v = diw_min_v + (mono_current_par.scr_max_height - mono_current_par.scr_height)/4;
2116 diwstop_v = (diwstrt_v + mono_current_par.scr_height/2);
2117 } else {
2118 bplmod = 0;
2119 diwstrt_v = diw_min_v + (mono_current_par.scr_max_height - mono_current_par.scr_height)/2;
2120 diwstop_v = (diwstrt_v + mono_current_par.scr_height);
2121 }
2122
2123 if (mono_current_par.bplcon0 & BPC0_HIRES) {
2124 diwstrt_h = diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/4;
2125 diwstop_h = (diwstrt_h + mono_current_par.scr_width/2);
2126
2127 } else if (mono_current_par.bplcon0 & BPC0_SHRES) {
2128 diwstrt_h = diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/8;
2129 diwstop_h = (diwstrt_h + mono_current_par.scr_width/4);
2130 } else {
2131 diwstrt_h = diw_min_h + (mono_current_par.scr_max_width - mono_current_par.scr_width)/2;
2132 diwstop_h = (diwstrt_h + mono_current_par.scr_width);
2133 }
2134
2135 if (mono_current_par.bplcon0 & BPC0_HIRES) {
2136 ddfstrt = (diwstrt_h >> 1) - 4;
2137 ddfstop = ddfstrt + (4 * (mono_current_par.bytes_per_row>>1)) - 8;
2138 } else if (mono_current_par.bplcon0 & BPC0_SHRES && boot_info.bi_amiga.chipset == CS_AGA) {
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152 ddfstrt = (diwstrt_h >> 1) - 8;
2153 ddfstop = ddfstrt + (2 * (mono_current_par.bytes_per_row>>1)) - 8;
2154 } else if (mono_current_par.bplcon0 & BPC0_SHRES && boot_info.bi_amiga.chipset == CS_ECS){
2155
2156
2157
2158
2159 ddfstrt = (diwstrt_h >> 1) - 2;
2160 ddfstop = ddfstrt + (2 * (mono_current_par.bytes_per_row>>1)) - 8;
2161 } else {
2162 ddfstrt = (diwstrt_h >> 1) - 8;
2163 ddfstop = ddfstrt + (8 * (mono_current_par.bytes_per_row>>1)) - 8;
2164 }
2165
2166 if (mono_current_par.bplcon0 & BPC0_LACE)
2167 cursorheight = p->fontheight/2;
2168 else
2169 cursorheight = p->fontheight;
2170
2171
2172
2173
2174
2175
2176
2177 size = mono_current_par.scr_depth*mono_current_par.plane_size+COP_MEM_REQ+SPR_MEM_REQ+4*(cursorheight-1);
2178 size += PAGE_SIZE-1;
2179 chipptr = amiga_chip_alloc(size);
2180 chipptr = (char *)PAGE_ALIGN((u_long)chipptr);
2181
2182
2183
2184
2185
2186 mono_current_par.smem_start = (u_long)chipptr;
2187 mono_current_par.smem_len = mono_current_par.plane_size*mono_current_par.scr_depth;
2188 mono_current_par.geometry = geom;
2189
2190 for (i = 0 ; i < mono_current_par.scr_depth ; i++, chipptr += mono_current_par.plane_size) {
2191 mono_current_par.bitplane[i] = (u_char *) chipptr;
2192 memset ((void *)chipptr, 0, mono_current_par.plane_size);
2193 }
2194
2195
2196 mono_current_par.coplist1hdr = (ushort *) chipptr; chipptr += MAX_COP_LIST_ENTS * 4;
2197 mono_current_par.coplist2hdr = (ushort *) chipptr; chipptr += MAX_COP_LIST_ENTS * 4;
2198
2199
2200 mono_current_par.cursor = (ushort *) chipptr; chipptr += 8+4*cursorheight;
2201 mono_current_par.dummy = (ushort *) chipptr; chipptr += 12;
2202
2203
2204 memset((void *)mono_current_par.cursor, 0, 8+4*cursorheight);
2205
2206
2207
2208 if (mono_current_par.bplcon0 & BPC0_ECSENA && boot_info.bi_amiga.chipset == CS_AGA)
2209
2210 for (i = 0; (i < p->fontwidth) && (i < 16); i++)
2211 cursormask |= 1<<(15-i);
2212 else
2213
2214 for (i = 0; (i < p->fontwidth/2) && (i < 8); i++)
2215 cursormask |= 1<<(15-i);
2216
2217 mono_current_par.cursor[0] = mono_cursor_data[0];
2218 mono_current_par.cursor[1] = mono_cursor_data[1];
2219
2220 #if (CRSR_BLOCK == 1)
2221 for (i = 0; i < cursorheight; i++)
2222 #else
2223 for (i = cursorheight-2; i < cursorheight; i++)
2224 #endif
2225 mono_current_par.cursor[2+2*i] = cursormask;
2226
2227
2228 memset((void *)mono_current_par.dummy, 0, 12);
2229
2230
2231 mono_current_par.cursor_flash = CRSR_FLASH;
2232
2233
2234 mono_current_par.cursor_visible = 0;
2235
2236
2237 mono_current_par.diwstrt_v = diwstrt_v;
2238 mono_current_par.diwstrt_h = diwstrt_h;
2239 mono_current_par.diwstop_v = diwstop_v;
2240 mono_current_par.diwstop_h = diwstop_h;
2241 diwstrt = ((diwstrt_v << 8) | diwstrt_h);
2242 diwstop = ((diwstop_v & 0xff) << 8) | (diwstop_h & 0xff);
2243
2244 custom.bplcon0 = mono_current_par.bplcon0;
2245 custom.bplcon1 = 0;
2246 custom.bplcon2 = 0;
2247 custom.bpl1mod = bplmod;
2248 custom.bpl2mod = bplmod;
2249 custom.diwstrt = diwstrt;
2250 custom.diwstop = diwstop;
2251 custom.ddfstrt = ddfstrt;
2252 custom.ddfstop = ddfstop;
2253
2254 custom.color[0] = COLOR_MSB(mono_current_par.bgcol);
2255 custom.color[1] = COLOR_MSB(mono_current_par.fgcol);
2256 custom.color[17] = COLOR_MSB(mono_current_par.crsrcol);
2257
2258 if (boot_info.bi_amiga.chipset == CS_AGA) {
2259
2260
2261 custom.bplcon3 = geom->bplcon3 | BPC3_LOCT;
2262 custom.color[0] = COLOR_LSB(mono_current_par.bgcol);
2263 custom.color[1] = COLOR_LSB(mono_current_par.fgcol);
2264 custom.color[17] = COLOR_LSB(mono_current_par.crsrcol);
2265 custom.bplcon3 = geom->bplcon3;
2266 }
2267
2268 if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279 mono_build_ecs_colors(COLOR_MSB(mono_current_par.bgcol), COLOR_MSB(mono_current_par.fgcol),
2280 0, 0, ecs_table);
2281
2282 #if 0
2283 for (i = 0; i < 8; i++){
2284 custom.color[i] = ecs_table[i*2];
2285 custom.color[i+8] = ecs_table[i*2+1];
2286 }
2287 #else
2288 for (i = 0; i < 16; i++){
2289 custom.color[i] = ecs_table[i];
2290 }
2291 #endif
2292
2293 mono_ecs_color_zero = ecs_table[0];
2294
2295
2296
2297
2298
2299
2300 mono_build_ecs_colors(0, COLOR_MSB(mono_current_par.crsrcol), 0, 0, ecs_table);
2301
2302 for (i = 0; i < 16; i++){
2303 custom.color[i+16] = ecs_table[i];
2304 }
2305 }
2306
2307 if (!(geom->isOCS)) {
2308
2309
2310 diwhigh = (diwstop_v & 0x700) | ((diwstop_h & 0x100) << 5);
2311
2312 custom.bplcon2 = geom->bplcon2;
2313 custom.bplcon3 = geom->bplcon3;
2314
2315 mono_save_bplcon3 = geom->bplcon3;
2316
2317 custom.diwhigh = diwhigh;
2318
2319 custom.htotal = geom->htotal;
2320 custom.hsstrt = geom->hsstrt;
2321 custom.hsstop = geom->hsstop;
2322 custom.hbstrt = geom->hbstrt;
2323 custom.hbstop = geom->hbstop;
2324 custom.vtotal = geom->vtotal;
2325 custom.vsstrt = geom->vsstrt;
2326 custom.vsstop = geom->vsstop;
2327 custom.vbstrt = geom->vbstrt;
2328 custom.vbstop = geom->vbstop;
2329 custom.hcenter = geom->hcenter;
2330 custom.beamcon0 = geom->beamcon0;
2331 if (boot_info.bi_amiga.chipset == CS_AGA) {
2332 custom.fmode = geom->fmode;
2333 }
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343 if (boot_info.bi_amiga.chipset != CS_STONEAGE)
2344 amiga_audio_min_period = (geom->htotal>>1)+1;
2345 }
2346
2347
2348
2349
2350 if (mono_current_par.bplcon0 & BPC0_LACE) {
2351 mono_current_par.coplist1dyn = mono_build_clist_hdr(p,mono_current_par.coplist1hdr, mono_current_par.coplist2hdr),
2352 mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2353
2354 mono_current_par.coplist2dyn = mono_build_clist_hdr(p,mono_current_par.coplist2hdr, mono_current_par.coplist1hdr),
2355 mono_build_clist_dyn(p, mono_current_par.coplist2dyn, 1);
2356 } else {
2357 mono_current_par.coplist1dyn = mono_build_clist_hdr(p,mono_current_par.coplist1hdr, NULL),
2358 mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2359 }
2360
2361
2362
2363 custom.cop1lc = mono_current_par.coplist1hdr;
2364 custom.copjmp1 = 0;
2365
2366
2367 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_COPPER | DMAF_SPRITE;
2368
2369 if (mono_current_par.bplcon0 & BPC0_LACE) {
2370
2371
2372
2373 while (custom.vposr & 0x8000)
2374 ;
2375
2376
2377 while (!(custom.vposr & 0x8000))
2378 ;
2379
2380
2381 custom.cop1lc = mono_current_par.coplist1hdr;
2382 custom.copjmp1 = 0;
2383 }
2384 }
2385
2386
2387 static void mono_amifb_interrupt(int irq, struct pt_regs *fp, void *data)
2388 {
2389 register struct display *p = disp;
2390
2391 static ushort cursorcount = 0;
2392 static ushort cursorstate = 0;
2393
2394
2395
2396
2397
2398
2399
2400 if (!(mono_current_par.bplcon0 & BPC0_LACE) || (custom.vposr & 0x8000)) {
2401 if (mono_current_par.scroll_latch || mono_current_par.cursor_latch)
2402 mono_build_cursor(p);
2403
2404 if (mono_current_par.scroll_latch)
2405 if (mono_current_par.bplcon0 & BPC0_LACE) {
2406 mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2407 mono_build_clist_dyn(p, mono_current_par.coplist2dyn, 1);
2408 } else
2409 mono_build_clist_dyn(p, mono_current_par.coplist1dyn, 0);
2410 mono_current_par.scroll_latch = 0;
2411 mono_current_par.cursor_latch = 0;
2412 }
2413
2414 if (!(custom.potgor & (1<<10)))
2415 mono_vblank.right_count++;
2416
2417 if (mono_current_par.cursor_visible) {
2418 if (mono_current_par.cursor_flash) {
2419 if (cursorcount)
2420 cursorcount--;
2421 else {
2422 cursorcount = CRSR_RATE;
2423 if ((cursorstate = !cursorstate))
2424 custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
2425 else
2426 custom.dmacon = DMAF_SPRITE;
2427 }
2428 }
2429 } else
2430 custom.dmacon = DMAF_SPRITE;
2431
2432 if (mono_do_blank) {
2433 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
2434 custom.color[0] = 0;
2435 if (boot_info.bi_amiga.chipset == CS_AGA) {
2436
2437
2438 custom.bplcon3 = mono_save_bplcon3 | BPC3_LOCT;
2439 custom.color[0]= 0;
2440 custom.bplcon3 = mono_save_bplcon3;
2441 }
2442 mono_do_blank = 0;
2443 }
2444
2445 if (mono_do_unblank) {
2446 if (mono_current_par.cursor_visible)
2447 custom.dmacon = DMAF_SETCLR | DMAF_RASTER | DMAF_SPRITE;
2448 else
2449 custom.dmacon = DMAF_SETCLR | DMAF_RASTER;
2450 custom.color[0] = COLOR_MSB(mono_current_par.bgcol);
2451 if (boot_info.bi_amiga.chipset == CS_AGA) {
2452
2453
2454 custom.bplcon3 = mono_save_bplcon3 | BPC3_LOCT;
2455 custom.color[0] = COLOR_LSB(mono_current_par.bgcol);
2456 custom.bplcon3 = mono_save_bplcon3;
2457 }
2458
2459 if (boot_info.bi_amiga.chipset == CS_ECS && mono_current_par.bplcon0 & BPC0_ECSENA) {
2460 custom.color[0] = mono_ecs_color_zero;
2461 }
2462 mono_do_unblank = 0;
2463 }
2464
2465 mono_vblank.done = 1;
2466 }
2467
2468
2469 static int mono_amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
2470 {
2471 int i;
2472
2473 strcpy(fix->id, mono_current_par.geometry->modename);
2474 fix->smem_start = mono_current_par.smem_start;
2475 fix->smem_len = mono_current_par.smem_len;
2476
2477
2478
2479
2480
2481 fix->type = FB_TYPE_PACKED_PIXELS;
2482
2483 fix->type_aux = 0;
2484 if (mono_amifb_inverse)
2485 fix->visual = FB_VISUAL_MONO10;
2486 else
2487 fix->visual = FB_VISUAL_MONO01;
2488
2489 fix->xpanstep = 0;
2490 fix->ypanstep = 0;
2491 fix->ywrapstep = 1;
2492
2493 for (i = 0; i < arraysize(fix->reserved); i++)
2494 fix->reserved[i] = 0;
2495 return(0);
2496 }
2497
2498
2499 static int mono_amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
2500 {
2501 int i;
2502
2503 var->xres = mono_current_par.geometry->scr_width;
2504 var->yres = mono_current_par.geometry->scr_height;
2505 var->xres_virtual = var->xres;
2506 var->yres_virtual = var->yres;
2507 var->xoffset = 0;
2508 var->yoffset = 0;
2509
2510 var->bits_per_pixel = mono_current_par.geometry->scr_depth;
2511 var->grayscale = 0;
2512
2513 if (boot_info.bi_amiga.chipset == CS_AGA) {
2514 var->red.offset = 0;
2515 var->red.length = 8;
2516 var->red.msb_right = 0;
2517 var->green = var->red;
2518 var->blue = var->red;
2519 } else {
2520 var->red.offset = 0;
2521 var->red.length = 4;
2522 var->red.msb_right = 0;
2523 var->green = var->red;
2524 var->blue = var->red;
2525 }
2526
2527 var->nonstd = 0;
2528 var->activate = 0;
2529
2530 var->width = -1;
2531 var->height = -1;
2532
2533 var->accel = FB_ACCEL_NONE;
2534
2535 var->pixclock = 35242;
2536 var->left_margin = (mono_current_par.geometry->hbstop-mono_current_par.geometry->hsstrt)*8;
2537 var->right_margin = (mono_current_par.geometry->hsstrt-mono_current_par.geometry->hbstrt)*8;
2538 var->upper_margin = (mono_current_par.geometry->vbstop-mono_current_par.geometry->vsstrt)*8;
2539 var->lower_margin = (mono_current_par.geometry->vsstrt-mono_current_par.geometry->vbstrt)*8;
2540 var->hsync_len = (mono_current_par.geometry->hsstop-mono_current_par.geometry->hsstrt)*8;
2541 var->vsync_len = (mono_current_par.geometry->vsstop-mono_current_par.geometry->vsstrt)*8;
2542 var->sync = 0;
2543 if (mono_current_par.geometry->bplcon0 & BPC0_LACE)
2544 var->vmode = FB_VMODE_INTERLACED;
2545 else if ((boot_info.bi_amiga.chipset == CS_AGA) && (mono_current_par.geometry->fmode & FMODE_BSCAN2))
2546 var->vmode = FB_VMODE_DOUBLE;
2547 else
2548 var->vmode = FB_VMODE_NONINTERLACED;
2549
2550 for (i = 0; i < arraysize(var->reserved); i++)
2551 var->reserved[i] = 0;
2552
2553 return(0);
2554 }
2555
2556
2557 static void mono_amiga_fb_set_disp(int con)
2558 {
2559 struct fb_fix_screeninfo fix;
2560
2561 mono_amiga_fb_get_fix(&fix, con);
2562 if (con == -1)
2563 con = 0;
2564 disp[con].screen_base = (u_char *)fix.smem_start;
2565 disp[con].visual = fix.visual;
2566 disp[con].type = fix.type;
2567 disp[con].type_aux = fix.type_aux;
2568 disp[con].ypanstep = fix.ypanstep;
2569 disp[con].ywrapstep = fix.ywrapstep;
2570 disp[con].can_soft_blank = 1;
2571 disp[con].inverse = mono_amifb_inverse;
2572 }
2573
2574
2575 static int mono_amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
2576 {
2577
2578
2579
2580 return 0;
2581 return(-EINVAL);
2582 }
2583
2584
2585 static short mono_red_normal[] = {
2586 ((BG_COLOR & 0xff0000)>>8) | ((BG_COLOR & 0xff0000)>>16),
2587 ((FG_COLOR & 0xff0000)>>8) | ((FG_COLOR & 0xff0000)>>16)
2588 };
2589 static short mono_green_normal[] = {
2590 ((BG_COLOR & 0x00ff00)) | ((BG_COLOR & 0x00ff00)>>8),
2591 ((FG_COLOR & 0x00ff00)) | ((FG_COLOR & 0x00ff00)>>8)
2592 };
2593 static short mono_blue_normal[] = {
2594 ((BG_COLOR & 0x0000ff)<<8) | ((BG_COLOR & 0x0000ff)),
2595 ((FG_COLOR & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2596 };
2597
2598 static short mono_red_inverse[] = {
2599 ((BG_COLOR_INV & 0xff0000)>>8) | ((BG_COLOR_INV & 0xff0000)>>16),
2600 ((FG_COLOR_INV & 0xff0000)>>8) | ((FG_COLOR_INV & 0xff0000)>>16)
2601 };
2602 static short mono_green_inverse[] = {
2603 ((BG_COLOR_INV & 0x00ff00)) | ((BG_COLOR_INV & 0x00ff00)>>8),
2604 ((FG_COLOR_INV & 0x00ff00)) | ((FG_COLOR_INV & 0x00ff00)>>8)
2605 };
2606 static short mono_blue_inverse[] = {
2607 ((BG_COLOR_INV & 0x0000ff)<<8) | ((BG_COLOR_INV & 0x0000ff)),
2608 ((FG_COLOR_INV & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2609 };
2610
2611 static struct fb_cmap mono_default_cmap_normal = { 0, 2, mono_red_normal, mono_green_normal, mono_blue_normal, NULL };
2612 static struct fb_cmap mono_default_cmap_inverse = { 0, 2, mono_red_inverse, mono_green_inverse, mono_blue_inverse, NULL };
2613
2614 static int mono_amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
2615 {
2616 int i, start;
2617 unsigned short *red, *green, *blue, *transp;
2618 unsigned int hred, hgreen, hblue, htransp;
2619 struct fb_cmap *def_cmap;
2620
2621 red = cmap->red;
2622 green = cmap->green;
2623 blue = cmap->blue;
2624 transp = cmap->transp;
2625 start = cmap->start;
2626 if (start < 0)
2627 return(-EINVAL);
2628
2629 if (mono_amifb_inverse)
2630 def_cmap = &mono_default_cmap_inverse;
2631 else
2632 def_cmap = &mono_default_cmap_normal;
2633
2634 for (i = 0; i < cmap->len; i++) {
2635 if (i < def_cmap->len) {
2636 hred = def_cmap->red[i];
2637 hgreen = def_cmap->green[i];
2638 hblue = def_cmap->blue[i];
2639 if (def_cmap->transp)
2640 htransp = def_cmap->transp[i];
2641 else
2642 htransp = 0;
2643 } else
2644 hred = hgreen = hblue = htransp = 0;
2645 if (kspc) {
2646 *red = hred;
2647 *green = hgreen;
2648 *blue = hblue;
2649 if (transp)
2650 *transp = htransp;
2651 } else {
2652 put_fs_word(hred, red);
2653 put_fs_word(hgreen, green);
2654 put_fs_word(hblue, blue);
2655 if (transp)
2656 put_fs_word(htransp, transp);
2657 }
2658 red++;
2659 green++;
2660 blue++;
2661 if (transp)
2662 transp++;
2663 }
2664 return(0);
2665 }
2666
2667
2668 static int mono_amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
2669 {
2670
2671
2672
2673 return(-EINVAL);
2674 }
2675
2676
2677 static int mono_amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
2678 {
2679
2680
2681
2682 return(-EINVAL);
2683 }
2684
2685
2686 static int mono_amiga_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2687 unsigned long arg, int con)
2688 {
2689 return(-EINVAL);
2690 }
2691
2692 static struct fb_ops mono_amiga_fb_ops = {
2693 mono_amiga_fb_get_fix, mono_amiga_fb_get_var, mono_amiga_fb_set_var, mono_amiga_fb_get_cmap,
2694 mono_amiga_fb_set_cmap, mono_amiga_fb_pan_display, mono_amiga_fb_ioctl
2695 };
2696
2697
2698 static int mono_amifb_switch (int con)
2699 {
2700 mono_current_par.y_wrap = disp[con].var.yoffset;
2701 mono_current_par.cursor_latch = 1;
2702 mono_current_par.scroll_latch = 1;
2703 return(0);
2704 }
2705
2706
2707 static int mono_amifb_updatevar(int con)
2708 {
2709 mono_current_par.y_wrap = disp[con].var.yoffset;
2710 mono_current_par.cursor_latch = 1;
2711 mono_current_par.scroll_latch = 1;
2712 return(0);
2713 }
2714
2715
2716 static void mono_amifb_blank(int blank)
2717 {
2718 if (blank)
2719 mono_do_blank = 1;
2720 else
2721 mono_do_unblank = 1;
2722 }
2723
2724
2725 static struct fb_info *mono_amiga_fb_init(long *mem_start)
2726 {
2727 int mode = mono_amifb_mode;
2728 ulong model;
2729 int inverse_video = mono_amifb_inverse;
2730 int err;
2731
2732 err=register_framebuffer("Amiga Builtin", &node, &mono_amiga_fb_ops, mono_num_mono_amiga_fb_predefined,
2733 mono_mono_amiga_fb_predefined);
2734
2735 model = boot_info.bi_un.bi_ami.model;
2736 if (mode == -1)
2737 if (boot_info.bi_amiga.chipset == CS_AGA)
2738 mode = AGA_DEFMODE;
2739 else if (model == AMI_3000)
2740 mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_3000_DEFMODE : OCS_NTSC_3000_DEFMODE;
2741 else
2742 mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_LOWEND_DEFMODE : OCS_NTSC_LOWEND_DEFMODE;
2743
2744 mono_init_vblank();
2745 mono_display_init(disp, &mono_modes[mode], inverse_video);
2746 if (!add_isr(IRQ_AMIGA_VERTB, mono_amifb_interrupt, 0, NULL, "frame buffer"))
2747 panic("Couldn't add vblank interrupt");
2748
2749 mono_amiga_fb_get_var(&disp[0].var, 0);
2750 if (mono_amifb_inverse)
2751 disp[0].cmap = mono_default_cmap_inverse;
2752 else
2753 disp[0].cmap = mono_default_cmap_normal;
2754 mono_amiga_fb_set_disp(-1);
2755
2756 strcpy(fb_info.modename, "Amiga Builtin ");
2757 fb_info.disp = disp;
2758 fb_info.switch_con = &mono_amifb_switch;
2759 fb_info.updatevar = &mono_amifb_updatevar;
2760 fb_info.blank = &mono_amifb_blank;
2761 strcat(fb_info.modename, mono_modes[mode].modename);
2762
2763 return(&fb_info);
2764 }
2765 #endif
2766
2767
2768
2769
2770
2771 #ifdef CONFIG_AMIFB_OCS
2772
2773
2774
2775
2776
2777
2778
2779
2780 static int ocs_init(void)
2781 {
2782 u_long p;
2783
2784
2785
2786
2787
2788 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2789
2790
2791
2792
2793
2794 if (!amifb_mode)
2795 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2796 DEFMODE_PAL : DEFMODE_NTSC);
2797
2798
2799
2800
2801
2802 videomemorysize = VIDEOMEMSIZE_OCS;
2803
2804
2805 ...
2806 ...
2807 ...
2808
2809
2810
2811
2812
2813
2814 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2815 DMAF_SPRITE;
2816
2817 return(0);
2818 }
2819 #endif
2820
2821
2822
2823
2824
2825 #ifdef CONFIG_AMIFB_ECS
2826
2827
2828
2829
2830
2831
2832
2833
2834 static int ecs_init(void)
2835 {
2836 u_long p;
2837
2838
2839
2840
2841
2842 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2843
2844
2845
2846
2847
2848 if (!amifb_mode)
2849 if (AMIGAHW_PRESENT(AMBER_FF))
2850 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2851 DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC);
2852 else
2853 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2854 DEFMODE_PAL : DEFMODE_NTSC);
2855
2856
2857
2858
2859
2860 if (boot_info.bi_amiga.chip_size > 1048576)
2861 videomemorysize = VIDEOMEMSIZE_ECS_2M;
2862 else
2863 videomemorysize = VIDEOMEMSIZE_ECS_1M;
2864
2865
2866 ...
2867 ...
2868 ...
2869
2870
2871
2872
2873
2874
2875 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2876 DMAF_SPRITE;
2877
2878 return(0);
2879 }
2880 #endif
2881
2882
2883
2884
2885
2886 #ifdef CONFIG_AMIFB_AGA
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924 #define hscroll2hw(hscroll) \
2925 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
2926 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
2927
2928 #define hw2hscroll(hscroll) \
2929 (((hscroll)>>8 & 0x00c3) | ((hscroll)<<2 & 0x003c))
2930
2931
2932
2933 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
2934 (((diwstrt_v)<<8 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
2935 #define diwstop2hw(distop_h, diwstop_v) \
2936 (((diwstop_v)<<8 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
2937 #define diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v) \
2938 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
2939 ((diwstop_v) & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
2940 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>8 & 0x0007))
2941
2942 #define hw2diwstrt_h(diwstrt, diwhigh) \
2943 (((diwhigh)<<5 & 0x0400) | ((diwstrt)<<2 & 0x03fc) | ((diwhigh)>>3 & 0x0003))
2944 #define hw2diwstrt_v(diwstrt, diwhigh) \
2945 (((diwhigh)<<8 & 0x0700) | ((diwstrt)>>8 & 0x00ff))
2946 #define hw2diwstop_h(diwstop, diwhigh) \
2947 (((diwhigh)>>3 & 0x0400) | ((diwstop)<<2 & 0x03fc) | \
2948 ((diwhigh)>>11 & 0x0003))
2949 #define hw2diwstop_v(diwstop, diwhigh) \
2950 (((diwhigh) & 0x0700) | ((diwstop)>>8 & 0x00ff))
2951
2952
2953
2954 #define ddfstrt2hw(ddfstrt) (div8(ddfstrt) & 0x00fe)
2955 #define ddfstop2hw(ddfstop) (div8(ddfstop) & 0x00fe)
2956
2957 #define hw2ddfstrt(ddfstrt) ((ddfstrt)<<3)
2958 #define hw2ddfstop(ddfstop) ((ddfstop)<<3)
2959
2960
2961
2962 #define hsstrt2hw(hsstrt) (div8(hsstrt))
2963 #define hsstop2hw(hsstop) (div8(hsstop))
2964 #define htotal2hw(htotal) (div8(htotal)-1)
2965 #define vsstrt2hw(vsstrt) (vsstrt)
2966 #define vsstop2hw(vsstop) (vsstop)
2967 #define vtotal2hw(vtotal) ((vtotal)-1)
2968
2969 #define hw2hsstrt(hsstrt) ((hsstrt)<<3)
2970 #define hw2hsstop(hsstop) ((hsstop)<<3)
2971 #define hw2htotal(htotal) (((htotal)+1)<<3)
2972 #define hw2vsstrt(vsstrt) (vsstrt)
2973 #define hw2vsstop(vsstop) (vsstop)
2974 #define hw2vtotal(vtotal) ((vtotal)+1)
2975
2976
2977
2978 #define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
2979 #define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
2980 #define vbstrt2hw(vbstrt) (vbstrt)
2981 #define vbstop2hw(vbstop) (vbstop)
2982
2983 #define hw2hbstrt(hbstrt) (((hbstrt)<<3 & 0x07f8) | ((hbstrt)>>8 & 0x0007))
2984 #define hw2hbstop(hbstop) (((hbstop)<<3 & 0x07f8) | ((hbstop)>>8 & 0x0007))
2985 #define hw2vbstrt(vbstrt) (vbstrt)
2986 #define hw2vbstop(vbstop) (vbstop)
2987
2988
2989
2990 #define rgb2hw_high(red, green, blue) \
2991 (((red)<<4 & 0xf00) | ((green) & 0x0f0) | ((blue)>>4 & 0x00f))
2992 #define rgb2hw_low(red, green, blue) \
2993 (((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
2994
2995 #define hw2red(high, low) (((high)>>4 & 0xf0) | ((low)>>8 & 0x0f))
2996 #define hw2green(high, low) (((high) & 0xf0) | ((low)>>4 & 0x0f))
2997 #define hw2blue(high, low) (((high)<<4 & 0xf0) | ((low) & 0x0f))
2998
2999
3000
3001 #define spr2hw_pos(start_v, start_h) \
3002 (((start_v)<<8&0xff00) | ((start_h)>>3&0x00ff))
3003 #define spr2hw_ctl(start_v, start_h, stop_v) \
3004 (((stop_v)<<8&0xff00) | ((start_v)>>3&0x0040) | ((stop_v)>>4&0x0020) | \
3005 ((start_h)<<3&0x0018) | ((start_v)>>6&0x0004) | ((stop_v)>>7&0x0002) | \
3006 ((start_h)>>2&0x0001))
3007
3008
3009
3010
3011
3012
3013 struct aga_cursorsprite {
3014 u_short sprpos;
3015 u_short pad1[3];
3016 u_short sprctl;
3017 u_short pad2[3];
3018 union {
3019 struct {
3020 u_long data[64*4];
3021 u_long trailer[4];
3022 } nonlaced;
3023 struct {
3024 u_long data[32*4];
3025 u_long trailer[4];
3026 } laced;
3027 } u;
3028 };
3029
3030 struct aga_dummysprite {
3031 u_short sprpos;
3032 u_short pad1[3];
3033 u_short sprctl;
3034 u_short pad2[3];
3035 u_long data[4];
3036 u_long trailer[4];
3037 };
3038
3039
3040
3041
3042
3043
3044 static u_short bplpixmode[3] = {
3045 BPC0_SHRES,
3046 BPC0_HIRES,
3047 0
3048 };
3049
3050 static u_short sprpixmode[3] = {
3051 BPC3_SPRES1 | BPC3_SPRES0,
3052 BPC3_SPRES1,
3053 BPC3_SPRES0
3054 };
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065 static int aga_init(void)
3066 {
3067 u_long p;
3068
3069
3070
3071
3072
3073 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3074
3075
3076
3077
3078
3079 if (!amifb_mode)
3080 amifb_mode = get_video_mode(DEFMODE_AGA);
3081
3082
3083
3084
3085
3086 if (boot_info.bi_amiga.chip_size > 1048576)
3087 videomemorysize = VIDEOMEMSIZE_AGA_2M;
3088 else
3089 videomemorysize = VIDEOMEMSIZE_AGA_1M;
3090
3091 p = chipalloc(videomemorysize+
3092 sizeof(struct clist_hdr)+
3093 2*sizeof(struct clist_dyn)+
3094 2*sizeof(struct aga_cursorsprite)+
3095 sizeof(struct aga_dummysprite));
3096
3097 assignchunk(videomemory, u_long, p, videomemorysize);
3098 assignchunk(clist_hdr, struct clist_hdr *, p, sizeof(struct clist_hdr));
3099 assignchunk(clist_lof, struct clist_dyn *, p, sizeof(struct clist_dyn));
3100 assignchunk(clist_shf, struct clist_dyn *, p, sizeof(struct clist_dyn));
3101 assignchunk(lofsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3102 assignchunk(shfsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3103 assignchunk(dummysprite, u_long *, p, sizeof(struct aga_dummysprite));
3104
3105
3106
3107
3108
3109 aga_build_clist_hdr(clist_hdr);
3110
3111 custom.cop1lc = (u_short *)ZTWO_PADDR(clist_hdr);
3112 custom.cop2lc = (u_short *)ZTWO_PADDR(&clist_hdr->wait_forever);
3113 custom.copjmp1 = 0;
3114
3115
3116
3117
3118
3119 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3120 DMAF_SPRITE;
3121
3122
3123
3124
3125
3126 custom.bplcon2 = BPC2_KILLEHB | BPC2_PF2P2 | BPC2_PF1P2;
3127 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3128
3129 return(0);
3130 }
3131
3132
3133
3134
3135
3136
3137
3138 static int aga_encode_fix(struct fb_fix_screeninfo *fix,
3139 struct amiga_fb_par *par)
3140 {
3141 int i;
3142
3143 strcpy(fix->id, amiga_fb_name);
3144 fix->smem_start = videomemory;
3145 fix->smem_len = videomemorysize;
3146
3147 if (amifb_ilbm) {
3148 fix->type = FB_TYPE_INTERLEAVED_PLANES;
3149 fix->type_aux = par->next_line;
3150 } else {
3151 fix->type = FB_TYPE_PLANES;
3152 fix->type_aux = 0;
3153 }
3154 fix->visual = FB_VISUAL_PSEUDOCOLOR;
3155
3156 if (par->diwstrt_h >= 323)
3157 fix->xpanstep = 1;
3158 else
3159 fix->xpanstep = 64;
3160 fix->ypanstep = 1;
3161
3162 if (hw2ddfstrt(par->ddfstrt) >= (par->bpp-1)*64)
3163 fix->ywrapstep = 1;
3164 else
3165 fix->ywrapstep = 0;
3166
3167 for (i = 0; i < arraysize(fix->reserved); i++)
3168 fix->reserved[i] = 0;
3169
3170 return(0);
3171 }
3172
3173
3174
3175
3176
3177
3178
3179 static int aga_decode_var(struct fb_var_screeninfo *var,
3180 struct amiga_fb_par *par)
3181 {
3182 u_short clk_shift, line_shift_incd;
3183 u_long upper, lower, hslen, vslen;
3184 int xres_n, yres_n, xoffset_n;
3185 u_long left_n, right_n, upper_n, lower_n, hslen_n, vslen_n;
3186 u_long diwstrt_h, diwstrt_v, diwstop_h, diwstop_v;
3187 u_long hsstrt, vsstrt, hsstop, vsstop, htotal, vtotal;
3188 u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3189 double hrate, vrate;
3190 u_short loopcnt = 0;
3191
3192
3193
3194
3195
3196 for (clk_shift = 0; clk_shift < 3; clk_shift++)
3197 if (var->pixclock <= pixclock[clk_shift])
3198 break;
3199 if (clk_shift >= 3)
3200 return(-EINVAL);
3201 par->clk_shift = clk_shift;
3202
3203
3204
3205
3206
3207 par->xres = max(var->xres, 64);
3208 par->yres = max(var->yres, 64);
3209 par->vxres = up64(max(var->xres_virtual, par->xres));
3210 par->vyres = max(var->yres_virtual, par->yres);
3211
3212 par->bpp = var->bits_per_pixel;
3213 if (par->bpp > 8)
3214 return(-EINVAL);
3215
3216 if (!var->nonstd) {
3217 if (par->bpp < 1)
3218 par->bpp = 1;
3219 } else if (var->nonstd == FB_NONSTD_HAM)
3220 par->bpp = par->bpp <= 6 ? 6 : 8;
3221 else
3222 return(-EINVAL);
3223
3224 upper = var->upper_margin;
3225 lower = var->lower_margin;
3226 hslen = var->hsync_len;
3227 vslen = var->vsync_len;
3228
3229 par->vmode = var->vmode;
3230 switch (par->vmode & FB_VMODE_MASK) {
3231 case FB_VMODE_NONINTERLACED:
3232 line_shift_incd = 1;
3233 break;
3234 case FB_VMODE_INTERLACED:
3235 line_shift_incd = 0;
3236 if (par->yres & 1)
3237 par->yres++;
3238 if (upper & 1)
3239 upper++;
3240 if (!(lower & 1))
3241 lower++;
3242 if (vslen & 1)
3243 vslen++;
3244 break;
3245 case FB_VMODE_DOUBLE:
3246 line_shift_incd = 2;
3247 break;
3248 default:
3249 return(-EINVAL);
3250 break;
3251 }
3252
3253 par->xoffset = var->xoffset;
3254 par->yoffset = var->yoffset;
3255 if (par->vmode & FB_VMODE_YWRAP) {
3256 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->yres)
3257 return(-EINVAL);
3258 } else {
3259 if (par->xoffset < 0 || par->xoffset+par->xres > par->vxres ||
3260 par->yoffset < 0 || par->yoffset+par->yres > par->vyres)
3261 return(-EINVAL);
3262 }
3263
3264 if (var->sync & FB_SYNC_BROADCAST) {
3265 if (hslen || vslen)
3266 return(-EINVAL);
3267 } else {
3268 hslen = hslen < 1 ? 1 : hslen;
3269 vslen = vslen < 1 ? 1 : vslen;
3270 }
3271
3272
3273
3274
3275
3276 if (par->vxres*par->vyres*par->bpp > videomemorysize<<3)
3277 return(-EINVAL);
3278
3279
3280
3281
3282
3283
3284
3285
3286 xres_n = par->xres<<clk_shift;
3287 xoffset_n = par->xoffset<<clk_shift;
3288 yres_n = par->yres<<line_shift_incd>>1;
3289
3290 left_n = var->left_margin<<clk_shift;
3291 right_n = var->right_margin<<clk_shift;
3292 hslen_n = hslen<<clk_shift;
3293 upper_n = upper<<line_shift_incd>>1;
3294 lower_n = lower<<line_shift_incd>>1;
3295 vslen_n = vslen<<line_shift_incd>>1;
3296
3297
3298
3299
3300
3301 par->bplcon3 = sprpixmode[clk_shift];
3302 aga_calculate_timings:
3303 if (var->sync & FB_SYNC_BROADCAST) {
3304 if (upper_n+yres_n+lower_n == PAL_WINDOW_V) {
3305
3306 diwstrt_v = PAL_DIWSTRT_V+upper_n;
3307 diwstop_v = diwstrt_v+yres_n;
3308 diwstrt_h = PAL_DIWSTRT_H+left_n;
3309 diwstop_h = diwstrt_h+xres_n+1;
3310 par->htotal = htotal2hw(PAL_HTOTAL);
3311 hrate = 15625;
3312 vrate = 50;
3313 par->beamcon0 = BMC0_PAL;
3314 } else if (upper_n+yres_n+lower_n == NTSC_WINDOW_V) {
3315
3316 diwstrt_v = NTSC_DIWSTRT_V+upper_n;
3317 diwstop_v = diwstrt_v+yres_n;
3318 diwstrt_h = NTSC_DIWSTRT_H+left_n;
3319 diwstop_h = diwstrt_h+xres_n+1;
3320 par->htotal = htotal2hw(NTSC_HTOTAL);
3321 hrate = 15750;
3322 vrate = 60;
3323 par->beamcon0 = 0;
3324 } else
3325 return(-EINVAL);
3326 } else {
3327
3328 vsstrt = lower_n;
3329 vsstop = vsstrt+vslen_n;
3330 diwstrt_v = vsstop+upper_n;
3331 diwstop_v = diwstrt_v+yres_n;
3332 vtotal = diwstop_v;
3333 hslen_n = up8(hslen_n);
3334 htotal = up8(left_n+xres_n+right_n+hslen_n);
3335 if (vtotal > 2048 || htotal > 2048)
3336 return(-EINVAL);
3337 right_n = htotal-left_n-xres_n-hslen_n;
3338 hsstrt = down8(right_n+4);
3339 hsstop = hsstrt+hslen_n;
3340 diwstop_h = htotal+hsstrt-right_n+1;
3341 diwstrt_h = diwstop_h-xres_n-1;
3342 hrate = (double)amiga_masterclock/htotal;
3343 vrate = hrate/vtotal;
3344 par->bplcon3 |= BPC3_BRDRBLNK | BPC3_EXTBLKEN;
3345 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
3346 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
3347 BMC0_PAL | BMC0_VARCSYEN;
3348 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
3349 par->beamcon0 |= BMC0_HSYTRUE;
3350 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
3351 par->beamcon0 |= BMC0_VSYTRUE;
3352 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
3353 par->beamcon0 |= BMC0_CSYTRUE;
3354 par->htotal = htotal2hw(htotal);
3355 par->hsstrt = hsstrt2hw(hsstrt);
3356 par->hsstop = hsstop2hw(hsstop);
3357 par->vtotal = vtotal2hw(vtotal);
3358 par->vsstrt = vsstrt2hw(vsstrt);
3359 par->vsstop = vsstop2hw(vsstop);
3360 par->hcenter = par->hsstrt+(par->htotal>>1);
3361 }
3362 par->diwstrt_v = diwstrt_v;
3363 par->diwstrt_h = diwstrt_h;
3364 par->crsr_x = 0;
3365 par->crsr_y = 0;
3366
3367
3368
3369
3370
3371 ddfmin = down64(xoffset_n);
3372 ddfmax = up64(xoffset_n+xres_n);
3373 hscroll = diwstrt_h-68-mod64(xoffset_n);
3374 ddfstrt = down64(hscroll);
3375 if (ddfstrt < 128) {
3376 right_n += (128-hscroll);
3377
3378 if (loopcnt++)
3379 return(-EINVAL);
3380 goto aga_calculate_timings;
3381 }
3382 hscroll -= ddfstrt;
3383 ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3384
3385
3386
3387
3388
3389 if (amifb_ilbm) {
3390 par->next_plane = div8(par->vxres);
3391 par->next_line = par->bpp*par->next_plane;
3392 } else {
3393 par->next_line = div8(par->vxres);
3394 par->next_plane = par->vyres*par->next_line;
3395 }
3396 par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3397 par->yoffset*par->next_line);
3398 par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3399 par->bpl2mod = par->bpl1mod;
3400
3401
3402
3403
3404
3405 par->bplcon0 = BPC0_COLOR | BPC0_ECSENA | bplpixmode[clk_shift];
3406 if (par->bpp == 8)
3407 par->bplcon0 |= BPC0_BPU3;
3408 else
3409 par->bplcon0 |= par->bpp<<12;
3410 if (var->nonstd == FB_NONSTD_HAM)
3411 par->bplcon0 |= BPC0_HAM;
3412 if (var->sync & FB_SYNC_EXT)
3413 par->bplcon0 |= BPC0_ERSY;
3414 par->bplcon1 = hscroll2hw(hscroll);
3415 par->diwstrt = diwstrt2hw(diwstrt_h, diwstrt_v);
3416 par->diwstop = diwstop2hw(diwstop_h, diwstop_v);
3417 par->diwhigh = diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v);
3418 par->ddfstrt = ddfstrt2hw(ddfstrt);
3419 par->ddfstop = ddfstop2hw(ddfstop);
3420 par->fmode = FMODE_SPAGEM | FMODE_SPR32 | FMODE_BPAGEM | FMODE_BPL32;
3421
3422 switch (par->vmode & FB_VMODE_MASK) {
3423 case FB_VMODE_INTERLACED:
3424 par->bpl1mod += par->next_line;
3425 par->bpl2mod += par->next_line;
3426 par->bplcon0 |= BPC0_LACE;
3427 break;
3428 case FB_VMODE_DOUBLE:
3429 par->bpl1mod -= par->next_line;
3430 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
3431 break;
3432 }
3433
3434 if (hrate < hfmin || hrate > hfmax || vrate < vfmin || vrate > vfmax)
3435 return(-EINVAL);
3436
3437 return(0);
3438 }
3439
3440
3441
3442
3443
3444
3445
3446 static int aga_encode_var(struct fb_var_screeninfo *var,
3447 struct amiga_fb_par *par)
3448 {
3449 u_short clk_shift, line_shift_incd;
3450 u_long left, right, upper, lower, hslen, vslen;
3451 u_short diwstop_h, diwstop_v;
3452 u_short hsstrt, vsstrt, hsstop, vsstop, htotal;
3453 int i;
3454
3455 var->xres = par->xres;
3456 var->yres = par->yres;
3457 var->xres_virtual = par->vxres;
3458 var->yres_virtual = par->vyres;
3459 var->xoffset = par->xoffset;
3460 var->yoffset = par->yoffset;
3461
3462 var->bits_per_pixel = par->bpp;
3463 var->grayscale = 0;
3464
3465 var->red.offset = 0;
3466 var->red.length = 8;
3467 var->red.msb_right = 0;
3468 var->blue = var->green = var->red;
3469 var->transp.offset = 0;
3470 var->transp.length = 0;
3471 var->transp.msb_right = 0;
3472
3473 if (par->bplcon0 & BPC0_HAM)
3474 var->nonstd = FB_NONSTD_HAM;
3475 else
3476 var->nonstd = 0;
3477 var->activate = 0;
3478
3479 var->height = -1;
3480 var->width = -1;
3481 var->accel = FB_ACCEL_NONE;
3482
3483 clk_shift = par->clk_shift;
3484 var->pixclock = pixclock[clk_shift];
3485
3486 diwstop_h = hw2diwstop_h(par->diwstop, par->diwhigh);
3487 if (par->beamcon0 & BMC0_VARBEAMEN) {
3488 hsstrt = hw2hsstrt(par->hsstrt);
3489 vsstrt = hw2vsstrt(par->vsstrt);
3490 hsstop = hw2hsstop(par->hsstop);
3491 vsstop = hw2vsstop(par->vsstop);
3492 htotal = hw2htotal(par->htotal);
3493 left = par->diwstrt_h-hsstop;
3494 right = htotal+hsstrt-diwstop_h+1;
3495 hslen = hsstop-hsstrt;
3496 upper = par->diwstrt_v-vsstop;
3497 lower = vsstrt;
3498 vslen = vsstop-vsstrt;
3499 var->sync = 0;
3500 } else {
3501 diwstop_v = hw2diwstop_v(par->diwstop, par->diwhigh);
3502 if (par->beamcon0 & BMC0_PAL) {
3503 left = par->diwstrt_h-PAL_DIWSTRT_H;
3504 right = PAL_DIWSTRT_H+PAL_WINDOW_H-diwstop_h+1;
3505 upper = par->diwstrt_v-PAL_DIWSTRT_V;
3506 lower = PAL_DIWSTRT_V+PAL_WINDOW_V-diwstop_v;
3507 } else {
3508 left = par->diwstrt_h-NTSC_DIWSTRT_H;
3509 right = NTSC_DIWSTRT_H+NTSC_WINDOW_H-diwstop_h;
3510 upper = par->diwstrt_v-NTSC_DIWSTRT_V;
3511 lower = NTSC_DIWSTRT_V+NTSC_WINDOW_V-diwstop_v;
3512 }
3513 hslen = 0;
3514 vslen = 0;
3515 var->sync = FB_SYNC_BROADCAST;
3516 }
3517
3518 if (par->bplcon0 & BPC0_ERSY)
3519 var->sync |= FB_SYNC_EXT;
3520 if (par->beamcon0 & BMC0_HSYTRUE)
3521 var->sync |= FB_SYNC_HOR_HIGH_ACT;
3522 if (par->beamcon0 & BMC0_VSYTRUE)
3523 var->sync |= FB_SYNC_VERT_HIGH_ACT;
3524 if (par->beamcon0 & BMC0_CSYTRUE)
3525 var->sync |= FB_SYNC_COMP_HIGH_ACT;
3526
3527 switch (par->vmode & FB_VMODE_MASK) {
3528 case FB_VMODE_NONINTERLACED:
3529 line_shift_incd = 1;
3530 break;
3531 case FB_VMODE_INTERLACED:
3532 line_shift_incd = 0;
3533 break;
3534 case FB_VMODE_DOUBLE:
3535 line_shift_incd = 2;
3536 break;
3537 }
3538
3539 var->left_margin = left>>clk_shift;
3540 var->right_margin = right>>clk_shift;
3541 var->upper_margin = upper<<1>>line_shift_incd;
3542 var->lower_margin = lower<<1>>line_shift_incd;
3543 var->hsync_len = hslen>>clk_shift;
3544 var->vsync_len = vslen<<1>>line_shift_incd;
3545 var->vmode = par->vmode;
3546 for (i = 0; i < arraysize(var->reserved); i++)
3547 var->reserved[i] = 0;
3548
3549 return(0);
3550 }
3551
3552
3553
3554
3555
3556
3557
3558 static int aga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
3559 u_int *transp)
3560 {
3561 if (regno > 255)
3562 return(1);
3563
3564 *red = palette[regno].red;
3565 *green = palette[regno].green;
3566 *blue = palette[regno].blue;
3567 return(0);
3568 }
3569
3570
3571
3572
3573
3574
3575
3576
3577 static int aga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3578 u_int transp)
3579 {
3580 u_short bplcon3 = current_par.bplcon3;
3581
3582 if (regno > 255)
3583 return(1);
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593 cli();
3594 if (regno || !is_blanked) {
3595 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3596 custom.color[regno&31] = rgb2hw_high(red, green, blue);
3597 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3598 custom.color[regno&31] = rgb2hw_low(red, green, blue);
3599 custom.bplcon3 = bplcon3;
3600 }
3601 sti();
3602
3603 palette[regno].red = red;
3604 palette[regno].green = green;
3605 palette[regno].blue = blue;
3606
3607 return(0);
3608 }
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618 static int aga_pan_display(struct fb_var_screeninfo *var,
3619 struct amiga_fb_par *par)
3620 {
3621 int xoffset, yoffset, vmode, xres_n, xoffset_n;
3622 u_short clk_shift, line_shift_incd;
3623 u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3624
3625 xoffset = var->xoffset;
3626 yoffset = var->yoffset;
3627 if (var->vmode & FB_VMODE_YWRAP) {
3628 if (hw2ddfstrt(par->ddfstrt) < (par->bpp-1)*64 || xoffset ||
3629 yoffset < 0 || yoffset >= par->yres)
3630 return(-EINVAL);
3631 vmode = par->vmode | FB_VMODE_YWRAP;
3632 } else {
3633 if (par->diwstrt_h < 323)
3634 xoffset = up64(xoffset);
3635 if (xoffset < 0 || xoffset+par->xres > par->vxres ||
3636 yoffset < 0 || yoffset+par->yres > par->vyres)
3637 return(-EINVAL);
3638 vmode = par->vmode & ~FB_VMODE_YWRAP;
3639 }
3640
3641 clk_shift = par->clk_shift;
3642 switch (vmode & FB_VMODE_MASK) {
3643 case FB_VMODE_NONINTERLACED:
3644 line_shift_incd = 1;
3645 break;
3646 case FB_VMODE_INTERLACED:
3647 line_shift_incd = 0;
3648 break;
3649 case FB_VMODE_DOUBLE:
3650 line_shift_incd = 2;
3651 break;
3652 }
3653 xres_n = par->xres<<clk_shift;
3654 xoffset_n = xoffset<<clk_shift;
3655
3656
3657
3658
3659
3660 ddfmin = down64(xoffset_n);
3661 ddfmax = up64(xoffset_n+xres_n);
3662 hscroll = par->diwstrt_h-68-mod64(xoffset_n);
3663 ddfstrt = down64(hscroll);
3664 if (ddfstrt < 128)
3665 return(-EINVAL);
3666 hscroll -= ddfstrt;
3667 ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3668 par->bplcon1 = hscroll2hw(hscroll);
3669 par->ddfstrt = ddfstrt2hw(ddfstrt);
3670 par->ddfstop = ddfstop2hw(ddfstop);
3671
3672
3673
3674
3675
3676 par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3677 yoffset*par->next_line);
3678 par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3679 par->bpl2mod = par->bpl1mod;
3680 switch (vmode & FB_VMODE_MASK) {
3681 case FB_VMODE_INTERLACED:
3682 par->bpl1mod += par->next_line;
3683 par->bpl2mod += par->next_line;
3684 break;
3685 case FB_VMODE_DOUBLE:
3686 par->bpl1mod -= par->next_line;
3687 break;
3688 }
3689
3690 par->xoffset = var->xoffset = xoffset;
3691 par->yoffset = var->yoffset = yoffset;
3692 par->vmode = var->vmode = vmode;
3693 return(0);
3694 }
3695
3696
3697
3698
3699
3700
3701 void aga_do_vmode(void)
3702 {
3703 struct amiga_fb_par *par = ¤t_par;
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3717 custom.vposw = 0x8000;
3718 aga_build_clist_dyn(clist_lof, clist_shf, 0, par);
3719 custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3720 aga_build_clist_dyn(clist_shf, clist_lof, 1, par);
3721 } else {
3722 aga_build_clist_dyn(clist_lof, NULL, 0, par);
3723 custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3724 }
3725
3726
3727
3728
3729
3730 if (full_vmode_change) {
3731 custom.fmode = par->fmode;
3732 custom.beamcon0 = par->beamcon0;
3733 if (par->beamcon0 & BMC0_VARBEAMEN) {
3734 custom.htotal = par->htotal;
3735 custom.vtotal = par->vtotal;
3736 custom.hsstrt = par->hsstrt;
3737 custom.hsstop = par->hsstop;
3738 custom.hbstrt = par->hsstrt;
3739 custom.hbstop = par->hsstop;
3740 custom.vsstrt = par->vsstrt;
3741 custom.vsstop = par->vsstop;
3742 custom.vbstrt = par->vsstrt;
3743 custom.vbstop = par->vsstop;
3744 custom.hcenter = par->hcenter;
3745 }
3746 custom.bplcon3 = par->bplcon3;
3747 full_vmode_change = 0;
3748 }
3749 custom.ddfstrt = par->ddfstrt;
3750 custom.ddfstop = par->ddfstop;
3751 custom.bpl1mod = par->bpl1mod;
3752 custom.bpl2mod = par->bpl2mod;
3753 custom.bplcon1 = par->bplcon1;
3754
3755
3756
3757
3758
3759 aga_update_clist_hdr(clist_hdr, par);
3760
3761
3762
3763
3764
3765 if ((boot_info.bi_amiga.chipset != CS_STONEAGE) && full_vmode_change)
3766 amiga_audio_min_period = (par->htotal>>1)+1;
3767 }
3768
3769
3770
3771
3772
3773
3774 void aga_do_blank(int blank)
3775 {
3776 struct amiga_fb_par *par = ¤t_par;
3777 u_short bplcon3 = par->bplcon3;
3778 u_char red, green, blue;
3779
3780 if (blank) {
3781 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3782 red = green = blue = 0;
3783 if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3784
3785 custom.hsstrt = par->htotal+2;
3786 custom.hsstop = par->htotal+2;
3787 }
3788 } else {
3789 custom.dmacon = DMAF_SETCLR | DMAF_RASTER;
3790 red = palette[0].red;
3791 green = palette[0].green;
3792 blue = palette[0].blue;
3793 if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3794 custom.hsstrt = par->hsstrt;
3795 custom.hsstop = par->hsstop;
3796 }
3797 }
3798 custom.bplcon3 = bplcon3;
3799 custom.color[0] = rgb2hw_high(red, green, blue);
3800 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3801 custom.color[0] = rgb2hw_low(red, green, blue);
3802 custom.bplcon3 = bplcon3;
3803
3804 is_blanked = blank;
3805 }
3806
3807
3808
3809
3810
3811
3812 void aga_do_movecursor(void)
3813 {
3814 struct amiga_fb_par *par = ¤t_par;
3815 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3816 long hs, vs, ve;
3817 u_short s1, s2, is_double = 0;
3818
3819 if (par->crsr_x <= -64 || par->crsr_x >= par->xres || par->crsr_y <= -64 ||
3820 par->crsr_y >= par->yres)
3821 hs = vs = ve = 0;
3822 else {
3823 hs = par->diwstrt_h-4+(par->crsr_x<<par->clk_shift);
3824 vs = par->crsr_y;
3825 ve = min(vs+64, par->yres);
3826 switch (par->vmode & FB_VMODE_MASK) {
3827 case FB_VMODE_INTERLACED:
3828 vs >>= 1;
3829 ve >>= 1;
3830 break;
3831 case FB_VMODE_DOUBLE:
3832 vs <<= 1;
3833 ve <<= 1;
3834 is_double = 1;
3835 break;
3836 }
3837 vs += par->diwstrt_v;
3838 ve += par->diwstrt_v;
3839 }
3840 s1 = spr2hw_pos(vs, hs);
3841 if (is_double)
3842 s1 |= 0x80;
3843 s2 = spr2hw_ctl(vs, hs, ve);
3844 sprite->sprpos = s1;
3845 sprite->sprctl = s2;
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856
3857 }
3858
3859
3860
3861
3862
3863
3864 void aga_do_flashcursor(void)
3865 {
3866 #if 1
3867 static int cursorcount = 0;
3868 static int cursorstate = 0;
3869
3870 switch (cursormode) {
3871 case FB_CURSOR_OFF:
3872 custom.dmacon = DMAF_SPRITE;
3873 break;
3874 case FB_CURSOR_ON:
3875 custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3876 break;
3877 case FB_CURSOR_FLASH:
3878 if (cursorcount)
3879 cursorcount--;
3880 else {
3881 cursorcount = CRSR_RATE;
3882 if ((cursorstate = !cursorstate))
3883 custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3884 else
3885 custom.dmacon = DMAF_SPRITE;
3886 }
3887 break;
3888 }
3889 #endif
3890 }
3891
3892
3893 #if 1
3894 static int aga_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
3895 {
3896 #if 0
3897 if (ddfstrt >= 192) {
3898 #endif
3899 fix->crsr_width = 64;
3900 fix->crsr_height = 64;
3901 fix->crsr_xsize = 64;
3902 fix->crsr_ysize = 64;
3903 fix->crsr_color1 = 17;
3904 fix->crsr_color2 = 18;
3905 #if 0
3906 } else {
3907 fix->crsr_width = 0;
3908 fix->crsr_height = 0;
3909 fix->crsr_xsize = 0;
3910 fix->crsr_ysize = 0;
3911 fix->crsr_color1 = 0;
3912 fix->crsr_color2 = 0;
3913 }
3914 #endif
3915 return(0);
3916 }
3917
3918
3919 static int aga_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3920 {
3921 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3922
3923
3924 memcpy(var->data, sprite->u.nonlaced.data, sizeof(var->data));
3925 return(0);
3926 }
3927
3928
3929 static int aga_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3930 {
3931 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3932
3933
3934 memcpy(sprite->u.nonlaced.data, var->data, sizeof(var->data));
3935 return(0);
3936 }
3937
3938
3939 static int aga_get_cursorstate(struct fb_cursorstate *state, int con)
3940 {
3941 state->xoffset = current_par.crsr_x;
3942 state->yoffset = current_par.crsr_y;
3943 state->mode = cursormode;
3944 return(0);
3945 }
3946
3947
3948 static int aga_set_cursorstate(struct fb_cursorstate *state, int con)
3949 {
3950 current_par.crsr_x = state->xoffset;
3951 current_par.crsr_y = state->yoffset;
3952 cursormode = state->mode;
3953 do_movecursor = 1;
3954 return(0);
3955 }
3956 #endif
3957
3958
3959
3960
3961
3962
3963 static __inline__ void aga_build_clist_hdr(struct clist_hdr *cop)
3964 {
3965 int i, j;
3966 u_long p;
3967
3968 cop->bplcon0.l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3969 cop->diwstrt.l = CMOVE(0x0181, diwstrt);
3970 cop->diwstop.l = CMOVE(0x0281, diwstop);
3971 cop->diwhigh.l = CMOVE(0x0000, diwhigh);
3972 for (i = 0; i < 8; i++)
3973 cop->sprfix[i].l = CMOVE(0, spr[i].pos);
3974 for (i = 0, j = 0; i < 8; i++) {
3975 p = ZTWO_PADDR(dummysprite);
3976 cop->sprstrtup[j++].l = CMOVE(highw(p), sprpt[i]);
3977 cop->sprstrtup[j++].l = CMOVE2(loww(p), sprpt[i]);
3978 }
3979 cop->wait.l = CWAIT(0, 12);
3980 cop->jump.l = CMOVE(0, copjmp2);
3981 cop->wait_forever.l = CEND;
3982 }
3983
3984
3985
3986
3987
3988
3989 static __inline__ void aga_update_clist_hdr(struct clist_hdr *cop,
3990 struct amiga_fb_par *par)
3991 {
3992 cop->bplcon0.l = CMOVE(~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) &
3993 par->bplcon0, bplcon0);
3994 cop->wait.l = CWAIT(0, par->diwstrt_v-2);
3995 }
3996
3997
3998
3999
4000
4001
4002 static void aga_build_clist_dyn(struct clist_dyn *cop,
4003 struct clist_dyn *othercop, u_short shf,
4004 struct amiga_fb_par *par)
4005 {
4006 u_long y_wrap, bplpt0, p, line;
4007 int i, j = 0;
4008
4009 cop->diwstrt.l = CMOVE(par->diwstrt, diwstrt);
4010 cop->diwstop.l = CMOVE(par->diwstop, diwstop);
4011 cop->diwhigh.l = CMOVE(par->diwhigh, diwhigh);
4012 cop->bplcon0.l = CMOVE(par->bplcon0, bplcon0);
4013
4014
4015
4016
4017 if (shf) {
4018 p = ZTWO_PADDR(shfsprite);
4019 cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4020 cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4021 } else {
4022 p = ZTWO_PADDR(lofsprite);
4023 cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4024 cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4025 }
4026
4027 bplpt0 = par->bplpt0;
4028 if (shf)
4029 bplpt0 += par->next_line;
4030 y_wrap = par->vmode & FB_VMODE_YWRAP ? par->yoffset : 0;
4031
4032
4033
4034 for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4035 cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4036 cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4037 }
4038
4039 if (y_wrap) {
4040 bplpt0 -= y_wrap*par->next_line;
4041 line = par->yres-y_wrap;
4042 switch (par->vmode & FB_VMODE_MASK) {
4043 case FB_VMODE_INTERLACED:
4044 line >>= 1;
4045 break;
4046 case FB_VMODE_DOUBLE:
4047 line <<= 1;
4048 break;
4049 }
4050 line += par->diwstrt_v;
4051
4052
4053
4054 while (line > 256) {
4055
4056 cop->rest[j++].l = CWAIT(par->htotal-4, 255);
4057
4058 cop->rest[j++].l = CWAIT(0, 0);
4059 line -= 256;
4060 }
4061 cop->rest[j++].l = CWAIT(par->htotal-11, line-1);
4062
4063 for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4064 cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4065 cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4066 }
4067 }
4068
4069 if (othercop) {
4070 p = ZTWO_PADDR(othercop);
4071 cop->rest[j++].l = CMOVE(highw(p), cop2lc);
4072 cop->rest[j++].l = CMOVE2(loww(p), cop2lc);
4073 }
4074
4075
4076 cop->rest[j++].l = CEND;
4077
4078 if (j > arraysize(cop->rest))
4079 printk("aga_build_clist_dyn: copper list overflow (%d entries)\n", j);
4080 }
4081 #endif
4082
4083
4084
4085
4086
4087 #ifdef CONFIG_AMIFB_OCS
4088 static struct fb_hwswitch ocs_switch = {
4089 ocs_init, ocs_encode_fix, ocs_decode_var, ocs_encode_var, ocs_getcolreg,
4090 ocs_setcolreg, ocs_pan_display, ocs_do_vmode, ocs_do_blank,
4091 ocs_do_movecursor, ocs_do_flashcursor
4092 };
4093 #endif
4094
4095 #ifdef CONFIG_AMIFB_ECS
4096 static struct fb_hwswitch ecs_switch = {
4097 ecs_init, ecs_encode_fix, ecs_decode_var, ecs_encode_var, ecs_getcolreg,
4098 ecs_setcolreg, ecs_pan_display, ecs_do_vmode, ecs_do_blank,
4099 ecs_do_movecursor, ecs_do_flashcursor
4100 };
4101 #endif
4102
4103 #ifdef CONFIG_AMIFB_AGA
4104 static struct fb_hwswitch aga_switch = {
4105 aga_init, aga_encode_fix, aga_decode_var, aga_encode_var, aga_getcolreg,
4106 aga_setcolreg, aga_pan_display, aga_do_vmode, aga_do_blank,
4107 aga_do_movecursor, aga_do_flashcursor
4108 };
4109 #endif
4110
4111
4112
4113
4114
4115
4116
4117
4118
4119 static u_long chipalloc(u_long size)
4120 {
4121 u_long ptr;
4122
4123 size += PAGE_SIZE-1;
4124 if (!(ptr = (u_long)amiga_chip_alloc(size)))
4125 panic("No Chip RAM for frame buffer");
4126 memset((void *)ptr, 0, size);
4127 ptr = PAGE_ALIGN(ptr);
4128
4129 return(ptr);
4130 }
4131
4132
4133
4134
4135
4136
4137 static void amiga_fb_get_par(struct amiga_fb_par *par)
4138 {
4139 if (current_par_valid)
4140 *par = current_par;
4141 else
4142 fbhw->decode_var(&amiga_fb_predefined[amifb_mode], par);
4143 }
4144
4145
4146 static void amiga_fb_set_par(struct amiga_fb_par *par)
4147 {
4148 do_vmode = 0;
4149 current_par = *par;
4150 full_vmode_change = 1;
4151 do_vmode = 1;
4152 current_par_valid = 1;
4153 }
4154
4155
4156 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
4157 {
4158 int err, activate;
4159 struct amiga_fb_par par;
4160
4161 if ((err = fbhw->decode_var(var, &par)))
4162 return(err);
4163 activate = var->activate;
4164 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
4165 amiga_fb_set_par(&par);
4166 fbhw->encode_var(var, &par);
4167 var->activate = activate;
4168 return(0);
4169 }
4170
4171
4172
4173
4174
4175
4176 static u_short red2[] =
4177 { 0x0000, 0xc000 };
4178 static u_short green2[] =
4179 { 0x0000, 0xc000 };
4180 static u_short blue2[] =
4181 { 0x0000, 0xc000 };
4182
4183 static u_short red4[] =
4184 { 0x0000, 0xc000, 0x8000, 0xffff };
4185 static u_short green4[] =
4186 { 0x0000, 0xc000, 0x8000, 0xffff };
4187 static u_short blue4[] =
4188 { 0x0000, 0xc000, 0x8000, 0xffff };
4189
4190 static u_short red8[] =
4191 { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000 };
4192 static u_short green8[] =
4193 { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000 };
4194 static u_short blue8[] =
4195 { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000 };
4196
4197 static u_short red16[] =
4198 { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
4199 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
4200 static u_short green16[] =
4201 { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
4202 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
4203 static u_short blue16[] =
4204 { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
4205 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
4206
4207
4208 static struct fb_cmap default_2_colors =
4209 { 0, 2, red2, green2, blue2, NULL };
4210 static struct fb_cmap default_8_colors =
4211 { 0, 8, red8, green8, blue8, NULL };
4212 static struct fb_cmap default_4_colors =
4213 { 0, 4, red4, green4, blue4, NULL };
4214 static struct fb_cmap default_16_colors =
4215 { 0, 16, red16, green16, blue16, NULL };
4216
4217
4218 static struct fb_cmap *get_default_colormap(int bpp)
4219 {
4220 switch (bpp) {
4221 case 1:
4222 return(&default_2_colors);
4223 break;
4224 case 2:
4225 return(&default_4_colors);
4226 break;
4227 case 3:
4228 return(&default_8_colors);
4229 break;
4230 default:
4231 return(&default_16_colors);
4232 break;
4233 }
4234 }
4235
4236
4237 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16)
4238 #define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
4239 ((1<<(width))-1)) : 0))
4240
4241 static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4242 int kspc)
4243 {
4244 int i, start;
4245 u_short *red, *green, *blue, *transp;
4246 u_int hred, hgreen, hblue, htransp;
4247
4248 red = cmap->red;
4249 green = cmap->green;
4250 blue = cmap->blue;
4251 transp = cmap->transp;
4252 start = cmap->start;
4253 if (start < 0)
4254 return(-EINVAL);
4255 for (i = 0; i < cmap->len; i++) {
4256 if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
4257 return(0);
4258 hred = CNVT_FROMHW(hred, var->red.length);
4259 hgreen = CNVT_FROMHW(hgreen, var->green.length);
4260 hblue = CNVT_FROMHW(hblue, var->blue.length);
4261 htransp = CNVT_FROMHW(htransp, var->transp.length);
4262 if (kspc) {
4263 *red = hred;
4264 *green = hgreen;
4265 *blue = hblue;
4266 if (transp)
4267 *transp = htransp;
4268 } else {
4269 put_fs_word(hred, red);
4270 put_fs_word(hgreen, green);
4271 put_fs_word(hblue, blue);
4272 if (transp)
4273 put_fs_word(htransp, transp);
4274 }
4275 red++;
4276 green++;
4277 blue++;
4278 if (transp)
4279 transp++;
4280 }
4281 return(0);
4282 }
4283
4284
4285 static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4286 int kspc)
4287 {
4288 int i, start;
4289 u_short *red, *green, *blue, *transp;
4290 u_int hred, hgreen, hblue, htransp;
4291
4292 red = cmap->red;
4293 green = cmap->green;
4294 blue = cmap->blue;
4295 transp = cmap->transp;
4296 start = cmap->start;
4297
4298 if (start < 0)
4299 return(-EINVAL);
4300 for (i = 0; i < cmap->len; i++) {
4301 if (kspc) {
4302 hred = *red;
4303 hgreen = *green;
4304 hblue = *blue;
4305 htransp = transp ? *transp : 0;
4306 } else {
4307 hred = get_fs_word(red);
4308 hgreen = get_fs_word(green);
4309 hblue = get_fs_word(blue);
4310 htransp = transp ? get_fs_word(transp) : 0;
4311 }
4312 hred = CNVT_TOHW(hred, var->red.length);
4313 hgreen = CNVT_TOHW(hgreen, var->green.length);
4314 hblue = CNVT_TOHW(hblue, var->blue.length);
4315 htransp = CNVT_TOHW(htransp, var->transp.length);
4316 red++;
4317 green++;
4318 blue++;
4319 if (transp)
4320 transp++;
4321 if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
4322 return(0);
4323 }
4324 return(0);
4325 }
4326
4327
4328 static void do_install_cmap(int con)
4329 {
4330 if (con != currcon)
4331 return;
4332 if (disp[con].cmap.len)
4333 do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
4334 else
4335 do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
4336 &disp[con].var, 1);
4337 }
4338
4339
4340 static void memcpy_fs(int fsfromto, void *to, void *from, int len)
4341 {
4342 switch (fsfromto) {
4343 case 0:
4344 memcpy(to, from, len);
4345 return;
4346 case 1:
4347 memcpy_fromfs(to, from, len);
4348 return;
4349 case 2:
4350 memcpy_tofs(to, from, len);
4351 return;
4352 }
4353 }
4354
4355
4356 static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
4357 {
4358 int size;
4359 int tooff = 0, fromoff = 0;
4360
4361 if (to->start > from->start)
4362 fromoff = to->start-from->start;
4363 else
4364 tooff = from->start-to->start;
4365 size = to->len-tooff;
4366 if (size > from->len-fromoff)
4367 size = from->len-fromoff;
4368 if (size < 0)
4369 return;
4370 size *= sizeof(u_short);
4371 memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
4372 memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
4373 memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
4374 if (from->transp && to->transp)
4375 memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
4376 }
4377
4378
4379 static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
4380 {
4381 int size = len*sizeof(u_short);
4382
4383 if (cmap->len != len) {
4384 if (cmap->red)
4385 kfree(cmap->red);
4386 if (cmap->green)
4387 kfree(cmap->green);
4388 if (cmap->blue)
4389 kfree(cmap->blue);
4390 if (cmap->transp)
4391 kfree(cmap->transp);
4392 cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
4393 cmap->len = 0;
4394 if (!len)
4395 return(0);
4396 if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
4397 return(-1);
4398 if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
4399 return(-1);
4400 if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
4401 return(-1);
4402 if (transp) {
4403 if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
4404 return(-1);
4405 } else
4406 cmap->transp = NULL;
4407 }
4408 cmap->start = 0;
4409 cmap->len = len;
4410 copy_cmap(get_default_colormap(len), cmap, 0);
4411 return(0);
4412 }
4413
4414
4415
4416
4417
4418
4419 static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
4420 {
4421 struct amiga_fb_par par;
4422 int error = 0;
4423
4424 if (con == -1)
4425 amiga_fb_get_par(&par);
4426 else
4427 error = fbhw->decode_var(&disp[con].var, &par);
4428 return(error ? error : fbhw->encode_fix(fix, &par));
4429 }
4430
4431
4432
4433
4434
4435
4436 static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
4437 {
4438 struct amiga_fb_par par;
4439 int error = 0;
4440
4441 if (con == -1) {
4442 amiga_fb_get_par(&par);
4443 error = fbhw->encode_var(var, &par);
4444 } else
4445 *var = disp[con].var;
4446 return(error);
4447 }
4448
4449
4450 static void amiga_fb_set_disp(int con)
4451 {
4452 struct fb_fix_screeninfo fix;
4453
4454 amiga_fb_get_fix(&fix, con);
4455 if (con == -1)
4456 con = 0;
4457 disp[con].screen_base = (u_char *)fix.smem_start;
4458 disp[con].visual = fix.visual;
4459 disp[con].type = fix.type;
4460 disp[con].type_aux = fix.type_aux;
4461 disp[con].ypanstep = fix.ypanstep;
4462 disp[con].ywrapstep = fix.ywrapstep;
4463 disp[con].can_soft_blank = 1;
4464 disp[con].inverse = amifb_inverse;
4465 }
4466
4467
4468
4469
4470
4471
4472 static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
4473 {
4474 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
4475
4476 if ((err = do_fb_set_var(var, con == currcon)))
4477 return(err);
4478 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
4479 oldxres = disp[con].var.xres;
4480 oldyres = disp[con].var.yres;
4481 oldvxres = disp[con].var.xres_virtual;
4482 oldvyres = disp[con].var.yres_virtual;
4483 oldbpp = disp[con].var.bits_per_pixel;
4484 disp[con].var = *var;
4485 if (oldxres != var->xres || oldyres != var->yres ||
4486 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
4487 oldbpp != var->bits_per_pixel) {
4488 amiga_fb_set_disp(con);
4489 (*fb_info.changevar)(con);
4490 alloc_cmap(&disp[con].cmap, 0, 0);
4491 do_install_cmap(con);
4492 }
4493 }
4494 var->activate = 0;
4495 return(0);
4496 }
4497
4498
4499
4500
4501
4502
4503 static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
4504 {
4505 if (con == currcon)
4506 return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
4507 else if (disp[con].cmap.len)
4508 copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
4509 else
4510 copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
4511 kspc ? 0 : 2);
4512 return(0);
4513 }
4514
4515
4516
4517
4518
4519
4520 static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
4521 {
4522 int err;
4523
4524 if (!disp[con].cmap.len) {
4525 if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
4526 0)))
4527 return(err);
4528 }
4529 if (con == currcon)
4530 return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
4531 else
4532 copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
4533 return(0);
4534 }
4535
4536
4537
4538
4539
4540
4541
4542
4543 static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
4544 {
4545 int err;
4546 u_short oldlatch;
4547
4548 if (var->vmode & FB_VMODE_YWRAP) {
4549 if (var->xoffset || var->yoffset >= disp[con].var.yres)
4550 return(-EINVAL);
4551 } else {
4552 if (var->xoffset+disp[con].var.xres > disp[con].var.xres_virtual ||
4553 var->yoffset+disp[con].var.yres > disp[con].var.yres_virtual)
4554 return(-EINVAL);
4555 }
4556 if (con == currcon) {
4557 cli();
4558 oldlatch = do_vmode;
4559 do_vmode = 0;
4560 sti();
4561 if ((err = fbhw->pan_display(var, ¤t_par))) {
4562 if (oldlatch)
4563 do_vmode = 1;
4564 return(err);
4565 }
4566 do_vmode = 1;
4567 }
4568 disp[con].var.xoffset = var->xoffset;
4569 disp[con].var.yoffset = var->yoffset;
4570 if (var->vmode & FB_VMODE_YWRAP)
4571 disp[con].var.vmode |= FB_VMODE_YWRAP;
4572 else
4573 disp[con].var.vmode &= ~FB_VMODE_YWRAP;
4574 return(0);
4575 }
4576
4577
4578
4579
4580
4581
4582 static int amiga_fb_ioctl(struct inode *inode, struct file *file,
4583 u_int cmd, u_long arg, int con)
4584 {
4585 int i;
4586 struct fb_fix_cursorinfo crsrfix;
4587 struct fb_var_cursorinfo crsrvar;
4588 struct fb_cursorstate crsrstate;
4589
4590 switch (cmd) {
4591 #ifdef CONFIG_AMIFB_AGA
4592 case FBIOGET_FCURSORINFO:
4593 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrfix));
4594 if (i)
4595 return(i);
4596 i = amiga_fb_get_fix_cursorinfo(&crsrfix, con);
4597 memcpy_tofs((void *)arg, &crsrfix, sizeof(crsrfix));
4598 return(i);
4599 case FBIOGET_VCURSORINFO:
4600 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrvar));
4601 if (i)
4602 return(i);
4603 i = amiga_fb_get_var_cursorinfo(&crsrvar, con);
4604 memcpy_tofs((void *)arg, &crsrvar, sizeof(crsrvar));
4605 return(i);
4606 case FBIOPUT_VCURSORINFO:
4607 i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrvar));
4608 if (i)
4609 return(i);
4610 memcpy_fromfs(&crsrvar, (void *)arg, sizeof(crsrvar));
4611 i = amiga_fb_set_var_cursorinfo(&crsrvar, con);
4612 return(i);
4613 case FBIOGET_CURSORSTATE:
4614 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrstate));
4615 if (i)
4616 return(i);
4617 i = amiga_fb_get_cursorstate(&crsrstate, con);
4618 memcpy_tofs((void *)arg, &crsrstate, sizeof(crsrstate));
4619 return(i);
4620 case FBIOPUT_CURSORSTATE:
4621 i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrstate));
4622 if (i)
4623 return(i);
4624 memcpy_fromfs(&crsrstate, (void *)arg, sizeof(crsrstate));
4625 i = amiga_fb_set_cursorstate(&crsrstate, con);
4626 return(i);
4627 #endif
4628 #if 1
4629 case FBCMD_GET_CURRENTPAR:
4630 if ((i = verify_area(VERIFY_WRITE, (void *)arg,
4631 sizeof(struct amiga_fb_par))))
4632 return(i);
4633 memcpy_tofs((void *)arg, (void *)¤t_par,
4634 sizeof(struct amiga_fb_par));
4635 return(0);
4636 break;
4637 case FBCMD_SET_CURRENTPAR:
4638 if ((i = verify_area(VERIFY_READ, (void *)arg,
4639 sizeof(struct amiga_fb_par))))
4640 return(i);
4641 memcpy_fromfs((void *)¤t_par, (void *)arg,
4642 sizeof(struct amiga_fb_par));
4643 return(0);
4644 break;
4645 #endif
4646 }
4647 return(-EINVAL);
4648 }
4649
4650
4651 #ifdef CONFIG_AMIFB_AGA
4652
4653
4654
4655
4656 static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
4657 {
4658 if (boot_info.bi_amiga.chipset == CS_AGA)
4659 return(aga_get_fix_cursorinfo(fix, con));
4660 return(-EINVAL);
4661 }
4662
4663
4664 static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4665 {
4666 if (boot_info.bi_amiga.chipset == CS_AGA)
4667 return(aga_get_var_cursorinfo(var, con));
4668 return(-EINVAL);
4669 }
4670
4671
4672 static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4673 {
4674 if (boot_info.bi_amiga.chipset == CS_AGA)
4675 return(aga_set_var_cursorinfo(var, con));
4676 return(-EINVAL);
4677 }
4678
4679
4680 static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con)
4681 {
4682 if (boot_info.bi_amiga.chipset == CS_AGA)
4683 return(aga_get_cursorstate(state, con));
4684 return(-EINVAL);
4685 }
4686
4687
4688 static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con)
4689 {
4690 if (boot_info.bi_amiga.chipset == CS_AGA)
4691 return(aga_set_cursorstate(state, con));
4692 return(-EINVAL);
4693 }
4694 #endif
4695
4696
4697 static struct fb_ops amiga_fb_ops = {
4698 amiga_fb_get_fix, amiga_fb_get_var, amiga_fb_set_var, amiga_fb_get_cmap,
4699 amiga_fb_set_cmap, amiga_fb_pan_display, amiga_fb_ioctl
4700 };
4701
4702
4703 void amiga_video_setup(char *options, int *ints)
4704 {
4705 char *this_opt;
4706 int i;
4707 char mcap_spec[80];
4708
4709
4710
4711
4712
4713 #ifdef CONFIG_FB_CYBER
4714 if (options && *options)
4715 if (!strncmp(options, "cyber", 5) && Cyber_probe()) {
4716 amifb_Cyber = 1;
4717 Cyber_video_setup(options, ints);
4718 return;
4719 }
4720 #endif
4721
4722 #ifdef USE_MONO_AMIFB_IF_NON_AGA
4723 if (boot_info.bi_amiga.chipset != CS_AGA) {
4724 mono_video_setup(options, ints);
4725 return;
4726 }
4727 #endif
4728
4729 mcap_spec[0] = '\0';
4730 fb_info.fontname[0] = '\0';
4731
4732 if (!options || !*options)
4733 return;
4734
4735 for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
4736 if (!strcmp(this_opt, "inverse")) {
4737 amifb_inverse = 1;
4738 for (i = 0; i < 16; i++) {
4739 red16[i] = ~red16[i];
4740 green16[i] = ~green16[i];
4741 blue16[i] = ~blue16[i];
4742 }
4743 for (i = 0; i < 8; i++) {
4744 red8[i] = ~red8[i];
4745 green8[i] = ~green8[i];
4746 blue8[i] = ~blue8[i];
4747 }
4748 for (i = 0; i < 4; i++) {
4749 red4[i] = ~red4[i];
4750 green4[i] = ~green4[i];
4751 blue4[i] = ~blue4[i];
4752 }
4753 for (i = 0; i < 2; i++) {
4754 red2[i] = ~red2[i];
4755 green2[i] = ~green2[i];
4756 blue2[i] = ~blue2[i];
4757 }
4758 } else if (!strcmp(this_opt, "ilbm"))
4759 amifb_ilbm = 1;
4760 else if (!strcmp(this_opt, "pwrsave"))
4761 pwrsave = 1;
4762 else if (!strncmp(this_opt, "monitorcap:", 11))
4763 strcpy(mcap_spec, this_opt+11);
4764 else if (!strncmp(this_opt, "font:", 5))
4765 strcpy(fb_info.fontname, this_opt+5);
4766 else
4767 amifb_mode = get_video_mode(this_opt);
4768
4769 if (*mcap_spec) {
4770 char *p;
4771 int vmin, vmax, hmin, hmax;
4772
4773
4774
4775
4776
4777
4778 if (!(p = strtoke(mcap_spec, ";")) || !*p)
4779 goto cap_invalid;
4780 vmin = simple_strtoul(p, NULL, 10);
4781 if (vmin <= 0)
4782 goto cap_invalid;
4783 if (!(p = strtoke(NULL, ";")) || !*p)
4784 goto cap_invalid;
4785 vmax = simple_strtoul(p, NULL, 10);
4786 if (vmax <= 0 || vmax <= vmin)
4787 goto cap_invalid;
4788 if (!(p = strtoke(NULL, ";")) || !*p)
4789 goto cap_invalid;
4790 hmin = 1000 * simple_strtoul(p, NULL, 10);
4791 if (hmin <= 0)
4792 goto cap_invalid;
4793 if (!(p = strtoke(NULL, "")) || !*p)
4794 goto cap_invalid;
4795 hmax = 1000 * simple_strtoul(p, NULL, 10);
4796 if (hmax <= 0 || hmax <= hmin)
4797 goto cap_invalid;
4798
4799 vfmin = vmin;
4800 vfmax = vmax;
4801 hfmin = hmin;
4802 hfmax = hmax;
4803 cap_invalid:
4804 ;
4805 }
4806 }
4807
4808
4809
4810
4811
4812
4813 struct fb_info *amiga_fb_init(long *mem_start)
4814 {
4815 int err, tag, i;
4816 struct fb_var_screeninfo *var;
4817
4818
4819
4820
4821
4822 #ifdef CONFIG_FB_CYBER
4823 if (amifb_Cyber)
4824 return(Cyber_fb_init(mem_start));
4825 #endif
4826
4827
4828
4829
4830
4831 if (!AMIGAHW_PRESENT(AMI_VIDEO))
4832 return(NULL);
4833
4834 #ifdef USE_MONO_AMIFB_IF_NON_AGA
4835 if (boot_info.bi_amiga.chipset != CS_AGA)
4836 return(mono_amiga_fb_init(mem_start));
4837 #endif
4838
4839 switch (boot_info.bi_amiga.chipset) {
4840 #ifdef CONFIG_AMIFB_OCS
4841 case CS_OCS:
4842 strcat(amiga_fb_name, "OCS");
4843 default_chipset:
4844 fbhw = &ocs_switch;
4845 maxdepth[TAG_SHRES-1] = 0;
4846 maxdepth[TAG_HIRES-1] = 4;
4847 maxdepth[TAG_LORES-1] = 6;
4848 break;
4849 #endif
4850
4851 #ifdef CONFIG_AMIFB_ECS
4852 case CS_ECS:
4853 strcat(amiga_fb_name, "ECS");
4854 fbhw = &ecs_switch;
4855 maxdepth[TAG_SHRES-1] = 2;
4856 maxdepth[TAG_HIRES-1] = 4;
4857 maxdepth[TAG_LORES-1] = 6;
4858 break;
4859 #endif
4860
4861 #ifdef CONFIG_AMIFB_AGA
4862 case CS_AGA:
4863 strcat(amiga_fb_name, "AGA");
4864 fbhw = &aga_switch;
4865 maxdepth[TAG_SHRES-1] = 8;
4866 maxdepth[TAG_HIRES-1] = 8;
4867 maxdepth[TAG_LORES-1] = 8;
4868 break;
4869 #endif
4870
4871 default:
4872 #ifdef CONFIG_AMIFB_OCS
4873 printk("Unknown graphics chipset, defaulting to OCS\n");
4874 strcat(amiga_fb_name, "Unknown");
4875 goto default_chipset;
4876 #else
4877 panic("Unknown graphics chipset, no default driver");
4878 #endif
4879 break;
4880 }
4881
4882
4883
4884
4885
4886 pixclock[TAG_SHRES-1] = 25E9/amiga_eclock;
4887 pixclock[TAG_HIRES-1] = 50E9/amiga_eclock;
4888 pixclock[TAG_LORES-1] = 100E9/amiga_eclock;
4889
4890
4891
4892
4893
4894 for (i = 0; i < NUM_PREDEF_MODES; i++) {
4895 tag = amiga_fb_predefined[i].pixclock;
4896 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
4897 amiga_fb_predefined[i].pixclock = pixclock[tag-1];
4898 if (amiga_fb_predefined[i].bits_per_pixel > maxdepth[tag-1])
4899 amiga_fb_predefined[i].bits_per_pixel = maxdepth[tag-1];
4900 }
4901 }
4902
4903 err = register_framebuffer(amiga_fb_name, &node, &amiga_fb_ops,
4904 NUM_TOTAL_MODES, amiga_fb_predefined);
4905 if (err < 0)
4906 panic("Cannot register frame buffer");
4907
4908 fbhw->init();
4909 check_default_mode();
4910
4911 if (!add_isr(IRQ_AMIGA_VERTB, amifb_interrupt, 0, NULL, "frame buffer"))
4912 panic("Couldn't add vblank interrupt");
4913
4914 strcpy(fb_info.modename, amiga_fb_name);
4915 fb_info.disp = disp;
4916 fb_info.switch_con = &amifb_switch;
4917 fb_info.updatevar = &amifb_updatevar;
4918 fb_info.blank = &amifb_blank;
4919
4920 var = &amiga_fb_predefined[amifb_mode];
4921 do_fb_set_var(var, 1);
4922 strcat(fb_info.modename, " ");
4923 strcat(fb_info.modename, amiga_fb_modenames[amifb_mode]);
4924
4925 amiga_fb_get_var(&disp[0].var, -1);
4926 amiga_fb_set_disp(-1);
4927 do_install_cmap(0);
4928 return(&fb_info);
4929 }
4930
4931
4932 static int amifb_switch(int con)
4933 {
4934
4935 if (disp[currcon].cmap.len)
4936 do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
4937
4938 do_fb_set_var(&disp[con].var, 1);
4939 currcon = con;
4940
4941 do_install_cmap(con);
4942 return(0);
4943 }
4944
4945
4946
4947
4948
4949
4950
4951
4952
4953 static int amifb_updatevar(int con)
4954 {
4955 do_vmode = 0;
4956 current_par.yoffset = disp[con].var.yoffset;
4957 current_par.vmode = disp[con].var.vmode;
4958 current_par.bplpt0 = ZTWO_PADDR((u_long)videomemory+
4959 current_par.yoffset*current_par.next_line);
4960 do_vmode = 1;
4961 return(0);
4962 }
4963
4964
4965
4966
4967
4968
4969 static void amifb_blank(int blank)
4970 {
4971 do_blank = blank ? 1 : -1;
4972 }
4973
4974
4975
4976
4977
4978
4979 static void amifb_interrupt(int irq, struct pt_regs *fp, void *dummy)
4980 {
4981 static int is_laced = 0;
4982
4983 #if 0
4984
4985
4986
4987
4988
4989
4990
4991 if (!current_par_valid)
4992 return;
4993 #endif
4994
4995
4996
4997
4998
4999 if (!is_laced || custom.vposr & 0x8000) {
5000 if (do_vmode) {
5001 fbhw->do_vmode();
5002 do_vmode = 0;
5003 is_laced = (current_par.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
5004 }
5005 if (do_movecursor) {
5006 fbhw->do_movecursor();
5007 do_movecursor = 0;
5008 }
5009 }
5010 if (do_blank) {
5011 fbhw->do_blank(do_blank > 0 ? 1 : 0);
5012 do_blank = 0;
5013 }
5014 if (!is_blanked)
5015 fbhw->do_flashcursor();
5016 }
5017
5018
5019
5020
5021
5022
5023 static char * strtoke(char * s,const char * ct)
5024 {
5025 char *sbegin, *send;
5026 static char *ssave = NULL;
5027
5028 sbegin = s ? s : ssave;
5029 if (!sbegin)
5030 return(NULL);
5031 if (*sbegin == '\0') {
5032 ssave = NULL;
5033 return(NULL);
5034 }
5035 send = strpbrk(sbegin, ct);
5036 if (send && *send != '\0')
5037 *send++ = '\0';
5038 ssave = send;
5039 return(sbegin);
5040 }
5041
5042
5043
5044
5045
5046
5047 static int get_video_mode(const char *name)
5048 {
5049 int i;
5050
5051 for (i = 1; i < NUM_PREDEF_MODES; i++)
5052 if (!strcmp(name, amiga_fb_modenames[i]))
5053 return(i);
5054 return(0);
5055 }
5056
5057
5058
5059
5060
5061
5062 static void check_default_mode(void)
5063 {
5064 struct fb_var_screeninfo var;
5065
5066
5067 if (amifb_mode) {
5068 var = amiga_fb_predefined[amifb_mode];
5069 var.activate = FB_ACTIVATE_TEST;
5070 if (!do_fb_set_var(&var, 1))
5071 goto found_video_mode;
5072 }
5073
5074
5075 printk("Can't use default video mode. Probing video modes...\n");
5076 for (amifb_mode = 1; amifb_mode < NUM_PREDEF_MODES; amifb_mode++) {
5077 var = amiga_fb_predefined[amifb_mode];
5078 var.activate = FB_ACTIVATE_TEST;
5079 if (!do_fb_set_var(&var, 1))
5080 goto found_video_mode;
5081 }
5082 panic("Can't find any usable video mode");
5083
5084 found_video_mode:
5085 amiga_fb_predefined[0] = var;
5086 }