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 fix->line_length = 0;
2494 for (i = 0; i < arraysize(fix->reserved); i++)
2495 fix->reserved[i] = 0;
2496 return(0);
2497 }
2498
2499
2500 static int mono_amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
2501 {
2502 int i;
2503
2504 var->xres = mono_current_par.geometry->scr_width;
2505 var->yres = mono_current_par.geometry->scr_height;
2506 var->xres_virtual = var->xres;
2507 var->yres_virtual = var->yres;
2508 var->xoffset = 0;
2509 var->yoffset = 0;
2510
2511 var->bits_per_pixel = mono_current_par.geometry->scr_depth;
2512 var->grayscale = 0;
2513
2514 if (boot_info.bi_amiga.chipset == CS_AGA) {
2515 var->red.offset = 0;
2516 var->red.length = 8;
2517 var->red.msb_right = 0;
2518 var->green = var->red;
2519 var->blue = var->red;
2520 } else {
2521 var->red.offset = 0;
2522 var->red.length = 4;
2523 var->red.msb_right = 0;
2524 var->green = var->red;
2525 var->blue = var->red;
2526 }
2527
2528 var->nonstd = 0;
2529 var->activate = 0;
2530
2531 var->width = -1;
2532 var->height = -1;
2533
2534 var->accel = FB_ACCEL_NONE;
2535
2536 var->pixclock = 35242;
2537 var->left_margin = (mono_current_par.geometry->hbstop-mono_current_par.geometry->hsstrt)*8;
2538 var->right_margin = (mono_current_par.geometry->hsstrt-mono_current_par.geometry->hbstrt)*8;
2539 var->upper_margin = (mono_current_par.geometry->vbstop-mono_current_par.geometry->vsstrt)*8;
2540 var->lower_margin = (mono_current_par.geometry->vsstrt-mono_current_par.geometry->vbstrt)*8;
2541 var->hsync_len = (mono_current_par.geometry->hsstop-mono_current_par.geometry->hsstrt)*8;
2542 var->vsync_len = (mono_current_par.geometry->vsstop-mono_current_par.geometry->vsstrt)*8;
2543 var->sync = 0;
2544 if (mono_current_par.geometry->bplcon0 & BPC0_LACE)
2545 var->vmode = FB_VMODE_INTERLACED;
2546 else if ((boot_info.bi_amiga.chipset == CS_AGA) && (mono_current_par.geometry->fmode & FMODE_BSCAN2))
2547 var->vmode = FB_VMODE_DOUBLE;
2548 else
2549 var->vmode = FB_VMODE_NONINTERLACED;
2550
2551 for (i = 0; i < arraysize(var->reserved); i++)
2552 var->reserved[i] = 0;
2553
2554 return(0);
2555 }
2556
2557
2558 static void mono_amiga_fb_set_disp(int con)
2559 {
2560 struct fb_fix_screeninfo fix;
2561
2562 mono_amiga_fb_get_fix(&fix, con);
2563 if (con == -1)
2564 con = 0;
2565 disp[con].screen_base = (u_char *)fix.smem_start;
2566 disp[con].visual = fix.visual;
2567 disp[con].type = fix.type;
2568 disp[con].type_aux = fix.type_aux;
2569 disp[con].ypanstep = fix.ypanstep;
2570 disp[con].ywrapstep = fix.ywrapstep;
2571 disp[con].line_length = fix.line_length;
2572 disp[con].can_soft_blank = 1;
2573 disp[con].inverse = mono_amifb_inverse;
2574 }
2575
2576
2577 static int mono_amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
2578 {
2579
2580
2581
2582 return 0;
2583 return(-EINVAL);
2584 }
2585
2586
2587 static short mono_red_normal[] = {
2588 ((BG_COLOR & 0xff0000)>>8) | ((BG_COLOR & 0xff0000)>>16),
2589 ((FG_COLOR & 0xff0000)>>8) | ((FG_COLOR & 0xff0000)>>16)
2590 };
2591 static short mono_green_normal[] = {
2592 ((BG_COLOR & 0x00ff00)) | ((BG_COLOR & 0x00ff00)>>8),
2593 ((FG_COLOR & 0x00ff00)) | ((FG_COLOR & 0x00ff00)>>8)
2594 };
2595 static short mono_blue_normal[] = {
2596 ((BG_COLOR & 0x0000ff)<<8) | ((BG_COLOR & 0x0000ff)),
2597 ((FG_COLOR & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2598 };
2599
2600 static short mono_red_inverse[] = {
2601 ((BG_COLOR_INV & 0xff0000)>>8) | ((BG_COLOR_INV & 0xff0000)>>16),
2602 ((FG_COLOR_INV & 0xff0000)>>8) | ((FG_COLOR_INV & 0xff0000)>>16)
2603 };
2604 static short mono_green_inverse[] = {
2605 ((BG_COLOR_INV & 0x00ff00)) | ((BG_COLOR_INV & 0x00ff00)>>8),
2606 ((FG_COLOR_INV & 0x00ff00)) | ((FG_COLOR_INV & 0x00ff00)>>8)
2607 };
2608 static short mono_blue_inverse[] = {
2609 ((BG_COLOR_INV & 0x0000ff)<<8) | ((BG_COLOR_INV & 0x0000ff)),
2610 ((FG_COLOR_INV & 0x0000ff)<<8) | ((FG_COLOR & 0x0000ff))
2611 };
2612
2613 static struct fb_cmap mono_default_cmap_normal = { 0, 2, mono_red_normal, mono_green_normal, mono_blue_normal, NULL };
2614 static struct fb_cmap mono_default_cmap_inverse = { 0, 2, mono_red_inverse, mono_green_inverse, mono_blue_inverse, NULL };
2615
2616 static int mono_amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
2617 {
2618 int i, start;
2619 unsigned short *red, *green, *blue, *transp;
2620 unsigned int hred, hgreen, hblue, htransp;
2621 struct fb_cmap *def_cmap;
2622
2623 red = cmap->red;
2624 green = cmap->green;
2625 blue = cmap->blue;
2626 transp = cmap->transp;
2627 start = cmap->start;
2628 if (start < 0)
2629 return(-EINVAL);
2630
2631 if (mono_amifb_inverse)
2632 def_cmap = &mono_default_cmap_inverse;
2633 else
2634 def_cmap = &mono_default_cmap_normal;
2635
2636 for (i = 0; i < cmap->len; i++) {
2637 if (i < def_cmap->len) {
2638 hred = def_cmap->red[i];
2639 hgreen = def_cmap->green[i];
2640 hblue = def_cmap->blue[i];
2641 if (def_cmap->transp)
2642 htransp = def_cmap->transp[i];
2643 else
2644 htransp = 0;
2645 } else
2646 hred = hgreen = hblue = htransp = 0;
2647 if (kspc) {
2648 *red = hred;
2649 *green = hgreen;
2650 *blue = hblue;
2651 if (transp)
2652 *transp = htransp;
2653 } else {
2654 put_fs_word(hred, red);
2655 put_fs_word(hgreen, green);
2656 put_fs_word(hblue, blue);
2657 if (transp)
2658 put_fs_word(htransp, transp);
2659 }
2660 red++;
2661 green++;
2662 blue++;
2663 if (transp)
2664 transp++;
2665 }
2666 return(0);
2667 }
2668
2669
2670 static int mono_amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
2671 {
2672
2673
2674
2675 return(-EINVAL);
2676 }
2677
2678
2679 static int mono_amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
2680 {
2681
2682
2683
2684 return(-EINVAL);
2685 }
2686
2687
2688 static int mono_amiga_fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
2689 unsigned long arg, int con)
2690 {
2691 return(-EINVAL);
2692 }
2693
2694 static struct fb_ops mono_amiga_fb_ops = {
2695 mono_amiga_fb_get_fix, mono_amiga_fb_get_var, mono_amiga_fb_set_var, mono_amiga_fb_get_cmap,
2696 mono_amiga_fb_set_cmap, mono_amiga_fb_pan_display, mono_amiga_fb_ioctl
2697 };
2698
2699
2700 static int mono_amifb_switch (int con)
2701 {
2702 mono_current_par.y_wrap = disp[con].var.yoffset;
2703 mono_current_par.cursor_latch = 1;
2704 mono_current_par.scroll_latch = 1;
2705 return(0);
2706 }
2707
2708
2709 static int mono_amifb_updatevar(int con)
2710 {
2711 mono_current_par.y_wrap = disp[con].var.yoffset;
2712 mono_current_par.cursor_latch = 1;
2713 mono_current_par.scroll_latch = 1;
2714 return(0);
2715 }
2716
2717
2718 static void mono_amifb_blank(int blank)
2719 {
2720 if (blank)
2721 mono_do_blank = 1;
2722 else
2723 mono_do_unblank = 1;
2724 }
2725
2726
2727 static struct fb_info *mono_amiga_fb_init(long *mem_start)
2728 {
2729 int mode = mono_amifb_mode;
2730 ulong model;
2731 int inverse_video = mono_amifb_inverse;
2732 int err;
2733
2734 err=register_framebuffer("Amiga Builtin", &node, &mono_amiga_fb_ops, mono_num_mono_amiga_fb_predefined,
2735 mono_mono_amiga_fb_predefined);
2736
2737 model = boot_info.bi_un.bi_ami.model;
2738 if (mode == -1)
2739 if (boot_info.bi_amiga.chipset == CS_AGA)
2740 mode = AGA_DEFMODE;
2741 else if (model == AMI_3000)
2742 mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_3000_DEFMODE : OCS_NTSC_3000_DEFMODE;
2743 else
2744 mode = boot_info.bi_un.bi_ami.vblank == 50 ? OCS_PAL_LOWEND_DEFMODE : OCS_NTSC_LOWEND_DEFMODE;
2745
2746 mono_init_vblank();
2747 mono_display_init(disp, &mono_modes[mode], inverse_video);
2748 if (!add_isr(IRQ_AMIGA_VERTB, mono_amifb_interrupt, 0, NULL, "frame buffer"))
2749 panic("Couldn't add vblank interrupt");
2750
2751 mono_amiga_fb_get_var(&disp[0].var, 0);
2752 if (mono_amifb_inverse)
2753 disp[0].cmap = mono_default_cmap_inverse;
2754 else
2755 disp[0].cmap = mono_default_cmap_normal;
2756 mono_amiga_fb_set_disp(-1);
2757
2758 strcpy(fb_info.modename, "Amiga Builtin ");
2759 fb_info.disp = disp;
2760 fb_info.switch_con = &mono_amifb_switch;
2761 fb_info.updatevar = &mono_amifb_updatevar;
2762 fb_info.blank = &mono_amifb_blank;
2763 strcat(fb_info.modename, mono_modes[mode].modename);
2764
2765 return(&fb_info);
2766 }
2767 #endif
2768
2769
2770
2771
2772
2773 #ifdef CONFIG_AMIFB_OCS
2774
2775
2776
2777
2778
2779
2780
2781
2782 static int ocs_init(void)
2783 {
2784 u_long p;
2785
2786
2787
2788
2789
2790 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2791
2792
2793
2794
2795
2796 if (!amifb_mode)
2797 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2798 DEFMODE_PAL : DEFMODE_NTSC);
2799
2800
2801
2802
2803
2804 videomemorysize = VIDEOMEMSIZE_OCS;
2805
2806
2807 ...
2808 ...
2809 ...
2810
2811
2812
2813
2814
2815
2816 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2817 DMAF_SPRITE;
2818
2819 return(0);
2820 }
2821 #endif
2822
2823
2824
2825
2826
2827 #ifdef CONFIG_AMIFB_ECS
2828
2829
2830
2831
2832
2833
2834
2835
2836 static int ecs_init(void)
2837 {
2838 u_long p;
2839
2840
2841
2842
2843
2844 custom.dmacon = DMAF_ALL | DMAF_MASTER;
2845
2846
2847
2848
2849
2850 if (!amifb_mode)
2851 if (AMIGAHW_PRESENT(AMBER_FF))
2852 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2853 DEFMODE_AMBER_PAL : DEFMODE_AMBER_NTSC);
2854 else
2855 amifb_mode = get_video_mode(boot_info.bi_un.bi_ami.vblank == 50 ?
2856 DEFMODE_PAL : DEFMODE_NTSC);
2857
2858
2859
2860
2861
2862 if (boot_info.bi_amiga.chip_size > 1048576)
2863 videomemorysize = VIDEOMEMSIZE_ECS_2M;
2864 else
2865 videomemorysize = VIDEOMEMSIZE_ECS_1M;
2866
2867
2868 ...
2869 ...
2870 ...
2871
2872
2873
2874
2875
2876
2877 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
2878 DMAF_SPRITE;
2879
2880 return(0);
2881 }
2882 #endif
2883
2884
2885
2886
2887
2888 #ifdef CONFIG_AMIFB_AGA
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
2925
2926 #define hscroll2hw(hscroll) \
2927 (((hscroll)<<12 & 0x3000) | ((hscroll)<<8 & 0xc300) | \
2928 ((hscroll)<<4 & 0x0c00) | ((hscroll)<<2 & 0x00f0) | ((hscroll)>>2 & 0x000f))
2929
2930 #define hw2hscroll(hscroll) \
2931 (((hscroll)>>8 & 0x00c3) | ((hscroll)<<2 & 0x003c))
2932
2933
2934
2935 #define diwstrt2hw(diwstrt_h, diwstrt_v) \
2936 (((diwstrt_v)<<8 & 0xff00) | ((diwstrt_h)>>2 & 0x00ff))
2937 #define diwstop2hw(distop_h, diwstop_v) \
2938 (((diwstop_v)<<8 & 0xff00) | ((diwstop_h)>>2 & 0x00ff))
2939 #define diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v) \
2940 (((diwstop_h)<<3 & 0x2000) | ((diwstop_h)<<11 & 0x1800) | \
2941 ((diwstop_v) & 0x0700) | ((diwstrt_h)>>5 & 0x0020) | \
2942 ((diwstrt_h)<<3 & 0x0018) | ((diwstrt_v)>>8 & 0x0007))
2943
2944 #define hw2diwstrt_h(diwstrt, diwhigh) \
2945 (((diwhigh)<<5 & 0x0400) | ((diwstrt)<<2 & 0x03fc) | ((diwhigh)>>3 & 0x0003))
2946 #define hw2diwstrt_v(diwstrt, diwhigh) \
2947 (((diwhigh)<<8 & 0x0700) | ((diwstrt)>>8 & 0x00ff))
2948 #define hw2diwstop_h(diwstop, diwhigh) \
2949 (((diwhigh)>>3 & 0x0400) | ((diwstop)<<2 & 0x03fc) | \
2950 ((diwhigh)>>11 & 0x0003))
2951 #define hw2diwstop_v(diwstop, diwhigh) \
2952 (((diwhigh) & 0x0700) | ((diwstop)>>8 & 0x00ff))
2953
2954
2955
2956 #define ddfstrt2hw(ddfstrt) (div8(ddfstrt) & 0x00fe)
2957 #define ddfstop2hw(ddfstop) (div8(ddfstop) & 0x00fe)
2958
2959 #define hw2ddfstrt(ddfstrt) ((ddfstrt)<<3)
2960 #define hw2ddfstop(ddfstop) ((ddfstop)<<3)
2961
2962
2963
2964 #define hsstrt2hw(hsstrt) (div8(hsstrt))
2965 #define hsstop2hw(hsstop) (div8(hsstop))
2966 #define htotal2hw(htotal) (div8(htotal)-1)
2967 #define vsstrt2hw(vsstrt) (vsstrt)
2968 #define vsstop2hw(vsstop) (vsstop)
2969 #define vtotal2hw(vtotal) ((vtotal)-1)
2970
2971 #define hw2hsstrt(hsstrt) ((hsstrt)<<3)
2972 #define hw2hsstop(hsstop) ((hsstop)<<3)
2973 #define hw2htotal(htotal) (((htotal)+1)<<3)
2974 #define hw2vsstrt(vsstrt) (vsstrt)
2975 #define hw2vsstop(vsstop) (vsstop)
2976 #define hw2vtotal(vtotal) ((vtotal)+1)
2977
2978
2979
2980 #define hbstrt2hw(hbstrt) (((hbstrt)<<8 & 0x0700) | ((hbstrt)>>3 & 0x00ff))
2981 #define hbstop2hw(hbstop) (((hbstop)<<8 & 0x0700) | ((hbstop)>>3 & 0x00ff))
2982 #define vbstrt2hw(vbstrt) (vbstrt)
2983 #define vbstop2hw(vbstop) (vbstop)
2984
2985 #define hw2hbstrt(hbstrt) (((hbstrt)<<3 & 0x07f8) | ((hbstrt)>>8 & 0x0007))
2986 #define hw2hbstop(hbstop) (((hbstop)<<3 & 0x07f8) | ((hbstop)>>8 & 0x0007))
2987 #define hw2vbstrt(vbstrt) (vbstrt)
2988 #define hw2vbstop(vbstop) (vbstop)
2989
2990
2991
2992 #define rgb2hw_high(red, green, blue) \
2993 (((red)<<4 & 0xf00) | ((green) & 0x0f0) | ((blue)>>4 & 0x00f))
2994 #define rgb2hw_low(red, green, blue) \
2995 (((red)<<8 & 0xf00) | ((green)<<4 & 0x0f0) | ((blue) & 0x00f))
2996
2997 #define hw2red(high, low) (((high)>>4 & 0xf0) | ((low)>>8 & 0x0f))
2998 #define hw2green(high, low) (((high) & 0xf0) | ((low)>>4 & 0x0f))
2999 #define hw2blue(high, low) (((high)<<4 & 0xf0) | ((low) & 0x0f))
3000
3001
3002
3003 #define spr2hw_pos(start_v, start_h) \
3004 (((start_v)<<8&0xff00) | ((start_h)>>3&0x00ff))
3005 #define spr2hw_ctl(start_v, start_h, stop_v) \
3006 (((stop_v)<<8&0xff00) | ((start_v)>>3&0x0040) | ((stop_v)>>4&0x0020) | \
3007 ((start_h)<<3&0x0018) | ((start_v)>>6&0x0004) | ((stop_v)>>7&0x0002) | \
3008 ((start_h)>>2&0x0001))
3009
3010
3011
3012
3013
3014
3015 struct aga_cursorsprite {
3016 u_short sprpos;
3017 u_short pad1[3];
3018 u_short sprctl;
3019 u_short pad2[3];
3020 union {
3021 struct {
3022 u_long data[64*4];
3023 u_long trailer[4];
3024 } nonlaced;
3025 struct {
3026 u_long data[32*4];
3027 u_long trailer[4];
3028 } laced;
3029 } u;
3030 };
3031
3032 struct aga_dummysprite {
3033 u_short sprpos;
3034 u_short pad1[3];
3035 u_short sprctl;
3036 u_short pad2[3];
3037 u_long data[4];
3038 u_long trailer[4];
3039 };
3040
3041
3042
3043
3044
3045
3046 static u_short bplpixmode[3] = {
3047 BPC0_SHRES,
3048 BPC0_HIRES,
3049 0
3050 };
3051
3052 static u_short sprpixmode[3] = {
3053 BPC3_SPRES1 | BPC3_SPRES0,
3054 BPC3_SPRES1,
3055 BPC3_SPRES0
3056 };
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067 static int aga_init(void)
3068 {
3069 u_long p;
3070
3071
3072
3073
3074
3075 custom.dmacon = DMAF_ALL | DMAF_MASTER;
3076
3077
3078
3079
3080
3081 if (!amifb_mode)
3082 amifb_mode = get_video_mode(DEFMODE_AGA);
3083
3084
3085
3086
3087
3088 if (boot_info.bi_amiga.chip_size > 1048576)
3089 videomemorysize = VIDEOMEMSIZE_AGA_2M;
3090 else
3091 videomemorysize = VIDEOMEMSIZE_AGA_1M;
3092
3093 p = chipalloc(videomemorysize+
3094 sizeof(struct clist_hdr)+
3095 2*sizeof(struct clist_dyn)+
3096 2*sizeof(struct aga_cursorsprite)+
3097 sizeof(struct aga_dummysprite));
3098
3099 assignchunk(videomemory, u_long, p, videomemorysize);
3100 assignchunk(clist_hdr, struct clist_hdr *, p, sizeof(struct clist_hdr));
3101 assignchunk(clist_lof, struct clist_dyn *, p, sizeof(struct clist_dyn));
3102 assignchunk(clist_shf, struct clist_dyn *, p, sizeof(struct clist_dyn));
3103 assignchunk(lofsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3104 assignchunk(shfsprite, u_long *, p, sizeof(struct aga_cursorsprite));
3105 assignchunk(dummysprite, u_long *, p, sizeof(struct aga_dummysprite));
3106
3107
3108
3109
3110
3111 aga_build_clist_hdr(clist_hdr);
3112
3113 custom.cop1lc = (u_short *)ZTWO_PADDR(clist_hdr);
3114 custom.cop2lc = (u_short *)ZTWO_PADDR(&clist_hdr->wait_forever);
3115 custom.copjmp1 = 0;
3116
3117
3118
3119
3120
3121 custom.dmacon = DMAF_SETCLR | DMAF_MASTER | DMAF_RASTER | DMAF_COPPER |
3122 DMAF_SPRITE;
3123
3124
3125
3126
3127
3128 custom.bplcon2 = BPC2_KILLEHB | BPC2_PF2P2 | BPC2_PF1P2;
3129 custom.bplcon4 = BPC4_ESPRM4 | BPC4_OSPRM4;
3130
3131 return(0);
3132 }
3133
3134
3135
3136
3137
3138
3139
3140 static int aga_encode_fix(struct fb_fix_screeninfo *fix,
3141 struct amiga_fb_par *par)
3142 {
3143 int i;
3144
3145 strcpy(fix->id, amiga_fb_name);
3146 fix->smem_start = videomemory;
3147 fix->smem_len = videomemorysize;
3148
3149 if (amifb_ilbm) {
3150 fix->type = FB_TYPE_INTERLEAVED_PLANES;
3151 fix->type_aux = par->next_line;
3152 } else {
3153 fix->type = FB_TYPE_PLANES;
3154 fix->type_aux = 0;
3155 }
3156 fix->visual = FB_VISUAL_PSEUDOCOLOR;
3157
3158 if (par->diwstrt_h >= 323)
3159 fix->xpanstep = 1;
3160 else
3161 fix->xpanstep = 64;
3162 fix->ypanstep = 1;
3163
3164 if (hw2ddfstrt(par->ddfstrt) >= (par->bpp-1)*64)
3165 fix->ywrapstep = 1;
3166 else
3167 fix->ywrapstep = 0;
3168
3169 fix->line_length = 0;
3170 for (i = 0; i < arraysize(fix->reserved); i++)
3171 fix->reserved[i] = 0;
3172
3173 return(0);
3174 }
3175
3176
3177
3178
3179
3180
3181
3182 static int aga_decode_var(struct fb_var_screeninfo *var,
3183 struct amiga_fb_par *par)
3184 {
3185 u_short clk_shift, line_shift_incd;
3186 u_long upper, lower, hslen, vslen;
3187 int xres_n, yres_n, xoffset_n;
3188 u_long left_n, right_n, upper_n, lower_n, hslen_n, vslen_n;
3189 u_long diwstrt_h, diwstrt_v, diwstop_h, diwstop_v;
3190 u_long hsstrt, vsstrt, hsstop, vsstop, htotal, vtotal;
3191 u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3192 double hrate, vrate;
3193 u_short loopcnt = 0;
3194
3195
3196
3197
3198
3199 for (clk_shift = 0; clk_shift < 3; clk_shift++)
3200 if (var->pixclock <= pixclock[clk_shift])
3201 break;
3202 if (clk_shift >= 3)
3203 return(-EINVAL);
3204 par->clk_shift = clk_shift;
3205
3206
3207
3208
3209
3210 par->xres = max(var->xres, 64);
3211 par->yres = max(var->yres, 64);
3212 par->vxres = up64(max(var->xres_virtual, par->xres));
3213 par->vyres = max(var->yres_virtual, par->yres);
3214
3215 par->bpp = var->bits_per_pixel;
3216 if (par->bpp > 8)
3217 return(-EINVAL);
3218
3219 if (!var->nonstd) {
3220 if (par->bpp < 1)
3221 par->bpp = 1;
3222 } else if (var->nonstd == FB_NONSTD_HAM)
3223 par->bpp = par->bpp <= 6 ? 6 : 8;
3224 else
3225 return(-EINVAL);
3226
3227 upper = var->upper_margin;
3228 lower = var->lower_margin;
3229 hslen = var->hsync_len;
3230 vslen = var->vsync_len;
3231
3232 par->vmode = var->vmode;
3233 switch (par->vmode & FB_VMODE_MASK) {
3234 case FB_VMODE_NONINTERLACED:
3235 line_shift_incd = 1;
3236 break;
3237 case FB_VMODE_INTERLACED:
3238 line_shift_incd = 0;
3239 if (par->yres & 1)
3240 par->yres++;
3241 if (upper & 1)
3242 upper++;
3243 if (!(lower & 1))
3244 lower++;
3245 if (vslen & 1)
3246 vslen++;
3247 break;
3248 case FB_VMODE_DOUBLE:
3249 line_shift_incd = 2;
3250 break;
3251 default:
3252 return(-EINVAL);
3253 break;
3254 }
3255
3256 par->xoffset = var->xoffset;
3257 par->yoffset = var->yoffset;
3258 if (par->vmode & FB_VMODE_YWRAP) {
3259 if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->yres)
3260 return(-EINVAL);
3261 } else {
3262 if (par->xoffset < 0 || par->xoffset+par->xres > par->vxres ||
3263 par->yoffset < 0 || par->yoffset+par->yres > par->vyres)
3264 return(-EINVAL);
3265 }
3266
3267 if (var->sync & FB_SYNC_BROADCAST) {
3268 if (hslen || vslen)
3269 return(-EINVAL);
3270 } else {
3271 hslen = hslen < 1 ? 1 : hslen;
3272 vslen = vslen < 1 ? 1 : vslen;
3273 }
3274
3275
3276
3277
3278
3279 if (par->vxres*par->vyres*par->bpp > videomemorysize<<3)
3280 return(-EINVAL);
3281
3282
3283
3284
3285
3286
3287
3288
3289 xres_n = par->xres<<clk_shift;
3290 xoffset_n = par->xoffset<<clk_shift;
3291 yres_n = par->yres<<line_shift_incd>>1;
3292
3293 left_n = var->left_margin<<clk_shift;
3294 right_n = var->right_margin<<clk_shift;
3295 hslen_n = hslen<<clk_shift;
3296 upper_n = upper<<line_shift_incd>>1;
3297 lower_n = lower<<line_shift_incd>>1;
3298 vslen_n = vslen<<line_shift_incd>>1;
3299
3300
3301
3302
3303
3304 par->bplcon3 = sprpixmode[clk_shift];
3305 aga_calculate_timings:
3306 if (var->sync & FB_SYNC_BROADCAST) {
3307 if (upper_n+yres_n+lower_n == PAL_WINDOW_V) {
3308
3309 diwstrt_v = PAL_DIWSTRT_V+upper_n;
3310 diwstop_v = diwstrt_v+yres_n;
3311 diwstrt_h = PAL_DIWSTRT_H+left_n;
3312 diwstop_h = diwstrt_h+xres_n+1;
3313 par->htotal = htotal2hw(PAL_HTOTAL);
3314 hrate = 15625;
3315 vrate = 50;
3316 par->beamcon0 = BMC0_PAL;
3317 } else if (upper_n+yres_n+lower_n == NTSC_WINDOW_V) {
3318
3319 diwstrt_v = NTSC_DIWSTRT_V+upper_n;
3320 diwstop_v = diwstrt_v+yres_n;
3321 diwstrt_h = NTSC_DIWSTRT_H+left_n;
3322 diwstop_h = diwstrt_h+xres_n+1;
3323 par->htotal = htotal2hw(NTSC_HTOTAL);
3324 hrate = 15750;
3325 vrate = 60;
3326 par->beamcon0 = 0;
3327 } else
3328 return(-EINVAL);
3329 } else {
3330
3331 vsstrt = lower_n;
3332 vsstop = vsstrt+vslen_n;
3333 diwstrt_v = vsstop+upper_n;
3334 diwstop_v = diwstrt_v+yres_n;
3335 vtotal = diwstop_v;
3336 hslen_n = up8(hslen_n);
3337 htotal = up8(left_n+xres_n+right_n+hslen_n);
3338 if (vtotal > 2048 || htotal > 2048)
3339 return(-EINVAL);
3340 right_n = htotal-left_n-xres_n-hslen_n;
3341 hsstrt = down8(right_n+4);
3342 hsstop = hsstrt+hslen_n;
3343 diwstop_h = htotal+hsstrt-right_n+1;
3344 diwstrt_h = diwstop_h-xres_n-1;
3345 hrate = (double)amiga_masterclock/htotal;
3346 vrate = hrate/vtotal;
3347 par->bplcon3 |= BPC3_BRDRBLNK | BPC3_EXTBLKEN;
3348 par->beamcon0 = BMC0_HARDDIS | BMC0_VARVBEN | BMC0_LOLDIS |
3349 BMC0_VARVSYEN | BMC0_VARHSYEN | BMC0_VARBEAMEN |
3350 BMC0_PAL | BMC0_VARCSYEN;
3351 if (var->sync & FB_SYNC_HOR_HIGH_ACT)
3352 par->beamcon0 |= BMC0_HSYTRUE;
3353 if (var->sync & FB_SYNC_VERT_HIGH_ACT)
3354 par->beamcon0 |= BMC0_VSYTRUE;
3355 if (var->sync & FB_SYNC_COMP_HIGH_ACT)
3356 par->beamcon0 |= BMC0_CSYTRUE;
3357 par->htotal = htotal2hw(htotal);
3358 par->hsstrt = hsstrt2hw(hsstrt);
3359 par->hsstop = hsstop2hw(hsstop);
3360 par->vtotal = vtotal2hw(vtotal);
3361 par->vsstrt = vsstrt2hw(vsstrt);
3362 par->vsstop = vsstop2hw(vsstop);
3363 par->hcenter = par->hsstrt+(par->htotal>>1);
3364 }
3365 par->diwstrt_v = diwstrt_v;
3366 par->diwstrt_h = diwstrt_h;
3367 par->crsr_x = 0;
3368 par->crsr_y = 0;
3369
3370
3371
3372
3373
3374 ddfmin = down64(xoffset_n);
3375 ddfmax = up64(xoffset_n+xres_n);
3376 hscroll = diwstrt_h-68-mod64(xoffset_n);
3377 ddfstrt = down64(hscroll);
3378 if (ddfstrt < 128) {
3379 right_n += (128-hscroll);
3380
3381 if (loopcnt++)
3382 return(-EINVAL);
3383 goto aga_calculate_timings;
3384 }
3385 hscroll -= ddfstrt;
3386 ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3387
3388
3389
3390
3391
3392 if (amifb_ilbm) {
3393 par->next_plane = div8(par->vxres);
3394 par->next_line = par->bpp*par->next_plane;
3395 } else {
3396 par->next_line = div8(par->vxres);
3397 par->next_plane = par->vyres*par->next_line;
3398 }
3399 par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3400 par->yoffset*par->next_line);
3401 par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3402 par->bpl2mod = par->bpl1mod;
3403
3404
3405
3406
3407
3408 par->bplcon0 = BPC0_COLOR | BPC0_ECSENA | bplpixmode[clk_shift];
3409 if (par->bpp == 8)
3410 par->bplcon0 |= BPC0_BPU3;
3411 else
3412 par->bplcon0 |= par->bpp<<12;
3413 if (var->nonstd == FB_NONSTD_HAM)
3414 par->bplcon0 |= BPC0_HAM;
3415 if (var->sync & FB_SYNC_EXT)
3416 par->bplcon0 |= BPC0_ERSY;
3417 par->bplcon1 = hscroll2hw(hscroll);
3418 par->diwstrt = diwstrt2hw(diwstrt_h, diwstrt_v);
3419 par->diwstop = diwstop2hw(diwstop_h, diwstop_v);
3420 par->diwhigh = diw2hw_high(diwstrt_h, diwstrt_v, distop_h, diwstop_v);
3421 par->ddfstrt = ddfstrt2hw(ddfstrt);
3422 par->ddfstop = ddfstop2hw(ddfstop);
3423 par->fmode = FMODE_SPAGEM | FMODE_SPR32 | FMODE_BPAGEM | FMODE_BPL32;
3424
3425 switch (par->vmode & FB_VMODE_MASK) {
3426 case FB_VMODE_INTERLACED:
3427 par->bpl1mod += par->next_line;
3428 par->bpl2mod += par->next_line;
3429 par->bplcon0 |= BPC0_LACE;
3430 break;
3431 case FB_VMODE_DOUBLE:
3432 par->bpl1mod -= par->next_line;
3433 par->fmode |= FMODE_SSCAN2 | FMODE_BSCAN2;
3434 break;
3435 }
3436
3437 if (hrate < hfmin || hrate > hfmax || vrate < vfmin || vrate > vfmax)
3438 return(-EINVAL);
3439
3440 return(0);
3441 }
3442
3443
3444
3445
3446
3447
3448
3449 static int aga_encode_var(struct fb_var_screeninfo *var,
3450 struct amiga_fb_par *par)
3451 {
3452 u_short clk_shift, line_shift_incd;
3453 u_long left, right, upper, lower, hslen, vslen;
3454 u_short diwstop_h, diwstop_v;
3455 u_short hsstrt, vsstrt, hsstop, vsstop, htotal;
3456 int i;
3457
3458 var->xres = par->xres;
3459 var->yres = par->yres;
3460 var->xres_virtual = par->vxres;
3461 var->yres_virtual = par->vyres;
3462 var->xoffset = par->xoffset;
3463 var->yoffset = par->yoffset;
3464
3465 var->bits_per_pixel = par->bpp;
3466 var->grayscale = 0;
3467
3468 var->red.offset = 0;
3469 var->red.length = 8;
3470 var->red.msb_right = 0;
3471 var->blue = var->green = var->red;
3472 var->transp.offset = 0;
3473 var->transp.length = 0;
3474 var->transp.msb_right = 0;
3475
3476 if (par->bplcon0 & BPC0_HAM)
3477 var->nonstd = FB_NONSTD_HAM;
3478 else
3479 var->nonstd = 0;
3480 var->activate = 0;
3481
3482 var->height = -1;
3483 var->width = -1;
3484 var->accel = FB_ACCEL_NONE;
3485
3486 clk_shift = par->clk_shift;
3487 var->pixclock = pixclock[clk_shift];
3488
3489 diwstop_h = hw2diwstop_h(par->diwstop, par->diwhigh);
3490 if (par->beamcon0 & BMC0_VARBEAMEN) {
3491 hsstrt = hw2hsstrt(par->hsstrt);
3492 vsstrt = hw2vsstrt(par->vsstrt);
3493 hsstop = hw2hsstop(par->hsstop);
3494 vsstop = hw2vsstop(par->vsstop);
3495 htotal = hw2htotal(par->htotal);
3496 left = par->diwstrt_h-hsstop;
3497 right = htotal+hsstrt-diwstop_h+1;
3498 hslen = hsstop-hsstrt;
3499 upper = par->diwstrt_v-vsstop;
3500 lower = vsstrt;
3501 vslen = vsstop-vsstrt;
3502 var->sync = 0;
3503 } else {
3504 diwstop_v = hw2diwstop_v(par->diwstop, par->diwhigh);
3505 if (par->beamcon0 & BMC0_PAL) {
3506 left = par->diwstrt_h-PAL_DIWSTRT_H;
3507 right = PAL_DIWSTRT_H+PAL_WINDOW_H-diwstop_h+1;
3508 upper = par->diwstrt_v-PAL_DIWSTRT_V;
3509 lower = PAL_DIWSTRT_V+PAL_WINDOW_V-diwstop_v;
3510 } else {
3511 left = par->diwstrt_h-NTSC_DIWSTRT_H;
3512 right = NTSC_DIWSTRT_H+NTSC_WINDOW_H-diwstop_h;
3513 upper = par->diwstrt_v-NTSC_DIWSTRT_V;
3514 lower = NTSC_DIWSTRT_V+NTSC_WINDOW_V-diwstop_v;
3515 }
3516 hslen = 0;
3517 vslen = 0;
3518 var->sync = FB_SYNC_BROADCAST;
3519 }
3520
3521 if (par->bplcon0 & BPC0_ERSY)
3522 var->sync |= FB_SYNC_EXT;
3523 if (par->beamcon0 & BMC0_HSYTRUE)
3524 var->sync |= FB_SYNC_HOR_HIGH_ACT;
3525 if (par->beamcon0 & BMC0_VSYTRUE)
3526 var->sync |= FB_SYNC_VERT_HIGH_ACT;
3527 if (par->beamcon0 & BMC0_CSYTRUE)
3528 var->sync |= FB_SYNC_COMP_HIGH_ACT;
3529
3530 switch (par->vmode & FB_VMODE_MASK) {
3531 case FB_VMODE_NONINTERLACED:
3532 line_shift_incd = 1;
3533 break;
3534 case FB_VMODE_INTERLACED:
3535 line_shift_incd = 0;
3536 break;
3537 case FB_VMODE_DOUBLE:
3538 line_shift_incd = 2;
3539 break;
3540 }
3541
3542 var->left_margin = left>>clk_shift;
3543 var->right_margin = right>>clk_shift;
3544 var->upper_margin = upper<<1>>line_shift_incd;
3545 var->lower_margin = lower<<1>>line_shift_incd;
3546 var->hsync_len = hslen>>clk_shift;
3547 var->vsync_len = vslen<<1>>line_shift_incd;
3548 var->vmode = par->vmode;
3549 for (i = 0; i < arraysize(var->reserved); i++)
3550 var->reserved[i] = 0;
3551
3552 return(0);
3553 }
3554
3555
3556
3557
3558
3559
3560
3561 static int aga_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,
3562 u_int *transp)
3563 {
3564 if (regno > 255)
3565 return(1);
3566
3567 *red = palette[regno].red;
3568 *green = palette[regno].green;
3569 *blue = palette[regno].blue;
3570 return(0);
3571 }
3572
3573
3574
3575
3576
3577
3578
3579
3580 static int aga_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
3581 u_int transp)
3582 {
3583 u_short bplcon3 = current_par.bplcon3;
3584
3585 if (regno > 255)
3586 return(1);
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596 cli();
3597 if (regno || !is_blanked) {
3598 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000);
3599 custom.color[regno&31] = rgb2hw_high(red, green, blue);
3600 custom.bplcon3 = bplcon3 | (regno<<8 & 0xe000) | BPC3_LOCT;
3601 custom.color[regno&31] = rgb2hw_low(red, green, blue);
3602 custom.bplcon3 = bplcon3;
3603 }
3604 sti();
3605
3606 palette[regno].red = red;
3607 palette[regno].green = green;
3608 palette[regno].blue = blue;
3609
3610 return(0);
3611 }
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621 static int aga_pan_display(struct fb_var_screeninfo *var,
3622 struct amiga_fb_par *par)
3623 {
3624 int xoffset, yoffset, vmode, xres_n, xoffset_n;
3625 u_short clk_shift, line_shift_incd;
3626 u_long ddfmin, ddfmax, ddfstrt, ddfstop, hscroll;
3627
3628 xoffset = var->xoffset;
3629 yoffset = var->yoffset;
3630 if (var->vmode & FB_VMODE_YWRAP) {
3631 if (hw2ddfstrt(par->ddfstrt) < (par->bpp-1)*64 || xoffset ||
3632 yoffset < 0 || yoffset >= par->yres)
3633 return(-EINVAL);
3634 vmode = par->vmode | FB_VMODE_YWRAP;
3635 } else {
3636 if (par->diwstrt_h < 323)
3637 xoffset = up64(xoffset);
3638 if (xoffset < 0 || xoffset+par->xres > par->vxres ||
3639 yoffset < 0 || yoffset+par->yres > par->vyres)
3640 return(-EINVAL);
3641 vmode = par->vmode & ~FB_VMODE_YWRAP;
3642 }
3643
3644 clk_shift = par->clk_shift;
3645 switch (vmode & FB_VMODE_MASK) {
3646 case FB_VMODE_NONINTERLACED:
3647 line_shift_incd = 1;
3648 break;
3649 case FB_VMODE_INTERLACED:
3650 line_shift_incd = 0;
3651 break;
3652 case FB_VMODE_DOUBLE:
3653 line_shift_incd = 2;
3654 break;
3655 }
3656 xres_n = par->xres<<clk_shift;
3657 xoffset_n = xoffset<<clk_shift;
3658
3659
3660
3661
3662
3663 ddfmin = down64(xoffset_n);
3664 ddfmax = up64(xoffset_n+xres_n);
3665 hscroll = par->diwstrt_h-68-mod64(xoffset_n);
3666 ddfstrt = down64(hscroll);
3667 if (ddfstrt < 128)
3668 return(-EINVAL);
3669 hscroll -= ddfstrt;
3670 ddfstop = ddfstrt+ddfmax-ddfmin-(64<<clk_shift);
3671 par->bplcon1 = hscroll2hw(hscroll);
3672 par->ddfstrt = ddfstrt2hw(ddfstrt);
3673 par->ddfstop = ddfstop2hw(ddfstop);
3674
3675
3676
3677
3678
3679 par->bplpt0 = ZTWO_PADDR((u_long)videomemory+div8(ddfmin>>clk_shift)+
3680 yoffset*par->next_line);
3681 par->bpl1mod = par->next_line-div8((ddfmax-ddfmin)>>clk_shift);
3682 par->bpl2mod = par->bpl1mod;
3683 switch (vmode & FB_VMODE_MASK) {
3684 case FB_VMODE_INTERLACED:
3685 par->bpl1mod += par->next_line;
3686 par->bpl2mod += par->next_line;
3687 break;
3688 case FB_VMODE_DOUBLE:
3689 par->bpl1mod -= par->next_line;
3690 break;
3691 }
3692
3693 par->xoffset = var->xoffset = xoffset;
3694 par->yoffset = var->yoffset = yoffset;
3695 par->vmode = var->vmode = vmode;
3696 return(0);
3697 }
3698
3699
3700
3701
3702
3703
3704 void aga_do_vmode(void)
3705 {
3706 struct amiga_fb_par *par = ¤t_par;
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719 if ((par->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) {
3720 custom.vposw = 0x8000;
3721 aga_build_clist_dyn(clist_lof, clist_shf, 0, par);
3722 custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3723 aga_build_clist_dyn(clist_shf, clist_lof, 1, par);
3724 } else {
3725 aga_build_clist_dyn(clist_lof, NULL, 0, par);
3726 custom.cop2lc = (u_short *)ZTWO_PADDR(clist_lof);
3727 }
3728
3729
3730
3731
3732
3733 if (full_vmode_change) {
3734 custom.fmode = par->fmode;
3735 custom.beamcon0 = par->beamcon0;
3736 if (par->beamcon0 & BMC0_VARBEAMEN) {
3737 custom.htotal = par->htotal;
3738 custom.vtotal = par->vtotal;
3739 custom.hsstrt = par->hsstrt;
3740 custom.hsstop = par->hsstop;
3741 custom.hbstrt = par->hsstrt;
3742 custom.hbstop = par->hsstop;
3743 custom.vsstrt = par->vsstrt;
3744 custom.vsstop = par->vsstop;
3745 custom.vbstrt = par->vsstrt;
3746 custom.vbstop = par->vsstop;
3747 custom.hcenter = par->hcenter;
3748 }
3749 custom.bplcon3 = par->bplcon3;
3750 full_vmode_change = 0;
3751 }
3752 custom.ddfstrt = par->ddfstrt;
3753 custom.ddfstop = par->ddfstop;
3754 custom.bpl1mod = par->bpl1mod;
3755 custom.bpl2mod = par->bpl2mod;
3756 custom.bplcon1 = par->bplcon1;
3757
3758
3759
3760
3761
3762 aga_update_clist_hdr(clist_hdr, par);
3763
3764
3765
3766
3767
3768 if ((boot_info.bi_amiga.chipset != CS_STONEAGE) && full_vmode_change)
3769 amiga_audio_min_period = (par->htotal>>1)+1;
3770 }
3771
3772
3773
3774
3775
3776
3777 void aga_do_blank(int blank)
3778 {
3779 struct amiga_fb_par *par = ¤t_par;
3780 u_short bplcon3 = par->bplcon3;
3781 u_char red, green, blue;
3782
3783 if (blank) {
3784 custom.dmacon = DMAF_RASTER | DMAF_SPRITE;
3785 red = green = blue = 0;
3786 if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3787
3788 custom.hsstrt = par->htotal+2;
3789 custom.hsstop = par->htotal+2;
3790 }
3791 } else {
3792 custom.dmacon = DMAF_SETCLR | DMAF_RASTER;
3793 red = palette[0].red;
3794 green = palette[0].green;
3795 blue = palette[0].blue;
3796 if (pwrsave && par->beamcon0 & BMC0_VARBEAMEN) {
3797 custom.hsstrt = par->hsstrt;
3798 custom.hsstop = par->hsstop;
3799 }
3800 }
3801 custom.bplcon3 = bplcon3;
3802 custom.color[0] = rgb2hw_high(red, green, blue);
3803 custom.bplcon3 = bplcon3 | BPC3_LOCT;
3804 custom.color[0] = rgb2hw_low(red, green, blue);
3805 custom.bplcon3 = bplcon3;
3806
3807 is_blanked = blank;
3808 }
3809
3810
3811
3812
3813
3814
3815 void aga_do_movecursor(void)
3816 {
3817 struct amiga_fb_par *par = ¤t_par;
3818 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3819 long hs, vs, ve;
3820 u_short s1, s2, is_double = 0;
3821
3822 if (par->crsr_x <= -64 || par->crsr_x >= par->xres || par->crsr_y <= -64 ||
3823 par->crsr_y >= par->yres)
3824 hs = vs = ve = 0;
3825 else {
3826 hs = par->diwstrt_h-4+(par->crsr_x<<par->clk_shift);
3827 vs = par->crsr_y;
3828 ve = min(vs+64, par->yres);
3829 switch (par->vmode & FB_VMODE_MASK) {
3830 case FB_VMODE_INTERLACED:
3831 vs >>= 1;
3832 ve >>= 1;
3833 break;
3834 case FB_VMODE_DOUBLE:
3835 vs <<= 1;
3836 ve <<= 1;
3837 is_double = 1;
3838 break;
3839 }
3840 vs += par->diwstrt_v;
3841 ve += par->diwstrt_v;
3842 }
3843 s1 = spr2hw_pos(vs, hs);
3844 if (is_double)
3845 s1 |= 0x80;
3846 s2 = spr2hw_ctl(vs, hs, ve);
3847 sprite->sprpos = s1;
3848 sprite->sprctl = s2;
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860 }
3861
3862
3863
3864
3865
3866
3867 void aga_do_flashcursor(void)
3868 {
3869 #if 1
3870 static int cursorcount = 0;
3871 static int cursorstate = 0;
3872
3873 switch (cursormode) {
3874 case FB_CURSOR_OFF:
3875 custom.dmacon = DMAF_SPRITE;
3876 break;
3877 case FB_CURSOR_ON:
3878 custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3879 break;
3880 case FB_CURSOR_FLASH:
3881 if (cursorcount)
3882 cursorcount--;
3883 else {
3884 cursorcount = CRSR_RATE;
3885 if ((cursorstate = !cursorstate))
3886 custom.dmacon = DMAF_SETCLR | DMAF_SPRITE;
3887 else
3888 custom.dmacon = DMAF_SPRITE;
3889 }
3890 break;
3891 }
3892 #endif
3893 }
3894
3895
3896 #if 1
3897 static int aga_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
3898 {
3899 #if 0
3900 if (ddfstrt >= 192) {
3901 #endif
3902 fix->crsr_width = 64;
3903 fix->crsr_height = 64;
3904 fix->crsr_xsize = 64;
3905 fix->crsr_ysize = 64;
3906 fix->crsr_color1 = 17;
3907 fix->crsr_color2 = 18;
3908 #if 0
3909 } else {
3910 fix->crsr_width = 0;
3911 fix->crsr_height = 0;
3912 fix->crsr_xsize = 0;
3913 fix->crsr_ysize = 0;
3914 fix->crsr_color1 = 0;
3915 fix->crsr_color2 = 0;
3916 }
3917 #endif
3918 return(0);
3919 }
3920
3921
3922 static int aga_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3923 {
3924 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3925
3926
3927 memcpy(var->data, sprite->u.nonlaced.data, sizeof(var->data));
3928 return(0);
3929 }
3930
3931
3932 static int aga_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
3933 {
3934 struct aga_cursorsprite *sprite = (struct aga_cursorsprite *)lofsprite;
3935
3936
3937 memcpy(sprite->u.nonlaced.data, var->data, sizeof(var->data));
3938 return(0);
3939 }
3940
3941
3942 static int aga_get_cursorstate(struct fb_cursorstate *state, int con)
3943 {
3944 state->xoffset = current_par.crsr_x;
3945 state->yoffset = current_par.crsr_y;
3946 state->mode = cursormode;
3947 return(0);
3948 }
3949
3950
3951 static int aga_set_cursorstate(struct fb_cursorstate *state, int con)
3952 {
3953 current_par.crsr_x = state->xoffset;
3954 current_par.crsr_y = state->yoffset;
3955 cursormode = state->mode;
3956 do_movecursor = 1;
3957 return(0);
3958 }
3959 #endif
3960
3961
3962
3963
3964
3965
3966 static __inline__ void aga_build_clist_hdr(struct clist_hdr *cop)
3967 {
3968 int i, j;
3969 u_long p;
3970
3971 cop->bplcon0.l = CMOVE(BPC0_COLOR | BPC0_SHRES | BPC0_ECSENA, bplcon0);
3972 cop->diwstrt.l = CMOVE(0x0181, diwstrt);
3973 cop->diwstop.l = CMOVE(0x0281, diwstop);
3974 cop->diwhigh.l = CMOVE(0x0000, diwhigh);
3975 for (i = 0; i < 8; i++)
3976 cop->sprfix[i].l = CMOVE(0, spr[i].pos);
3977 for (i = 0, j = 0; i < 8; i++) {
3978 p = ZTWO_PADDR(dummysprite);
3979 cop->sprstrtup[j++].l = CMOVE(highw(p), sprpt[i]);
3980 cop->sprstrtup[j++].l = CMOVE2(loww(p), sprpt[i]);
3981 }
3982 cop->wait.l = CWAIT(0, 12);
3983 cop->jump.l = CMOVE(0, copjmp2);
3984 cop->wait_forever.l = CEND;
3985 }
3986
3987
3988
3989
3990
3991
3992 static __inline__ void aga_update_clist_hdr(struct clist_hdr *cop,
3993 struct amiga_fb_par *par)
3994 {
3995 cop->bplcon0.l = CMOVE(~(BPC0_BPU3 | BPC0_BPU2 | BPC0_BPU1 | BPC0_BPU0) &
3996 par->bplcon0, bplcon0);
3997 cop->wait.l = CWAIT(0, par->diwstrt_v-2);
3998 }
3999
4000
4001
4002
4003
4004
4005 static void aga_build_clist_dyn(struct clist_dyn *cop,
4006 struct clist_dyn *othercop, u_short shf,
4007 struct amiga_fb_par *par)
4008 {
4009 u_long y_wrap, bplpt0, p, line;
4010 int i, j = 0;
4011
4012 cop->diwstrt.l = CMOVE(par->diwstrt, diwstrt);
4013 cop->diwstop.l = CMOVE(par->diwstop, diwstop);
4014 cop->diwhigh.l = CMOVE(par->diwhigh, diwhigh);
4015 cop->bplcon0.l = CMOVE(par->bplcon0, bplcon0);
4016
4017
4018
4019
4020 if (shf) {
4021 p = ZTWO_PADDR(shfsprite);
4022 cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4023 cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4024 } else {
4025 p = ZTWO_PADDR(lofsprite);
4026 cop->sprpt[0].l = CMOVE(highw(p), sprpt[0]);
4027 cop->sprpt[1].l = CMOVE2(loww(p), sprpt[0]);
4028 }
4029
4030 bplpt0 = par->bplpt0;
4031 if (shf)
4032 bplpt0 += par->next_line;
4033 y_wrap = par->vmode & FB_VMODE_YWRAP ? par->yoffset : 0;
4034
4035
4036
4037 for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4038 cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4039 cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4040 }
4041
4042 if (y_wrap) {
4043 bplpt0 -= y_wrap*par->next_line;
4044 line = par->yres-y_wrap;
4045 switch (par->vmode & FB_VMODE_MASK) {
4046 case FB_VMODE_INTERLACED:
4047 line >>= 1;
4048 break;
4049 case FB_VMODE_DOUBLE:
4050 line <<= 1;
4051 break;
4052 }
4053 line += par->diwstrt_v;
4054
4055
4056
4057 while (line > 256) {
4058
4059 cop->rest[j++].l = CWAIT(par->htotal-4, 255);
4060
4061 cop->rest[j++].l = CWAIT(0, 0);
4062 line -= 256;
4063 }
4064 cop->rest[j++].l = CWAIT(par->htotal-11, line-1);
4065
4066 for (i = 0, p = bplpt0; i < par->bpp; i++, p += par->next_plane) {
4067 cop->rest[j++].l = CMOVE(highw(p), bplpt[i]);
4068 cop->rest[j++].l = CMOVE2(loww(p), bplpt[i]);
4069 }
4070 }
4071
4072 if (othercop) {
4073 p = ZTWO_PADDR(othercop);
4074 cop->rest[j++].l = CMOVE(highw(p), cop2lc);
4075 cop->rest[j++].l = CMOVE2(loww(p), cop2lc);
4076 }
4077
4078
4079 cop->rest[j++].l = CEND;
4080
4081 if (j > arraysize(cop->rest))
4082 printk("aga_build_clist_dyn: copper list overflow (%d entries)\n", j);
4083 }
4084 #endif
4085
4086
4087
4088
4089
4090 #ifdef CONFIG_AMIFB_OCS
4091 static struct fb_hwswitch ocs_switch = {
4092 ocs_init, ocs_encode_fix, ocs_decode_var, ocs_encode_var, ocs_getcolreg,
4093 ocs_setcolreg, ocs_pan_display, ocs_do_vmode, ocs_do_blank,
4094 ocs_do_movecursor, ocs_do_flashcursor
4095 };
4096 #endif
4097
4098 #ifdef CONFIG_AMIFB_ECS
4099 static struct fb_hwswitch ecs_switch = {
4100 ecs_init, ecs_encode_fix, ecs_decode_var, ecs_encode_var, ecs_getcolreg,
4101 ecs_setcolreg, ecs_pan_display, ecs_do_vmode, ecs_do_blank,
4102 ecs_do_movecursor, ecs_do_flashcursor
4103 };
4104 #endif
4105
4106 #ifdef CONFIG_AMIFB_AGA
4107 static struct fb_hwswitch aga_switch = {
4108 aga_init, aga_encode_fix, aga_decode_var, aga_encode_var, aga_getcolreg,
4109 aga_setcolreg, aga_pan_display, aga_do_vmode, aga_do_blank,
4110 aga_do_movecursor, aga_do_flashcursor
4111 };
4112 #endif
4113
4114
4115
4116
4117
4118
4119
4120
4121
4122 static u_long chipalloc(u_long size)
4123 {
4124 u_long ptr;
4125
4126 size += PAGE_SIZE-1;
4127 if (!(ptr = (u_long)amiga_chip_alloc(size)))
4128 panic("No Chip RAM for frame buffer");
4129 memset((void *)ptr, 0, size);
4130 ptr = PAGE_ALIGN(ptr);
4131
4132 return(ptr);
4133 }
4134
4135
4136
4137
4138
4139
4140 static void amiga_fb_get_par(struct amiga_fb_par *par)
4141 {
4142 if (current_par_valid)
4143 *par = current_par;
4144 else
4145 fbhw->decode_var(&amiga_fb_predefined[amifb_mode], par);
4146 }
4147
4148
4149 static void amiga_fb_set_par(struct amiga_fb_par *par)
4150 {
4151 do_vmode = 0;
4152 current_par = *par;
4153 full_vmode_change = 1;
4154 do_vmode = 1;
4155 current_par_valid = 1;
4156 }
4157
4158
4159 static int do_fb_set_var(struct fb_var_screeninfo *var, int isactive)
4160 {
4161 int err, activate;
4162 struct amiga_fb_par par;
4163
4164 if ((err = fbhw->decode_var(var, &par)))
4165 return(err);
4166 activate = var->activate;
4167 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW && isactive)
4168 amiga_fb_set_par(&par);
4169 fbhw->encode_var(var, &par);
4170 var->activate = activate;
4171 return(0);
4172 }
4173
4174
4175
4176
4177
4178
4179 static u_short red2[] =
4180 { 0x0000, 0xc000 };
4181 static u_short green2[] =
4182 { 0x0000, 0xc000 };
4183 static u_short blue2[] =
4184 { 0x0000, 0xc000 };
4185
4186 static u_short red4[] =
4187 { 0x0000, 0xc000, 0x8000, 0xffff };
4188 static u_short green4[] =
4189 { 0x0000, 0xc000, 0x8000, 0xffff };
4190 static u_short blue4[] =
4191 { 0x0000, 0xc000, 0x8000, 0xffff };
4192
4193 static u_short red8[] =
4194 { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000 };
4195 static u_short green8[] =
4196 { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000 };
4197 static u_short blue8[] =
4198 { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000 };
4199
4200 static u_short red16[] =
4201 { 0x0000, 0x0000, 0x0000, 0x0000, 0xc000, 0xc000, 0xc000, 0xc000,
4202 0x8000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff };
4203 static u_short green16[] =
4204 { 0x0000, 0x0000, 0xc000, 0xc000, 0x0000, 0x0000, 0xc000, 0xc000,
4205 0x8000, 0x0000, 0xffff, 0xffff, 0x0000, 0x0000, 0xffff, 0xffff };
4206 static u_short blue16[] =
4207 { 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000, 0x0000, 0xc000,
4208 0x8000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff, 0x0000, 0xffff };
4209
4210
4211 static struct fb_cmap default_2_colors =
4212 { 0, 2, red2, green2, blue2, NULL };
4213 static struct fb_cmap default_8_colors =
4214 { 0, 8, red8, green8, blue8, NULL };
4215 static struct fb_cmap default_4_colors =
4216 { 0, 4, red4, green4, blue4, NULL };
4217 static struct fb_cmap default_16_colors =
4218 { 0, 16, red16, green16, blue16, NULL };
4219
4220
4221 static struct fb_cmap *get_default_colormap(int bpp)
4222 {
4223 switch (bpp) {
4224 case 1:
4225 return(&default_2_colors);
4226 break;
4227 case 2:
4228 return(&default_4_colors);
4229 break;
4230 case 3:
4231 return(&default_8_colors);
4232 break;
4233 default:
4234 return(&default_16_colors);
4235 break;
4236 }
4237 }
4238
4239
4240 #define CNVT_TOHW(val,width) ((((val)<<(width))+0x7fff-(val))>>16)
4241 #define CNVT_FROMHW(val,width) (((width) ? ((((val)<<16)-(val)) / \
4242 ((1<<(width))-1)) : 0))
4243
4244 static int do_fb_get_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4245 int kspc)
4246 {
4247 int i, start;
4248 u_short *red, *green, *blue, *transp;
4249 u_int hred, hgreen, hblue, htransp;
4250
4251 red = cmap->red;
4252 green = cmap->green;
4253 blue = cmap->blue;
4254 transp = cmap->transp;
4255 start = cmap->start;
4256 if (start < 0)
4257 return(-EINVAL);
4258 for (i = 0; i < cmap->len; i++) {
4259 if (fbhw->getcolreg(start++, &hred, &hgreen, &hblue, &htransp))
4260 return(0);
4261 hred = CNVT_FROMHW(hred, var->red.length);
4262 hgreen = CNVT_FROMHW(hgreen, var->green.length);
4263 hblue = CNVT_FROMHW(hblue, var->blue.length);
4264 htransp = CNVT_FROMHW(htransp, var->transp.length);
4265 if (kspc) {
4266 *red = hred;
4267 *green = hgreen;
4268 *blue = hblue;
4269 if (transp)
4270 *transp = htransp;
4271 } else {
4272 put_fs_word(hred, red);
4273 put_fs_word(hgreen, green);
4274 put_fs_word(hblue, blue);
4275 if (transp)
4276 put_fs_word(htransp, transp);
4277 }
4278 red++;
4279 green++;
4280 blue++;
4281 if (transp)
4282 transp++;
4283 }
4284 return(0);
4285 }
4286
4287
4288 static int do_fb_set_cmap(struct fb_cmap *cmap, struct fb_var_screeninfo *var,
4289 int kspc)
4290 {
4291 int i, start;
4292 u_short *red, *green, *blue, *transp;
4293 u_int hred, hgreen, hblue, htransp;
4294
4295 red = cmap->red;
4296 green = cmap->green;
4297 blue = cmap->blue;
4298 transp = cmap->transp;
4299 start = cmap->start;
4300
4301 if (start < 0)
4302 return(-EINVAL);
4303 for (i = 0; i < cmap->len; i++) {
4304 if (kspc) {
4305 hred = *red;
4306 hgreen = *green;
4307 hblue = *blue;
4308 htransp = transp ? *transp : 0;
4309 } else {
4310 hred = get_fs_word(red);
4311 hgreen = get_fs_word(green);
4312 hblue = get_fs_word(blue);
4313 htransp = transp ? get_fs_word(transp) : 0;
4314 }
4315 hred = CNVT_TOHW(hred, var->red.length);
4316 hgreen = CNVT_TOHW(hgreen, var->green.length);
4317 hblue = CNVT_TOHW(hblue, var->blue.length);
4318 htransp = CNVT_TOHW(htransp, var->transp.length);
4319 red++;
4320 green++;
4321 blue++;
4322 if (transp)
4323 transp++;
4324 if (fbhw->setcolreg(start++, hred, hgreen, hblue, htransp))
4325 return(0);
4326 }
4327 return(0);
4328 }
4329
4330
4331 static void do_install_cmap(int con)
4332 {
4333 if (con != currcon)
4334 return;
4335 if (disp[con].cmap.len)
4336 do_fb_set_cmap(&disp[con].cmap, &disp[con].var, 1);
4337 else
4338 do_fb_set_cmap(get_default_colormap(disp[con].var.bits_per_pixel),
4339 &disp[con].var, 1);
4340 }
4341
4342
4343 static void memcpy_fs(int fsfromto, void *to, void *from, int len)
4344 {
4345 switch (fsfromto) {
4346 case 0:
4347 memcpy(to, from, len);
4348 return;
4349 case 1:
4350 memcpy_fromfs(to, from, len);
4351 return;
4352 case 2:
4353 memcpy_tofs(to, from, len);
4354 return;
4355 }
4356 }
4357
4358
4359 static void copy_cmap(struct fb_cmap *from, struct fb_cmap *to, int fsfromto)
4360 {
4361 int size;
4362 int tooff = 0, fromoff = 0;
4363
4364 if (to->start > from->start)
4365 fromoff = to->start-from->start;
4366 else
4367 tooff = from->start-to->start;
4368 size = to->len-tooff;
4369 if (size > from->len-fromoff)
4370 size = from->len-fromoff;
4371 if (size < 0)
4372 return;
4373 size *= sizeof(u_short);
4374 memcpy_fs(fsfromto, to->red+tooff, from->red+fromoff, size);
4375 memcpy_fs(fsfromto, to->green+tooff, from->green+fromoff, size);
4376 memcpy_fs(fsfromto, to->blue+tooff, from->blue+fromoff, size);
4377 if (from->transp && to->transp)
4378 memcpy_fs(fsfromto, to->transp+tooff, from->transp+fromoff, size);
4379 }
4380
4381
4382 static int alloc_cmap(struct fb_cmap *cmap, int len, int transp)
4383 {
4384 int size = len*sizeof(u_short);
4385
4386 if (cmap->len != len) {
4387 if (cmap->red)
4388 kfree(cmap->red);
4389 if (cmap->green)
4390 kfree(cmap->green);
4391 if (cmap->blue)
4392 kfree(cmap->blue);
4393 if (cmap->transp)
4394 kfree(cmap->transp);
4395 cmap->red = cmap->green = cmap->blue = cmap->transp = NULL;
4396 cmap->len = 0;
4397 if (!len)
4398 return(0);
4399 if (!(cmap->red = kmalloc(size, GFP_ATOMIC)))
4400 return(-1);
4401 if (!(cmap->green = kmalloc(size, GFP_ATOMIC)))
4402 return(-1);
4403 if (!(cmap->blue = kmalloc(size, GFP_ATOMIC)))
4404 return(-1);
4405 if (transp) {
4406 if (!(cmap->transp = kmalloc(size, GFP_ATOMIC)))
4407 return(-1);
4408 } else
4409 cmap->transp = NULL;
4410 }
4411 cmap->start = 0;
4412 cmap->len = len;
4413 copy_cmap(get_default_colormap(len), cmap, 0);
4414 return(0);
4415 }
4416
4417
4418
4419
4420
4421
4422 static int amiga_fb_get_fix(struct fb_fix_screeninfo *fix, int con)
4423 {
4424 struct amiga_fb_par par;
4425 int error = 0;
4426
4427 if (con == -1)
4428 amiga_fb_get_par(&par);
4429 else
4430 error = fbhw->decode_var(&disp[con].var, &par);
4431 return(error ? error : fbhw->encode_fix(fix, &par));
4432 }
4433
4434
4435
4436
4437
4438
4439 static int amiga_fb_get_var(struct fb_var_screeninfo *var, int con)
4440 {
4441 struct amiga_fb_par par;
4442 int error = 0;
4443
4444 if (con == -1) {
4445 amiga_fb_get_par(&par);
4446 error = fbhw->encode_var(var, &par);
4447 } else
4448 *var = disp[con].var;
4449 return(error);
4450 }
4451
4452
4453 static void amiga_fb_set_disp(int con)
4454 {
4455 struct fb_fix_screeninfo fix;
4456
4457 amiga_fb_get_fix(&fix, con);
4458 if (con == -1)
4459 con = 0;
4460 disp[con].screen_base = (u_char *)fix.smem_start;
4461 disp[con].visual = fix.visual;
4462 disp[con].type = fix.type;
4463 disp[con].type_aux = fix.type_aux;
4464 disp[con].ypanstep = fix.ypanstep;
4465 disp[con].ywrapstep = fix.ywrapstep;
4466 disp[con].line_length = fix.line_length;
4467 disp[con].can_soft_blank = 1;
4468 disp[con].inverse = amifb_inverse;
4469 }
4470
4471
4472
4473
4474
4475
4476 static int amiga_fb_set_var(struct fb_var_screeninfo *var, int con)
4477 {
4478 int err, oldxres, oldyres, oldvxres, oldvyres, oldbpp;
4479
4480 if ((err = do_fb_set_var(var, con == currcon)))
4481 return(err);
4482 if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
4483 oldxres = disp[con].var.xres;
4484 oldyres = disp[con].var.yres;
4485 oldvxres = disp[con].var.xres_virtual;
4486 oldvyres = disp[con].var.yres_virtual;
4487 oldbpp = disp[con].var.bits_per_pixel;
4488 disp[con].var = *var;
4489 if (oldxres != var->xres || oldyres != var->yres ||
4490 oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||
4491 oldbpp != var->bits_per_pixel) {
4492 amiga_fb_set_disp(con);
4493 (*fb_info.changevar)(con);
4494 alloc_cmap(&disp[con].cmap, 0, 0);
4495 do_install_cmap(con);
4496 }
4497 }
4498 var->activate = 0;
4499 return(0);
4500 }
4501
4502
4503
4504
4505
4506
4507 static int amiga_fb_get_cmap(struct fb_cmap *cmap, int kspc, int con)
4508 {
4509 if (con == currcon)
4510 return(do_fb_get_cmap(cmap, &disp[con].var, kspc));
4511 else if (disp[con].cmap.len)
4512 copy_cmap(&disp[con].cmap, cmap, kspc ? 0 : 2);
4513 else
4514 copy_cmap(get_default_colormap(disp[con].var.bits_per_pixel), cmap,
4515 kspc ? 0 : 2);
4516 return(0);
4517 }
4518
4519
4520
4521
4522
4523
4524 static int amiga_fb_set_cmap(struct fb_cmap *cmap, int kspc, int con)
4525 {
4526 int err;
4527
4528 if (!disp[con].cmap.len) {
4529 if ((err = alloc_cmap(&disp[con].cmap, 1<<disp[con].var.bits_per_pixel,
4530 0)))
4531 return(err);
4532 }
4533 if (con == currcon)
4534 return(do_fb_set_cmap(cmap, &disp[con].var, kspc));
4535 else
4536 copy_cmap(cmap, &disp[con].cmap, kspc ? 0 : 1);
4537 return(0);
4538 }
4539
4540
4541
4542
4543
4544
4545
4546
4547 static int amiga_fb_pan_display(struct fb_var_screeninfo *var, int con)
4548 {
4549 int err;
4550 u_short oldlatch;
4551
4552 if (var->vmode & FB_VMODE_YWRAP) {
4553 if (var->xoffset || var->yoffset >= disp[con].var.yres)
4554 return(-EINVAL);
4555 } else {
4556 if (var->xoffset+disp[con].var.xres > disp[con].var.xres_virtual ||
4557 var->yoffset+disp[con].var.yres > disp[con].var.yres_virtual)
4558 return(-EINVAL);
4559 }
4560 if (con == currcon) {
4561 cli();
4562 oldlatch = do_vmode;
4563 do_vmode = 0;
4564 sti();
4565 if ((err = fbhw->pan_display(var, ¤t_par))) {
4566 if (oldlatch)
4567 do_vmode = 1;
4568 return(err);
4569 }
4570 do_vmode = 1;
4571 }
4572 disp[con].var.xoffset = var->xoffset;
4573 disp[con].var.yoffset = var->yoffset;
4574 if (var->vmode & FB_VMODE_YWRAP)
4575 disp[con].var.vmode |= FB_VMODE_YWRAP;
4576 else
4577 disp[con].var.vmode &= ~FB_VMODE_YWRAP;
4578 return(0);
4579 }
4580
4581
4582
4583
4584
4585
4586 static int amiga_fb_ioctl(struct inode *inode, struct file *file,
4587 u_int cmd, u_long arg, int con)
4588 {
4589 int i;
4590 struct fb_fix_cursorinfo crsrfix;
4591 struct fb_var_cursorinfo crsrvar;
4592 struct fb_cursorstate crsrstate;
4593
4594 switch (cmd) {
4595 #ifdef CONFIG_AMIFB_AGA
4596 case FBIOGET_FCURSORINFO:
4597 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrfix));
4598 if (i)
4599 return(i);
4600 i = amiga_fb_get_fix_cursorinfo(&crsrfix, con);
4601 memcpy_tofs((void *)arg, &crsrfix, sizeof(crsrfix));
4602 return(i);
4603 case FBIOGET_VCURSORINFO:
4604 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrvar));
4605 if (i)
4606 return(i);
4607 i = amiga_fb_get_var_cursorinfo(&crsrvar, con);
4608 memcpy_tofs((void *)arg, &crsrvar, sizeof(crsrvar));
4609 return(i);
4610 case FBIOPUT_VCURSORINFO:
4611 i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrvar));
4612 if (i)
4613 return(i);
4614 memcpy_fromfs(&crsrvar, (void *)arg, sizeof(crsrvar));
4615 i = amiga_fb_set_var_cursorinfo(&crsrvar, con);
4616 return(i);
4617 case FBIOGET_CURSORSTATE:
4618 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(crsrstate));
4619 if (i)
4620 return(i);
4621 i = amiga_fb_get_cursorstate(&crsrstate, con);
4622 memcpy_tofs((void *)arg, &crsrstate, sizeof(crsrstate));
4623 return(i);
4624 case FBIOPUT_CURSORSTATE:
4625 i = verify_area(VERIFY_READ, (void *)arg, sizeof(crsrstate));
4626 if (i)
4627 return(i);
4628 memcpy_fromfs(&crsrstate, (void *)arg, sizeof(crsrstate));
4629 i = amiga_fb_set_cursorstate(&crsrstate, con);
4630 return(i);
4631 #endif
4632 #if 1
4633 case FBCMD_GET_CURRENTPAR:
4634 if ((i = verify_area(VERIFY_WRITE, (void *)arg,
4635 sizeof(struct amiga_fb_par))))
4636 return(i);
4637 memcpy_tofs((void *)arg, (void *)¤t_par,
4638 sizeof(struct amiga_fb_par));
4639 return(0);
4640 break;
4641 case FBCMD_SET_CURRENTPAR:
4642 if ((i = verify_area(VERIFY_READ, (void *)arg,
4643 sizeof(struct amiga_fb_par))))
4644 return(i);
4645 memcpy_fromfs((void *)¤t_par, (void *)arg,
4646 sizeof(struct amiga_fb_par));
4647 return(0);
4648 break;
4649 #endif
4650 }
4651 return(-EINVAL);
4652 }
4653
4654
4655 #ifdef CONFIG_AMIFB_AGA
4656
4657
4658
4659
4660 static int amiga_fb_get_fix_cursorinfo(struct fb_fix_cursorinfo *fix, int con)
4661 {
4662 if (boot_info.bi_amiga.chipset == CS_AGA)
4663 return(aga_get_fix_cursorinfo(fix, con));
4664 return(-EINVAL);
4665 }
4666
4667
4668 static int amiga_fb_get_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4669 {
4670 if (boot_info.bi_amiga.chipset == CS_AGA)
4671 return(aga_get_var_cursorinfo(var, con));
4672 return(-EINVAL);
4673 }
4674
4675
4676 static int amiga_fb_set_var_cursorinfo(struct fb_var_cursorinfo *var, int con)
4677 {
4678 if (boot_info.bi_amiga.chipset == CS_AGA)
4679 return(aga_set_var_cursorinfo(var, con));
4680 return(-EINVAL);
4681 }
4682
4683
4684 static int amiga_fb_get_cursorstate(struct fb_cursorstate *state, int con)
4685 {
4686 if (boot_info.bi_amiga.chipset == CS_AGA)
4687 return(aga_get_cursorstate(state, con));
4688 return(-EINVAL);
4689 }
4690
4691
4692 static int amiga_fb_set_cursorstate(struct fb_cursorstate *state, int con)
4693 {
4694 if (boot_info.bi_amiga.chipset == CS_AGA)
4695 return(aga_set_cursorstate(state, con));
4696 return(-EINVAL);
4697 }
4698 #endif
4699
4700
4701 static struct fb_ops amiga_fb_ops = {
4702 amiga_fb_get_fix, amiga_fb_get_var, amiga_fb_set_var, amiga_fb_get_cmap,
4703 amiga_fb_set_cmap, amiga_fb_pan_display, amiga_fb_ioctl
4704 };
4705
4706
4707 void amiga_video_setup(char *options, int *ints)
4708 {
4709 char *this_opt;
4710 int i;
4711 char mcap_spec[80];
4712
4713
4714
4715
4716
4717 #ifdef CONFIG_FB_CYBER
4718 if (options && *options)
4719 if (!strncmp(options, "cyber", 5) && Cyber_probe()) {
4720 amifb_Cyber = 1;
4721 Cyber_video_setup(options, ints);
4722 return;
4723 }
4724 #endif
4725
4726 #ifdef USE_MONO_AMIFB_IF_NON_AGA
4727 if (boot_info.bi_amiga.chipset != CS_AGA) {
4728 mono_video_setup(options, ints);
4729 return;
4730 }
4731 #endif
4732
4733 mcap_spec[0] = '\0';
4734 fb_info.fontname[0] = '\0';
4735
4736 if (!options || !*options)
4737 return;
4738
4739 for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ","))
4740 if (!strcmp(this_opt, "inverse")) {
4741 amifb_inverse = 1;
4742 for (i = 0; i < 16; i++) {
4743 red16[i] = ~red16[i];
4744 green16[i] = ~green16[i];
4745 blue16[i] = ~blue16[i];
4746 }
4747 for (i = 0; i < 8; i++) {
4748 red8[i] = ~red8[i];
4749 green8[i] = ~green8[i];
4750 blue8[i] = ~blue8[i];
4751 }
4752 for (i = 0; i < 4; i++) {
4753 red4[i] = ~red4[i];
4754 green4[i] = ~green4[i];
4755 blue4[i] = ~blue4[i];
4756 }
4757 for (i = 0; i < 2; i++) {
4758 red2[i] = ~red2[i];
4759 green2[i] = ~green2[i];
4760 blue2[i] = ~blue2[i];
4761 }
4762 } else if (!strcmp(this_opt, "ilbm"))
4763 amifb_ilbm = 1;
4764 else if (!strcmp(this_opt, "pwrsave"))
4765 pwrsave = 1;
4766 else if (!strncmp(this_opt, "monitorcap:", 11))
4767 strcpy(mcap_spec, this_opt+11);
4768 else if (!strncmp(this_opt, "font:", 5))
4769 strcpy(fb_info.fontname, this_opt+5);
4770 else
4771 amifb_mode = get_video_mode(this_opt);
4772
4773 if (*mcap_spec) {
4774 char *p;
4775 int vmin, vmax, hmin, hmax;
4776
4777
4778
4779
4780
4781
4782 if (!(p = strtoke(mcap_spec, ";")) || !*p)
4783 goto cap_invalid;
4784 vmin = simple_strtoul(p, NULL, 10);
4785 if (vmin <= 0)
4786 goto cap_invalid;
4787 if (!(p = strtoke(NULL, ";")) || !*p)
4788 goto cap_invalid;
4789 vmax = simple_strtoul(p, NULL, 10);
4790 if (vmax <= 0 || vmax <= vmin)
4791 goto cap_invalid;
4792 if (!(p = strtoke(NULL, ";")) || !*p)
4793 goto cap_invalid;
4794 hmin = 1000 * simple_strtoul(p, NULL, 10);
4795 if (hmin <= 0)
4796 goto cap_invalid;
4797 if (!(p = strtoke(NULL, "")) || !*p)
4798 goto cap_invalid;
4799 hmax = 1000 * simple_strtoul(p, NULL, 10);
4800 if (hmax <= 0 || hmax <= hmin)
4801 goto cap_invalid;
4802
4803 vfmin = vmin;
4804 vfmax = vmax;
4805 hfmin = hmin;
4806 hfmax = hmax;
4807 cap_invalid:
4808 ;
4809 }
4810 }
4811
4812
4813
4814
4815
4816
4817 struct fb_info *amiga_fb_init(long *mem_start)
4818 {
4819 int err, tag, i;
4820 struct fb_var_screeninfo *var;
4821
4822
4823
4824
4825
4826 #ifdef CONFIG_FB_CYBER
4827 if (amifb_Cyber)
4828 return(Cyber_fb_init(mem_start));
4829 #endif
4830
4831
4832
4833
4834
4835 if (!AMIGAHW_PRESENT(AMI_VIDEO))
4836 return(NULL);
4837
4838 #ifdef USE_MONO_AMIFB_IF_NON_AGA
4839 if (boot_info.bi_amiga.chipset != CS_AGA)
4840 return(mono_amiga_fb_init(mem_start));
4841 #endif
4842
4843 switch (boot_info.bi_amiga.chipset) {
4844 #ifdef CONFIG_AMIFB_OCS
4845 case CS_OCS:
4846 strcat(amiga_fb_name, "OCS");
4847 default_chipset:
4848 fbhw = &ocs_switch;
4849 maxdepth[TAG_SHRES-1] = 0;
4850 maxdepth[TAG_HIRES-1] = 4;
4851 maxdepth[TAG_LORES-1] = 6;
4852 break;
4853 #endif
4854
4855 #ifdef CONFIG_AMIFB_ECS
4856 case CS_ECS:
4857 strcat(amiga_fb_name, "ECS");
4858 fbhw = &ecs_switch;
4859 maxdepth[TAG_SHRES-1] = 2;
4860 maxdepth[TAG_HIRES-1] = 4;
4861 maxdepth[TAG_LORES-1] = 6;
4862 break;
4863 #endif
4864
4865 #ifdef CONFIG_AMIFB_AGA
4866 case CS_AGA:
4867 strcat(amiga_fb_name, "AGA");
4868 fbhw = &aga_switch;
4869 maxdepth[TAG_SHRES-1] = 8;
4870 maxdepth[TAG_HIRES-1] = 8;
4871 maxdepth[TAG_LORES-1] = 8;
4872 break;
4873 #endif
4874
4875 default:
4876 #ifdef CONFIG_AMIFB_OCS
4877 printk("Unknown graphics chipset, defaulting to OCS\n");
4878 strcat(amiga_fb_name, "Unknown");
4879 goto default_chipset;
4880 #else
4881 panic("Unknown graphics chipset, no default driver");
4882 #endif
4883 break;
4884 }
4885
4886
4887
4888
4889
4890 pixclock[TAG_SHRES-1] = 25E9/amiga_eclock;
4891 pixclock[TAG_HIRES-1] = 50E9/amiga_eclock;
4892 pixclock[TAG_LORES-1] = 100E9/amiga_eclock;
4893
4894
4895
4896
4897
4898 for (i = 0; i < NUM_PREDEF_MODES; i++) {
4899 tag = amiga_fb_predefined[i].pixclock;
4900 if (tag == TAG_SHRES || tag == TAG_HIRES || tag == TAG_LORES) {
4901 amiga_fb_predefined[i].pixclock = pixclock[tag-1];
4902 if (amiga_fb_predefined[i].bits_per_pixel > maxdepth[tag-1])
4903 amiga_fb_predefined[i].bits_per_pixel = maxdepth[tag-1];
4904 }
4905 }
4906
4907 err = register_framebuffer(amiga_fb_name, &node, &amiga_fb_ops,
4908 NUM_TOTAL_MODES, amiga_fb_predefined);
4909 if (err < 0)
4910 panic("Cannot register frame buffer");
4911
4912 fbhw->init();
4913 check_default_mode();
4914
4915 if (!add_isr(IRQ_AMIGA_VERTB, amifb_interrupt, 0, NULL, "frame buffer"))
4916 panic("Couldn't add vblank interrupt");
4917
4918 strcpy(fb_info.modename, amiga_fb_name);
4919 fb_info.disp = disp;
4920 fb_info.switch_con = &amifb_switch;
4921 fb_info.updatevar = &amifb_updatevar;
4922 fb_info.blank = &amifb_blank;
4923
4924 var = &amiga_fb_predefined[amifb_mode];
4925 do_fb_set_var(var, 1);
4926 strcat(fb_info.modename, " ");
4927 strcat(fb_info.modename, amiga_fb_modenames[amifb_mode]);
4928
4929 amiga_fb_get_var(&disp[0].var, -1);
4930 amiga_fb_set_disp(-1);
4931 do_install_cmap(0);
4932 return(&fb_info);
4933 }
4934
4935
4936 static int amifb_switch(int con)
4937 {
4938
4939 if (disp[currcon].cmap.len)
4940 do_fb_get_cmap(&disp[currcon].cmap, &disp[currcon].var, 1);
4941
4942 do_fb_set_var(&disp[con].var, 1);
4943 currcon = con;
4944
4945 do_install_cmap(con);
4946 return(0);
4947 }
4948
4949
4950
4951
4952
4953
4954
4955
4956
4957 static int amifb_updatevar(int con)
4958 {
4959 do_vmode = 0;
4960 current_par.yoffset = disp[con].var.yoffset;
4961 current_par.vmode = disp[con].var.vmode;
4962 current_par.bplpt0 = ZTWO_PADDR((u_long)videomemory+
4963 current_par.yoffset*current_par.next_line);
4964 do_vmode = 1;
4965 return(0);
4966 }
4967
4968
4969
4970
4971
4972
4973 static void amifb_blank(int blank)
4974 {
4975 do_blank = blank ? 1 : -1;
4976 }
4977
4978
4979
4980
4981
4982
4983 static void amifb_interrupt(int irq, struct pt_regs *fp, void *dummy)
4984 {
4985 static int is_laced = 0;
4986
4987 #if 0
4988
4989
4990
4991
4992
4993
4994
4995 if (!current_par_valid)
4996 return;
4997 #endif
4998
4999
5000
5001
5002
5003 if (!is_laced || custom.vposr & 0x8000) {
5004 if (do_vmode) {
5005 fbhw->do_vmode();
5006 do_vmode = 0;
5007 is_laced = (current_par.vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED;
5008 }
5009 if (do_movecursor) {
5010 fbhw->do_movecursor();
5011 do_movecursor = 0;
5012 }
5013 }
5014 if (do_blank) {
5015 fbhw->do_blank(do_blank > 0 ? 1 : 0);
5016 do_blank = 0;
5017 }
5018 if (!is_blanked)
5019 fbhw->do_flashcursor();
5020 }
5021
5022
5023
5024
5025
5026
5027 static char * strtoke(char * s,const char * ct)
5028 {
5029 char *sbegin, *send;
5030 static char *ssave = NULL;
5031
5032 sbegin = s ? s : ssave;
5033 if (!sbegin)
5034 return(NULL);
5035 if (*sbegin == '\0') {
5036 ssave = NULL;
5037 return(NULL);
5038 }
5039 send = strpbrk(sbegin, ct);
5040 if (send && *send != '\0')
5041 *send++ = '\0';
5042 ssave = send;
5043 return(sbegin);
5044 }
5045
5046
5047
5048
5049
5050
5051 static int get_video_mode(const char *name)
5052 {
5053 int i;
5054
5055 for (i = 1; i < NUM_PREDEF_MODES; i++)
5056 if (!strcmp(name, amiga_fb_modenames[i]))
5057 return(i);
5058 return(0);
5059 }
5060
5061
5062
5063
5064
5065
5066 static void check_default_mode(void)
5067 {
5068 struct fb_var_screeninfo var;
5069
5070
5071 if (amifb_mode) {
5072 var = amiga_fb_predefined[amifb_mode];
5073 var.activate = FB_ACTIVATE_TEST;
5074 if (!do_fb_set_var(&var, 1))
5075 goto found_video_mode;
5076 }
5077
5078
5079 printk("Can't use default video mode. Probing video modes...\n");
5080 for (amifb_mode = 1; amifb_mode < NUM_PREDEF_MODES; amifb_mode++) {
5081 var = amiga_fb_predefined[amifb_mode];
5082 var.activate = FB_ACTIVATE_TEST;
5083 if (!do_fb_set_var(&var, 1))
5084 goto found_video_mode;
5085 }
5086 panic("Can't find any usable video mode");
5087
5088 found_video_mode:
5089 amiga_fb_predefined[0] = var;
5090 }