3 * \brief Hardware Acceleration for ATI Radeon cards
6 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
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.
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. */
19 /* most stuff taken from Linux 2.6.13: driver/video/radeon.c */
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>
33 #include "radeon_reg.h"
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
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
81 #define PCI_DEVICE_ID_ATI_RADEON_LY 0x4c59
82 #define PCI_DEVICE_ID_ATI_RADEON_LZ 0x4c5a
84 #define PCI_DEVICE_ID_ATI_RADEON_LW 0x4c57
85 #define PCI_DEVICE_ID_ATI_RADEON_LX 0x4c58
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
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
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
106 static const struct pci_device_id radeon_pci_tbl[] __init =
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},
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
150 #define OUTPLL(addr,val) \
152 OUTREG8(CLOCK_CNTL_INDEX, (addr & 0x0000003f) | 0x00000080); \
153 OUTREG(CLOCK_CNTL_DATA, val); \
156 #define OUTREGP(addr,val,mask) \
158 unsigned int _tmp = INREG(addr); \
161 OUTREG(addr, _tmp); \
164 static l4_addr_t mmio_base = 0;
166 static l4_uint32_t dp_gui_master_cntl;
168 static inline l4_uint32_t INPLL(l4_uint32_t addr)
170 OUTREG8(CLOCK_CNTL_INDEX, addr & 0x0000003f);
171 return (INREG(CLOCK_CNTL_DATA));
175 radeon_engine_flush(void)
180 OUTREGP(RB2D_DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL, ~RB2D_DC_FLUSH_ALL);
182 for (i=0; i < 2000000; i++)
183 if (!(INREG(RB2D_DSTCACHE_CTLSTAT) & RB2D_DC_BUSY))
188 radeon_fifo_wait(unsigned entries)
192 for (i=0; i<2000000; i++)
193 if ((INREG(RBBM_STATUS) & 0x7f) >= entries)
198 radeon_engine_idle(void)
202 /* ensure FIFO is empty before waiting for idle */
203 radeon_fifo_wait (64);
205 for (i=0; i<2000000; i++)
206 if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0)
208 radeon_engine_flush ();
214 radeon_engine_reset(void)
216 l4_uint32_t clock_cntl_index, mclk_cntl, rbbm_soft_reset;
218 radeon_engine_flush ();
220 clock_cntl_index = INREG(CLOCK_CNTL_INDEX);
221 mclk_cntl = INPLL(MCLK_CNTL);
223 OUTPLL(MCLK_CNTL, (mclk_cntl | FORCEON_MCLKA
229 rbbm_soft_reset = INREG(RBBM_SOFT_RESET);
231 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | SOFT_RESET_CP
238 INREG(RBBM_SOFT_RESET);
239 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (l4_uint32_t) ~(SOFT_RESET_CP |
246 INREG(RBBM_SOFT_RESET);
248 OUTPLL(MCLK_CNTL, mclk_cntl);
249 OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index);
250 OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset);
256 radeon_engine_init (void)
260 /* disable 3D engine */
261 OUTREG(RB3D_CNTL, 0);
263 radeon_engine_reset ();
265 radeon_fifo_wait (1);
266 OUTREG(RB2D_DSTCACHE_MODE, 0);
268 radeon_fifo_wait (1);
269 temp = INREG(DEFAULT_PITCH_OFFSET);
270 OUTREG(DEFAULT_PITCH_OFFSET, ((temp & 0xc0000000) | (pitch << 0x16)));
272 radeon_fifo_wait (1);
273 OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN);
275 radeon_fifo_wait (1);
276 OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX |
277 DEFAULT_SC_BOTTOM_MAX));
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;
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));
293 radeon_fifo_wait (7);
295 /* clear line drawing regs */
296 OUTREG(DST_LINE_START, 0);
297 OUTREG(DST_LINE_END, 0);
299 /* set brush color regs */
300 OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff);
301 OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000);
303 /* set source color regs */
304 OUTREG(DP_SRC_FRGD_CLR, 0xffffffff);
305 OUTREG(DP_SRC_BKGD_CLR, 0x00000000);
307 /* default write mask */
308 OUTREG(DP_WRITE_MSK, 0xffffffff);
310 radeon_engine_idle ();
314 radeon_fill(struct l4con_vc *vc,
315 int sx, int sy, int width, int height, unsigned color)
320 OUTREG(DP_GUI_MASTER_CNTL, dp_gui_master_cntl | GMC_BRUSH_SOLID_COLOR
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));
327 OUTREG(DST_Y_X, (sy << 16) | sx);
328 OUTREG(DST_WIDTH_HEIGHT, (width << 16) | height);
332 radeon_copy(struct l4con_vc *vc,
333 int sx, int sy, int width, int height, int dx, int dy)
335 int xdir = sx - dx, ydir = sy - dy;
350 OUTREG(DP_GUI_MASTER_CNTL, dp_gui_master_cntl | GMC_BRUSH_NONE
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));
359 OUTREG(SRC_Y_X, (sy << 16) | sx);
360 OUTREG(DST_Y_X, (dy << 16) | dx);
361 OUTREG(DST_HEIGHT_WIDTH, (height << 16) | width);
365 radeon_pan(int *x, int *y)
368 OUTREG(CRTC_OFFSET, ((*y * hw_xres + *x) * hw_bits / 8) & ~7);
374 radeon_engine_idle();
380 pitch = ((hw_xres * ((hw_bits + 1) / 8) + 0x3f) & ~(0x3f)) / 64;
381 printf("Found ATI Radeon\n");
387 radeon_probe(unsigned int bus, unsigned int devfn,
388 const struct pci_device_id *dev, con_accel_t *accel)
394 PCIBIOS_READ_CONFIG_DWORD (bus, devfn, PCI_BASE_ADDRESS_0, &addr);
398 addr &= PCI_BASE_ADDRESS_MEM_MASK;
400 PCIBIOS_READ_CONFIG_WORD (bus, devfn, PCI_COMMAND, &tmp);
401 if (!(tmp & PCI_COMMAND_MEMORY))
403 tmp |= PCI_COMMAND_MEMORY;
404 PCIBIOS_WRITE_CONFIG_WORD(bus, devfn, PCI_COMMAND, tmp);
407 PCIBIOS_READ_CONFIG_DWORD(bus, devfn, PCI_BASE_ADDRESS_2, &addr);
408 addr &= PCI_BASE_ADDRESS_MEM_MASK;
410 // check if we have enough memory
411 if (hw_vid_mem_size < 7*1024*1024)
413 printf("radeon: graphics memory size less than 8MB (%ldkB)\n",
414 hw_vid_mem_size/1024);
418 if (map_io_mem(addr, 0x4000, 0, "ctrl", (l4_addr_t *)&mmio_base)<0)
423 unmap_io_mem(addr, 0x4000, "ctrl", mmio_base);
427 radeon_engine_init();
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)
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;
443 radeon_register(void)
445 pci_register(radeon_pci_tbl, radeon_probe);