2 * ATI Radeon Video card Framebuffer driver.
4 * Copyright 2007 Freescale Semiconductor, Inc.
5 * Zhang Wei <wei.zhang@freescale.com>
6 * Jason Jin <jason.jin@freescale.com>
8 * See file CREDITS for list of people who contributed to this
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.
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.
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,
26 * Some codes of this file is partly ported from Linux kernel
27 * ATI video framebuffer driver.
29 * Now the driver is tested on below ATI chips:
40 #include <asm/processor.h>
41 #include <asm/errno.h>
45 #include "videomodes.h"
49 #include "ati_radeon_fb.h"
54 #define DPRINT(x...) printf(x)
56 #define DPRINT(x...) do{}while(0)
60 #define min_t(type,x,y) \
61 ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
64 #define MAX_MAPPED_VRAM (2048*2048*4)
65 #define MIN_MAPPED_VRAM (1024*768*1)
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))
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))
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
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},
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},
116 u16 get_radeon_id_family(u16 device)
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];
125 struct radeonfb_info *rinfo;
127 static void radeon_identify_vram(struct radeonfb_info *rinfo)
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);
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);
144 /* This is supposed to fix the crtc2 noise problem. */
145 OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
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.
152 OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
153 ~CRTC_H_CUTOFF_ACTIVE_EN);
156 tmp = INREG(CONFIG_MEMSIZE);
159 /* mem size is bits [28:0], mask off the rest */
160 rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
163 * Hack to get around some busted production M6's
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;
178 * Now try to identify VRAM type
180 if ((rinfo->family >= CHIP_FAMILY_R300) ||
181 (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
186 tmp = INREG(MEM_CNTL);
187 if (IS_R300_VARIANT(rinfo)) {
188 tmp &= R300_MEM_NUM_CHANNELS_MASK;
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;
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;
201 rinfo->vram_width = 64;
203 if (tmp & MEM_NUM_CHANNELS_MASK)
204 rinfo->vram_width = 128;
206 rinfo->vram_width = 64;
209 /* This may not be correct, as some cards can have half of channel disabled
210 * ToDo: identify these cases
213 DPRINT("radeonfb: Found %dk of %s %d bits wide videoram\n",
214 rinfo->video_ram / 1024,
215 rinfo->vram_ddr ? "DDR" : "SDRAM",
220 static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
224 radeon_fifo_wait(20);
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.
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,
245 radeon_pll_errata_after_index(rinfo);
246 radeon_pll_errata_after_data(rinfo);
251 if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
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);
256 /* Reset PPLL & enable atomic update */
258 PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
259 ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
261 /* Switch to selected PPLL divider */
262 OUTREGP(CLOCK_CNTL_INDEX,
263 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
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
275 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
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);
283 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
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);
290 while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
292 OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
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++)
302 OUTPLL(HTOTAL_CNTL, 0);
304 /* Clear reset & atomic update */
305 OUTPLLP(PPLL_CNTL, 0,
306 ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
308 /* We may want some locking ... oh well */
311 /* Switch back VCLK source to PPLL */
312 OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
320 #if 0 /* unused ? -> scheduled for removal */
321 /* these common regs are cleared before mode setting so they do not
322 * interfere with anything
324 static reg_val common_regs[] = {
326 { OVR_WID_LEFT_RIGHT, 0 },
327 { OVR_WID_TOP_BOTTOM, 0 },
328 { OV0_SCALE_CNTL, 0 },
333 { CAP0_TRIG_CNTL, 0 },
334 { CAP1_TRIG_CNTL, 0 },
338 void radeon_setmode(void)
340 struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
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;
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);
363 mode->clk_cntl_index = 0x300;
364 mode->ppll_ref_div = 0xc;
365 mode->ppll_div_3 = 0x00030059;
367 radeon_write_pll_regs(rinfo, mode);
370 static void set_pal(void)
374 for (idx = 0; idx < 256; idx++) {
375 OUTREG8(PALETTE_INDEX, idx);
376 OUTREG(PALETTE_DATA, val);
381 void radeon_setmode_9200(int vesa_idx, int bpp)
383 struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
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;
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;
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;
406 mode->crtc_gen_cntl |= 0x2 << 8; /* palette */
407 mode->surface_cntl = 0x00000000;
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;
424 * for this mode pitch expands to the same value for 32, 16 and 8 bpp,
425 * so we set it here once only.
427 mode->crtc_pitch = RADEON_CRT_PITCH(1280,32);
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);
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);
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);
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;
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;
457 /* also same pitch value for 32, 16 and 8 bpp */
458 mode->crtc_pitch = RADEON_CRT_PITCH(1024,32);
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);
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);
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);
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;
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;
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);
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);
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);
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;
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;
519 /* also same pitch value for 32, 16 and 8 bpp */
520 mode->crtc_pitch = RADEON_CRT_PITCH(640,32);
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);
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);
531 mode->crtc_offset_cntl = 0x00000000;
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);
550 mode->clk_cntl_index = 0x300;
551 mode->ppll_ref_div = 0xc;
553 radeon_write_pll_regs(rinfo, mode);
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);
568 #include "../bios_emulator/include/biosemu.h"
569 extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
571 int radeon_probe(struct radeonfb_info *rinfo)
576 pdev = pci_find_devices(ati_radeon_pci_ids, 0);
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);
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_bus);
590 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
591 &rinfo->mmio_base_bus);
592 rinfo->fb_base_bus &= 0xfffff000;
593 rinfo->mmio_base_bus &= ~0x04;
595 rinfo->mmio_base = pci_bus_to_virt(pdev, rinfo->mmio_base_bus,
596 PCI_REGION_MEM, 0, MAP_NOCACHE);
597 DPRINT("rinfo->mmio_base = 0x%p bus=0x%x\n",
598 rinfo->mmio_base, rinfo->mmio_base_bus);
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 if (!BootVideoCardBIOS(pdev, NULL, 0))
607 * (These will be added in the future for the chipfamily
608 * R300, RV200, RS200, RV100, RS100.)
611 /* Get VRAM size and type */
612 radeon_identify_vram(rinfo);
614 rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
616 rinfo->fb_base = pci_bus_to_virt(pdev, rinfo->fb_base_bus,
617 PCI_REGION_MEM, 0, MAP_NOCACHE);
618 DPRINT("Radeon: framebuffer base address 0x%08x, "
619 "bus address 0x%08x\n"
620 "MMIO base address 0x%08x, bus address 0x%08x, "
621 "framebuffer local base 0x%08x.\n ",
622 (u32)rinfo->fb_base, rinfo->fb_base_bus,
623 (u32)rinfo->mmio_base, rinfo->mmio_base_bus,
624 rinfo->fb_local_base);
635 #define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
636 #define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
637 #define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
638 #define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
640 void *video_hw_init(void)
642 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
645 unsigned long t1, hsynch, vsynch;
646 int bits_per_pixel, i, tmp, vesa_idx = 0, videomode;
647 struct ctfb_res_modes *res_mode;
648 struct ctfb_res_modes var_mode;
650 rinfo = malloc(sizeof(struct radeonfb_info));
653 if(radeon_probe(rinfo)) {
654 printf("No radeon video card found!\n");
660 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
661 /* get video mode via environment */
662 if ((penv = getenv ("videomode")) != NULL) {
663 /* deceide if it is a string */
664 if (penv[0] <= '9') {
665 videomode = (int) simple_strtoul (penv, NULL, 16);
672 /* parameter are vesa modes */
674 for (i = 0; i < VESA_MODES_COUNT; i++) {
675 if (vesa_modes[i].vesanr == videomode)
678 if (i == VESA_MODES_COUNT) {
679 printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
682 res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].resindex];
683 bits_per_pixel = vesa_modes[i].bits_per_pixel;
684 vesa_idx = vesa_modes[i].resindex;
686 res_mode = (struct ctfb_res_modes *) &var_mode;
687 bits_per_pixel = video_get_params (res_mode, penv);
690 /* calculate hsynch and vsynch freq (info only) */
691 t1 = (res_mode->left_margin + res_mode->xres +
692 res_mode->right_margin + res_mode->hsync_len) / 8;
694 t1 *= res_mode->pixclock;
696 hsynch = 1000000000L / t1;
697 t1 *= (res_mode->upper_margin + res_mode->yres +
698 res_mode->lower_margin + res_mode->vsync_len);
700 vsynch = 1000000000L / t1;
702 /* fill in Graphic device struct */
703 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
704 res_mode->yres, bits_per_pixel, (hsynch / 1000),
706 printf ("%s\n", pGD->modeIdent);
707 pGD->winSizeX = res_mode->xres;
708 pGD->winSizeY = res_mode->yres;
709 pGD->plnSizeX = res_mode->xres;
710 pGD->plnSizeY = res_mode->yres;
712 switch (bits_per_pixel) {
715 pGD->gdfIndex = GDF_32BIT_X888RGB;
716 if (res_mode->xres == 800) {
723 pGD->gdfIndex = GDF_16BIT_565RGB;
724 if (res_mode->xres == 800) {
730 if (res_mode->xres == 800) {
731 pGD->winSizeX = 1024;
732 pGD->plnSizeX = 1024;
735 pGD->gdfIndex = GDF__8BIT_INDEX;
739 pGD->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS;
740 pGD->pciBase = (unsigned int)rinfo->fb_base;
741 pGD->frameAdrs = (unsigned int)rinfo->fb_base;
742 pGD->memSize = 64 * 1024 * 1024;
744 /* Cursor Start Address */
745 pGD->dprBase = (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) +
746 (unsigned int)rinfo->fb_base;
747 if ((pGD->dprBase & 0x0fff) != 0) {
749 pGD->dprBase &= 0xfffff000;
750 pGD->dprBase += 0x00001000;
752 DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
754 pGD->vprBase = (unsigned int)rinfo->fb_base; /* Dummy */
755 pGD->cprBase = (unsigned int)rinfo->fb_base; /* Dummy */
756 /* set up Hardware */
758 /* Clear video memory (only visible screen area) */
759 i = pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP / 4;
760 vm = (unsigned int *) pGD->pciBase;
763 /*SetDrawingEngine (bits_per_pixel);*/
765 if (rinfo->family == CHIP_FAMILY_RV280)
766 radeon_setmode_9200(vesa_idx, bits_per_pixel);
770 return ((void *) pGD);
773 void video_set_lut (unsigned int index, /* color number */
774 unsigned char r, /* red */
775 unsigned char g, /* green */
776 unsigned char b /* blue */
779 OUTREG(PALETTE_INDEX, index);
780 OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);