]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - drivers/video/ati_radeon_fb.c
Merge branch 'u-boot/master' into u-boot-arm/master
[karo-tx-uboot.git] / drivers / video / ati_radeon_fb.c
1 /*
2  * ATI Radeon Video card Framebuffer driver.
3  *
4  * Copyright 2007 Freescale Semiconductor, Inc.
5  * Zhang Wei <wei.zhang@freescale.com>
6  * Jason Jin <jason.jin@freescale.com>
7  *
8  * SPDX-License-Identifier:     GPL-2.0+
9  *
10  * Some codes of this file is partly ported from Linux kernel
11  * ATI video framebuffer driver.
12  *
13  * Now the driver is tested on below ATI chips:
14  *   9200
15  *   X300
16  *   X700
17  */
18
19 #include <common.h>
20
21 #include <command.h>
22 #include <pci.h>
23 #include <asm/processor.h>
24 #include <asm/errno.h>
25 #include <asm/io.h>
26 #include <malloc.h>
27 #include <video_fb.h>
28 #include "videomodes.h"
29
30 #include <radeon.h>
31 #include "ati_ids.h"
32 #include "ati_radeon_fb.h"
33
34 #undef DEBUG
35
36 #ifdef DEBUG
37 #define DPRINT(x...) printf(x)
38 #else
39 #define DPRINT(x...) do{}while(0)
40 #endif
41
42 #ifndef min_t
43 #define min_t(type,x,y) \
44         ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
45 #endif
46
47 #define MAX_MAPPED_VRAM (2048*2048*4)
48 #define MIN_MAPPED_VRAM (1024*768*1)
49
50 #define RADEON_BUFFER_ALIGN             0x00000fff
51 #define SURF_UPPER_BOUND(x,y,bpp)       (((((x) * (((y) + 15) & ~15) * (bpp)/8) + RADEON_BUFFER_ALIGN) \
52                                           & ~RADEON_BUFFER_ALIGN) - 1)
53 #define RADEON_CRT_PITCH(width, bpp)    ((((width) * (bpp) + ((bpp) * 8 - 1)) / ((bpp) * 8)) | \
54                                          ((((width) * (bpp) + ((bpp) * 8 - 1)) / ((bpp) * 8)) << 16))
55
56 #define CRTC_H_TOTAL_DISP_VAL(htotal, hdisp) \
57                 (((((htotal) / 8) - 1) & 0x3ff) | (((((hdisp) / 8) - 1) & 0x1ff) << 16))
58 #define CRTC_HSYNC_STRT_WID_VAL(hsync_srtr, hsync_wid) \
59                 (((hsync_srtr) & 0x1fff) | (((hsync_wid) & 0x3f) << 16))
60 #define CRTC_V_TOTAL_DISP_VAL(vtotal, vdisp) \
61                 ((((vtotal) - 1) & 0xffff) | (((vdisp) - 1) << 16))
62 #define CRTC_VSYNC_STRT_WID_VAL(vsync_srtr, vsync_wid) \
63                 ((((vsync_srtr) - 1) & 0xfff) | (((vsync_wid) & 0x1f) << 16))
64
65 /*#define PCI_VENDOR_ID_ATI*/
66 #define PCI_CHIP_RV280_5960             0x5960
67 #define PCI_CHIP_RV280_5961             0x5961
68 #define PCI_CHIP_RV280_5962             0x5962
69 #define PCI_CHIP_RV280_5964             0x5964
70 #define PCI_CHIP_RV280_5C63             0x5C63
71 #define PCI_CHIP_RV370_5B60             0x5B60
72 #define PCI_CHIP_RV380_5657             0x5657
73 #define PCI_CHIP_R420_554d              0x554d
74
75 static struct pci_device_id ati_radeon_pci_ids[] = {
76         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5960},
77         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
78         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
79         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
80         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5C63},
81         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
82         {PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
83         {PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
84         {0, 0}
85 };
86
87 static u16 ati_radeon_id_family_table[][2] = {
88         {PCI_CHIP_RV280_5960, CHIP_FAMILY_RV280},
89         {PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
90         {PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
91         {PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
92         {PCI_CHIP_RV280_5C63, CHIP_FAMILY_RV280},
93         {PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
94         {PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
95         {PCI_CHIP_R420_554d,  CHIP_FAMILY_R420},
96         {0, 0}
97 };
98
99 u16 get_radeon_id_family(u16 device)
100 {
101         int i;
102         for (i=0; ati_radeon_id_family_table[0][i]; i+=2)
103                 if (ati_radeon_id_family_table[0][i] == device)
104                         return ati_radeon_id_family_table[0][i + 1];
105         return 0;
106 }
107
108 struct radeonfb_info *rinfo;
109
110 static void radeon_identify_vram(struct radeonfb_info *rinfo)
111 {
112         u32 tmp;
113
114         /* framebuffer size */
115         if ((rinfo->family == CHIP_FAMILY_RS100) ||
116                 (rinfo->family == CHIP_FAMILY_RS200) ||
117                 (rinfo->family == CHIP_FAMILY_RS300)) {
118                 u32 tom = INREG(NB_TOM);
119                 tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
120
121                 radeon_fifo_wait(6);
122                 OUTREG(MC_FB_LOCATION, tom);
123                 OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
124                 OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
125                 OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
126
127                 /* This is supposed to fix the crtc2 noise problem. */
128                 OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
129
130                 if ((rinfo->family == CHIP_FAMILY_RS100) ||
131                         (rinfo->family == CHIP_FAMILY_RS200)) {
132                 /* This is to workaround the asic bug for RMX, some versions
133                    of BIOS dosen't have this register initialized correctly.
134                 */
135                         OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
136                                 ~CRTC_H_CUTOFF_ACTIVE_EN);
137                 }
138         } else {
139                 tmp = INREG(CONFIG_MEMSIZE);
140         }
141
142         /* mem size is bits [28:0], mask off the rest */
143         rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
144
145         /*
146          * Hack to get around some busted production M6's
147          * reporting no ram
148          */
149         if (rinfo->video_ram == 0) {
150                 switch (rinfo->pdev.device) {
151                 case PCI_CHIP_RADEON_LY:
152                 case PCI_CHIP_RADEON_LZ:
153                         rinfo->video_ram = 8192 * 1024;
154                         break;
155                 default:
156                         break;
157                 }
158         }
159
160         /*
161          * Now try to identify VRAM type
162          */
163         if ((rinfo->family >= CHIP_FAMILY_R300) ||
164             (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
165                 rinfo->vram_ddr = 1;
166         else
167                 rinfo->vram_ddr = 0;
168
169         tmp = INREG(MEM_CNTL);
170         if (IS_R300_VARIANT(rinfo)) {
171                 tmp &=  R300_MEM_NUM_CHANNELS_MASK;
172                 switch (tmp) {
173                 case 0:  rinfo->vram_width = 64; break;
174                 case 1:  rinfo->vram_width = 128; break;
175                 case 2:  rinfo->vram_width = 256; break;
176                 default: rinfo->vram_width = 128; break;
177                 }
178         } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
179                    (rinfo->family == CHIP_FAMILY_RS100) ||
180                    (rinfo->family == CHIP_FAMILY_RS200)){
181                 if (tmp & RV100_MEM_HALF_MODE)
182                         rinfo->vram_width = 32;
183                 else
184                         rinfo->vram_width = 64;
185         } else {
186                 if (tmp & MEM_NUM_CHANNELS_MASK)
187                         rinfo->vram_width = 128;
188                 else
189                         rinfo->vram_width = 64;
190         }
191
192         /* This may not be correct, as some cards can have half of channel disabled
193          * ToDo: identify these cases
194          */
195
196         DPRINT("radeonfb: Found %dk of %s %d bits wide videoram\n",
197                rinfo->video_ram / 1024,
198                rinfo->vram_ddr ? "DDR" : "SDRAM",
199                rinfo->vram_width);
200
201 }
202
203 static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
204 {
205         int i;
206
207         radeon_fifo_wait(20);
208
209 #if 0
210         /* Workaround from XFree */
211         if (rinfo->is_mobility) {
212                 /* A temporal workaround for the occational blanking on certain laptop
213                  * panels. This appears to related to the PLL divider registers
214                  * (fail to lock?). It occurs even when all dividers are the same
215                  * with their old settings. In this case we really don't need to
216                  * fiddle with PLL registers. By doing this we can avoid the blanking
217                  * problem with some panels.
218                  */
219                 if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
220                     (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
221                                           (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
222                         /* We still have to force a switch to selected PPLL div thanks to
223                          * an XFree86 driver bug which will switch it away in some cases
224                          * even when using UseFDev */
225                         OUTREGP(CLOCK_CNTL_INDEX,
226                                 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
227                                 ~PPLL_DIV_SEL_MASK);
228                         radeon_pll_errata_after_index(rinfo);
229                         radeon_pll_errata_after_data(rinfo);
230                         return;
231                 }
232         }
233 #endif
234         if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
235
236         /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
237         OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
238
239         /* Reset PPLL & enable atomic update */
240         OUTPLLP(PPLL_CNTL,
241                 PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
242                 ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
243
244         /* Switch to selected PPLL divider */
245         OUTREGP(CLOCK_CNTL_INDEX,
246                 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
247                 ~PPLL_DIV_SEL_MASK);
248
249         /* Set PPLL ref. div */
250         if (rinfo->family == CHIP_FAMILY_R300 ||
251             rinfo->family == CHIP_FAMILY_RS300 ||
252             rinfo->family == CHIP_FAMILY_R350 ||
253             rinfo->family == CHIP_FAMILY_RV350) {
254                 if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
255                         /* When restoring console mode, use saved PPLL_REF_DIV
256                          * setting.
257                          */
258                         OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
259                 } else {
260                         /* R300 uses ref_div_acc field as real ref divider */
261                         OUTPLLP(PPLL_REF_DIV,
262                                 (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
263                                 ~R300_PPLL_REF_DIV_ACC_MASK);
264                 }
265         } else
266                 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
267
268         /* Set PPLL divider 3 & post divider*/
269         OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
270         OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
271
272         /* Write update */
273         while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
274                 ;
275         OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
276
277         /* Wait read update complete */
278         /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
279            the cause yet, but this workaround will mask the problem for now.
280            Other chips usually will pass at the very first test, so the
281            workaround shouldn't have any effect on them. */
282         for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
283                 ;
284
285         OUTPLL(HTOTAL_CNTL, 0);
286
287         /* Clear reset & atomic update */
288         OUTPLLP(PPLL_CNTL, 0,
289                 ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
290
291         /* We may want some locking ... oh well */
292         udelay(5000);
293
294         /* Switch back VCLK source to PPLL */
295         OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
296 }
297
298 typedef struct {
299         u16 reg;
300         u32 val;
301 } reg_val;
302
303 #if 0   /* unused ? -> scheduled for removal */
304 /* these common regs are cleared before mode setting so they do not
305  * interfere with anything
306  */
307 static reg_val common_regs[] = {
308         { OVR_CLR, 0 },
309         { OVR_WID_LEFT_RIGHT, 0 },
310         { OVR_WID_TOP_BOTTOM, 0 },
311         { OV0_SCALE_CNTL, 0 },
312         { SUBPIC_CNTL, 0 },
313         { VIPH_CONTROL, 0 },
314         { I2C_CNTL_1, 0 },
315         { GEN_INT_CNTL, 0 },
316         { CAP0_TRIG_CNTL, 0 },
317         { CAP1_TRIG_CNTL, 0 },
318 };
319 #endif /* 0 */
320
321 void radeon_setmode(void)
322 {
323         struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
324
325         mode->crtc_gen_cntl = 0x03000200;
326         mode->crtc_ext_cntl = 0x00008048;
327         mode->dac_cntl = 0xff002100;
328         mode->crtc_h_total_disp = 0x4f0063;
329         mode->crtc_h_sync_strt_wid = 0x8c02a2;
330         mode->crtc_v_total_disp = 0x01df020c;
331         mode->crtc_v_sync_strt_wid = 0x8201ea;
332         mode->crtc_pitch = 0x00500050;
333
334         OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
335         OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
336                 ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
337         OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
338         OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
339         OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
340         OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
341         OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
342         OUTREG(CRTC_OFFSET, 0);
343         OUTREG(CRTC_OFFSET_CNTL, 0);
344         OUTREG(CRTC_PITCH, mode->crtc_pitch);
345
346         mode->clk_cntl_index = 0x300;
347         mode->ppll_ref_div = 0xc;
348         mode->ppll_div_3 = 0x00030059;
349
350         radeon_write_pll_regs(rinfo, mode);
351 }
352
353 static void set_pal(void)
354 {
355         int idx, val = 0;
356
357         for (idx = 0; idx < 256; idx++) {
358                 OUTREG8(PALETTE_INDEX, idx);
359                 OUTREG(PALETTE_DATA, val);
360                 val += 0x00010101;
361         }
362 }
363
364 void radeon_setmode_9200(int vesa_idx, int bpp)
365 {
366         struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
367
368         mode->crtc_gen_cntl = CRTC_EN | CRTC_EXT_DISP_EN;
369         mode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON;
370         mode->dac_cntl = DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN;
371         mode->crtc_offset_cntl = CRTC_OFFSET_CNTL__CRTC_TILE_EN;
372
373         switch (bpp) {
374         case 24:
375                 mode->crtc_gen_cntl |= 0x6 << 8; /* x888 */
376 #if defined(__BIG_ENDIAN)
377                 mode->surface_cntl = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
378                 mode->surf_info[0] = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
379 #endif
380                 break;
381         case 16:
382                 mode->crtc_gen_cntl |= 0x4 << 8; /* 565 */
383 #if defined(__BIG_ENDIAN)
384                 mode->surface_cntl = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
385                 mode->surf_info[0] = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
386 #endif
387                 break;
388         default:
389                 mode->crtc_gen_cntl |= 0x2 << 8; /* palette */
390                 mode->surface_cntl = 0x00000000;
391                 break;
392         }
393
394         switch (vesa_idx) {
395         case RES_MODE_1280x1024:
396                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1688,1280);
397                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(1066,1024);
398                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(1025,3);
399 #if defined(CONFIG_RADEON_VREFRESH_75HZ)
400                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1288,18);
401                 mode->ppll_div_3 = 0x00010078;
402 #else /* default @ 60 Hz */
403                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1320,14);
404                 mode->ppll_div_3 = 0x00010060;
405 #endif
406                 /*
407                  * for this mode pitch expands to the same value for 32, 16 and 8 bpp,
408                  * so we set it here once only.
409                  */
410                 mode->crtc_pitch = RADEON_CRT_PITCH(1280,32);
411                 switch (bpp) {
412                 case 24:
413                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 4 / 16);
414                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,32);
415                         break;
416                 case 16:
417                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 2 / 16);
418                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,16);
419                         break;
420                 default: /* 8 bpp */
421                         mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1280 * 1 / 16);
422                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,8);
423                         break;
424                 }
425                 break;
426         case RES_MODE_1024x768:
427 #if defined(CONFIG_RADEON_VREFRESH_75HZ)
428                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1312,1024);
429                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1032,12);
430                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(800,768);
431                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(769,3);
432                 mode->ppll_div_3 = 0x0002008c;
433 #else /* @ 60 Hz */
434                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1344,1024);
435                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1040,17) | CRTC_H_SYNC_POL;
436                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(806,768);
437                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(771,6) | CRTC_V_SYNC_POL;
438                 mode->ppll_div_3 = 0x00020074;
439 #endif
440                 /* also same pitch value for 32, 16 and 8 bpp */
441                 mode->crtc_pitch = RADEON_CRT_PITCH(1024,32);
442                 switch (bpp) {
443                 case 24:
444                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 4 / 16);
445                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,32);
446                         break;
447                 case 16:
448                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 2 / 16);
449                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,16);
450                         break;
451                 default: /* 8 bpp */
452                         mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
453                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,8);
454                         break;
455                 }
456                 break;
457         case RES_MODE_800x600:
458                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1056,800);
459 #if defined(CONFIG_RADEON_VREFRESH_75HZ)
460                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(808,10);
461                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(625,600);
462                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,3);
463                 mode->ppll_div_3 = 0x000300b0;
464 #else /* @ 60 Hz */
465                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(832,16);
466                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(628,600);
467                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,4);
468                 mode->ppll_div_3 = 0x0003008e;
469 #endif
470                 switch (bpp) {
471                 case 24:
472                         mode->crtc_pitch = RADEON_CRT_PITCH(832,32);
473                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (832 * 4 / 16);
474                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(832,600,32);
475                         break;
476                 case 16:
477                         mode->crtc_pitch = RADEON_CRT_PITCH(896,16);
478                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (896 * 2 / 16);
479                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(896,600,16);
480                         break;
481                 default: /* 8 bpp */
482                         mode->crtc_pitch = RADEON_CRT_PITCH(1024,8);
483                         mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
484                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,600,8);
485                         break;
486                 }
487                 break;
488         default: /* RES_MODE_640x480 */
489 #if defined(CONFIG_RADEON_VREFRESH_75HZ)
490                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(840,640);
491                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(648,8) | CRTC_H_SYNC_POL;
492                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(500,480);
493                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(481,3) | CRTC_V_SYNC_POL;
494                 mode->ppll_div_3 = 0x00030070;
495 #else /* @ 60 Hz */
496                 mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(800,640);
497                 mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(674,12) | CRTC_H_SYNC_POL;
498                 mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(525,480);
499                 mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(491,2) | CRTC_V_SYNC_POL;
500                 mode->ppll_div_3 = 0x00030059;
501 #endif
502                 /* also same pitch value for 32, 16 and 8 bpp */
503                 mode->crtc_pitch = RADEON_CRT_PITCH(640,32);
504                 switch (bpp) {
505                 case 24:
506                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 4 / 16);
507                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,32);
508                         break;
509                 case 16:
510                         mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 2 / 16);
511                         mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,16);
512                         break;
513                 default: /* 8 bpp */
514                         mode->crtc_offset_cntl = 0x00000000;
515                         break;
516                 }
517                 break;
518         }
519
520         OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
521         OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
522                 (CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
523         OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
524         OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
525         OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
526         OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
527         OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
528         OUTREG(CRTC_OFFSET, 0);
529         OUTREG(CRTC_OFFSET_CNTL, mode->crtc_offset_cntl);
530         OUTREG(CRTC_PITCH, mode->crtc_pitch);
531         OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
532
533         mode->clk_cntl_index = 0x300;
534         mode->ppll_ref_div = 0xc;
535
536         radeon_write_pll_regs(rinfo, mode);
537
538         OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
539                 ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
540         OUTREG(SURFACE0_INFO, mode->surf_info[0]);
541         OUTREG(SURFACE0_LOWER_BOUND, 0);
542         OUTREG(SURFACE0_UPPER_BOUND, mode->surf_upper_bound[0]);
543         OUTREG(SURFACE_CNTL, mode->surface_cntl);
544
545         if (bpp > 8)
546                 set_pal();
547
548         free(mode);
549 }
550
551 #include "../bios_emulator/include/biosemu.h"
552 extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
553
554 int radeon_probe(struct radeonfb_info *rinfo)
555 {
556         pci_dev_t pdev;
557         u16 did;
558
559         pdev = pci_find_devices(ati_radeon_pci_ids, 0);
560
561         if (pdev != -1) {
562                 pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
563                 printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
564                                 PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
565                                 (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
566
567                 strcpy(rinfo->name, "ATI Radeon");
568                 rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
569                 rinfo->pdev.device = did;
570                 rinfo->family = get_radeon_id_family(rinfo->pdev.device);
571                 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
572                                 &rinfo->fb_base_bus);
573                 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
574                                 &rinfo->mmio_base_bus);
575                 rinfo->fb_base_bus &= 0xfffff000;
576                 rinfo->mmio_base_bus &= ~0x04;
577
578                 rinfo->mmio_base = pci_bus_to_virt(pdev, rinfo->mmio_base_bus,
579                                         PCI_REGION_MEM, 0, MAP_NOCACHE);
580                 DPRINT("rinfo->mmio_base = 0x%p bus=0x%x\n",
581                        rinfo->mmio_base, rinfo->mmio_base_bus);
582                 rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
583                 DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
584                 /* PostBIOS with x86 emulater */
585                 if (!BootVideoCardBIOS(pdev, NULL, 0))
586                         return -1;
587
588                 /*
589                  * Check for errata
590                  * (These will be added in the future for the chipfamily
591                  * R300, RV200, RS200, RV100, RS100.)
592                  */
593
594                 /* Get VRAM size and type */
595                 radeon_identify_vram(rinfo);
596
597                 rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
598                                 rinfo->video_ram);
599                 rinfo->fb_base = pci_bus_to_virt(pdev, rinfo->fb_base_bus,
600                                         PCI_REGION_MEM, 0, MAP_NOCACHE);
601                 DPRINT("Radeon: framebuffer base address 0x%08x, "
602                        "bus address 0x%08x\n"
603                        "MMIO base address 0x%08x, bus address 0x%08x, "
604                        "framebuffer local base 0x%08x.\n ",
605                        (u32)rinfo->fb_base, rinfo->fb_base_bus,
606                        (u32)rinfo->mmio_base, rinfo->mmio_base_bus,
607                        rinfo->fb_local_base);
608                 return 0;
609         }
610         return -1;
611 }
612
613 /*
614  * The Graphic Device
615  */
616 GraphicDevice ctfb;
617
618 #define CURSOR_SIZE     0x1000  /* in KByte for HW Cursor */
619 #define PATTERN_ADR     (pGD->dprBase + CURSOR_SIZE)    /* pattern Memory after Cursor Memory */
620 #define PATTERN_SIZE    8*8*4   /* 4 Bytes per Pixel 8 x 8 Pixel */
621 #define ACCELMEMORY     (CURSOR_SIZE + PATTERN_SIZE)    /* reserved Memory for BITBlt and hw cursor */
622
623 void *video_hw_init(void)
624 {
625         GraphicDevice *pGD = (GraphicDevice *) & ctfb;
626         u32 *vm;
627         char *penv;
628         unsigned long t1, hsynch, vsynch;
629         int bits_per_pixel, i, tmp, vesa_idx = 0, videomode;
630         struct ctfb_res_modes *res_mode;
631         struct ctfb_res_modes var_mode;
632
633         rinfo = malloc(sizeof(struct radeonfb_info));
634
635         printf("Video: ");
636         if(radeon_probe(rinfo)) {
637                 printf("No radeon video card found!\n");
638                 return NULL;
639         }
640
641         tmp = 0;
642
643         videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
644         /* get video mode via environment */
645         if ((penv = getenv ("videomode")) != NULL) {
646                 /* deceide if it is a string */
647                 if (penv[0] <= '9') {
648                         videomode = (int) simple_strtoul (penv, NULL, 16);
649                         tmp = 1;
650                 }
651         } else {
652                 tmp = 1;
653         }
654         if (tmp) {
655                 /* parameter are vesa modes */
656                 /* search params */
657                 for (i = 0; i < VESA_MODES_COUNT; i++) {
658                         if (vesa_modes[i].vesanr == videomode)
659                                 break;
660                 }
661                 if (i == VESA_MODES_COUNT) {
662                         printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
663                         i = 0;
664                 }
665                 res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].resindex];
666                 bits_per_pixel = vesa_modes[i].bits_per_pixel;
667                 vesa_idx = vesa_modes[i].resindex;
668         } else {
669                 res_mode = (struct ctfb_res_modes *) &var_mode;
670                 bits_per_pixel = video_get_params (res_mode, penv);
671         }
672
673         /* calculate hsynch and vsynch freq (info only) */
674         t1 = (res_mode->left_margin + res_mode->xres +
675               res_mode->right_margin + res_mode->hsync_len) / 8;
676         t1 *= 8;
677         t1 *= res_mode->pixclock;
678         t1 /= 1000;
679         hsynch = 1000000000L / t1;
680         t1 *= (res_mode->upper_margin + res_mode->yres +
681                res_mode->lower_margin + res_mode->vsync_len);
682         t1 /= 1000;
683         vsynch = 1000000000L / t1;
684
685         /* fill in Graphic device struct */
686         sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
687                  res_mode->yres, bits_per_pixel, (hsynch / 1000),
688                  (vsynch / 1000));
689         printf ("%s\n", pGD->modeIdent);
690         pGD->winSizeX = res_mode->xres;
691         pGD->winSizeY = res_mode->yres;
692         pGD->plnSizeX = res_mode->xres;
693         pGD->plnSizeY = res_mode->yres;
694
695         switch (bits_per_pixel) {
696         case 24:
697                 pGD->gdfBytesPP = 4;
698                 pGD->gdfIndex = GDF_32BIT_X888RGB;
699                 if (res_mode->xres == 800) {
700                         pGD->winSizeX = 832;
701                         pGD->plnSizeX = 832;
702                 }
703                 break;
704         case 16:
705                 pGD->gdfBytesPP = 2;
706                 pGD->gdfIndex = GDF_16BIT_565RGB;
707                 if (res_mode->xres == 800) {
708                         pGD->winSizeX = 896;
709                         pGD->plnSizeX = 896;
710                 }
711                 break;
712         default:
713                 if (res_mode->xres == 800) {
714                         pGD->winSizeX = 1024;
715                         pGD->plnSizeX = 1024;
716                 }
717                 pGD->gdfBytesPP = 1;
718                 pGD->gdfIndex = GDF__8BIT_INDEX;
719                 break;
720         }
721
722         pGD->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS;
723         pGD->pciBase = (unsigned int)rinfo->fb_base;
724         pGD->frameAdrs = (unsigned int)rinfo->fb_base;
725         pGD->memSize = 64 * 1024 * 1024;
726
727         /* Cursor Start Address */
728         pGD->dprBase = (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) +
729                 (unsigned int)rinfo->fb_base;
730         if ((pGD->dprBase & 0x0fff) != 0) {
731                 /* allign it */
732                 pGD->dprBase &= 0xfffff000;
733                 pGD->dprBase += 0x00001000;
734         }
735         DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
736                 PATTERN_ADR);
737         pGD->vprBase = (unsigned int)rinfo->fb_base;    /* Dummy */
738         pGD->cprBase = (unsigned int)rinfo->fb_base;    /* Dummy */
739         /* set up Hardware */
740
741         /* Clear video memory (only visible screen area) */
742         i = pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP / 4;
743         vm = (unsigned int *) pGD->pciBase;
744         while (i--)
745                 *vm++ = 0;
746         /*SetDrawingEngine (bits_per_pixel);*/
747
748         if (rinfo->family == CHIP_FAMILY_RV280)
749                 radeon_setmode_9200(vesa_idx, bits_per_pixel);
750         else
751                 radeon_setmode();
752
753         return ((void *) pGD);
754 }
755
756 void video_set_lut (unsigned int index, /* color number */
757                unsigned char r, /* red */
758                unsigned char g, /* green */
759                unsigned char b  /* blue */
760                )
761 {
762         OUTREG(PALETTE_INDEX, index);
763         OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
764 }