blob: c174f37b3fa99b88e32dec7c8be7b3129bc6fdff [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
303
304/* 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};
319
320
321void radeon_setmode(void)
322{
323 int i;
324 struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
325
326 mode->crtc_gen_cntl = 0x03000200;
327 mode->crtc_ext_cntl = 0x00008048;
328 mode->dac_cntl = 0xff002100;
329 mode->crtc_h_total_disp = 0x4f0063;
330 mode->crtc_h_sync_strt_wid = 0x8c02a2;
331 mode->crtc_v_total_disp = 0x01df020c;
332 mode->crtc_v_sync_strt_wid = 0x8201ea;
333 mode->crtc_pitch = 0x00500050;
334
335 OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
336 OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
337 ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
338 OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
339 OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
340 OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
341 OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
342 OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
343 OUTREG(CRTC_OFFSET, 0);
344 OUTREG(CRTC_OFFSET_CNTL, 0);
345 OUTREG(CRTC_PITCH, mode->crtc_pitch);
346
347 mode->clk_cntl_index = 0x300;
348 mode->ppll_ref_div = 0xc;
349 mode->ppll_div_3 = 0x00030059;
350
351 radeon_write_pll_regs(rinfo, mode);
352}
353
354int radeon_probe(struct radeonfb_info *rinfo)
355{
356 pci_dev_t pdev;
357 u16 did;
358
359 pdev = pci_find_devices(ati_radeon_pci_ids, 0);
360
361 if (pdev != -1) {
362 pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
363 printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
364 PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
365 (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
366
367 strcpy(rinfo->name, "ATI Radeon");
368 rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
369 rinfo->pdev.device = did;
370 rinfo->family = get_radeon_id_family(rinfo->pdev.device);
371 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
372 &rinfo->fb_base_phys);
373 pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
374 &rinfo->mmio_base_phys);
375 rinfo->fb_base_phys &= 0xfffff000;
376 rinfo->mmio_base_phys &= ~0x04;
377
378 rinfo->mmio_base = (void *)rinfo->mmio_base_phys;
379 DPRINT("rinfo->mmio_base = 0x%x\n",rinfo->mmio_base);
380 rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
381 DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
382 /* PostBIOS with x86 emulater */
383 BootVideoCardBIOS(pdev, NULL, 0);
384
385 /*
386 * Check for errata
387 * (These will be added in the future for the chipfamily
388 * R300, RV200, RS200, RV100, RS100.)
389 */
390
391 /* Get VRAM size and type */
392 radeon_identify_vram(rinfo);
393
394 rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
395 rinfo->video_ram);
396 rinfo->fb_base = (void *)rinfo->fb_base_phys;
397
398 DPRINT("Radeon: framebuffer base phy address 0x%08x," \
399 "MMIO base phy address 0x%08x," \
400 "framebuffer local base 0x%08x.\n ",
401 rinfo->fb_base_phys, rinfo->mmio_base_phys,
402 rinfo->fb_local_base);
403
404 return 0;
405 }
406 return -1;
407}
408
409/*
410 * The Graphic Device
411 */
412GraphicDevice ctfb;
413
414#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */
415#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */
416#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */
417#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */
418
419void *video_hw_init(void)
420{
421 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
422 int i;
423 u32 *vm;
424
425 rinfo = malloc(sizeof(struct radeonfb_info));
426
427 if(radeon_probe(rinfo)) {
428 printf("No radeon video card found!\n");
429 return NULL;
430 }
431
432 /* fill in Graphic device struct */
433 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
434 480, 16, (1000 / 1000),
435 (2000 / 1000));
436 printf ("%s\n", pGD->modeIdent);
437
438 pGD->winSizeX = 640;
439 pGD->winSizeY = 480;
440 pGD->plnSizeX = 640;
441 pGD->plnSizeY = 480;
442
443 pGD->gdfBytesPP = 1;
444 pGD->gdfIndex = GDF__8BIT_INDEX;
445
446 pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS;
447 pGD->pciBase = rinfo->fb_base_phys;
448 pGD->frameAdrs = rinfo->fb_base_phys;
449 pGD->memSize = 64 * 1024 * 1024;
450
451 /* Cursor Start Address */
452 pGD->dprBase =
453 (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys;
454 if ((pGD->dprBase & 0x0fff) != 0) {
455 /* allign it */
456 pGD->dprBase &= 0xfffff000;
457 pGD->dprBase += 0x00001000;
458 }
459 DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
460 PATTERN_ADR);
461 pGD->vprBase = rinfo->fb_base_phys; /* Dummy */
462 pGD->cprBase = rinfo->fb_base_phys; /* Dummy */
463 /* set up Hardware */
464
465 /* Clear video memory */
466 i = pGD->memSize / 4;
467 vm = (unsigned int *) pGD->pciBase;
468 while (i--)
469 *vm++ = 0;
470 /*SetDrawingEngine (bits_per_pixel);*/
471
472 radeon_setmode();
473
474 return ((void *) pGD);
475}
476
477void video_set_lut (unsigned int index, /* color number */
478 unsigned char r, /* red */
479 unsigned char g, /* green */
480 unsigned char b /* blue */
481 )
482{
483 OUTREG(PALETTE_INDEX, index);
484 OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
485}
486#endif