]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4con/server/src/con_hw/ati.c
Inital import
[l4.git] / l4 / pkg / l4con / server / src / con_hw / ati.c
1 /*!
2  * \file        ati.c
3  * \brief       Hardware Acceleration for ATI Mach64 cards
4  *
5  * \date        07/2002
6  * \author      Frank Mehnert <fm3@os.inf.tu-dresden.de> */
7 /*
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.
12  */
13
14 /* most stuff taken from Linux 2.2.21: driver/video/atyfb.c */
15
16 #include <stdio.h>
17
18 #include <l4/sys/types.h>
19 #include <l4/sys/err.h>
20 #include <l4/sys/consts.h>
21 #include <l4/util/util.h>
22
23 #include "init.h"
24 #include "pci.h"
25 #include "iomem.h"
26 #include "ati.h"
27 #include "aty.h"
28
29 struct aty_features 
30 {
31   unsigned short pci_id;
32   unsigned short chip_type;
33   const char *name;
34 };
35
36 static struct aty_features aty_features[] =
37 {
38     /* mach64GX family */
39     { 0x4758, 0x00d7, "mach64GX (ATI888GX00)" },
40     { 0x4358, 0x0057, "mach64CX (ATI888CX00)" },
41
42     /* mach64CT family */
43     { 0x4354, 0x4354, "mach64CT (ATI264CT)" },
44     { 0x4554, 0x4554, "mach64ET (ATI264ET)" },
45
46     /* mach64CT family / mach64VT class */
47     { 0x5654, 0x5654, "mach64VT (ATI264VT)" },
48     { 0x5655, 0x5655, "mach64VTB (ATI264VTB)" },
49     { 0x5656, 0x5656, "mach64VT4 (ATI264VT4)" },
50
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)" },
71 };
72
73 static const struct pci_device_id ati_pci_tbl[] __init =
74 {
75     {PCI_VENDOR_ID_ATI, 0, 0, 0, 0},
76     {0, 0, 0, 0, 0}
77 };
78
79 l4_addr_t ati_regbase = 0;
80 unsigned blitter_may_be_busy = 0;
81 int ati_supports_planar = 0;
82
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;
87
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 */
93 void
94 ati_test_for_card_disappeared(void)
95 {
96   if (aty_ld_le32(FIFO_STAT) == 0xffffffff)
97     {
98       unsigned short tmp;
99       
100       printf("ATI video card disappered -- re-mapping memory mapped "
101              "  registers.\n");
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);
105     }
106 }
107
108 static void 
109 reset_engine(void)
110 {
111   /* reset engine */
112   aty_st_le32(GEN_TEST_CNTL,
113               aty_ld_le32(GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE);
114   /* enable engine */
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 */
118   /* HOST errors */
119   aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL) | BUS_HOST_ERR_ACK |
120               BUS_FIFO_ERR_ACK);
121 }
122
123 static void 
124 reset_GTC_3D_engine(void)
125 {
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);
132 }
133
134 static void 
135 init_engine(void)
136 {
137   unsigned pitch_value;
138   unsigned dp_pix_width, dp_chain_mask;
139
140   /* determine modal information from global mode structure */
141   pitch_value = hw_xres;
142
143   if (hw_bits <= 8)
144     {
145       hw_bits = 8;
146       dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
147       dp_chain_mask = 0x8080;
148     }
149   else if (hw_bits <= 16)
150     {
151       hw_bits = 16;
152       dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | BYTE_ORDER_LSB_TO_MSB;
153       dp_chain_mask = 0x4210;
154     }
155   else if (hw_bits <= 24)
156     {
157       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 */
160       pitch_value *= 3;
161       dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | BYTE_ORDER_LSB_TO_MSB;
162       dp_chain_mask = 0x8080;
163     }
164   else
165     {
166       hw_bits = 32;
167       dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | BYTE_ORDER_LSB_TO_MSB;
168       dp_chain_mask = 0x8080;
169     }
170
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();
177
178   /* Reset engine, enable, and clear any engine errors */
179   reset_engine();
180
181   /* Ensure that vga page pointers are set to zero - the upper */
182   /* page pointers are set to 1 to handle overflows in the */
183   /* lower page */
184   aty_st_le32(MEM_VGA_WP_SEL, 0x00010000);
185   aty_st_le32(MEM_VGA_RP_SEL, 0x00010000);
186
187   /* ---- Setup standard engine context ---- */
188
189   /* All GUI registers here are FIFOed - therefore, wait for */
190   /* the appropriate number of empty FIFO entries */
191   wait_for_fifo(14);
192
193   /* enable all registers to be loaded for context loads */
194   aty_st_le32(CONTEXT_MASK, 0xFFFFFFFF);
195
196   /* set destination pitch to modal pitch, set offset to zero */
197   aty_st_le32(DST_OFF_PITCH, (pitch_value / 8) << 22);
198
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);
205
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);
209
210   /* set source pitch to modal pitch, set offset to zero */
211   aty_st_le32(SRC_OFF_PITCH, (pitch_value / 8) << 22);
212
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);
218
219   /* set source pixel retrieving attributes */
220   aty_st_le32(SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
221
222   /* set host attributes */
223   wait_for_fifo(13);
224   aty_st_le32(HOST_CNTL, 0);
225
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);
230
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);
236
237   /* set background color to minimum value (usually BLACK) */
238   aty_st_le32(DP_BKGD_CLR, 0);
239
240   /* set foreground color to maximum value (usually WHITE) */
241   aty_st_le32(DP_FRGD_CLR, 0xFFFFFFFF);
242
243   /* set write mask to effect all pixel bits */
244   aty_st_le32(DP_WRITE_MASK, 0xFFFFFFFF);
245   
246   /* set foreground mix to overpaint and background mix to */
247   /* no-effect */
248   aty_st_le32(DP_MIX, FRGD_MIX_S | BKGD_MIX_D);
249
250   /* set primary source pixel channel to foreground color */
251   /* register */
252   aty_st_le32(DP_SRC, FRGD_SRC_FRGD_CLR);
253
254   /* set compare functionality to false (no-effect on */
255   /* destination) */
256   wait_for_fifo(3);
257   aty_st_le32(CLR_CMP_CLR, 0);
258   aty_st_le32(CLR_CMP_MASK, 0xFFFFFFFF);
259   aty_st_le32(CLR_CMP_CNTL, 0);
260
261   /* set pixel depth */
262   wait_for_fifo(2);
263   aty_st_le32(DP_PIX_WIDTH, dp_pix_width);
264   aty_st_le32(DP_CHAIN_MASK, dp_chain_mask);
265
266   wait_for_fifo(5);
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);
271
272   /* insure engine is idle before leaving */
273   wait_for_idle();
274 }
275
276 static inline void 
277 draw_rect(short x, short y, unsigned short width, unsigned short height)
278 {
279   /* perform rectangle fill */
280   wait_for_fifo(2);
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;
284 }
285
286 /* exported: wait until graphics engine is idle */
287 static void
288 ati_pan(int *x, int *y)
289 {
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;
294
295   if (bpp == 24)
296     {
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);
305     }
306   
307   wait_for_fifo(3);
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));
313 }
314
315 static void 
316 ati_bmove(struct l4con_vc *vc,
317           int sx, int sy, int width, int height, int dx, int dy)
318 {
319   (void)vc;
320   unsigned direction = DST_LAST_PEL;
321
322   if (hw_bits == 24)
323     {
324       /* In 24 bpp, the engine is in 8 bpp - this requires that all */
325       /* horizontal coordinates and widths must be adjusted */
326       sx *= 3;
327       dx *= 3;
328       width *= 3;
329     }
330
331   if (sy < dy) 
332     {
333       dy += height - 1;
334       sy += height - 1;
335     } 
336   else
337     direction |= DST_Y_TOP_TO_BOTTOM;
338   
339   if (sx < dx) 
340     {
341       dx += width - 1;
342       sx += width - 1;
343     } 
344   else
345     direction |= DST_X_LEFT_TO_RIGHT;
346
347   wait_for_fifo(4);
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);
353 }
354
355 static void 
356 ati_fill(struct l4con_vc *vc,
357          int sx, int sy, int width, int height, unsigned color)
358 {
359   (void)vc;
360   if (hw_bits == 24)
361     {
362       /* In 24 bpp, the engine is in 8 bpp - this requires that all */
363       /* horizontal coordinates and widths must be adjusted */
364       sx *= 3;
365       width *= 3;
366     }
367
368   wait_for_fifo(3);
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);
374 }
375
376 static void
377 ati_sync(void)
378 {
379   if (blitter_may_be_busy)
380     wait_for_idle();
381 }
382
383 static int
384 ati_init(void)
385 {
386   unsigned chip_id, j;
387   const char *chipname = NULL;
388   
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) 
394       {
395         chipname = aty_features[j].name;
396         break;
397       }
398   
399   if (!chipname)
400     return 0;
401
402   printf("Found ATI %s [0x%04x rev 0x%02x] (PCI %02x/%02x)\n", 
403         chipname, Gx, Rev, ati_pci_bus, ati_pci_devfn);
404
405   return 1;
406 }
407
408 static int
409 ati_probe(unsigned int bus, unsigned int devfn,
410           const struct pci_device_id *dev, con_accel_t *accel)
411 {
412   unsigned int addr;
413   unsigned short tmp;
414
415   (void)dev;
416
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);
420
421   if (!addr)
422     return -L4_ENODEV;
423
424   addr &= PCI_BASE_ADDRESS_MEM_MASK;
425
426   PCIBIOS_READ_CONFIG_WORD(bus, devfn, PCI_COMMAND, &tmp);
427   if (!(tmp & PCI_COMMAND_MEMORY)) 
428     {
429       tmp |= PCI_COMMAND_MEMORY;
430       PCIBIOS_WRITE_CONFIG_WORD(bus, devfn, PCI_COMMAND, tmp);
431     }
432
433   PCIBIOS_READ_CONFIG_DWORD(bus, devfn, PCI_BASE_ADDRESS_2, &addr);
434   addr &= PCI_BASE_ADDRESS_MEM_MASK;
435
436   // check if we have enough memory
437   if (hw_vid_mem_size < 7*1024*1024)
438     {
439       printf("ati: graphics memory size less than 8MB (%ldkB)\n",
440           hw_vid_mem_size/1024);
441       return -L4_ENODEV;
442     }
443
444   if (map_io_mem(addr, 0x1000, 0, "ctrl", &ati_regbase)<0)
445     return -L4_ENODEV;
446
447   ati_pci_bus = bus;
448   ati_pci_devfn = devfn;
449   ati_regbase += 0x400;
450
451   if (!ati_init())
452     {
453       unmap_io_mem(addr, 0x1000, "ctrl", ati_regbase-0x400);
454       return -L4_ENODEV;
455     }
456
457   init_engine();
458
459   if (map_io_mem(hw_vid_mem_addr, hw_vid_mem_size, 1, "video",
460                  &hw_map_vid_mem_addr)<0)
461     return -L4_ENODEV;
462
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;
468
469   ati_vid_init(accel);
470
471   return 0;
472 }
473
474 void
475 ati_register(void)
476 {
477   pci_register(ati_pci_tbl, ati_probe);
478 }
479