/* * drivers/video/aty/radeon_base.c * * framebuffer driver for ATI Radeon chipset video boards * * Copyright 2003 Ben. Herrenschmidt <benh@kernel.crashing.org> * Copyright 2000 Ani Joshi <ajoshi@kernel.crashing.org> * * i2c bits from Luca Tettamanti <kronos@kronoz.cjb.net> * * Special thanks to ATI DevRel team for their hardware donations. * * ...Insert GPL boilerplate here... * * Significant portions of this driver apdated from XFree86 Radeon * driver which has the following copyright notice: * * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and * VA Linux Systems Inc., Fremont, California. * * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation on the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial * portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * XFree86 driver authors: * * Kevin E. Martin <martin@xfree86.org> * Rickard E. Faith <faith@valinux.com> * Alan Hourihane <alanh@fairlite.demon.co.uk> *
*/
/* Note about this function: we have some rare cases where we must not schedule, * this typically happen with our special "wake up early" hook which allows us to * wake up the graphic chip (and thus get the console back) before everything else * on some machines that support that mechanism. At this point, interrupts are off * and scheduling is not permitted
*/ void _radeon_msleep(struct radeonfb_info *rinfo, unsignedlong ms)
{ if (rinfo->no_schedule || oops_in_progress)
mdelay(ms); else
msleep(ms);
}
void radeon_pll_errata_after_index_slow(struct radeonfb_info *rinfo)
{ /* Called if (rinfo->errata & CHIP_ERRATA_PLL_DUMMYREADS) is set */
(void)INREG(CLOCK_CNTL_DATA);
(void)INREG(CRTC_GEN_CNTL);
}
void radeon_pll_errata_after_data_slow(struct radeonfb_info *rinfo)
{ if (rinfo->errata & CHIP_ERRATA_PLL_DELAY) { /* we can't deal with posted writes here ... */
_radeon_msleep(rinfo, 5);
} if (rinfo->errata & CHIP_ERRATA_R300_CG) {
u32 save, tmp;
save = INREG(CLOCK_CNTL_INDEX);
tmp = save & ~(0x3f | PLL_WR_EN);
OUTREG(CLOCK_CNTL_INDEX, tmp);
tmp = INREG(CLOCK_CNTL_DATA);
OUTREG(CLOCK_CNTL_INDEX, save);
}
}
/* Ensure FIFO is empty, ie, make sure the flush commands * has reached the cache
*/
_radeon_fifo_wait(rinfo, 64);
/* Wait for the flush to complete */ for (i=0; i < 2000000; i++) { if (!(INREG(DSTCACHE_CTLSTAT) & RB2D_DC_BUSY)) return;
udelay(1);
}
printk(KERN_ERR "radeonfb: Flush Timeout !\n");
}
void _radeon_engine_idle(struct radeonfb_info *rinfo)
{ int i;
/* ensure FIFO is empty before waiting for idle */
_radeon_fifo_wait(rinfo, 64);
/* If this is a primary card, there is a shadow copy of the * ROM somewhere in the first meg. We will just ignore the copy * and use the ROM directly.
*/
/* Fix from ATI for problem with Radeon hardware not leaving ROM enabled */ unsignedint temp;
temp = INREG(MPP_TB_CONFIG);
temp &= 0x00ffffffu;
temp |= 0x04 << 24;
OUTREG(MPP_TB_CONFIG, temp);
temp = INREG(MPP_TB_CONFIG);
rom = pci_map_rom(dev, &rom_size); if (!rom) {
printk(KERN_ERR "radeonfb (%s): ROM failed to map\n",
pci_name(rinfo->pdev)); return -ENOMEM;
}
rinfo->bios_seg = rom;
/* Very simple test to make sure it appeared */ if (BIOS_IN16(0) != 0xaa55) {
printk(KERN_DEBUG "radeonfb (%s): Invalid ROM signature %x " "should be 0xaa55\n",
pci_name(rinfo->pdev), BIOS_IN16(0)); goto failed;
} /* Look for the PCI data to check the ROM type */
dptr = BIOS_IN16(0x18);
/* Check the PCI data signature. If it's wrong, we still assume a normal x86 ROM * for now, until I've verified this works everywhere. The goal here is more * to phase out Open Firmware images. * * Currently, we only look at the first PCI data, we could iteratre and deal with * them all, and we should use fb_bios_start relative to start of image and not * relative start of ROM, but so far, I never found a dual-image ATI card * * typedef struct { * u32 signature; + 0x00 * u16 vendor; + 0x04 * u16 device; + 0x06 * u16 reserved_1; + 0x08 * u16 dlen; + 0x0a * u8 drevision; + 0x0c * u8 class_hi; + 0x0d * u16 class_lo; + 0x0e * u16 ilen; + 0x10 * u16 irevision; + 0x12 * u8 type; + 0x14 * u8 indicator; + 0x15 * u16 reserved_2; + 0x16 * } pci_data_t;
*/ if (BIOS_IN32(dptr) != (('R' << 24) | ('I' << 16) | ('C' << 8) | 'P')) {
printk(KERN_WARNING "radeonfb (%s): PCI DATA signature in ROM" "incorrect: %08x\n", pci_name(rinfo->pdev), BIOS_IN32(dptr)); goto anyway;
}
rom_type = BIOS_IN8(dptr + 0x14); switch(rom_type) { case 0:
printk(KERN_INFO "radeonfb: Found Intel x86 BIOS ROM Image\n"); break; case 1:
printk(KERN_INFO "radeonfb: Found Open Firmware ROM Image\n"); goto failed; case 2:
printk(KERN_INFO "radeonfb: Found HP PA-RISC ROM Image\n"); goto failed; default:
printk(KERN_INFO "radeonfb: Found unknown type %d ROM Image\n", rom_type); goto failed;
}
anyway: /* Locate the flat panel infos, do some sanity checking !!! */
rinfo->fp_bios_start = BIOS_IN16(0x48); return 0;
#ifdef CONFIG_X86 staticint radeon_find_mem_vbios(struct radeonfb_info *rinfo)
{ /* I simplified this code as we used to miss the signatures in * a lot of case. It's now closer to XFree, we just don't check * for signatures at all... Something better will have to be done * if we end up having conflicts
*/
u32 segstart; void __iomem *rom_base = NULL;
/* Locate the flat panel infos, do some sanity checking !!! */
rinfo->bios_seg = rom_base;
rinfo->fp_bios_start = BIOS_IN16(0x48);
return 0;
} #endif
#ifdefined(CONFIG_PPC) || defined(CONFIG_SPARC) /* * Read XTAL (ref clock), SCLK and MCLK from Open Firmware device * tree. Hopefully, ATI OF driver is kind enough to fill these
*/ staticint radeon_read_xtal_OF(struct radeonfb_info *rinfo)
{ struct device_node *dp = rinfo->of_node; const u32 *val;
if (dp == NULL) return -ENODEV;
val = of_get_property(dp, "ATY,RefCLK", NULL); if (!val || !*val) {
printk(KERN_WARNING "radeonfb: No ATY,RefCLK property !\n"); return -EINVAL;
}
rinfo->pll.ref_clk = (*val) / 10;
val = of_get_property(dp, "ATY,SCLK", NULL); if (val && *val)
rinfo->pll.sclk = (*val) / 10;
val = of_get_property(dp, "ATY,MCLK", NULL); if (val && *val)
rinfo->pll.mclk = (*val) / 10;
/* * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...)
*/ staticvoid radeon_get_pllinfo(struct radeonfb_info *rinfo)
{ /* * In the case nothing works, these are defaults; they are mostly * incomplete, however. It does provide ppll_max and _min values * even for most other methods, however.
*/ switch (rinfo->chipset) { case PCI_DEVICE_ID_ATI_RADEON_QW: case PCI_DEVICE_ID_ATI_RADEON_QX:
rinfo->pll.ppll_max = 35000;
rinfo->pll.ppll_min = 12000;
rinfo->pll.mclk = 23000;
rinfo->pll.sclk = 23000;
rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_QL: case PCI_DEVICE_ID_ATI_RADEON_QN: case PCI_DEVICE_ID_ATI_RADEON_QO: case PCI_DEVICE_ID_ATI_RADEON_Ql: case PCI_DEVICE_ID_ATI_RADEON_BB:
rinfo->pll.ppll_max = 35000;
rinfo->pll.ppll_min = 12000;
rinfo->pll.mclk = 27500;
rinfo->pll.sclk = 27500;
rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_Id: case PCI_DEVICE_ID_ATI_RADEON_Ie: case PCI_DEVICE_ID_ATI_RADEON_If: case PCI_DEVICE_ID_ATI_RADEON_Ig:
rinfo->pll.ppll_max = 35000;
rinfo->pll.ppll_min = 12000;
rinfo->pll.mclk = 25000;
rinfo->pll.sclk = 25000;
rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_ND: case PCI_DEVICE_ID_ATI_RADEON_NE: case PCI_DEVICE_ID_ATI_RADEON_NF: case PCI_DEVICE_ID_ATI_RADEON_NG:
rinfo->pll.ppll_max = 40000;
rinfo->pll.ppll_min = 20000;
rinfo->pll.mclk = 27000;
rinfo->pll.sclk = 27000;
rinfo->pll.ref_clk = 2700; break; case PCI_DEVICE_ID_ATI_RADEON_QD: case PCI_DEVICE_ID_ATI_RADEON_QE: case PCI_DEVICE_ID_ATI_RADEON_QF: case PCI_DEVICE_ID_ATI_RADEON_QG: default:
rinfo->pll.ppll_max = 35000;
rinfo->pll.ppll_min = 12000;
rinfo->pll.mclk = 16600;
rinfo->pll.sclk = 16600;
rinfo->pll.ref_clk = 2700; break;
}
rinfo->pll.ref_div = INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK;
#ifdefined(CONFIG_PPC) || defined(CONFIG_SPARC) /* * Retrieve PLL infos from Open Firmware first
*/ if (!force_measure_pll && radeon_read_xtal_OF(rinfo) == 0) {
printk(KERN_INFO "radeonfb: Retrieved PLL infos from Open Firmware\n"); goto found;
} #endif/* CONFIG_PPC || CONFIG_SPARC */
/* * Check out if we have an X86 which gave us some PLL informations * and if yes, retrieve them
*/ if (!force_measure_pll && rinfo->bios_seg) {
u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30);
printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n"); goto found;
}
/* * We didn't get PLL parameters from either OF or BIOS, we try to * probe them
*/ if (radeon_probe_pll_params(rinfo) == 0) {
printk(KERN_INFO "radeonfb: Retrieved PLL infos from registers\n"); goto found;
}
/* * Fall back to already-set defaults...
*/
printk(KERN_INFO "radeonfb: Used default PLL infos\n");
found: /* * Some methods fail to retrieve SCLK and MCLK values, we apply default * settings in this case (200Mhz). If that really happens often, we * could fetch from registers instead...
*/ if (rinfo->pll.mclk == 0)
rinfo->pll.mclk = 20000; if (rinfo->pll.sclk == 0)
rinfo->pll.sclk = 20000;
switch (cmd) { /* * TODO: set mirror accordingly for non-Mobility chipsets with 2 CRTC's * and do something better using 2nd CRTC instead of just hackish * routing to second output
*/ case FBIO_RADEON_SET_MIRROR: if (!rinfo->is_mobility) return -EINVAL;
rc = get_user(value, (__u32 __user *)arg);
if (rc) return rc;
radeon_fifo_wait(2); if (value & 0x01) {
tmp = INREG(LVDS_GEN_CNTL);
int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch)
{
u32 val;
u32 tmp_pix_clks; int unblank = 0;
if (rinfo->lock_blank) return 0;
radeon_engine_idle();
val = INREG(CRTC_EXT_CNTL);
val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS |
CRTC_VSYNC_DIS); switch (blank) { case FB_BLANK_VSYNC_SUSPEND:
val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS); break; case FB_BLANK_HSYNC_SUSPEND:
val |= (CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS); break; case FB_BLANK_POWERDOWN:
val |= (CRTC_DISPLAY_DIS | CRTC_VSYNC_DIS |
CRTC_HSYNC_DIS); break; case FB_BLANK_NORMAL:
val |= CRTC_DISPLAY_DIS; break; case FB_BLANK_UNBLANK: default:
unblank = 1;
}
OUTREG(CRTC_EXT_CNTL, val);
/* We don't do a full switch-off on a simple mode switch */ if (mode_switch || blank == FB_BLANK_NORMAL) break;
/* Asic bug, when turning off LVDS_ON, we have to make sure * RADEON_PIXCLK_LVDS_ALWAYS_ON bit is off
*/
tmp_pix_clks = INPLL(PIXCLKS_CNTL); if (rinfo->is_mobility || rinfo->is_IGP)
OUTPLLP(PIXCLKS_CNTL, 0, ~PIXCLK_LVDS_ALWAYS_ONb);
val &= ~(LVDS_BL_MOD_EN);
OUTREG(LVDS_GEN_CNTL, val);
udelay(100);
val &= ~(LVDS_ON | LVDS_EN);
OUTREG(LVDS_GEN_CNTL, val);
val &= ~LVDS_DIGON;
rinfo->pending_lvds_gen_cntl = val;
mod_timer(&rinfo->lvds_timer,
jiffies +
msecs_to_jiffies(rinfo->panel_info.pwr_delay));
rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK;
rinfo->init_state.lvds_gen_cntl |= val & LVDS_STATE_MASK; if (rinfo->is_mobility || rinfo->is_IGP)
OUTPLL(PIXCLKS_CNTL, tmp_pix_clks);
} break; case MT_CRT: // todo: powerdown DAC default: break;
}
red >>= 8;
green >>= 8;
blue >>= 8;
rinfo->palette[regno].red = red;
rinfo->palette[regno].green = green;
rinfo->palette[regno].blue = blue;
/* default */
pindex = regno;
if (!rinfo->asleep) {
radeon_fifo_wait(9);
if (rinfo->bpp == 16) {
pindex = regno * 8;
if (rinfo->depth == 16 && regno > 63) return -EINVAL; if (rinfo->depth == 15 && regno > 31) return -EINVAL;
/* For 565, the green component is mixed one order * below
*/ if (rinfo->depth == 16) {
OUTREG(PALETTE_INDEX, pindex>>1);
OUTREG(PALETTE_DATA,
(rinfo->palette[regno>>1].red << 16) |
(green << 8) |
(rinfo->palette[regno>>1].blue));
green = rinfo->palette[regno<<1].green;
}
}
if (!rinfo->asleep) { if (rinfo->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL,
vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
}
/* Make sure we are on first palette */ if (rinfo->has_CRTC2) {
dac_cntl2 = INREG(DAC_CNTL2);
dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
OUTREG(DAC_CNTL2, dac_cntl2);
}
}
if (!rinfo->asleep) { if (rinfo->is_mobility) {
vclk_cntl = INPLL(VCLK_ECP_CNTL);
OUTPLL(VCLK_ECP_CNTL,
vclk_cntl & ~PIXCLK_DAC_ALWAYS_ONb);
}
/* Make sure we are on first palette */ if (rinfo->has_CRTC2) {
dac_cntl2 = INREG(DAC_CNTL2);
dac_cntl2 &= ~DAC2_PALETTE_ACCESS_CNTL;
OUTREG(DAC_CNTL2, dac_cntl2);
}
}
red = cmap->red;
green = cmap->green;
blue = cmap->blue;
transp = cmap->transp;
start = cmap->start;
for (i = 0; i < cmap->len; i++) {
u_int hred, hgreen, hblue, htransp = 0xffff;
staticvoid radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
{ int i;
radeon_fifo_wait(20);
/* Workaround from XFree */ if (rinfo->is_mobility) { /* A temporal workaround for the occasional blanking on certain laptop * panels. This appears to related to the PLL divider registers * (fail to lock?). It occurs even when all dividers are the same * with their old settings. In this case we really don't need to * fiddle with PLL registers. By doing this we can avoid the blanking * problem with some panels.
*/ if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
(mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
(PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) { /* We still have to force a switch to selected PPLL div thanks to * an XFree86 driver bug which will switch it away in some cases
* even when using UseFDev */
OUTREGP(CLOCK_CNTL_INDEX,
mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
~PPLL_DIV_SEL_MASK);
radeon_pll_errata_after_index(rinfo);
radeon_pll_errata_after_data(rinfo); return;
}
}
/* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
/* Wait read update complete */ /* FIXME: Certain revisions of R300 can't recover here. Not sure of the cause yet, but this workaround will mask the problem for now. Other chips usually will pass at the very first test, so the
workaround shouldn't have any effect on them. */ for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
;
/* * Apply a video mode. This will apply the whole register set, including * the PLL registers, to the card
*/ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, int regs_only)
{ int i; int primary_mon = PRIMARY_MONITOR(rinfo);
if (nomodeset) return;
if (!regs_only)
radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0);
radeon_fifo_wait(31); for (i=0; i<10; i++)
OUTREG(common_regs[i].reg, common_regs[i].val);
/* * Calculate the PLL values for a given mode
*/ staticvoid radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, unsignedlong freq)
{ staticconststruct { int divider; int bitvalue;
} *post_div,
post_divs[] = {
{ 1, 0 },
{ 2, 1 },
{ 4, 2 },
{ 8, 3 },
{ 3, 4 },
{ 16, 5 },
{ 6, 6 },
{ 12, 7 },
{ 0, 0 },
}; int fb_div, pll_output_freq = 0; int uses_dvo = 0;
/* Check if the DVO port is enabled and sourced from the primary CRTC. I'm * not sure which model starts having FP2_GEN_CNTL, I assume anything more * recent than an r(v)100...
*/ #if 1 /* XXX I had reports of flicker happening with the cinema display * on TMDS1 that seem to be fixed if I also forbit odd dividers in * this case. This could just be a bandwidth calculation issue, I * haven't implemented the bandwidth code yet, but in the meantime, * forcing uses_dvo to 1 fixes it and shouln't have bad side effects, * I haven't seen a case were were absolutely needed an odd PLL * divider. I'll find a better fix once I have more infos on the * real cause of the problem.
*/ while (rinfo->has_CRTC2) {
u32 fp2_gen_cntl = INREG(FP2_GEN_CNTL);
u32 disp_output_cntl; int source;
/* FP2 path not enabled */ if ((fp2_gen_cntl & FP2_ON) == 0) break; /* Not all chip revs have the same format for this register, * extract the source selection
*/ if (rinfo->family == CHIP_FAMILY_R200 || IS_R300_VARIANT(rinfo)) {
source = (fp2_gen_cntl >> 10) & 0x3; /* sourced from transform unit, check for transform unit * own source
*/ if (source == 3) {
disp_output_cntl = INREG(DISP_OUTPUT_CNTL);
source = (disp_output_cntl >> 12) & 0x3;
}
} else
source = (fp2_gen_cntl >> 13) & 0x1; /* sourced from CRTC2 -> exit */ if (source == 1) break;
/* so we end up on CRTC1, let's set uses_dvo to 1 now */
uses_dvo = 1; break;
} #else
uses_dvo = 1; #endif if (freq > rinfo->pll.ppll_max)
freq = rinfo->pll.ppll_max; if (freq*12 < rinfo->pll.ppll_min)
freq = rinfo->pll.ppll_min / 12;
pr_debug("freq = %lu, PLL min = %u, PLL max = %u\n",
freq, rinfo->pll.ppll_min, rinfo->pll.ppll_max);
for (post_div = &post_divs[0]; post_div->divider; ++post_div) {
pll_output_freq = post_div->divider * freq; /* If we output to the DVO port (external TMDS), we don't allow an * odd PLL divider as those aren't supported on this path
*/ if (uses_dvo && (post_div->divider & 1)) continue; if (pll_output_freq >= rinfo->pll.ppll_min &&
pll_output_freq <= rinfo->pll.ppll_max) break;
}
/* If we fall through the bottom, try the "default value"
given by the terminal post_div->bitvalue */ if ( !post_div->divider ) {
post_div = &post_divs[post_div->bitvalue];
pll_output_freq = post_div->divider * freq;
}
pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
rinfo->pll.ref_div, rinfo->pll.ref_clk,
pll_output_freq);
/* If we fall through the bottom, try the "default value"
given by the terminal post_div->bitvalue */ if ( !post_div->divider ) {
post_div = &post_divs[post_div->bitvalue];
pll_output_freq = post_div->divider * freq;
}
pr_debug("ref_div = %d, ref_clk = %d, output_freq = %d\n",
rinfo->pll.ref_div, rinfo->pll.ref_clk,
pll_output_freq);
/* * It looks like recent chips have a problem with SURFACE_CNTL, * setting SURF_TRANSLATION_DIS completely disables the * swapper as well, so we leave it unset now.
*/
newmode->surface_cntl = 0;
#ifdefined(__BIG_ENDIAN)
/* Setup swapping on both apertures, though we currently * only use aperture 0, enabling swapper on aperture 1 * won't harm
*/ switch (mode->bits_per_pixel) { case 16:
newmode->surface_cntl |= NONSURF_AP0_SWP_16BPP;
newmode->surface_cntl |= NONSURF_AP1_SWP_16BPP; break; case 24: case 32:
newmode->surface_cntl |= NONSURF_AP0_SWP_32BPP;
newmode->surface_cntl |= NONSURF_AP1_SWP_32BPP; break;
} #endif
if (noaccel)
info->flags |= FBINFO_HWACCEL_DISABLED;
return 0;
}
/* * This reconfigure the card's internal memory map. In theory, we'd like * to setup the card's memory at the same address as it's PCI bus address, * and the AGP aperture right after that so that system RAM on 32 bits * machines at least, is directly accessible. However, doing so would * conflict with the current XFree drivers... * Ultimately, I hope XFree, GATOS and ATI binary drivers will all agree * on the proper way to set this up and duplicate this here. In the meantime, * I put the card's memory at 0 in card space and AGP at some random high * local (0xe0000000 for now) that will be changed by XFree/DRI anyway
*/ #ifdef CONFIG_PPC #undef SET_MC_FB_FROM_APERTURE staticvoid fixup_memory_mappings(struct radeonfb_info *rinfo)
{
u32 save_crtc_gen_cntl, save_crtc2_gen_cntl = 0;
u32 save_crtc_ext_cntl;
u32 aper_base, aper_size;
u32 agp_base;
/* First, we disable display to avoid interfering */ if (rinfo->has_CRTC2) {
save_crtc2_gen_cntl = INREG(CRTC2_GEN_CNTL);
OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl | CRTC2_DISP_REQ_EN_B);
}
save_crtc_gen_cntl = INREG(CRTC_GEN_CNTL);
save_crtc_ext_cntl = INREG(CRTC_EXT_CNTL);
#ifdef SET_MC_FB_FROM_APERTURE /* Set framebuffer to be at the same address as set in PCI BAR */
OUTREG(MC_FB_LOCATION,
((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16));
rinfo->fb_local_base = aper_base; #else
OUTREG(MC_FB_LOCATION, 0x7fff0000);
rinfo->fb_local_base = 0; #endif
agp_base = aper_base + aper_size; if (agp_base & 0xf0000000)
agp_base = (aper_base | 0x0fffffff) + 1;
/* Set AGP to be just after the framebuffer on a 256Mb boundary. This * assumes the FB isn't mapped to 0xf0000000 or above, but this is * always the case on PPCs afaik.
*/ #ifdef SET_MC_FB_FROM_APERTURE
OUTREG(MC_AGP_LOCATION, 0xffff0000 | (agp_base >> 16)); #else
OUTREG(MC_AGP_LOCATION, 0xffffe000); #endif
/* Fixup the display base addresses & engine offsets while we * are at it as well
*/ #ifdef SET_MC_FB_FROM_APERTURE
OUTREG(DISPLAY_BASE_ADDR, aper_base); if (rinfo->has_CRTC2)
OUTREG(CRTC2_DISPLAY_BASE_ADDR, aper_base);
OUTREG(OV0_BASE_ADDR, aper_base); #else
OUTREG(DISPLAY_BASE_ADDR, 0); if (rinfo->has_CRTC2)
OUTREG(CRTC2_DISPLAY_BASE_ADDR, 0);
OUTREG(OV0_BASE_ADDR, 0); #endif
mdelay(100);
/* This is supposed to fix the crtc2 noise problem. */
OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
if ((rinfo->family == CHIP_FAMILY_RS100) ||
(rinfo->family == CHIP_FAMILY_RS200)) { /* This is to workaround the asic bug for RMX, some versions * of BIOS doesn't have this register initialized correctly.
*/
OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
~CRTC_H_CUTOFF_ACTIVE_EN);
}
} else {
tmp = INREG(CNFG_MEMSIZE);
}
/* mem size is bits [28:0], mask off the rest */
rinfo->video_ram = tmp & CNFG_MEMSIZE_MASK;
/* * Hack to get around some busted production M6's * reporting no ram
*/ if (rinfo->video_ram == 0) { switch (rinfo->pdev->device) { case PCI_CHIP_RADEON_LY: case PCI_CHIP_RADEON_LZ:
rinfo->video_ram = 8192 * 1024; break; default: break;
}
}
/* * Now try to identify VRAM type
*/ if (rinfo->is_IGP || (rinfo->family >= CHIP_FAMILY_R300) ||
(INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
rinfo->vram_ddr = 1; else
rinfo->vram_ddr = 0;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.