pre-2.1.132-4..
[davej-history.git] / drivers / video / cgsixfb.c
blob2891b4877419211e889c4e0bac7977f525a32789
1 /* $Id: cgsixfb.c,v 1.12 1998/11/27 00:02:04 anton Exp $
2 * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver
4 * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz)
5 * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx)
6 * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be)
7 */
9 #include <linux/module.h>
10 #include <linux/sched.h>
11 #include <linux/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
14 #include <linux/mm.h>
15 #include <linux/tty.h>
16 #include <linux/malloc.h>
17 #include <linux/vmalloc.h>
18 #include <linux/delay.h>
19 #include <linux/interrupt.h>
20 #include <linux/fb.h>
21 #include <linux/init.h>
22 #include <linux/selection.h>
24 #include <video/sbusfb.h>
25 #include <asm/io.h>
27 /* Offset of interesting structures in the OBIO space */
29 * Brooktree is the video dac and is funny to program on the cg6.
30 * (it's even funnier on the cg3)
31 * The FBC could be the frame buffer control
32 * The FHC could is the frame buffer hardware control.
34 #define CG6_ROM_OFFSET 0x0
35 #define CG6_BROOKTREE_OFFSET 0x200000
36 #define CG6_DHC_OFFSET 0x240000
37 #define CG6_ALT_OFFSET 0x280000
38 #define CG6_FHC_OFFSET 0x300000
39 #define CG6_THC_OFFSET 0x301000
40 #define CG6_FBC_OFFSET 0x700000
41 #define CG6_TEC_OFFSET 0x701000
42 #define CG6_RAM_OFFSET 0x800000
44 /* FHC definitions */
45 #define CG6_FHC_FBID_SHIFT 24
46 #define CG6_FHC_FBID_MASK 255
47 #define CG6_FHC_REV_SHIFT 20
48 #define CG6_FHC_REV_MASK 15
49 #define CG6_FHC_FROP_DISABLE (1 << 19)
50 #define CG6_FHC_ROW_DISABLE (1 << 18)
51 #define CG6_FHC_SRC_DISABLE (1 << 17)
52 #define CG6_FHC_DST_DISABLE (1 << 16)
53 #define CG6_FHC_RESET (1 << 15)
54 #define CG6_FHC_LITTLE_ENDIAN (1 << 13)
55 #define CG6_FHC_RES_MASK (3 << 11)
56 #define CG6_FHC_1024 (0 << 11)
57 #define CG6_FHC_1152 (1 << 11)
58 #define CG6_FHC_1280 (2 << 11)
59 #define CG6_FHC_1600 (3 << 11)
60 #define CG6_FHC_CPU_MASK (3 << 9)
61 #define CG6_FHC_CPU_SPARC (0 << 9)
62 #define CG6_FHC_CPU_68020 (1 << 9)
63 #define CG6_FHC_CPU_386 (2 << 9)
64 #define CG6_FHC_TEST (1 << 8)
65 #define CG6_FHC_TEST_X_SHIFT 4
66 #define CG6_FHC_TEST_X_MASK 15
67 #define CG6_FHC_TEST_Y_SHIFT 0
68 #define CG6_FHC_TEST_Y_MASK 15
70 /* FBC mode definitions */
71 #define CG6_FBC_BLIT_IGNORE 0x00000000
72 #define CG6_FBC_BLIT_NOSRC 0x00100000
73 #define CG6_FBC_BLIT_SRC 0x00200000
74 #define CG6_FBC_BLIT_ILLEGAL 0x00300000
75 #define CG6_FBC_BLIT_MASK 0x00300000
77 #define CG6_FBC_VBLANK 0x00080000
79 #define CG6_FBC_MODE_IGNORE 0x00000000
80 #define CG6_FBC_MODE_COLOR8 0x00020000
81 #define CG6_FBC_MODE_COLOR1 0x00040000
82 #define CG6_FBC_MODE_HRMONO 0x00060000
83 #define CG6_FBC_MODE_MASK 0x00060000
85 #define CG6_FBC_DRAW_IGNORE 0x00000000
86 #define CG6_FBC_DRAW_RENDER 0x00008000
87 #define CG6_FBC_DRAW_PICK 0x00010000
88 #define CG6_FBC_DRAW_ILLEGAL 0x00018000
89 #define CG6_FBC_DRAW_MASK 0x00018000
91 #define CG6_FBC_BWRITE0_IGNORE 0x00000000
92 #define CG6_FBC_BWRITE0_ENABLE 0x00002000
93 #define CG6_FBC_BWRITE0_DISABLE 0x00004000
94 #define CG6_FBC_BWRITE0_ILLEGAL 0x00006000
95 #define CG6_FBC_BWRITE0_MASK 0x00006000
97 #define CG6_FBC_BWRITE1_IGNORE 0x00000000
98 #define CG6_FBC_BWRITE1_ENABLE 0x00000800
99 #define CG6_FBC_BWRITE1_DISABLE 0x00001000
100 #define CG6_FBC_BWRITE1_ILLEGAL 0x00001800
101 #define CG6_FBC_BWRITE1_MASK 0x00001800
103 #define CG6_FBC_BREAD_IGNORE 0x00000000
104 #define CG6_FBC_BREAD_0 0x00000200
105 #define CG6_FBC_BREAD_1 0x00000400
106 #define CG6_FBC_BREAD_ILLEGAL 0x00000600
107 #define CG6_FBC_BREAD_MASK 0x00000600
109 #define CG6_FBC_BDISP_IGNORE 0x00000000
110 #define CG6_FBC_BDISP_0 0x00000080
111 #define CG6_FBC_BDISP_1 0x00000100
112 #define CG6_FBC_BDISP_ILLEGAL 0x00000180
113 #define CG6_FBC_BDISP_MASK 0x00000180
115 #define CG6_FBC_INDEX_MOD 0x00000040
116 #define CG6_FBC_INDEX_MASK 0x00000030
118 /* THC definitions */
119 #define CG6_THC_MISC_REV_SHIFT 16
120 #define CG6_THC_MISC_REV_MASK 15
121 #define CG6_THC_MISC_RESET (1 << 12)
122 #define CG6_THC_MISC_VIDEO (1 << 10)
123 #define CG6_THC_MISC_SYNC (1 << 9)
124 #define CG6_THC_MISC_VSYNC (1 << 8)
125 #define CG6_THC_MISC_SYNC_ENAB (1 << 7)
126 #define CG6_THC_MISC_CURS_RES (1 << 6)
127 #define CG6_THC_MISC_INT_ENAB (1 << 5)
128 #define CG6_THC_MISC_INT (1 << 4)
129 #define CG6_THC_MISC_INIT 0x9f
131 /* The contents are unknown */
132 struct cg6_tec {
133 volatile int tec_matrix;
134 volatile int tec_clip;
135 volatile int tec_vdc;
138 struct cg6_thc {
139 uint thc_pad0[512];
140 volatile uint thc_hs; /* hsync timing */
141 volatile uint thc_hsdvs;
142 volatile uint thc_hd;
143 volatile uint thc_vs; /* vsync timing */
144 volatile uint thc_vd;
145 volatile uint thc_refresh;
146 volatile uint thc_misc;
147 uint thc_pad1[56];
148 volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */
149 volatile uint thc_cursmask[32]; /* cursor mask bits */
150 volatile uint thc_cursbits[32]; /* what to show where mask enabled */
153 struct cg6_fbc {
154 u32 xxx0[1];
155 volatile u32 mode;
156 volatile u32 clip;
157 u32 xxx1[1];
158 volatile u32 s;
159 volatile u32 draw;
160 volatile u32 blit;
161 volatile u32 font;
162 u32 xxx2[24];
163 volatile u32 x0, y0, z0, color0;
164 volatile u32 x1, y1, z1, color1;
165 volatile u32 x2, y2, z2, color2;
166 volatile u32 x3, y3, z3, color3;
167 volatile u32 offx, offy;
168 u32 xxx3[2];
169 volatile u32 incx, incy;
170 u32 xxx4[2];
171 volatile u32 clipminx, clipminy;
172 u32 xxx5[2];
173 volatile u32 clipmaxx, clipmaxy;
174 u32 xxx6[2];
175 volatile u32 fg;
176 volatile u32 bg;
177 volatile u32 alu;
178 volatile u32 pm;
179 volatile u32 pixelm;
180 u32 xxx7[2];
181 volatile u32 patalign;
182 volatile u32 pattern[8];
183 u32 xxx8[432];
184 volatile u32 apointx, apointy, apointz;
185 u32 xxx9[1];
186 volatile u32 rpointx, rpointy, rpointz;
187 u32 xxx10[5];
188 volatile u32 pointr, pointg, pointb, pointa;
189 volatile u32 alinex, aliney, alinez;
190 u32 xxx11[1];
191 volatile u32 rlinex, rliney, rlinez;
192 u32 xxx12[5];
193 volatile u32 liner, lineg, lineb, linea;
194 volatile u32 atrix, atriy, atriz;
195 u32 xxx13[1];
196 volatile u32 rtrix, rtriy, rtriz;
197 u32 xxx14[5];
198 volatile u32 trir, trig, trib, tria;
199 volatile u32 aquadx, aquady, aquadz;
200 u32 xxx15[1];
201 volatile u32 rquadx, rquady, rquadz;
202 u32 xxx16[5];
203 volatile u32 quadr, quadg, quadb, quada;
204 volatile u32 arectx, arecty, arectz;
205 u32 xxx17[1];
206 volatile u32 rrectx, rrecty, rrectz;
207 u32 xxx18[5];
208 volatile u32 rectr, rectg, rectb, recta;
211 static struct sbus_mmap_map cg6_mmap_map[] = {
212 { CG6_FBC, CG6_FBC_OFFSET, PAGE_SIZE },
213 { CG6_TEC, CG6_TEC_OFFSET, PAGE_SIZE },
214 { CG6_BTREGS, CG6_BROOKTREE_OFFSET, PAGE_SIZE },
215 { CG6_FHC, CG6_FHC_OFFSET, PAGE_SIZE },
216 { CG6_THC, CG6_THC_OFFSET, PAGE_SIZE },
217 { CG6_ROM, CG6_ROM_OFFSET, 0x10000 },
218 { CG6_RAM, CG6_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) },
219 { CG6_DHC, CG6_DHC_OFFSET, 0x40000 },
220 { 0, 0, 0 }
223 static void cg6_setup(struct display *p)
225 p->next_line = sbusfbinfo(p->fb_info)->var.xres_virtual;
226 p->next_plane = 0;
229 static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx,
230 int height, int width)
232 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
233 register struct cg6_fbc *fbc = fb->s.cg6.fbc;
234 int x, y, w, h;
235 int i;
237 do {
238 i = fbc->s;
239 } while (i & 0x10000000);
240 fbc->fg = attr_bgcol_ec(p,conp);
241 fbc->bg = attr_bgcol_ec(p,conp);
242 fbc->pixelm = ~(0);
243 fbc->alu = 0xea80ff00;
244 fbc->s = 0;
245 fbc->clip = 0;
246 fbc->pm = ~(0);
248 if (fontheightlog(p)) {
249 y = sy << fontheightlog(p); h = height << fontheightlog(p);
250 } else {
251 y = sy * fontheight(p); h = height * fontheight(p);
253 if (fontwidthlog(p)) {
254 x = sx << fontwidthlog(p); w = width << fontwidthlog(p);
255 } else {
256 x = sx * fontwidth(p); w = width * fontwidth(p);
258 fbc->arecty = y + fb->y_margin;
259 fbc->arectx = x + fb->x_margin;
260 fbc->arecty = y + fb->y_margin + h;
261 fbc->arectx = x + fb->x_margin + w;
262 do {
263 i = fbc->draw;
264 } while (i < 0 && (i & 0x20000000));
267 static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s,
268 int count, unsigned short *boxes)
270 int i;
271 register struct cg6_fbc *fbc = fb->s.cg6.fbc;
273 do {
274 i = fbc->s;
275 } while (i & 0x10000000);
276 fbc->fg = attr_bgcol(p,s);
277 fbc->bg = attr_bgcol(p,s);
278 fbc->pixelm = ~(0);
279 fbc->alu = 0xea80ff00;
280 fbc->s = 0;
281 fbc->clip = 0;
282 fbc->pm = ~(0);
283 while (count-- > 0) {
284 fbc->arecty = boxes[1];
285 fbc->arectx = boxes[0];
286 fbc->arecty = boxes[3];
287 fbc->arectx = boxes[2];
288 boxes += 4;
289 do {
290 i = fbc->draw;
291 } while (i < 0 && (i & 0x20000000));
295 static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx)
297 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
298 register struct cg6_fbc *fbc = fb->s.cg6.fbc;
299 int i, x, y;
300 u8 *fd;
302 if (fontheightlog(p)) {
303 y = fb->y_margin + (yy << fontheightlog(p));
304 i = ((c & p->charmask) << fontheightlog(p));
305 } else {
306 y = fb->y_margin + (yy * fontheight(p));
307 i = (c & p->charmask) * fontheight(p);
309 if (fontwidth(p) <= 8)
310 fd = p->fontdata + i;
311 else
312 fd = p->fontdata + (i << 1);
313 if (fontwidthlog(p))
314 x = fb->x_margin + (xx << fontwidthlog(p));
315 else
316 x = fb->x_margin + (xx * fontwidth(p));
317 do {
318 i = fbc->s;
319 } while (i & 0x10000000);
320 fbc->fg = attr_fgcol(p,c);
321 fbc->bg = attr_bgcol(p,c);
322 fbc->mode = 0x140000;
323 fbc->alu = 0xe880fc30;
324 fbc->pixelm = ~(0);
325 fbc->s = 0;
326 fbc->clip = 0;
327 fbc->pm = 0xff;
328 fbc->incx = 0;
329 fbc->incy = 1;
330 fbc->x0 = x;
331 fbc->x1 = x + fontwidth(p) - 1;
332 fbc->y0 = y;
333 if (fontwidth(p) <= 8) {
334 for (i = 0; i < fontheight(p); i++)
335 fbc->font = *fd++ << 24;
336 } else {
337 for (i = 0; i < fontheight(p); i++) {
338 fbc->font = *(u16 *)fd << 16;
339 fd += 2;
344 static void cg6_putcs(struct vc_data *conp, struct display *p, const unsigned short *s,
345 int count, int yy, int xx)
347 struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info;
348 register struct cg6_fbc *fbc = fb->s.cg6.fbc;
349 int i, x, y;
350 u8 *fd1, *fd2, *fd3, *fd4;
352 do {
353 i = fbc->s;
354 } while (i & 0x10000000);
355 fbc->fg = attr_fgcol(p,*s);
356 fbc->bg = attr_bgcol(p,*s);
357 fbc->mode = 0x140000;
358 fbc->alu = 0xe880fc30;
359 fbc->pixelm = ~(0);
360 fbc->s = 0;
361 fbc->clip = 0;
362 fbc->pm = 0xff;
363 x = fb->x_margin;
364 y = fb->y_margin;
365 if (fontwidthlog(p))
366 x += (xx << fontwidthlog(p));
367 else
368 x += xx * fontwidth(p);
369 if (fontheightlog(p))
370 y += (yy << fontheightlog(p));
371 else
372 y += (yy * fontheight(p));
373 if (fontwidth(p) <= 8) {
374 while (count >= 4) {
375 count -= 4;
376 fbc->incx = 0;
377 fbc->incy = 1;
378 fbc->x0 = x;
379 fbc->x1 = (x += 4 * fontwidth(p)) - 1;
380 fbc->y0 = y;
381 if (fontheightlog(p)) {
382 fd1 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
383 fd2 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
384 fd3 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
385 fd4 = p->fontdata + ((*s++ & p->charmask) << fontheightlog(p));
386 } else {
387 fd1 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
388 fd2 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
389 fd3 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
390 fd4 = p->fontdata + ((*s++ & p->charmask) * fontheight(p));
392 if (fontwidth(p) == 8) {
393 for (i = 0; i < fontheight(p); i++)
394 fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
395 << 8)) << 8)) << 8);
396 } else {
397 for (i = 0; i < fontheight(p); i++)
398 fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++)
399 << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p));
402 } else {
403 while (count >= 2) {
404 count -= 2;
405 fbc->incx = 0;
406 fbc->incy = 1;
407 fbc->x0 = x;
408 fbc->x1 = (x += 2 * fontwidth(p)) - 1;
409 fbc->y0 = y;
410 if (fontheightlog(p)) {
411 fd1 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
412 fd2 = p->fontdata + ((*s++ & p->charmask) << (fontheightlog(p) + 1));
413 } else {
414 fd1 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
415 fd2 = p->fontdata + (((*s++ & p->charmask) * fontheight(p)) << 1);
417 for (i = 0; i < fontheight(p); i++) {
418 fbc->font = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p));
419 fd1 += 2; fd2 += 2;
423 while (count) {
424 count--;
425 fbc->incx = 0;
426 fbc->incy = 1;
427 fbc->x0 = x;
428 fbc->x1 = (x += fontwidth(p)) - 1;
429 fbc->y0 = y;
430 if (fontheightlog(p))
431 i = ((*s++ & p->charmask) << fontheightlog(p));
432 else
433 i = ((*s++ & p->charmask) * fontheight(p));
434 if (fontwidth(p) <= 8) {
435 fd1 = p->fontdata + i;
436 for (i = 0; i < fontheight(p); i++)
437 fbc->font = *fd1++ << 24;
438 } else {
439 fd1 = p->fontdata + (i << 1);
440 for (i = 0; i < fontheight(p); i++) {
441 fbc->font = *(u16 *)fd1 << 16;
442 fd1 += 2;
448 static void cg6_revc(struct display *p, int xx, int yy)
450 /* Not used if hw cursor */
453 static void cg6_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count)
455 struct bt_regs *bt = fb->s.cg6.bt;
456 int i;
458 bt->addr = index << 24;
459 for (i = index; count--; i++){
460 bt->color_map = fb->color_map CM(i,0) << 24;
461 bt->color_map = fb->color_map CM(i,1) << 24;
462 bt->color_map = fb->color_map CM(i,2) << 24;
466 static void cg6_restore_palette (struct fb_info_sbusfb *fb)
468 struct bt_regs *bt = fb->s.cg6.bt;
470 bt->addr = 0;
471 bt->color_map = 0xffffffff;
472 bt->color_map = 0xffffffff;
473 bt->color_map = 0xffffffff;
476 static struct display_switch cg6_dispsw __initdata = {
477 cg6_setup, fbcon_redraw_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc,
478 NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */
481 static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue)
483 struct bt_regs *bt = fb->s.cg6.bt;
485 bt->addr = 1 << 24;
486 bt->cursor = red[0] << 24;
487 bt->cursor = green[0] << 24;
488 bt->cursor = blue[0] << 24;
489 bt->addr = 3 << 24;
490 bt->cursor = red[1] << 24;
491 bt->cursor = green[1] << 24;
492 bt->cursor = blue[1] << 24;
495 /* Set cursor shape */
496 static void cg6_setcurshape (struct fb_info_sbusfb *fb)
498 struct cg6_thc *thc = fb->s.cg6.thc;
499 int i;
501 for (i = 0; i < 32; i++) {
502 thc->thc_cursmask [i] = fb->cursor.bits[0][i];
503 thc->thc_cursbits [i] = fb->cursor.bits[1][i];
507 /* Load cursor information */
508 static void cg6_setcursor (struct fb_info_sbusfb *fb)
510 unsigned int v;
511 struct cg_cursor *c = &fb->cursor;
513 if (c->enable)
514 v = ((c->cpos.fbx - c->chot.fbx) << 16)
515 |((c->cpos.fby - c->chot.fby) & 0xffff);
516 else
517 /* Magic constant to turn off the cursor */
518 v = ((65536-32) << 16) | (65536-32);
519 fb->s.cg6.thc->thc_cursxy = v;
522 static void cg6_blank (struct fb_info_sbusfb *fb)
524 fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO;
527 static void cg6_unblank (struct fb_info_sbusfb *fb)
529 fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO;
532 static void cg6_reset (struct fb_info_sbusfb *fb)
534 unsigned int rev, conf;
535 struct cg6_tec *tec = fb->s.cg6.tec;
536 struct cg6_fbc *fbc = fb->s.cg6.fbc;
537 u32 mode;
539 /* Turn off stuff in the Transform Engine. */
540 tec->tec_matrix = 0;
541 tec->tec_clip = 0;
542 tec->tec_vdc = 0;
544 /* Take care of bugs in old revisions. */
545 rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK;
546 if (rev < 5) {
547 conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) |
548 CG6_FHC_CPU_68020 | CG6_FHC_TEST |
549 (11 << CG6_FHC_TEST_X_SHIFT) |
550 (11 << CG6_FHC_TEST_Y_SHIFT);
551 if (rev < 2)
552 conf |= CG6_FHC_DST_DISABLE;
553 *(fb->s.cg6.fhc) = conf;
556 /* Set things in the FBC. Bad things appear to happen if we do
557 * back to back store/loads on the mode register, so copy it
558 * out instead. */
559 mode = fbc->mode;
560 mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK |
561 CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK |
562 CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK |
563 CG6_FBC_BDISP_MASK);
564 mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 |
565 CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE |
566 CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 |
567 CG6_FBC_BDISP_0);
568 fbc->mode = mode;
570 fbc->clip = 0;
571 fbc->offx = 0;
572 fbc->offy = 0;
573 fbc->clipminx = 0;
574 fbc->clipminy = 0;
575 fbc->clipmaxx = fb->type.fb_width - 1;
576 fbc->clipmaxy = fb->type.fb_height - 1;
577 /* Enable cursor in Brooktree DAC. */
578 fb->s.cg6.bt->addr = 0x06 << 24;
579 fb->s.cg6.bt->control |= 0x03 << 24;
582 static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin)
584 p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin);
587 static char idstring[60] __initdata = { 0 };
589 __initfunc(char *cgsixfb_init(struct fb_info_sbusfb *fb))
591 struct fb_fix_screeninfo *fix = &fb->fix;
592 struct fb_var_screeninfo *var = &fb->var;
593 struct display *disp = &fb->disp;
594 struct fbtype *type = &fb->type;
595 unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr;
596 u32 conf;
597 char *p;
598 struct bt_regs *bt;
600 strcpy(fb->info.modename, "CGsix");
602 strcpy(fix->id, "CGsix");
603 fix->line_length = fb->var.xres_virtual;
604 fix->accel = FB_ACCEL_SUN_CGSIX;
606 var->accel_flags = FB_ACCELF_TEXT;
608 disp->scrollmode = SCROLL_YREDRAW;
609 if (!disp->screen_base)
610 disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0,
611 type->fb_size, "cgsix_ram", fb->iospace, 0);
612 disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin;
613 fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0,
614 4096, "cgsix_fbc", fb->iospace, 0);
615 fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0,
616 sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0);
617 fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0,
618 sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0);
619 fb->s.cg6.bt = bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0,
620 sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0);
621 fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0,
622 sizeof(u32), "cgsix_fhc", fb->iospace, 0);
623 fb->dispsw = cg6_dispsw;
625 fb->margins = cg6_margins;
626 fb->loadcmap = cg6_loadcmap;
627 fb->setcursor = cg6_setcursor;
628 fb->setcursormap = cg6_setcursormap;
629 fb->setcurshape = cg6_setcurshape;
630 fb->restore_palette = cg6_restore_palette;
631 fb->fill = cg6_fill;
632 fb->blank = cg6_blank;
633 fb->unblank = cg6_unblank;
634 fb->reset = cg6_reset;
636 fb->physbase = phys;
637 fb->mmap_map = cg6_mmap_map;
639 /* Initialize Brooktree DAC */
640 bt->addr = 0x04 << 24; /* color planes */
641 bt->control = 0xff << 24;
642 bt->addr = 0x05 << 24;
643 bt->control = 0x00 << 24;
644 bt->addr = 0x06 << 24; /* overlay plane */
645 bt->control = 0x73 << 24;
646 bt->addr = 0x07 << 24;
647 bt->control = 0x00 << 24;
649 conf = *fb->s.cg6.fhc;
650 switch(conf & CG6_FHC_CPU_MASK) {
651 case CG6_FHC_CPU_SPARC: p = "sparc"; break;
652 case CG6_FHC_CPU_68020: p = "68020"; break;
653 default: p = "i386"; break;
656 sprintf(idstring,
657 #ifdef __sparc_v9__
658 "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys,
659 #else
660 "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys,
661 #endif
662 (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK,
663 p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK);
665 cg6_reset(fb);
667 return idstring;