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