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