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