]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/pc/vgaradeon.c
audiohda: fix syntax error
[plan9front.git] / sys / src / 9 / pc / vgaradeon.c
1 /*
2  * ATI Radeon [789]XXX vga driver
3  * see /sys/src/cmd/aux/vga/radeon.c
4  */
5 #include "u.h"
6 #include "../port/lib.h"
7 #include "mem.h"
8 #include "dat.h"
9 #include "fns.h"
10 #include "io.h"
11 #include "../port/pci.h"
12 #include "../port/error.h"
13
14 #define Image   IMAGE
15 #include <draw.h>
16 #include <memdraw.h>
17 #include <cursor.h>
18 #include "screen.h"
19
20 #include "/sys/src/cmd/aux/vga/radeon.h"        /* ugh */
21
22 /* #define HW_ACCEL */
23
24 enum {
25         Kilo    = 1024,
26         Meg     = Kilo * Kilo,
27 };
28
29 /* mmio access */
30
31 static void
32 OUTREG8(ulong *mmio, ulong offset, uchar val)
33 {
34         ((uchar*)KADDR((((uintptr)mmio) + offset)))[0] = val;
35 }
36
37 static void
38 OUTREG(ulong *mmio, ulong offset, ulong val)
39 {
40         ((ulong*)KADDR((((uintptr)mmio) + offset)))[0] = val;
41 }
42
43 static ulong
44 INREG(ulong *mmio, ulong offset)
45 {
46         return ((ulong*)KADDR((((uintptr)mmio) + offset)))[0];
47 }
48
49 static void
50 OUTREGP(ulong *mmio, ulong offset, ulong val, ulong mask)
51 {
52         OUTREG(mmio, offset, (INREG(mmio, offset) & mask) | val);
53 }
54
55 static void
56 OUTPLL(ulong *mmio, ulong offset, ulong val)
57 {
58         OUTREG8(mmio, CLOCK_CNTL_INDEX, (offset & 0x3f) | PLL_WR_EN);
59         OUTREG(mmio, CLOCK_CNTL_DATA, val);
60 }
61
62 static ulong
63 INPLL(ulong *mmio, ulong offset)
64 {
65         OUTREG8(mmio, CLOCK_CNTL_INDEX, offset & 0x3f);
66         return INREG(mmio, CLOCK_CNTL_DATA);
67 }
68
69 static void
70 OUTPLLP(ulong *mmio, ulong offset, ulong val, ulong mask)
71 {
72         OUTPLL(mmio, offset, (INPLL(mmio, offset) & mask) | val);
73 }
74
75 static void
76 radeonlinear(VGAscr *, int, int)
77 {
78 }
79
80 static void
81 radeonenable(VGAscr *scr)
82 {
83         Pcidev *p;
84
85         if (scr->mmio)
86                 return;
87         p = scr->pci;
88         if (p == nil)
89                 return;
90         scr->id = p->did;
91         if(p->mem[2].bar & 1)
92                 return;
93         scr->mmio = vmap(p->mem[2].bar & ~0x0f, p->mem[2].size);
94         if(scr->mmio == nil)
95                 return;
96         addvgaseg("radeonmmio", p->mem[2].bar & ~0x0f, p->mem[2].size);
97
98         vgalinearpci(scr);
99         if(scr->apsize)
100                 addvgaseg("radeonscreen", scr->paddr, scr->apsize);
101 }
102
103 static void
104 radeoncurload(VGAscr *scr, Cursor *curs)
105 {
106         int x, y;
107         ulong *p;
108
109         if(scr->mmio == nil)
110                 return;
111
112         p = (ulong*)KADDR(scr->storage);
113
114         for(y = 0; y < 64; y++){
115                 int cv, sv;
116
117                 if (y < 16) {
118                         cv = curs->clr[2*y] << 8 | curs->clr[2*y+1];
119                         sv = curs->set[2*y] << 8 | curs->set[2*y+1];
120                 } else
121                         cv = sv = 0;
122
123                 for(x = 0; x < 64; x++){
124                         ulong col = 0;
125                         int c, s;
126
127                         if (x < 16) {
128                                 c = (cv >> (15 - x)) & 1;
129                                 s = (sv >> (15 - x)) & 1;
130                         } else
131                                 c = s = 0;
132
133                         switch(c | s<<1) {
134                         case 0:
135                                 col = 0;
136                                 break;
137                         case 1:
138                                 col = ~0ul;             /* white */
139                                 break;
140                         case 2:
141                         case 3:
142                                 col = 0xff000000;       /* black */
143                                 break;
144                         }
145
146                         *p++ = col;
147                 }
148         }
149
150         scr->offset.x = curs->offset.x;
151         scr->offset.y = curs->offset.y;
152 }
153
154 static int
155 radeoncurmove(VGAscr *scr, Point p)
156 {
157         int x, y, ox, oy;
158         static ulong storage = 0;
159
160         if(scr->mmio == nil)
161                 return 1;
162
163         if (storage == 0)
164                 storage = scr->apsize - 1*Meg;
165
166         x = p.x + scr->offset.x;
167         y = p.y + scr->offset.y;
168         ox = oy = 0;
169
170         if (x < 0) {
171                 ox = -x - 1;
172                 x = 0;
173         }
174         if (y < 0) {
175                 oy = -y - 1;
176                 y = 0;
177         }
178
179         OUTREG(scr->mmio, CUR_OFFSET, storage + oy * 256);
180         OUTREG(scr->mmio, CUR_HORZ_VERT_OFF,
181                 (ox & 0x7fff) << 16 | (oy & 0x7fff));
182         OUTREG(scr->mmio, CUR_HORZ_VERT_POSN,
183                 (x & 0x7fff) << 16 | (y & 0x7fff));
184         return 0;
185 }
186
187 static void
188 radeoncurdisable(VGAscr *scr)
189 {
190         if(scr->mmio == nil)
191                 return;
192         OUTREGP(scr->mmio, CRTC_GEN_CNTL, 0, ~CRTC_CUR_EN);
193 }
194
195 static void
196 radeoncurenable(VGAscr *scr)
197 {
198         ulong storage;
199
200         if(scr->mmio == 0)
201                 return;
202
203         radeoncurdisable(scr);
204         storage = scr->apsize - 1*Meg;
205         scr->storage = (uintptr)KADDR(scr->paddr + storage);
206         radeoncurload(scr, &cursor);
207         radeoncurmove(scr, ZP);
208
209         OUTREGP(scr->mmio, CRTC_GEN_CNTL, CRTC_CUR_EN | 2<<20,
210                 ~(CRTC_CUR_EN | 3<<20));
211 }
212
213 /* hw blank */
214
215 static void
216 radeonblank(VGAscr* scr, int blank)
217 {
218         ulong mask;
219         char *cp;
220
221         if (scr->mmio == 0)
222                 return;
223
224 //      iprint("radeon: hwblank(%d)\n", blank);
225
226         mask = CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | CRTC_VSYNC_DIS;
227         if (blank == 0) {
228                 OUTREGP(scr->mmio, CRTC_EXT_CNTL, 0, ~mask);
229                 return;
230         }
231
232         cp = getconf("*dpms");
233         if (cp) {
234                 if (strcmp(cp, "standby") == 0)
235                         OUTREGP(scr->mmio, CRTC_EXT_CNTL,
236                                 CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS, ~mask);
237                 else if (strcmp(cp, "suspend") == 0)
238                         OUTREGP(scr->mmio, CRTC_EXT_CNTL,
239                                 CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS, ~mask);
240                 else if (strcmp(cp, "off") == 0)
241                         OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
242                 return;
243         }
244
245         OUTREGP(scr->mmio, CRTC_EXT_CNTL, mask, ~mask);
246 }
247
248 /* hw acceleration */
249
250 static void
251 radeonwaitfifo(VGAscr *scr, int entries)
252 {
253         int i;
254
255         for (i = 0; i < 2000000; i++)
256                 if (INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK >=
257                     entries)
258                         return;
259         iprint("radeon: fifo timeout\n");
260 }
261
262 static void
263 radeonwaitidle(VGAscr *scr)
264 {
265         radeonwaitfifo(scr, 64);
266
267         for (; ; ) {
268                 int i;
269
270                 for (i = 0; i < 2000000; i++)
271                         if (!(INREG(scr->mmio, RBBM_STATUS) & RBBM_ACTIVE))
272                                 return;
273
274                 iprint("radeon: idle timed out: %uld entries, stat=0x%.8ulx\n",
275                         INREG(scr->mmio, RBBM_STATUS) & RBBM_FIFOCNT_MASK,
276                         INREG(scr->mmio, RBBM_STATUS));
277         }
278 }
279
280 static ulong dp_gui_master_cntl = 0;
281
282 static int
283 radeonfill(VGAscr *scr, Rectangle r, ulong color)
284 {
285         if (scr->mmio == nil)
286                 return 0;
287
288         radeonwaitfifo(scr, 6);
289         OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
290                 dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR |
291                 GMC_SRC_DATATYPE_COLOR | ROP3_P);
292         OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, color);
293         OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
294         OUTREG(scr->mmio, DP_CNTL,
295                 DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
296         OUTREG(scr->mmio, DST_Y_X, r.min.y << 16 | r.min.x);
297         OUTREG(scr->mmio, DST_WIDTH_HEIGHT, Dx(r) << 16 | Dy(r));
298
299         radeonwaitidle(scr);
300         return 1;
301 }
302
303 static int
304 radeonscroll(VGAscr*scr, Rectangle dst, Rectangle src)
305 {
306         int xs, ys, xd, yd, w, h;
307         ulong dp_cntl = 0x20;
308
309         if (scr->mmio == nil)
310                 return 0;
311
312         // iprint("radeon: hwscroll(dst:%R, src:%R)\n", dst, src);
313
314         xd = dst.min.x;
315         yd = dst.min.y;
316         xs = src.min.x;
317         ys = src.min.y;
318         w = Dx(dst);
319         h = Dy(dst);
320
321         if (ys < yd) {
322                 ys += h - 1;
323                 yd += h - 1;
324         } else
325                 dp_cntl |= DST_Y_TOP_TO_BOTTOM;
326
327         if (xs < xd) {
328                 xs += w - 1;
329                 xd += w - 1;
330         } else
331                 dp_cntl |= DST_X_LEFT_TO_RIGHT;
332
333         radeonwaitfifo(scr, 6);
334         OUTREG(scr->mmio, DP_GUI_MASTER_CNTL, dp_gui_master_cntl |
335                 GMC_BRUSH_NONE | GMC_SRC_DATATYPE_COLOR | DP_SRC_SOURCE_MEMORY |
336                 ROP3_S);
337         OUTREG(scr->mmio, DP_WRITE_MASK, ~0ul);
338         OUTREG(scr->mmio, DP_CNTL, dp_cntl);
339         OUTREG(scr->mmio, SRC_Y_X, ys << 16 | xs);
340         OUTREG(scr->mmio, DST_Y_X, yd << 16 | xd);
341         OUTREG(scr->mmio, DST_WIDTH_HEIGHT, w << 16 | h);
342
343         radeonwaitidle(scr);
344
345         // iprint("radeon: hwscroll(xs=%d ys=%d xd=%d yd=%d w=%d h=%d)\n",
346         //      xs, ys, xd, yd, w, h);
347         return 1;
348 }
349
350 static void
351 radeondrawinit(VGAscr*scr)
352 {
353         ulong dtype, i, clock_cntl_index, mclk_cntl, rbbm_soft_reset;
354
355         if (scr->mmio == 0)
356                 return;
357
358         switch (scr->gscreen->depth) {
359         case 6:
360         case 8:
361                 dtype = 2;
362                 break;
363         case 15:
364                 dtype = 3;
365                 break;
366         case 16:
367                 dtype = 4;
368                 break;
369         case 32:
370                 dtype = 6;
371                 break;
372         default:
373                 return;
374         }
375
376         /* disable 3D */
377         OUTREG(scr->mmio, RB3D_CNTL, 0);
378
379         /* flush engine */
380         OUTREGP(scr->mmio, RB2D_DSTCACHE_CTLSTAT,
381                 RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
382         for (i = 0; i < 2000000; i++)
383                 if (!(INREG(scr->mmio, RB2D_DSTCACHE_CTLSTAT) &
384                     RB2D_DC_BUSY))
385                         break;
386
387         /* reset 2D engine */
388         clock_cntl_index = INREG(scr->mmio, CLOCK_CNTL_INDEX);
389
390         mclk_cntl = INPLL(scr->mmio, MCLK_CNTL);
391         OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl | FORCEON_MCLKA |
392                 FORCEON_MCLKB | FORCEON_YCLKA | FORCEON_YCLKB | FORCEON_MC |
393                 FORCEON_AIC);
394         rbbm_soft_reset = INREG(scr->mmio, RBBM_SOFT_RESET);
395
396         OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset |
397                 SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
398                 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB);
399         INREG(scr->mmio, RBBM_SOFT_RESET);
400         OUTREG(scr->mmio, RBBM_SOFT_RESET, rbbm_soft_reset &
401                 ~(SOFT_RESET_CP | SOFT_RESET_HI | SOFT_RESET_SE | SOFT_RESET_RE |
402                 SOFT_RESET_PP | SOFT_RESET_E2 | SOFT_RESET_RB));
403         INREG(scr->mmio, RBBM_SOFT_RESET);
404
405         OUTPLL(scr->mmio, MCLK_CNTL, mclk_cntl);
406         OUTREG(scr->mmio, CLOCK_CNTL_INDEX, clock_cntl_index);
407
408         /* init 2D engine */
409         radeonwaitfifo(scr, 1);
410         OUTREG(scr->mmio, RB2D_DSTCACHE_MODE, 0);
411
412         radeonwaitfifo(scr, 4);
413         OUTREG(scr->mmio, DEFAULT_PITCH, scr->pitch);
414         OUTREG(scr->mmio, DST_PITCH, scr->pitch);
415         OUTREG(scr->mmio, SRC_PITCH, scr->pitch);
416         OUTREG(scr->mmio, DST_PITCH_OFFSET_C, 0);
417
418         radeonwaitfifo(scr, 3);
419         OUTREG(scr->mmio, DEFAULT_OFFSET, 0);
420         OUTREG(scr->mmio, DST_OFFSET, 0);
421         OUTREG(scr->mmio, SRC_OFFSET, 0);
422
423         radeonwaitfifo(scr, 1);
424         OUTREGP(scr->mmio, DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
425
426         radeonwaitfifo(scr, 1);
427         OUTREG(scr->mmio, DEFAULT_SC_BOTTOM_RIGHT,
428                 DEFAULT_SC_RIGHT_MAX | DEFAULT_SC_BOTTOM_MAX);
429
430         dp_gui_master_cntl = dtype << GMC_DST_DATATYPE_SHIFT |
431                 GMC_SRC_PITCH_OFFSET_CNTL | GMC_DST_PITCH_OFFSET_CNTL |
432                 GMC_CLR_CMP_CNTL_DIS;
433         radeonwaitfifo(scr, 1);
434         OUTREG(scr->mmio, DP_GUI_MASTER_CNTL,
435             dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR | GMC_SRC_DATATYPE_COLOR);
436
437         radeonwaitfifo(scr, 7);
438         OUTREG(scr->mmio, DST_LINE_START,    0);
439         OUTREG(scr->mmio, DST_LINE_END,      0);
440         OUTREG(scr->mmio, DP_BRUSH_FRGD_CLR, ~0ul);
441         OUTREG(scr->mmio, DP_BRUSH_BKGD_CLR, 0);
442         OUTREG(scr->mmio, DP_SRC_FRGD_CLR,   ~0ul);
443         OUTREG(scr->mmio, DP_SRC_BKGD_CLR,   0);
444         OUTREG(scr->mmio, DP_WRITE_MASK,     ~0ul);
445
446         radeonwaitidle(scr);
447
448         scr->fill = radeonfill;
449         scr->scroll = radeonscroll;
450         scr->blank = radeonblank;
451 }
452
453 /* hw overlay */
454
455 static void
456 radeonovlctl(VGAscr *scr, Chan *c, void *data, int len)
457 {
458         USED(scr, c, data, len);
459 }
460
461 static int
462 radeonovlwrite(VGAscr *scr, void *data, int len, vlong opt)
463 {
464         USED(scr, data, len, opt);
465         return -1;
466 }
467
468 static void
469 radeonflush(VGAscr *scr, Rectangle r)
470 {
471         USED(scr, r);
472 }
473
474 /* Export */
475
476 VGAdev vgaradeondev = {
477         "radeon",
478
479         radeonenable,
480         0,                              /* disable */
481         0,                              /* page */
482         radeonlinear,
483
484         radeondrawinit,
485 #ifdef HW_ACCEL
486         radeonfill,
487
488         radeonovlctl,
489         radeonovlwrite,
490         radeonflush,
491 #endif
492 };
493 VGAcur vgaradeoncur = {
494         "radeonhwgc",
495         radeoncurenable,
496         radeoncurdisable,
497         radeoncurload,
498         radeoncurmove,
499 };