blob: 9613d80cc85e5f9452bc009c5a4174880c1665c5 [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>
47
48#include <radeon.h>
49#include "ati_ids.h"
50#include "ati_radeon_fb.h"
51
52#undef DEBUG
53
54#ifdef DEBUG
55#define DPRINT(x...) printf(x)
56#else
57#define DPRINT(x...) do{}while(0)
58#endif
59
60#ifndef min_t
61#define min_t(type,x,y) \
62 ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
63#endif
64
65#define MAX_MAPPED_VRAM (2048*2048*4)
66#define MIN_MAPPED_VRAM (1024*768*1)
67
68/*#define PCI_VENDOR_ID_ATI*/
69#define PCI_CHIP_RV280_5960 0x5960
70#define PCI_CHIP_RV280_5961 0x5961
71#define PCI_CHIP_RV280_5962 0x5962
72#define PCI_CHIP_RV280_5964 0x5964
73#define PCI_CHIP_RV370_5B60 0x5B60
74#define PCI_CHIP_RV380_5657 0x5657
75#define PCI_CHIP_R420_554d 0x554d
76
77static struct pci_device_id ati_radeon_pci_ids[] = {
78 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5960},
79 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
80 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
81 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
82 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
83 {PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
84 {PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
85 {0, 0}
86};
87
88static u16 ati_radeon_id_family_table[][2] = {
89 {PCI_CHIP_RV280_5960, CHIP_FAMILY_RV280},
90 {PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
91 {PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
92 {PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
93 {PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
94 {PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
95 {PCI_CHIP_R420_554d, CHIP_FAMILY_R420},
96 {0, 0}
97};
98
99u16 get_radeon_id_family(u16 device)
100{
101 int i;
102 for (i=0; ati_radeon_id_family_table[0][i]; i+=2)
103 if (ati_radeon_id_family_table[0][i] == device)
104 return ati_radeon_id_family_table[0][i + 1];
105 return 0;
106}
107
108struct radeonfb_info *rinfo;
109
110static void radeon_identify_vram(struct radeonfb_info *rinfo)
111{
112 u32 tmp;
113
114 /* framebuffer size */
115 if ((rinfo->family == CHIP_FAMILY_RS100) ||
116 (rinfo->family == CHIP_FAMILY_RS200) ||
117 (rinfo->family == CHIP_FAMILY_RS300)) {
118 u32 tom = INREG(NB_TOM);
119 tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
120
121 radeon_fifo_wait(6);
122 OUTREG(MC_FB_LOCATION, tom);
123 OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
124 OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
125 OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
126
127 /* This is supposed to fix the crtc2 noise problem. */
128 OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
129
130 if ((rinfo->family == CHIP_FAMILY_RS100) ||
131 (rinfo->family == CHIP_FAMILY_RS200)) {
132 /* This is to workaround the asic bug for RMX, some versions
133 of BIOS dosen't have this register initialized correctly.
134 */
135 OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
136 ~CRTC_H_CUTOFF_ACTIVE_EN);
137 }
138 } else {
139 tmp = INREG(CONFIG_MEMSIZE);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200140 }
Jason Jin2181b5d2007-07-06 08:33:33 +0800141
142 /* mem size is bits [28:0], mask off the rest */
143 rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
144
145 /*
146 * Hack to get around some busted production M6's
147 * reporting no ram
148 */
149 if (rinfo->video_ram == 0) {
150 switch (rinfo->pdev.device) {
151 case PCI_CHIP_RADEON_LY:
152 case PCI_CHIP_RADEON_LZ:
153 rinfo->video_ram = 8192 * 1024;
154 break;
155 default:
156 break;
157 }
158 }
159
160 /*
161 * Now try to identify VRAM type
162 */
163 if ((rinfo->family >= CHIP_FAMILY_R300) ||
164 (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
165 rinfo->vram_ddr = 1;
166 else
167 rinfo->vram_ddr = 0;
168
169 tmp = INREG(MEM_CNTL);
170 if (IS_R300_VARIANT(rinfo)) {
171 tmp &= R300_MEM_NUM_CHANNELS_MASK;
172 switch (tmp) {
173 case 0: rinfo->vram_width = 64; break;
174 case 1: rinfo->vram_width = 128; break;
175 case 2: rinfo->vram_width = 256; break;
176 default: rinfo->vram_width = 128; break;
177 }
178 } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
179 (rinfo->family == CHIP_FAMILY_RS100) ||
180 (rinfo->family == CHIP_FAMILY_RS200)){
181 if (tmp & RV100_MEM_HALF_MODE)
182 rinfo->vram_width = 32;
183 else
184 rinfo->vram_width = 64;
185 } else {
186 if (tmp & MEM_NUM_CHANNELS_MASK)
187 rinfo->vram_width = 128;
188 else
189 rinfo->vram_width = 64;
190 }
191
192 /* This may not be correct, as some cards can have half of channel disabled
193 * ToDo: identify these cases
194 */
195
196 DPRINT("radeonfb: Found %ldk of %s %d bits wide videoram\n",
197 rinfo->video_ram / 1024,
198 rinfo->vram_ddr ? "DDR" : "SDRAM",
199 rinfo->vram_width);
200
201}
202
203static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
204{
205 int i;
206
207 radeon_fifo_wait(20);
208
209#if 0
210 /* Workaround from XFree */
211 if (rinfo->is_mobility) {
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200212 /* A temporal workaround for the occational blanking on certain laptop
Jason Jin2181b5d2007-07-06 08:33:33 +0800213 * panels. This appears to related to the PLL divider registers
214 * (fail to lock?). It occurs even when all dividers are the same
215 * with their old settings. In this case we really don't need to
216 * fiddle with PLL registers. By doing this we can avoid the blanking
217 * problem with some panels.
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200218 */
Jason Jin2181b5d2007-07-06 08:33:33 +0800219 if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
220 (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
221 (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
222 /* We still have to force a switch to selected PPLL div thanks to
223 * an XFree86 driver bug which will switch it away in some cases
224 * even when using UseFDev */
225 OUTREGP(CLOCK_CNTL_INDEX,
226 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
227 ~PPLL_DIV_SEL_MASK);
228 radeon_pll_errata_after_index(rinfo);
229 radeon_pll_errata_after_data(rinfo);
230 return;
231 }
232 }
233#endif
234 if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
235
236 /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
237 OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
238
239 /* Reset PPLL & enable atomic update */
240 OUTPLLP(PPLL_CNTL,
241 PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
242 ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
243
244 /* Switch to selected PPLL divider */
245 OUTREGP(CLOCK_CNTL_INDEX,
246 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
247 ~PPLL_DIV_SEL_MASK);
248
249 /* Set PPLL ref. div */
250 if (rinfo->family == CHIP_FAMILY_R300 ||
251 rinfo->family == CHIP_FAMILY_RS300 ||
252 rinfo->family == CHIP_FAMILY_R350 ||
253 rinfo->family == CHIP_FAMILY_RV350) {
254 if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
255 /* When restoring console mode, use saved PPLL_REF_DIV
256 * setting.
257 */
258 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
259 } else {
260 /* R300 uses ref_div_acc field as real ref divider */
261 OUTPLLP(PPLL_REF_DIV,
262 (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
263 ~R300_PPLL_REF_DIV_ACC_MASK);
264 }
265 } else
266 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
267
268 /* Set PPLL divider 3 & post divider*/
269 OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
270 OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
271
272 /* Write update */
273 while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
274 ;
275 OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
276
277 /* Wait read update complete */
278 /* FIXME: Certain revisions of R300 can't recover here. Not sure of
279 the cause yet, but this workaround will mask the problem for now.
280 Other chips usually will pass at the very first test, so the
281 workaround shouldn't have any effect on them. */
282 for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
283 ;
284
285 OUTPLL(HTOTAL_CNTL, 0);
286
287 /* Clear reset & atomic update */
288 OUTPLLP(PPLL_CNTL, 0,
289 ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
290
291 /* We may want some locking ... oh well */
292 udelay(5000);
293
294 /* Switch back VCLK source to PPLL */
295 OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
296}
297
298typedef struct {
299 u16 reg;
300 u32 val;
301} reg_val;
302
Wolfgang Denk92254112007-11-18 16:36:27 +0100303#if 0 /* unused ? -> scheduled for removal */
Jason Jin2181b5d2007-07-06 08:33:33 +0800304/* these common regs are cleared before mode setting so they do not
305 * interfere with anything
306 */
307static reg_val common_regs[] = {
308 { OVR_CLR, 0 },
309 { OVR_WID_LEFT_RIGHT, 0 },
310 { OVR_WID_TOP_BOTTOM, 0 },
311 { OV0_SCALE_CNTL, 0 },
312 { SUBPIC_CNTL, 0 },
313 { VIPH_CONTROL, 0 },
314 { I2C_CNTL_1, 0 },
315 { GEN_INT_CNTL, 0 },
316 { CAP0_TRIG_CNTL, 0 },
317 { CAP1_TRIG_CNTL, 0 },
318};
Wolfgang Denk92254112007-11-18 16:36:27 +0100319#endif /* 0 */
Jason Jin2181b5d2007-07-06 08:33:33 +0800320
321void radeon_setmode(void)
322{
Jason Jin2181b5d2007-07-06 08:33:33 +0800323 struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
324
325 mode->crtc_gen_cntl = 0x03000200;
326 mode->crtc_ext_cntl = 0x00008048;
327 mode->dac_cntl = 0xff002100;
328 mode->crtc_h_total_disp = 0x4f0063;
329 mode->crtc_h_sync_strt_wid = 0x8c02a2;
330 mode->crtc_v_total_disp = 0x01df020c;
331 mode->crtc_v_sync_strt_wid = 0x8201ea;
332 mode->crtc_pitch = 0x00500050;
333
334 OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
335 OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
336 ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
337 OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
338 OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
339 OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
340 OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
341 OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
342 OUTREG(CRTC_OFFSET, 0);
343 OUTREG(CRTC_OFFSET_CNTL, 0);
344 OUTREG(CRTC_PITCH, mode->crtc_pitch);
345
346 mode->clk_cntl_index = 0x300;
347 mode->ppll_ref_div = 0xc;
348 mode->ppll_div_3 = 0x00030059;
349
350 radeon_write_pll_regs(rinfo, mode);
351}
352
Wolfgang Denk92254112007-11-18 16:36:27 +0100353#include "bios_emulator/include/biosemu.h"
354extern int BootVideoCardBIOS(pci_dev_t pcidev, BE_VGAInfo ** pVGAInfo, int cleanUp);
355
Jason Jin2181b5d2007-07-06 08:33:33 +0800356int radeon_probe(struct radeonfb_info *rinfo)
357{
358 pci_dev_t pdev;
359 u16 did;
360
361 pdev = pci_find_devices(ati_radeon_pci_ids, 0);
362
363 if (pdev != -1) {
364 pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
365 printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
366 PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
367 (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
368
369 strcpy(rinfo->name, "ATI Radeon");
370 rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
371 rinfo->pdev.device = did;
372 rinfo->family = get_radeon_id_family(rinfo->pdev.device);
373 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
374 &rinfo->fb_base_phys);
375 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
376 &rinfo->mmio_base_phys);
377 rinfo->fb_base_phys &= 0xfffff000;
378 rinfo->mmio_base_phys &= ~0x04;
379
380 rinfo->mmio_base = (void *)rinfo->mmio_base_phys;
381 DPRINT("rinfo->mmio_base = 0x%x\n",rinfo->mmio_base);
382 rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
383 DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
384 /* PostBIOS with x86 emulater */
385 BootVideoCardBIOS(pdev, NULL, 0);
386
387 /*
388 * Check for errata
389 * (These will be added in the future for the chipfamily
390 * R300, RV200, RS200, RV100, RS100.)
391 */
392
393 /* Get VRAM size and type */
394 radeon_identify_vram(rinfo);
395
396 rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
397 rinfo->video_ram);
398 rinfo->fb_base = (void *)rinfo->fb_base_phys;
399
400 DPRINT("Radeon: framebuffer base phy address 0x%08x," \
401 "MMIO base phy address 0x%08x," \
402 "framebuffer local base 0x%08x.\n ",
403 rinfo->fb_base_phys, rinfo->mmio_base_phys,
404 rinfo->fb_local_base);
405
406 return 0;
407 }
408 return -1;
409}
410
411/*
412 * The Graphic Device
413 */
414GraphicDevice ctfb;
415
416#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
417#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
418#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
419#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
420
421void *video_hw_init(void)
422{
423 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
424 int i;
425 u32 *vm;
426
427 rinfo = malloc(sizeof(struct radeonfb_info));
428
429 if(radeon_probe(rinfo)) {
430 printf("No radeon video card found!\n");
431 return NULL;
432 }
433
434 /* fill in Graphic device struct */
435 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
436 480, 16, (1000 / 1000),
437 (2000 / 1000));
438 printf ("%s\n", pGD->modeIdent);
439
440 pGD->winSizeX = 640;
441 pGD->winSizeY = 480;
442 pGD->plnSizeX = 640;
443 pGD->plnSizeY = 480;
444
445 pGD->gdfBytesPP = 1;
446 pGD->gdfIndex = GDF__8BIT_INDEX;
447
448 pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
449 pGD->pciBase = rinfo->fb_base_phys;
450 pGD->frameAdrs = rinfo->fb_base_phys;
451 pGD->memSize = 64 * 1024 * 1024;
452
453 /* Cursor Start Address */
454 pGD->dprBase =
455 (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys;
456 if ((pGD->dprBase & 0x0fff) != 0) {
457 /* allign it */
458 pGD->dprBase &= 0xfffff000;
459 pGD->dprBase += 0x00001000;
460 }
461 DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
462 PATTERN_ADR);
463 pGD->vprBase = rinfo->fb_base_phys; /* Dummy */
464 pGD->cprBase = rinfo->fb_base_phys; /* Dummy */
465 /* set up Hardware */
466
467 /* Clear video memory */
468 i = pGD->memSize / 4;
469 vm = (unsigned int *) pGD->pciBase;
470 while (i--)
471 *vm++ = 0;
472 /*SetDrawingEngine (bits_per_pixel);*/
473
474 radeon_setmode();
475
476 return ((void *) pGD);
477}
478
479void video_set_lut (unsigned int index, /* color number */
480 unsigned char r, /* red */
481 unsigned char g, /* green */
482 unsigned char b /* blue */
483 )
484{
485 OUTREG(PALETTE_INDEX, index);
486 OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
487}
488#endif