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:
38 #ifdef CONFIG_ATI_RADEON_FB
42 #include <asm/processor.h>
43 #include <asm/errno.h>
50 #include "ati_radeon_fb.h"
55 #define DPRINT(x...) printf(x)
57 #define DPRINT(x...) do{}while(0)
61 #define min_t(type,x,y) \
62 ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; })
65 #define MAX_MAPPED_VRAM (2048*2048*4)
66 #define MIN_MAPPED_VRAM (1024*768*1)
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
77 static 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},
88 static 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},
99 u16 get_radeon_id_family(u16 device)
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];
108 struct radeonfb_info *rinfo;
110 static void radeon_identify_vram(struct radeonfb_info *rinfo)
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);
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);
127 /* This is supposed to fix the crtc2 noise problem. */
128 OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
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.
135 OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
136 ~CRTC_H_CUTOFF_ACTIVE_EN);
139 tmp = INREG(CONFIG_MEMSIZE);
142 /* mem size is bits [28:0], mask off the rest */
143 rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
146 * Hack to get around some busted production M6's
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;
161 * Now try to identify VRAM type
163 if ((rinfo->family >= CHIP_FAMILY_R300) ||
164 (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
169 tmp = INREG(MEM_CNTL);
170 if (IS_R300_VARIANT(rinfo)) {
171 tmp &= R300_MEM_NUM_CHANNELS_MASK;
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;
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;
184 rinfo->vram_width = 64;
186 if (tmp & MEM_NUM_CHANNELS_MASK)
187 rinfo->vram_width = 128;
189 rinfo->vram_width = 64;
192 /* This may not be correct, as some cards can have half of channel disabled
193 * ToDo: identify these cases
196 DPRINT("radeonfb: Found %ldk of %s %d bits wide videoram\n",
197 rinfo->video_ram / 1024,
198 rinfo->vram_ddr ? "DDR" : "SDRAM",
203 static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
207 radeon_fifo_wait(20);
210 /* Workaround from XFree */
211 if (rinfo->is_mobility) {
212 /* A temporal workaround for the occational blanking on certain laptop
213 * 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.
219 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,
228 radeon_pll_errata_after_index(rinfo);
229 radeon_pll_errata_after_data(rinfo);
234 if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
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);
239 /* Reset PPLL & enable atomic update */
241 PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
242 ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
244 /* Switch to selected PPLL divider */
245 OUTREGP(CLOCK_CNTL_INDEX,
246 mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
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
258 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
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);
266 OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
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);
273 while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
275 OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
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++)
285 OUTPLL(HTOTAL_CNTL, 0);
287 /* Clear reset & atomic update */
288 OUTPLLP(PPLL_CNTL, 0,
289 ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
291 /* We may want some locking ... oh well */
294 /* Switch back VCLK source to PPLL */
295 OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
304 /* these common regs are cleared before mode setting so they do not
305 * interfere with anything
307 static reg_val common_regs[] = {
309 { OVR_WID_LEFT_RIGHT, 0 },
310 { OVR_WID_TOP_BOTTOM, 0 },
311 { OV0_SCALE_CNTL, 0 },
316 { CAP0_TRIG_CNTL, 0 },
317 { CAP1_TRIG_CNTL, 0 },
321 void radeon_setmode(void)
324 struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
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;
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);
347 mode->clk_cntl_index = 0x300;
348 mode->ppll_ref_div = 0xc;
349 mode->ppll_div_3 = 0x00030059;
351 radeon_write_pll_regs(rinfo, mode);
354 int radeon_probe(struct radeonfb_info *rinfo)
359 pdev = pci_find_devices(ati_radeon_pci_ids, 0);
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);
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;
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);
387 * (These will be added in the future for the chipfamily
388 * R300, RV200, RS200, RV100, RS100.)
391 /* Get VRAM size and type */
392 radeon_identify_vram(rinfo);
394 rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
396 rinfo->fb_base = (void *)rinfo->fb_base_phys;
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);
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 */
419 void *video_hw_init(void)
421 GraphicDevice *pGD = (GraphicDevice *) & ctfb;
425 rinfo = malloc(sizeof(struct radeonfb_info));
427 if(radeon_probe(rinfo)) {
428 printf("No radeon video card found!\n");
432 /* fill in Graphic device struct */
433 sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", 640,
434 480, 16, (1000 / 1000),
436 printf ("%s\n", pGD->modeIdent);
444 pGD->gdfIndex = GDF__8BIT_INDEX;
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;
451 /* Cursor Start Address */
453 (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + rinfo->fb_base_phys;
454 if ((pGD->dprBase & 0x0fff) != 0) {
456 pGD->dprBase &= 0xfffff000;
457 pGD->dprBase += 0x00001000;
459 DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
461 pGD->vprBase = rinfo->fb_base_phys; /* Dummy */
462 pGD->cprBase = rinfo->fb_base_phys; /* Dummy */
463 /* set up Hardware */
465 /* Clear video memory */
466 i = pGD->memSize / 4;
467 vm = (unsigned int *) pGD->pciBase;
470 /*SetDrawingEngine (bits_per_pixel);*/
474 return ((void *) pGD);
477 void video_set_lut (unsigned int index, /* color number */
478 unsigned char r, /* red */
479 unsigned char g, /* green */
480 unsigned char b /* blue */
483 OUTREG(PALETTE_INDEX, index);
484 OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);