|
|
{ PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) } | { PCI_VENDOR_ID_ATI, id, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (flags) | (CHIP_FAMILY_##family) } |
| |
static struct pci_device_id radeonfb_pci_table[] = { | static struct pci_device_id radeonfb_pci_table[] = { |
|
/* Radeon Xpress 200m */ |
|
CHIP_DEF(PCI_CHIP_RS480_5955, RS480, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), |
/* Mobility M6 */ | /* Mobility M6 */ |
CHIP_DEF(PCI_CHIP_RADEON_LY, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), | CHIP_DEF(PCI_CHIP_RADEON_LY, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), |
CHIP_DEF(PCI_CHIP_RADEON_LZ, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), | CHIP_DEF(PCI_CHIP_RADEON_LZ, RV100, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), |
|
|
#endif | #endif |
static int force_sleep; | static int force_sleep; |
static int ignore_devlist; | static int ignore_devlist; |
|
#ifdef CONFIG_PMAC_BACKLIGHT |
|
static int backlight = 1; |
|
#else |
|
static int backlight = 0; |
|
#endif |
| |
/* | /* |
* prototypes | * prototypes |
|
|
return 0; | return 0; |
} | } |
| |
|
static void radeon_detect_bios_type(struct radeonfb_info *rinfo) |
|
{ |
|
#ifndef CONFIG_PPC_OF |
|
int offset = rinfo->fp_bios_start + 4; |
|
unsigned char sign[4]; |
|
|
|
sign[0] = BIOS_IN8(offset); |
|
sign[1] = BIOS_IN8(offset + 1); |
|
sign[2] = BIOS_IN8(offset + 2); |
|
sign[3] = BIOS_IN8(offset + 3); |
|
|
|
if (!memcmp(sign, "ATOM", 4) || !memcmp(sign, "MOTA", 4)) { |
|
rinfo->is_atom_bios = 1; |
|
rinfo->atom_data_start = BIOS_IN16(rinfo->fp_bios_start + 32); |
|
|
|
printk(KERN_INFO "radeonfb: ATOM BIOS signature found\n"); |
|
|
|
return; |
|
} |
|
#endif /* NOT CONFIG_PPC_OF */ |
|
|
|
rinfo->is_atom_bios = 0; |
|
|
|
return; |
|
} |
|
|
/* | /* |
* Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...) | * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...) |
*/ | */ |
|
|
#endif /* CONFIG_PPC_OF */ | #endif /* CONFIG_PPC_OF */ |
| |
/* | /* |
* Check out if we have an X86 which gave us some PLL informations |
* Check out if we have an ATOM BIOS which gave us some PLL informations |
* and if yes, retrieve them | * and if yes, retrieve them |
*/ | */ |
|
|
if (!force_measure_pll && rinfo->bios_seg) { | if (!force_measure_pll && rinfo->bios_seg) { |
u16 pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30); |
u16 pll_info_block; |
| |
rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08); |
if(rinfo->is_atom_bios) { |
rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a); |
pll_info_block = BIOS_IN16(rinfo->atom_data_start + 12); |
rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e); |
|
rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10); |
|
rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12); |
|
rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16); |
|
| |
|
rinfo->pll.sclk = BIOS_IN32(pll_info_block + 8); |
|
rinfo->pll.mclk = BIOS_IN32(pll_info_block + 12); |
|
rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 82); |
|
rinfo->pll.ref_div = 0; /* Have to get it elsewhere */ |
|
rinfo->pll.ppll_min = BIOS_IN16(pll_info_block + 78); |
|
rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 32); |
|
} else { |
|
/* |
|
* Check out if we have an X86 which gave us some PLL informations |
|
* and if yes, retrieve them |
|
*/ |
|
pll_info_block = BIOS_IN16(rinfo->fp_bios_start + 0x30); |
|
|
|
rinfo->pll.sclk = BIOS_IN16(pll_info_block + 0x08); |
|
rinfo->pll.mclk = BIOS_IN16(pll_info_block + 0x0a); |
|
rinfo->pll.ref_clk = BIOS_IN16(pll_info_block + 0x0e); |
|
rinfo->pll.ref_div = BIOS_IN16(pll_info_block + 0x10); |
|
rinfo->pll.ppll_min = BIOS_IN32(pll_info_block + 0x12); |
|
rinfo->pll.ppll_max = BIOS_IN32(pll_info_block + 0x16); |
|
} |
printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n"); | printk(KERN_INFO "radeonfb: Retrieved PLL infos from BIOS\n"); |
|
|
goto found; | goto found; |
} | } |
| |
|
|
/* | /* |
* Fall back to already-set defaults... | * Fall back to already-set defaults... |
*/ | */ |
printk(KERN_INFO "radeonfb: Used default PLL infos\n"); |
printk(KERN_INFO "radeonfb: Fall back to default PLL infos\n"); |
| |
found: | found: |
|
/* Check and fix-up the PLL divisor if necessary */ |
|
if (rinfo->pll.ref_div < 2) { |
|
int tmp = INPLL(PPLL_REF_DIV); |
|
if (rinfo->family == CHIP_FAMILY_RS300) { |
|
rinfo->pll.ref_div = (tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT; |
|
} else { |
|
rinfo->pll.ref_div = tmp & PPLL_REF_DIV_MASK; |
|
} |
|
|
|
/* Sane default */ |
|
if (rinfo->pll.ref_div < 2) { |
|
printk(KERN_INFO "radeonfb: Set a sane default PLL divisor\n"); |
|
rinfo->pll.ref_div = 12; |
|
} |
|
} |
|
|
/* | /* |
* Some methods fail to retrieve SCLK and MCLK values, we apply default | * Some methods fail to retrieve SCLK and MCLK values, we apply default |
* settings in this case (200Mhz). If that really happne often, we could |
* settings in this case (200Mhz). If that really happen often, we could |
* fetch from registers instead... | * fetch from registers instead... |
*/ | */ |
if (rinfo->pll.mclk == 0) |
if (rinfo->pll.mclk == 0) { |
|
printk(KERN_INFO "radeonfb: Set a sane default MCLK value\n"); |
rinfo->pll.mclk = 20000; | rinfo->pll.mclk = 20000; |
if (rinfo->pll.sclk == 0) |
} |
|
if (rinfo->pll.mclk == 0) { |
|
printk(KERN_INFO "radeonfb: Set a sane default SCLK value\n"); |
rinfo->pll.sclk = 20000; | rinfo->pll.sclk = 20000; |
|
} |
| |
printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n", | printk("radeonfb: Reference=%d.%02d MHz (RefDiv=%d) Memory=%d.%02d Mhz, System=%d.%02d MHz\n", |
rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100, | rinfo->pll.ref_clk / 100, rinfo->pll.ref_clk % 100, |
|
|
break; | break; |
} | } |
| |
/* let fbcon do a soft blank for us */ |
return 0; |
return (blank == FB_BLANK_NORMAL) ? -EINVAL : 0; |
|
} | } |
| |
static int radeonfb_blank (int blank, struct fb_info *info) | static int radeonfb_blank (int blank, struct fb_info *info) |
|
|
/* framebuffer size */ | /* framebuffer size */ |
if ((rinfo->family == CHIP_FAMILY_RS100) || | if ((rinfo->family == CHIP_FAMILY_RS100) || |
(rinfo->family == CHIP_FAMILY_RS200) || | (rinfo->family == CHIP_FAMILY_RS200) || |
(rinfo->family == CHIP_FAMILY_RS300)) { |
(rinfo->family == CHIP_FAMILY_RS300) || |
|
(rinfo->family == CHIP_FAMILY_RS480) ) { |
u32 tom = INREG(NB_TOM); | u32 tom = INREG(NB_TOM); |
tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); | tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); |
| |
|
|
if (rinfo->bios_seg == NULL && rinfo->is_mobility) | if (rinfo->bios_seg == NULL && rinfo->is_mobility) |
radeon_map_ROM(rinfo, pdev); | radeon_map_ROM(rinfo, pdev); |
| |
|
/* Check BIOS Type */ |
|
radeon_detect_bios_type(rinfo); |
|
|
/* Get informations about the board's PLL */ | /* Get informations about the board's PLL */ |
radeon_get_pllinfo(rinfo); | radeon_get_pllinfo(rinfo); |
| |
|
|
MTRR_TYPE_WRCOMB, 1); | MTRR_TYPE_WRCOMB, 1); |
#endif | #endif |
| |
radeonfb_bl_init(rinfo); |
if (backlight) |
|
radeonfb_bl_init(rinfo); |
| |
printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); | printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); |
| |
|
|
if (!rinfo) | if (!rinfo) |
return; | return; |
| |
radeonfb_bl_exit(rinfo); |
|
radeonfb_pm_exit(rinfo); | radeonfb_pm_exit(rinfo); |
| |
if (rinfo->mon1_EDID) | if (rinfo->mon1_EDID) |
|
|
| |
unregister_framebuffer(info); | unregister_framebuffer(info); |
| |
|
radeonfb_bl_exit(rinfo); |
|
|
iounmap(rinfo->mmio_base); | iounmap(rinfo->mmio_base); |
iounmap(rinfo->fb_base); | iounmap(rinfo->fb_base); |
| |
|
|
force_dfp = 1; | force_dfp = 1; |
} else if (!strncmp(this_opt, "panel_yres:", 11)) { | } else if (!strncmp(this_opt, "panel_yres:", 11)) { |
panel_yres = simple_strtoul((this_opt+11), NULL, 0); | panel_yres = simple_strtoul((this_opt+11), NULL, 0); |
|
} else if (!strncmp(this_opt, "backlight:", 10)) { |
|
backlight = simple_strtoul(this_opt+10, NULL, 0); |
#ifdef CONFIG_MTRR | #ifdef CONFIG_MTRR |
} else if (!strncmp(this_opt, "nomtrr", 6)) { | } else if (!strncmp(this_opt, "nomtrr", 6)) { |
nomtrr = 1; | nomtrr = 1; |