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