3 * \brief Hardware Acceleration for ATI Mach64 cards
6 * \author Frank Mehnert <fm3@os.inf.tu-dresden.de> */
8 * (c) 2002-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 /* most stuff taken from Linux 2.2.21: driver/video/atyfb.c */
18 #include <l4/sys/types.h>
19 #include <l4/sys/err.h>
20 #include <l4/sys/consts.h>
21 #include <l4/util/util.h>
31 unsigned short pci_id;
32 unsigned short chip_type;
36 static struct aty_features aty_features[] =
39 { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
40 { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
43 { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
44 { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
46 /* mach64CT family / mach64VT class */
47 { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
48 { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
49 { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
51 /* mach64CT family / mach64GT (3D RAGE) class */
52 { 0x4c42, 0x4c42, "3D RAGE LT PRO (AGP)" },
53 { 0x4c44, 0x4c44, "3D RAGE LT PRO" },
54 { 0x4c47, 0x4c47, "3D RAGE LT-G" },
55 { 0x4c49, 0x4c49, "3D RAGE LT PRO" },
56 { 0x4c50, 0x4c50, "3D RAGE LT PRO" },
57 { 0x4c54, 0x4c54, "3D RAGE LT" },
58 { 0x4752, 0x4752, "3D RAGE (XL)" },
59 { 0x4754, 0x4754, "3D RAGE (GT)" },
60 { 0x4755, 0x4755, "3D RAGE II+ (GTB)" },
61 { 0x4756, 0x4756, "3D RAGE IIC (PCI)" },
62 { 0x4757, 0x4757, "3D RAGE IIC (AGP)" },
63 { 0x475a, 0x475a, "3D RAGE IIC (AGP)" },
64 { 0x4742, 0x4742, "3D RAGE PRO (BGA, AGP)" },
65 { 0x4744, 0x4744, "3D RAGE PRO (BGA, AGP, 1x only)" },
66 { 0x4749, 0x4749, "3D RAGE PRO (BGA, PCI)" },
67 { 0x4750, 0x4750, "3D RAGE PRO (PQFP, PCI)" },
68 { 0x4751, 0x4751, "3D RAGE PRO (PQFP, PCI, limited 3D)" },
69 { 0x4c4d, 0x4c4d, "3D RAGE Mobility (PCI)" },
70 { 0x4c4e, 0x4c4e, "3D RAGE Mobility (AGP)" },
73 static const struct pci_device_id ati_pci_tbl[] __init =
75 {PCI_VENDOR_ID_ATI, 0, 0, 0, 0},
79 l4_addr_t ati_regbase = 0;
80 unsigned blitter_may_be_busy = 0;
81 int ati_supports_planar = 0;
83 static unsigned ati_pci_bus = 0;
84 static unsigned ati_pci_devfn = 0;
85 static unsigned short Gx = 0;
86 static unsigned char Rev = 0;
88 /* While we don't have I/O flexpages in Fiasco, we can't prohibit other
89 * L4 tasks to write to I/O ports. In that case it is possible, that
90 * we start X in L4Linux which does some things with the PCI configuration
91 * area of our graphics card so that it's memory mapped registers are
92 * no longer mapped. Test this case here and get back registers if needed */
94 ati_test_for_card_disappeared(void)
96 if (aty_ld_le32(FIFO_STAT) == 0xffffffff)
100 printf("ATI video card disappered -- re-mapping memory mapped "
102 PCIBIOS_READ_CONFIG_WORD(ati_pci_bus, ati_pci_devfn, PCI_COMMAND, &tmp);
103 tmp |= PCI_COMMAND_MEMORY;
104 PCIBIOS_WRITE_CONFIG_WORD(ati_pci_bus, ati_pci_devfn, PCI_COMMAND, tmp);
112 aty_st_le32(GEN_TEST_CNTL,
113 aty_ld_le32(GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE);
115 aty_st_le32(GEN_TEST_CNTL,
116 aty_ld_le32(GEN_TEST_CNTL) | GUI_ENGINE_ENABLE);
117 /* ensure engine is not locked up by clearing any FIFO or */
119 aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_HOST_ERR_ACK |
124 reset_GTC_3D_engine(void)
126 aty_st_le32(SCALE_3D_CNTL, 0xc0);
127 l4_sleep(GTC_3D_RESET_DELAY);
128 aty_st_le32(SETUP_CNTL, 0x00);
129 l4_sleep(GTC_3D_RESET_DELAY);
130 aty_st_le32(SCALE_3D_CNTL, 0x00);
131 l4_sleep(GTC_3D_RESET_DELAY);
137 unsigned pitch_value;
138 unsigned dp_pix_width, dp_chain_mask;
140 /* determine modal information from global mode structure */
141 pitch_value = hw_xres;
146 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
147 dp_chain_mask = 0x8080;
149 else if (hw_bits <= 16)
152 dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | BYTE_ORDER_LSB_TO_MSB;
153 dp_chain_mask = 0x4210;
155 else if (hw_bits <= 24)
158 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
159 /* horizontal coordinates and widths must be adjusted */
161 dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
162 dp_chain_mask = 0x8080;
167 dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | BYTE_ORDER_LSB_TO_MSB;
168 dp_chain_mask = 0x8080;
171 /* On GTC (RagePro), we need to reset the 3D engine first */
172 if (Gx == LB_CHIP_ID || Gx == LD_CHIP_ID || Gx == LI_CHIP_ID ||
173 Gx == LP_CHIP_ID || Gx == GB_CHIP_ID || Gx == GD_CHIP_ID ||
174 Gx == GI_CHIP_ID || Gx == GP_CHIP_ID || Gx == GQ_CHIP_ID ||
175 Gx == LM_CHIP_ID || Gx == LN_CHIP_ID)
176 reset_GTC_3D_engine();
178 /* Reset engine, enable, and clear any engine errors */
181 /* Ensure that vga page pointers are set to zero - the upper */
182 /* page pointers are set to 1 to handle overflows in the */
184 aty_st_le32(MEM_VGA_WP_SEL, 0x00010000);
185 aty_st_le32(MEM_VGA_RP_SEL, 0x00010000);
187 /* ---- Setup standard engine context ---- */
189 /* All GUI registers here are FIFOed - therefore, wait for */
190 /* the appropriate number of empty FIFO entries */
193 /* enable all registers to be loaded for context loads */
194 aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF);
196 /* set destination pitch to modal pitch, set offset to zero */
197 aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22);
199 /* zero these registers (set them to a known state) */
200 aty_st_le32(DST_Y_X, 0);
201 aty_st_le32(DST_HEIGHT, 0);
202 aty_st_le32(DST_BRES_ERR, 0);
203 aty_st_le32(DST_BRES_INC, 0);
204 aty_st_le32(DST_BRES_DEC, 0);
206 /* set destination drawing attributes */
207 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
208 DST_X_LEFT_TO_RIGHT);
210 /* set source pitch to modal pitch, set offset to zero */
211 aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22);
213 /* set these registers to a known state */
214 aty_st_le32(SRC_Y_X, 0);
215 aty_st_le32(SRC_HEIGHT1_WIDTH1, 1);
216 aty_st_le32(SRC_Y_X_START, 0);
217 aty_st_le32(SRC_HEIGHT2_WIDTH2, 1);
219 /* set source pixel retrieving attributes */
220 aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
222 /* set host attributes */
224 aty_st_le32(HOST_CNTL, 0);
226 /* set pattern attributes */
227 aty_st_le32(PAT_REG0, 0);
228 aty_st_le32(PAT_REG1, 0);
229 aty_st_le32(PAT_CNTL, 0);
231 /* set scissors to modal size */
232 aty_st_le32(SC_LEFT, 0);
233 aty_st_le32(SC_TOP, 0);
234 aty_st_le32(SC_BOTTOM, hw_yres-1);
235 aty_st_le32(SC_RIGHT, pitch_value-1);
237 /* set background color to minimum value (usually BLACK) */
238 aty_st_le32(DP_BKGD_CLR, 0);
240 /* set foreground color to maximum value (usually WHITE) */
241 aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF);
243 /* set write mask to effect all pixel bits */
244 aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
246 /* set foreground mix to overpaint and background mix to */
248 aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D);
250 /* set primary source pixel channel to foreground color */
252 aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR);
254 /* set compare functionality to false (no-effect on */
257 aty_st_le32(CLR_CMP_CLR, 0);
258 aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF);
259 aty_st_le32(CLR_CMP_CNTL, 0);
261 /* set pixel depth */
263 aty_st_le32(DP_PIX_WIDTH, dp_pix_width);
264 aty_st_le32(DP_CHAIN_MASK, dp_chain_mask);
267 aty_st_le32(SCALE_3D_CNTL, 0);
268 aty_st_le32(Z_CNTL, 0);
269 aty_st_le32(CRTC_INT_CNTL, aty_ld_le32(CRTC_INT_CNTL) & ~0x20);
270 aty_st_le32(GUI_TRAJ_CNTL, 0x100023);
272 /* insure engine is idle before leaving */
277 draw_rect(short x, short y, unsigned short width, unsigned short height)
279 /* perform rectangle fill */
281 aty_st_le32(DST_Y_X, (x << 16) | y);
282 aty_st_le32(DST_HEIGHT_WIDTH, (width << 16) | height);
283 blitter_may_be_busy = 1;
286 /* exported: wait until graphics engine is idle */
288 ati_pan(int *x, int *y)
290 unsigned bpp = (hw_bits + 1) & ~7;
291 unsigned offset = ((*y * hw_xres + *x) * bpp / 64);
292 unsigned margin_left = *x;
293 unsigned margin_right = *x + hw_xres;
297 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
298 /* horizontal coordinates and widths must be adjusted.
299 * The offset value has to been corrected so that it is dividable
300 * by 3 because we have 3 bytes per pixel (packed). */
301 offset = (offset / 3) * 3;
302 *x = (64*offset)/bpp - *y*hw_xres;
303 margin_left = 3 * *x;
304 margin_right = 3 * (*x + hw_xres);
308 aty_st_le32(SC_TOP, *y);
309 aty_st_le32(SC_BOTTOM, *y+hw_yres-1);
310 aty_st_le32(SC_LEFT, margin_left);
311 aty_st_le32(SC_RIGHT, margin_right);
312 aty_st_le32(CRTC_OFF_PITCH, offset | (hw_xres << 19));
316 ati_bmove(struct l4con_vc *vc,
317 int sx, int sy, int width, int height, int dx, int dy)
320 unsigned direction = DST_LAST_PEL;
324 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
325 /* horizontal coordinates and widths must be adjusted */
337 direction |= DST_Y_TOP_TO_BOTTOM;
345 direction |= DST_X_LEFT_TO_RIGHT;
348 aty_st_le32(DP_SRC, FRGD_SRC_BLIT);
349 aty_st_le32(SRC_Y_X, (sx << 16) | sy);
350 aty_st_le32(SRC_HEIGHT1_WIDTH1, (width << 16) | height);
351 aty_st_le32(DST_CNTL, direction);
352 draw_rect(dx, dy, width, height);
356 ati_fill(struct l4con_vc *vc,
357 int sx, int sy, int width, int height, unsigned color)
362 /* In 24 bpp, the engine is in 8 bpp - this requires that all */
363 /* horizontal coordinates and widths must be adjusted */
369 aty_st_le32(DP_FRGD_CLR, color);
370 aty_st_le32(DP_SRC, BKGD_SRC_BKGD_CLR | FRGD_SRC_FRGD_CLR | MONO_SRC_ONE);
371 aty_st_le32(DST_CNTL, DST_LAST_PEL | DST_Y_TOP_TO_BOTTOM |
372 DST_X_LEFT_TO_RIGHT);
373 draw_rect(sx, sy, width, height);
379 if (blitter_may_be_busy)
387 const char *chipname = NULL;
389 chip_id = aty_ld_le32(CONFIG_CHIP_ID);
390 Gx = chip_id & CFG_CHIP_TYPE;
391 Rev = (chip_id & CFG_CHIP_REV)>>24;
392 for (j = 0; j < (sizeof(aty_features)/sizeof(*aty_features)); j++)
393 if (aty_features[j].chip_type == Gx)
395 chipname = aty_features[j].name;
402 printf("Found ATI %s [0x%04x rev 0x%02x] (PCI %02x/%02x)\n",
403 chipname, Gx, Rev, ati_pci_bus, ati_pci_devfn);
409 ati_probe(unsigned int bus, unsigned int devfn,
410 const struct pci_device_id *dev, con_accel_t *accel)
417 PCIBIOS_READ_CONFIG_DWORD (bus, devfn, PCI_BASE_ADDRESS_0, &addr);
418 if ((addr & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
419 PCIBIOS_READ_CONFIG_DWORD (bus, devfn, PCI_BASE_ADDRESS_1, &addr);
424 addr &= PCI_BASE_ADDRESS_MEM_MASK;
426 PCIBIOS_READ_CONFIG_WORD(bus, devfn, PCI_COMMAND, &tmp);
427 if (!(tmp & PCI_COMMAND_MEMORY))
429 tmp |= PCI_COMMAND_MEMORY;
430 PCIBIOS_WRITE_CONFIG_WORD(bus, devfn, PCI_COMMAND, tmp);
433 PCIBIOS_READ_CONFIG_DWORD(bus, devfn, PCI_BASE_ADDRESS_2, &addr);
434 addr &= PCI_BASE_ADDRESS_MEM_MASK;
436 // check if we have enough memory
437 if (hw_vid_mem_size < 7*1024*1024)
439 printf("ati: graphics memory size less than 8MB (%ldkB)\n",
440 hw_vid_mem_size/1024);
444 if (map_io_mem(addr, 0x1000, 0, "ctrl", &ati_regbase)<0)
448 ati_pci_devfn = devfn;
449 ati_regbase += 0x400;
453 unmap_io_mem(addr, 0x1000, "ctrl", ati_regbase-0x400);
459 if (map_io_mem(hw_vid_mem_addr, hw_vid_mem_size, 1, "video",
460 &hw_map_vid_mem_addr)<0)
463 accel->copy = ati_bmove;
464 accel->fill = ati_fill;
465 accel->sync = ati_sync;
466 accel->pan = ati_pan;
467 accel->caps = ACCEL_FAST_COPY | ACCEL_FAST_FILL;
477 pci_register(ati_pci_tbl, ati_probe);