]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/con_hw/radeon.c
431caef7d8ecb525e6fed55c76e8b14a9ba2026f
[l4.git] / l4 / pkg / l4con / server / src / con_hw / radeon.c
1 /*!
2  * \file        radeon.c
3  * \brief       Hardware Acceleration for ATI Radeon cards
4  *
5  * \date        10/2005
6  * \author      Frank Mehnert <fm3@os.inf.tu-dresden.de> */
7 /*
8  * (c) 2008-2009 Technische Universität Dresden
9  * This file is part of TUD:OS and distributed under the terms of the
10  * GNU General Public License 2.
11  * Please see the COPYING-GPL-2 file for details.
12  */
13
14 /* (c) 2005 'Technische Universitaet Dresden'
15  * This file is part of the con package, which is distributed under
16  * the terms of the GNU General Public License 2. Please see the
17  * COPYING file for details. */
18
19 /* most stuff taken from Linux 2.6.13: driver/video/radeon.c */
20
21 #include <stdio.h>
22
23 #include <l4/sys/types.h>
24 #include <l4/sys/err.h>
25 #include <l4/sys/consts.h>
26 #include <l4/sys/kdebug.h>
27 #include <l4/util/util.h>
28
29 #include "init.h"
30 #include "pci.h"
31 #include "iomem.h"
32 #include "radeon.h"
33 #include "radeon_reg.h"
34
35 #define PCI_DEVICE_ID_ATI_RADEON_QD     0x5144
36 #define PCI_DEVICE_ID_ATI_RADEON_QE     0x5145
37 #define PCI_DEVICE_ID_ATI_RADEON_QF     0x5146
38 #define PCI_DEVICE_ID_ATI_RADEON_QG     0x5147
39 /* Radeon RV100 (VE) */
40 #define PCI_DEVICE_ID_ATI_RADEON_QY     0x5159
41 #define PCI_DEVICE_ID_ATI_RADEON_QZ     0x515a
42 /* Radeon R200 (8500) */
43 #define PCI_DEVICE_ID_ATI_RADEON_QL     0x514c
44 #define PCI_DEVICE_ID_ATI_RADEON_QN     0x514e
45 #define PCI_DEVICE_ID_ATI_RADEON_QO     0x514f
46 #define PCI_DEVICE_ID_ATI_RADEON_Ql     0x516c
47 #define PCI_DEVICE_ID_ATI_RADEON_BB     0x4242
48 /* Radeon R200 (9100) */
49 #define PCI_DEVICE_ID_ATI_RADEON_QM     0x514d
50 /* Radeon RV200 (7500) */
51 #define PCI_DEVICE_ID_ATI_RADEON_QW     0x5157
52 #define PCI_DEVICE_ID_ATI_RADEON_QX     0x5158
53 /* Radeon NV-100 */
54 #define PCI_DEVICE_ID_ATI_RADEON_N1     0x5159
55 #define PCI_DEVICE_ID_ATI_RADEON_N2     0x515a
56 /* Radeon RV250 (9000) */
57 #define PCI_DEVICE_ID_ATI_RADEON_Id     0x4964
58 #define PCI_DEVICE_ID_ATI_RADEON_Ie     0x4965
59 #define PCI_DEVICE_ID_ATI_RADEON_If     0x4966
60 #define PCI_DEVICE_ID_ATI_RADEON_Ig     0x4967
61 /* Radeon RV280 (9200) */
62 #define PCI_DEVICE_ID_ATI_RADEON_Y_     0x5960
63 #define PCI_DEVICE_ID_ATI_RADEON_Ya     0x5961
64 #define PCI_DEVICE_ID_ATI_RADEON_Yd     0x5964
65 /* Radeon R300 (9500) */
66 #define PCI_DEVICE_ID_ATI_RADEON_AD     0x4144
67 /* Radeon R300 (9700) */
68 #define PCI_DEVICE_ID_ATI_RADEON_ND     0x4e44
69 #define PCI_DEVICE_ID_ATI_RADEON_NE     0x4e45
70 #define PCI_DEVICE_ID_ATI_RADEON_NF     0x4e46
71 #define PCI_DEVICE_ID_ATI_RADEON_NG     0x4e47
72 #define PCI_DEVICE_ID_ATI_RADEON_AE     0x4145
73 #define PCI_DEVICE_ID_ATI_RADEON_AF     0x4146
74 /* Radeon R350 (9800) */
75 #define PCI_DEVICE_ID_ATI_RADEON_NH     0x4e48
76 #define PCI_DEVICE_ID_ATI_RADEON_NI     0x4e49
77 /* Radeon RV350 (9600) */
78 #define PCI_DEVICE_ID_ATI_RADEON_AP     0x4150
79 #define PCI_DEVICE_ID_ATI_RADEON_AR     0x4152
80 /* Radeon M6 */
81 #define PCI_DEVICE_ID_ATI_RADEON_LY     0x4c59
82 #define PCI_DEVICE_ID_ATI_RADEON_LZ     0x4c5a
83 /* Radeon M7 */
84 #define PCI_DEVICE_ID_ATI_RADEON_LW     0x4c57
85 #define PCI_DEVICE_ID_ATI_RADEON_LX     0x4c58
86 /* Radeon M9 */
87 #define PCI_DEVICE_ID_ATI_RADEON_Ld     0x4c64
88 #define PCI_DEVICE_ID_ATI_RADEON_Le     0x4c65
89 #define PCI_DEVICE_ID_ATI_RADEON_Lf     0x4c66
90 #define PCI_DEVICE_ID_ATI_RADEON_Lg     0x4c67
91 /* Radeon */
92 #define PCI_DEVICE_ID_ATI_RADEON_RA     0x5144
93 #define PCI_DEVICE_ID_ATI_RADEON_RB     0x5145
94 #define PCI_DEVICE_ID_ATI_RADEON_RC     0x5146
95 #define PCI_DEVICE_ID_ATI_RADEON_RD     0x5147
96
97 enum radeon_chips
98 {
99   RADEON_QD, RADEON_QE, RADEON_QF, RADEON_QG, RADEON_QY, RADEON_QZ, RADEON_LW,
100   RADEON_LX, RADEON_LY, RADEON_LZ, RADEON_QL, RADEON_QN, RADEON_QO, RADEON_Ql,
101   RADEON_BB, RADEON_QW, RADEON_QX, RADEON_Id, RADEON_Ie, RADEON_If, RADEON_Ig,
102   RADEON_Ya, RADEON_Yd, RADEON_Ld, RADEON_Le, RADEON_Lf, RADEON_Lg, RADEON_ND,
103   RADEON_NE, RADEON_NF, RADEON_NG, RADEON_QM
104 };
105
106 static const struct pci_device_id radeon_pci_tbl[] __init =
107 {
108     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QD, 0, 0, RADEON_QD},
109     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QE, 0, 0, RADEON_QE},
110     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QF, 0, 0, RADEON_QF},
111     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QG, 0, 0, RADEON_QG},
112     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QY, 0, 0, RADEON_QY},
113     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QZ, 0, 0, RADEON_QZ},
114     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LW, 0, 0, RADEON_LW},
115     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LX, 0, 0, RADEON_LX},
116     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LY, 0, 0, RADEON_LY},
117     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_LZ, 0, 0, RADEON_LZ},
118     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QL, 0, 0, RADEON_QL},
119     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QN, 0, 0, RADEON_QN},
120     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QO, 0, 0, RADEON_QO},
121     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ql, 0, 0, RADEON_Ql},
122     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_BB, 0, 0, RADEON_BB},
123     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QW, 0, 0, RADEON_QW},
124     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QX, 0, 0, RADEON_QX},
125     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Id, 0, 0, RADEON_Id},
126     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ie, 0, 0, RADEON_Ie},
127     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_If, 0, 0, RADEON_If},
128     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ig, 0, 0, RADEON_Ig},
129     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ya, 0, 0, RADEON_Ya},
130     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Yd, 0, 0, RADEON_Yd},
131     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Ld, 0, 0, RADEON_Ld},
132     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Le, 0, 0, RADEON_Le},
133     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lf, 0, 0, RADEON_Lf},
134     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_Lg, 0, 0, RADEON_Lg},
135     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_ND, 0, 0, RADEON_ND},
136     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NE, 0, 0, RADEON_NE},
137     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NF, 0, 0, RADEON_NF},
138     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_NG, 0, 0, RADEON_NG},
139     { PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RADEON_QM, 0, 0, RADEON_QM},
140     { PCI_VENDOR_ID_ATI, 0x5B60,                      0, 0, 0},
141     { 0, 0, 0, 0, 0}
142 };
143
144
145 #define INREG8(addr)       *(volatile l4_uint8_t*)(mmio_base + addr)
146 #define OUTREG8(addr,val)  *(volatile l4_uint8_t*)(mmio_base + addr) = val
147 #define INREG(addr)        *(volatile l4_uint32_t*)(mmio_base + addr)
148 #define OUTREG(addr,val)   *(volatile l4_uint32_t*)(mmio_base + addr) = val
149
150 #define OUTPLL(addr,val)        \
151         do {    \
152                 OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
153                 OUTREG(CLOCK_CNTL_DATA, val); \
154         } while(0)
155
156 #define OUTREGP(addr,val,mask)                                          \
157         do {                                                            \
158                 unsigned int _tmp = INREG(addr);                        \
159                 _tmp &= (mask);                                         \
160                 _tmp |= (val);                                          \
161                 OUTREG(addr, _tmp);                                     \
162         } while (0)
163
164 static l4_addr_t mmio_base = 0;
165 static int pitch;
166 static l4_uint32_t dp_gui_master_cntl;
167
168 static inline l4_uint32_t INPLL(l4_uint32_t addr)
169 {
170   OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
171   return (INREG(CLOCK_CNTL_DATA));
172 }
173
174 static inline void
175 radeon_engine_flush(void)
176 {
177   int i;
178
179   /* initiate flush */
180   OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
181
182   for (i=0; i < 2000000; i++)
183     if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
184       break;
185 }
186
187 static inline void
188 radeon_fifo_wait(unsigned entries)
189 {
190   int i;
191
192   for (i=0; i<2000000; i++)
193     if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
194       return;
195 }
196
197 static void
198 radeon_engine_idle(void)
199 {
200   int i;
201
202   /* ensure FIFO is empty before waiting for idle */
203   radeon_fifo_wait (64);
204
205   for (i=0; i<2000000; i++)
206     if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0)
207         {
208           radeon_engine_flush ();
209           return;
210         }
211 }
212
213 static void
214 radeon_engine_reset(void)
215 {
216   l4_uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
217
218   radeon_engine_flush ();
219
220   clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
221   mclk_cntl = INPLL(MCLK_CNTL);
222
223   OUTPLL(MCLK_CNTL, (mclk_cntl | FORCEON_MCLKA 
224                                | FORCEON_MCLKB
225                                | FORCEON_YCLKA
226                                | FORCEON_YCLKB
227                                | FORCEON_MC
228                                | FORCEON_AIC));
229   rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
230
231   OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | SOFT_RESET_CP
232                                           | SOFT_RESET_HI
233                                           | SOFT_RESET_SE
234                                           | SOFT_RESET_RE
235                                           | SOFT_RESET_PP
236                                           | SOFT_RESET_E2
237                                           | SOFT_RESET_RB);
238   INREG(RBBM_SOFT_RESET);
239   OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (l4_uint32_t) ~(SOFT_RESET_CP |
240                                                             SOFT_RESET_HI |
241                                                             SOFT_RESET_SE |
242                                                             SOFT_RESET_RE |
243                                                             SOFT_RESET_PP |
244                                                             SOFT_RESET_E2 |
245                                                             SOFT_RESET_RB));
246   INREG(RBBM_SOFT_RESET);
247
248   OUTPLL(MCLK_CNTL, mclk_cntl);
249   OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
250   OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
251
252   return;
253 }
254
255 static void
256 radeon_engine_init (void)
257 {
258   l4_uint32_t temp;
259
260   /* disable 3D engine */
261   OUTREG(RB3D_CNTL, 0);
262
263   radeon_engine_reset ();
264
265   radeon_fifo_wait (1);
266   OUTREG(RB2D_DSTCACHE_MODE, 0);
267
268   radeon_fifo_wait (1);
269   temp = INREG(DEFAULT_PITCH_OFFSET);
270   OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | (pitch << 0x16)));
271
272   radeon_fifo_wait (1);
273   OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
274
275   radeon_fifo_wait (1);
276   OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
277         DEFAULT_SC_BOTTOM_MAX));
278
279   switch (hw_bits)
280     {
281     case 8:  temp = DST_8BPP;  break;
282     case 15: temp = DST_15BPP; break;
283     case 16: temp = DST_16BPP; break;
284     case 32: temp = DST_32BPP; break;
285     default: temp = 0;         break;
286     }
287
288   dp_gui_master_cntl = (temp << 8) | GMC_CLR_CMP_CNTL_DIS;
289   radeon_fifo_wait (1);
290   OUTREG(DP_GUI_MASTER_CNTL, (dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR 
291                                                  | GMC_SRC_DATATYPE_COLOR));
292
293   radeon_fifo_wait (7);
294
295   /* clear line drawing regs */
296   OUTREG(DST_LINE_START, 0);
297   OUTREG(DST_LINE_END, 0);
298
299   /* set brush color regs */
300   OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
301   OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
302
303   /* set source color regs */
304   OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
305   OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
306
307   /* default write mask */
308   OUTREG(DP_WRITE_MSK, 0xffffffff);
309
310   radeon_engine_idle ();
311 }
312
313 static void
314 radeon_fill(struct l4con_vc *vc,
315             int sx, int sy, int width, int height, unsigned color)
316 {
317   (void)vc;
318   radeon_fifo_wait(4);  
319
320   OUTREG(DP_GUI_MASTER_CNTL, dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR
321                                                 | ROP3_P);
322   OUTREG(DP_BRUSH_FRGD_CLR, color);
323   OUTREG(DP_WRITE_MSK, 0xffffffff);
324   OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM));
325
326   radeon_fifo_wait(2);  
327   OUTREG(DST_Y_X, (sy << 16) | sx);
328   OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height);
329 }
330
331 static void
332 radeon_copy(struct l4con_vc *vc,
333             int sx, int sy, int width, int height, int dx, int dy)
334 {
335   int xdir = sx - dx, ydir = sy - dy;
336
337   (void)vc;
338   if (xdir < 0)
339     {
340       sx += width-1; 
341       dx += width-1;
342     }
343   if (ydir < 0)
344     {
345       sy += height-1;
346       dy += height-1;
347     }
348
349   radeon_fifo_wait(3);
350   OUTREG(DP_GUI_MASTER_CNTL, dp_gui_master_cntl | GMC_BRUSH_NONE
351                                                 | GMC_SRC_DSTCOLOR
352                                                 | ROP3_S 
353                                                 | DP_SRC_SOURCE_MEMORY );
354   OUTREG(DP_WRITE_MSK, 0xffffffff);
355   OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
356                   (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0));
357
358   radeon_fifo_wait(3);
359   OUTREG(SRC_Y_X, (sy << 16) | sx);
360   OUTREG(DST_Y_X, (dy << 16) | dx);
361   OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width);
362 }
363
364 static void
365 radeon_pan(int *x, int *y)
366 {
367   radeon_fifo_wait(2);
368   OUTREG(CRTC_OFFSET, ((*y * hw_xres + *x) * hw_bits / 8) & ~7);
369 }
370
371 static void
372 radeon_sync(void)
373 {
374   radeon_engine_idle();
375 }
376
377 static int
378 radeon_init(void)
379 {
380   pitch = ((hw_xres * ((hw_bits + 1) / 8) + 0x3f) & ~(0x3f)) / 64;
381   printf("Found ATI Radeon\n");
382
383   return 1;
384 }
385
386 static int
387 radeon_probe(unsigned int bus, unsigned int devfn,
388              const struct pci_device_id *dev, con_accel_t *accel)
389 {
390   unsigned int addr;
391   unsigned short tmp;
392   (void)dev;
393
394   PCIBIOS_READ_CONFIG_DWORD (bus, devfn, PCI_BASE_ADDRESS_0, &addr);
395   if (!addr)
396     return -L4_ENODEV;
397
398   addr &= PCI_BASE_ADDRESS_MEM_MASK;
399
400   PCIBIOS_READ_CONFIG_WORD (bus, devfn, PCI_COMMAND, &tmp);
401   if (!(tmp & PCI_COMMAND_MEMORY)) 
402     {
403       tmp |= PCI_COMMAND_MEMORY;
404       PCIBIOS_WRITE_CONFIG_WORD(bus, devfn, PCI_COMMAND, tmp);
405     }
406
407   PCIBIOS_READ_CONFIG_DWORD(bus, devfn, PCI_BASE_ADDRESS_2, &addr);
408   addr &= PCI_BASE_ADDRESS_MEM_MASK;
409
410   // check if we have enough memory
411   if (hw_vid_mem_size < 7*1024*1024)
412     {
413       printf("radeon: graphics memory size less than 8MB (%ldkB)\n",
414              hw_vid_mem_size/1024);
415       return -L4_ENODEV;
416     }
417
418   if (map_io_mem(addr, 0x4000, 0, "ctrl", (l4_addr_t *)&mmio_base)<0)
419     return -L4_ENODEV;
420
421   if (!radeon_init())
422     {
423       unmap_io_mem(addr, 0x4000, "ctrl", mmio_base);
424       return -L4_ENODEV;
425     }
426
427   radeon_engine_init();
428
429   if (map_io_mem(hw_vid_mem_addr, hw_vid_mem_size, 1, "video",
430                  (l4_addr_t *)&hw_map_vid_mem_addr)<0)
431     return -L4_ENODEV;
432
433   accel->copy = radeon_copy;
434   accel->fill = radeon_fill;
435   accel->sync = radeon_sync;
436   accel->pan  = radeon_pan;
437   accel->caps = ACCEL_FAST_COPY | ACCEL_FAST_FILL;
438
439   return 0;
440 }
441
442 void
443 radeon_register(void)
444 {
445   pci_register(radeon_pci_tbl, radeon_probe);
446 }