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