diff options
author | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-02-13 14:31:38 +0100 |
---|---|---|
committer | Tomi Valkeinen <tomi.valkeinen@ti.com> | 2014-04-17 07:10:19 +0200 |
commit | f7018c21350204c4cf628462f229d44d03545254 (patch) | |
tree | 408787177164cf51cc06f7aabdb04fcff8d2b6aa /drivers/video/aty/radeon_base.c | |
parent | video: bf54x-lq043fb: fix build error (diff) | |
download | linux-f7018c21350204c4cf628462f229d44d03545254.tar.xz linux-f7018c21350204c4cf628462f229d44d03545254.zip |
video: move fbdev to drivers/video/fbdev
The drivers/video directory is a mess. It contains generic video related
files, directories for backlight, console, linux logo, lots of fbdev
device drivers, fbdev framework files.
Make some order into the chaos by creating drivers/video/fbdev
directory, and move all fbdev related files there.
No functionality is changed, although I guess it is possible that some
subtle Makefile build order related issue could be created by this
patch.
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Rob Clark <robdclark@gmail.com>
Acked-by: Jingoo Han <jg1.han@samsung.com>
Acked-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/video/aty/radeon_base.c')
-rw-r--r-- | drivers/video/aty/radeon_base.c | 2568 |
1 files changed, 0 insertions, 2568 deletions
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c deleted file mode 100644 index 26d80a4486fb..000000000000 --- a/drivers/video/aty/radeon_base.c +++ /dev/null @@ -1,2568 +0,0 @@ -/* - * 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> - * - */ - - -#define RADEON_VERSION "0.2.0" - -#include "radeonfb.h" - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/ctype.h> -#include <linux/mm.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/time.h> -#include <linux/fb.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/vmalloc.h> -#include <linux/device.h> - -#include <asm/io.h> -#include <linux/uaccess.h> - -#ifdef CONFIG_PPC_OF - -#include <asm/pci-bridge.h> -#include "../macmodes.h" - -#ifdef CONFIG_BOOTX_TEXT -#include <asm/btext.h> -#endif - -#endif /* CONFIG_PPC_OF */ - -#ifdef CONFIG_MTRR -#include <asm/mtrr.h> -#endif - -#include <video/radeon.h> -#include <linux/radeonfb.h> - -#include "../edid.h" // MOVE THAT TO include/video -#include "ati_ids.h" - -#define MAX_MAPPED_VRAM (2048*2048*4) -#define MIN_MAPPED_VRAM (1024*768*1) - -#define CHIP_DEF(id, family, flags) \ - { 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[] = { - /* Radeon Xpress 200m */ - CHIP_DEF(PCI_CHIP_RS480_5955, RS480, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RS482_5975, RS480, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* Mobility M6 */ - 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), - /* Radeon VE/7000 */ - CHIP_DEF(PCI_CHIP_RV100_QY, RV100, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV100_QZ, RV100, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RN50, RV100, CHIP_HAS_CRTC2), - /* Radeon IGP320M (U1) */ - CHIP_DEF(PCI_CHIP_RS100_4336, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* Radeon IGP320 (A3) */ - CHIP_DEF(PCI_CHIP_RS100_4136, RS100, CHIP_HAS_CRTC2 | CHIP_IS_IGP), - /* IGP330M/340M/350M (U2) */ - CHIP_DEF(PCI_CHIP_RS200_4337, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* IGP330/340/350 (A4) */ - CHIP_DEF(PCI_CHIP_RS200_4137, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP), - /* Mobility 7000 IGP */ - CHIP_DEF(PCI_CHIP_RS250_4437, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* 7000 IGP (A4+) */ - CHIP_DEF(PCI_CHIP_RS250_4237, RS200, CHIP_HAS_CRTC2 | CHIP_IS_IGP), - /* 8500 AIW */ - CHIP_DEF(PCI_CHIP_R200_BB, R200, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R200_BC, R200, CHIP_HAS_CRTC2), - /* 8700/8800 */ - CHIP_DEF(PCI_CHIP_R200_QH, R200, CHIP_HAS_CRTC2), - /* 8500 */ - CHIP_DEF(PCI_CHIP_R200_QL, R200, CHIP_HAS_CRTC2), - /* 9100 */ - CHIP_DEF(PCI_CHIP_R200_QM, R200, CHIP_HAS_CRTC2), - /* Mobility M7 */ - CHIP_DEF(PCI_CHIP_RADEON_LW, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RADEON_LX, RV200, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - /* 7500 */ - CHIP_DEF(PCI_CHIP_RV200_QW, RV200, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV200_QX, RV200, CHIP_HAS_CRTC2), - /* Mobility M9 */ - CHIP_DEF(PCI_CHIP_RV250_Ld, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV250_Le, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV250_Lf, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV250_Lg, RV250, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - /* 9000/Pro */ - CHIP_DEF(PCI_CHIP_RV250_If, RV250, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV250_Ig, RV250, CHIP_HAS_CRTC2), - - CHIP_DEF(PCI_CHIP_RC410_5A62, RC410, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* Mobility 9100 IGP (U3) */ - CHIP_DEF(PCI_CHIP_RS300_5835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RS350_7835, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP | CHIP_IS_MOBILITY), - /* 9100 IGP (A5) */ - CHIP_DEF(PCI_CHIP_RS300_5834, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP), - CHIP_DEF(PCI_CHIP_RS350_7834, RS300, CHIP_HAS_CRTC2 | CHIP_IS_IGP), - /* Mobility 9200 (M9+) */ - CHIP_DEF(PCI_CHIP_RV280_5C61, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV280_5C63, RV280, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - /* 9200 */ - CHIP_DEF(PCI_CHIP_RV280_5960, RV280, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV280_5961, RV280, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV280_5962, RV280, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV280_5964, RV280, CHIP_HAS_CRTC2), - /* 9500 */ - CHIP_DEF(PCI_CHIP_R300_AD, R300, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R300_AE, R300, CHIP_HAS_CRTC2), - /* 9600TX / FireGL Z1 */ - CHIP_DEF(PCI_CHIP_R300_AF, R300, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R300_AG, R300, CHIP_HAS_CRTC2), - /* 9700/9500/Pro/FireGL X1 */ - CHIP_DEF(PCI_CHIP_R300_ND, R300, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R300_NE, R300, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R300_NF, R300, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R300_NG, R300, CHIP_HAS_CRTC2), - /* Mobility M10/M11 */ - CHIP_DEF(PCI_CHIP_RV350_NP, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV350_NQ, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV350_NR, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV350_NS, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV350_NT, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV350_NV, RV350, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - /* 9600/FireGL T2 */ - CHIP_DEF(PCI_CHIP_RV350_AP, RV350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV350_AQ, RV350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV360_AR, RV350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV350_AS, RV350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV350_AT, RV350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV350_AV, RV350, CHIP_HAS_CRTC2), - /* 9800/Pro/FileGL X2 */ - CHIP_DEF(PCI_CHIP_R350_AH, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_AI, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_AJ, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_AK, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_NH, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_NI, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R360_NJ, R350, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R350_NK, R350, CHIP_HAS_CRTC2), - /* Newer stuff */ - CHIP_DEF(PCI_CHIP_RV380_3E50, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV380_3E54, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV380_3150, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV380_3154, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV370_5B60, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV370_5B62, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV370_5B63, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV370_5B64, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV370_5B65, RV380, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_RV370_5460, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_RV370_5464, RV380, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_R420_JH, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JI, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JJ, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JK, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JL, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JM, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R420_JN, R420, CHIP_HAS_CRTC2 | CHIP_IS_MOBILITY), - CHIP_DEF(PCI_CHIP_R420_JP, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UH, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UI, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UJ, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UK, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UQ, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UR, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_UT, R420, CHIP_HAS_CRTC2), - CHIP_DEF(PCI_CHIP_R423_5D57, R420, CHIP_HAS_CRTC2), - /* Original Radeon/7200 */ - CHIP_DEF(PCI_CHIP_RADEON_QD, RADEON, 0), - CHIP_DEF(PCI_CHIP_RADEON_QE, RADEON, 0), - CHIP_DEF(PCI_CHIP_RADEON_QF, RADEON, 0), - CHIP_DEF(PCI_CHIP_RADEON_QG, RADEON, 0), - { 0, } -}; -MODULE_DEVICE_TABLE(pci, radeonfb_pci_table); - - -typedef struct { - u16 reg; - u32 val; -} reg_val; - - -/* these common regs are cleared before mode setting so they do not - * interfere with anything - */ -static reg_val common_regs[] = { - { OVR_CLR, 0 }, - { OVR_WID_LEFT_RIGHT, 0 }, - { OVR_WID_TOP_BOTTOM, 0 }, - { OV0_SCALE_CNTL, 0 }, - { SUBPIC_CNTL, 0 }, - { VIPH_CONTROL, 0 }, - { I2C_CNTL_1, 0 }, - { GEN_INT_CNTL, 0 }, - { CAP0_TRIG_CNTL, 0 }, - { CAP1_TRIG_CNTL, 0 }, -}; - -/* - * globals - */ - -static char *mode_option; -static char *monitor_layout; -static bool noaccel = 0; -static int default_dynclk = -2; -static bool nomodeset = 0; -static bool ignore_edid = 0; -static bool mirror = 0; -static int panel_yres = 0; -static bool force_dfp = 0; -static bool force_measure_pll = 0; -#ifdef CONFIG_MTRR -static bool nomtrr = 0; -#endif -static bool force_sleep; -static bool ignore_devlist; -#ifdef CONFIG_PMAC_BACKLIGHT -static int backlight = 1; -#else -static int backlight = 0; -#endif - -/* - * prototypes - */ - -static void radeon_unmap_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) -{ - if (!rinfo->bios_seg) - return; - pci_unmap_rom(dev, rinfo->bios_seg); -} - -static int radeon_map_ROM(struct radeonfb_info *rinfo, struct pci_dev *dev) -{ - void __iomem *rom; - u16 dptr; - u8 rom_type; - size_t rom_size; - - /* 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 */ - unsigned int 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; - - failed: - rinfo->bios_seg = NULL; - radeon_unmap_ROM(rinfo, dev); - return -ENXIO; -} - -#ifdef CONFIG_X86 -static int 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; - - for(segstart=0x000c0000; segstart<0x000f0000; segstart+=0x00001000) { - rom_base = ioremap(segstart, 0x10000); - if (rom_base == NULL) - return -ENOMEM; - if (readb(rom_base) == 0x55 && readb(rom_base + 1) == 0xaa) - break; - iounmap(rom_base); - rom_base = NULL; - } - if (rom_base == NULL) - return -ENXIO; - - /* Locate the flat panel infos, do some sanity checking !!! */ - rinfo->bios_seg = rom_base; - rinfo->fp_bios_start = BIOS_IN16(0x48); - - return 0; -} -#endif - -#if defined(CONFIG_PPC_OF) || 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 - */ -static int 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; - - return 0; -} -#endif /* CONFIG_PPC_OF || CONFIG_SPARC */ - -/* - * Read PLL infos from chip registers - */ -static int radeon_probe_pll_params(struct radeonfb_info *rinfo) -{ - unsigned char ppll_div_sel; - unsigned Ns, Nm, M; - unsigned sclk, mclk, tmp, ref_div; - int hTotal, vTotal, num, denom, m, n; - unsigned long long hz, vclk; - long xtal; - struct timeval start_tv, stop_tv; - long total_secs, total_usecs; - int i; - - /* Ugh, we cut interrupts, bad bad bad, but we want some precision - * here, so... --BenH - */ - - /* Flush PCI buffers ? */ - tmp = INREG16(DEVICE_ID); - - local_irq_disable(); - - for(i=0; i<1000000; i++) - if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) - break; - - do_gettimeofday(&start_tv); - - for(i=0; i<1000000; i++) - if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) != 0) - break; - - for(i=0; i<1000000; i++) - if (((INREG(CRTC_VLINE_CRNT_VLINE) >> 16) & 0x3ff) == 0) - break; - - do_gettimeofday(&stop_tv); - - local_irq_enable(); - - total_secs = stop_tv.tv_sec - start_tv.tv_sec; - if (total_secs > 10) - return -1; - total_usecs = stop_tv.tv_usec - start_tv.tv_usec; - total_usecs += total_secs * 1000000; - if (total_usecs < 0) - total_usecs = -total_usecs; - hz = 1000000/total_usecs; - - hTotal = ((INREG(CRTC_H_TOTAL_DISP) & 0x1ff) + 1) * 8; - vTotal = ((INREG(CRTC_V_TOTAL_DISP) & 0x3ff) + 1); - vclk = (long long)hTotal * (long long)vTotal * hz; - - switch((INPLL(PPLL_REF_DIV) & 0x30000) >> 16) { - case 0: - default: - num = 1; - denom = 1; - break; - case 1: - n = ((INPLL(M_SPLL_REF_FB_DIV) >> 16) & 0xff); - m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff); - num = 2*n; - denom = 2*m; - break; - case 2: - n = ((INPLL(M_SPLL_REF_FB_DIV) >> 8) & 0xff); - m = (INPLL(M_SPLL_REF_FB_DIV) & 0xff); - num = 2*n; - denom = 2*m; - break; - } - - ppll_div_sel = INREG8(CLOCK_CNTL_INDEX + 1) & 0x3; - radeon_pll_errata_after_index(rinfo); - - n = (INPLL(PPLL_DIV_0 + ppll_div_sel) & 0x7ff); - m = (INPLL(PPLL_REF_DIV) & 0x3ff); - - num *= n; - denom *= m; - - switch ((INPLL(PPLL_DIV_0 + ppll_div_sel) >> 16) & 0x7) { - case 1: - denom *= 2; - break; - case 2: - denom *= 4; - break; - case 3: - denom *= 8; - break; - case 4: - denom *= 3; - break; - case 6: - denom *= 6; - break; - case 7: - denom *= 12; - break; - } - - vclk *= denom; - do_div(vclk, 1000 * num); - xtal = vclk; - - if ((xtal > 26900) && (xtal < 27100)) - xtal = 2700; - else if ((xtal > 14200) && (xtal < 14400)) - xtal = 1432; - else if ((xtal > 29400) && (xtal < 29600)) - xtal = 2950; - else { - printk(KERN_WARNING "xtal calculation failed: %ld\n", xtal); - return -1; - } - - tmp = INPLL(M_SPLL_REF_FB_DIV); - ref_div = INPLL(PPLL_REF_DIV) & 0x3ff; - - Ns = (tmp & 0xff0000) >> 16; - Nm = (tmp & 0xff00) >> 8; - M = (tmp & 0xff); - sclk = round_div((2 * Ns * xtal), (2 * M)); - mclk = round_div((2 * Nm * xtal), (2 * M)); - - /* we're done, hopefully these are sane values */ - rinfo->pll.ref_clk = xtal; - rinfo->pll.ref_div = ref_div; - rinfo->pll.sclk = sclk; - rinfo->pll.mclk = mclk; - - return 0; -} - -/* - * Retrieve PLL infos by different means (BIOS, Open Firmware, register probing...) - */ -static void 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; - - -#if defined(CONFIG_PPC_OF) || 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_OF || 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); - - 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"); - 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; - - 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_div, - rinfo->pll.mclk / 100, rinfo->pll.mclk % 100, - rinfo->pll.sclk / 100, rinfo->pll.sclk % 100); - printk("radeonfb: PLL min %d max %d\n", rinfo->pll.ppll_min, rinfo->pll.ppll_max); -} - -static int radeonfb_check_var (struct fb_var_screeninfo *var, struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - struct fb_var_screeninfo v; - int nom, den; - unsigned int pitch; - - if (radeon_match_mode(rinfo, &v, var)) - return -EINVAL; - - switch (v.bits_per_pixel) { - case 0 ... 8: - v.bits_per_pixel = 8; - break; - case 9 ... 16: - v.bits_per_pixel = 16; - break; - case 17 ... 24: -#if 0 /* Doesn't seem to work */ - v.bits_per_pixel = 24; - break; -#endif - return -EINVAL; - case 25 ... 32: - v.bits_per_pixel = 32; - break; - default: - return -EINVAL; - } - - switch (var_to_depth(&v)) { - case 8: - nom = den = 1; - v.red.offset = v.green.offset = v.blue.offset = 0; - v.red.length = v.green.length = v.blue.length = 8; - v.transp.offset = v.transp.length = 0; - break; - case 15: - nom = 2; - den = 1; - v.red.offset = 10; - v.green.offset = 5; - v.blue.offset = 0; - v.red.length = v.green.length = v.blue.length = 5; - v.transp.offset = v.transp.length = 0; - break; - case 16: - nom = 2; - den = 1; - v.red.offset = 11; - v.green.offset = 5; - v.blue.offset = 0; - v.red.length = 5; - v.green.length = 6; - v.blue.length = 5; - v.transp.offset = v.transp.length = 0; - break; - case 24: - nom = 4; - den = 1; - v.red.offset = 16; - v.green.offset = 8; - v.blue.offset = 0; - v.red.length = v.blue.length = v.green.length = 8; - v.transp.offset = v.transp.length = 0; - break; - case 32: - nom = 4; - den = 1; - v.red.offset = 16; - v.green.offset = 8; - v.blue.offset = 0; - v.red.length = v.blue.length = v.green.length = 8; - v.transp.offset = 24; - v.transp.length = 8; - break; - default: - printk ("radeonfb: mode %dx%dx%d rejected, color depth invalid\n", - var->xres, var->yres, var->bits_per_pixel); - return -EINVAL; - } - - if (v.yres_virtual < v.yres) - v.yres_virtual = v.yres; - if (v.xres_virtual < v.xres) - v.xres_virtual = v.xres; - - - /* XXX I'm adjusting xres_virtual to the pitch, that may help XFree - * with some panels, though I don't quite like this solution - */ - if (rinfo->info->flags & FBINFO_HWACCEL_DISABLED) { - v.xres_virtual = v.xres_virtual & ~7ul; - } else { - pitch = ((v.xres_virtual * ((v.bits_per_pixel + 1) / 8) + 0x3f) - & ~(0x3f)) >> 6; - v.xres_virtual = (pitch << 6) / ((v.bits_per_pixel + 1) / 8); - } - - if (((v.xres_virtual * v.yres_virtual * nom) / den) > rinfo->mapped_vram) - return -EINVAL; - - if (v.xres_virtual < v.xres) - v.xres = v.xres_virtual; - - if (v.xoffset > v.xres_virtual - v.xres) - v.xoffset = v.xres_virtual - v.xres - 1; - - if (v.yoffset > v.yres_virtual - v.yres) - v.yoffset = v.yres_virtual - v.yres - 1; - - v.red.msb_right = v.green.msb_right = v.blue.msb_right = - v.transp.offset = v.transp.length = - v.transp.msb_right = 0; - - memcpy(var, &v, sizeof(v)); - - return 0; -} - - -static int radeonfb_pan_display (struct fb_var_screeninfo *var, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - - if ((var->xoffset + info->var.xres > info->var.xres_virtual) - || (var->yoffset + info->var.yres > info->var.yres_virtual)) - return -EINVAL; - - if (rinfo->asleep) - return 0; - - radeon_fifo_wait(2); - OUTREG(CRTC_OFFSET, (var->yoffset * info->fix.line_length + - var->xoffset * info->var.bits_per_pixel / 8) & ~7); - return 0; -} - - -static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, - unsigned long arg) -{ - struct radeonfb_info *rinfo = info->par; - unsigned int tmp; - u32 value = 0; - int rc; - - 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); - - tmp |= (LVDS_ON | LVDS_BLON); - } else { - tmp = INREG(LVDS_GEN_CNTL); - - tmp &= ~(LVDS_ON | LVDS_BLON); - } - - OUTREG(LVDS_GEN_CNTL, tmp); - - if (value & 0x02) { - tmp = INREG(CRTC_EXT_CNTL); - tmp |= CRTC_CRT_ON; - - mirror = 1; - } else { - tmp = INREG(CRTC_EXT_CNTL); - tmp &= ~CRTC_CRT_ON; - - mirror = 0; - } - - OUTREG(CRTC_EXT_CNTL, tmp); - - return 0; - case FBIO_RADEON_GET_MIRROR: - if (!rinfo->is_mobility) - return -EINVAL; - - tmp = INREG(LVDS_GEN_CNTL); - if ((LVDS_ON | LVDS_BLON) & tmp) - value |= 0x01; - - tmp = INREG(CRTC_EXT_CNTL); - if (CRTC_CRT_ON & tmp) - value |= 0x02; - - return put_user(value, (__u32 __user *)arg); - default: - return -EINVAL; - } - - return -EINVAL; -} - - -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); - - - switch (rinfo->mon1_type) { - case MT_DFP: - if (unblank) - OUTREGP(FP_GEN_CNTL, (FP_FPON | FP_TMDS_EN), - ~(FP_FPON | FP_TMDS_EN)); - else { - if (mode_switch || blank == FB_BLANK_NORMAL) - break; - OUTREGP(FP_GEN_CNTL, 0, ~(FP_FPON | FP_TMDS_EN)); - } - break; - case MT_LCD: - del_timer_sync(&rinfo->lvds_timer); - val = INREG(LVDS_GEN_CNTL); - if (unblank) { - u32 target_val = (val & ~LVDS_DISPLAY_DIS) | LVDS_BLON | LVDS_ON - | LVDS_EN | (rinfo->init_state.lvds_gen_cntl - & (LVDS_DIGON | LVDS_BL_MOD_EN)); - if ((val ^ target_val) == LVDS_DISPLAY_DIS) - OUTREG(LVDS_GEN_CNTL, target_val); - else if ((val ^ target_val) != 0) { - OUTREG(LVDS_GEN_CNTL, target_val - & ~(LVDS_ON | LVDS_BL_MOD_EN)); - rinfo->init_state.lvds_gen_cntl &= ~LVDS_STATE_MASK; - rinfo->init_state.lvds_gen_cntl |= - target_val & LVDS_STATE_MASK; - if (mode_switch) { - radeon_msleep(rinfo->panel_info.pwr_delay); - OUTREG(LVDS_GEN_CNTL, target_val); - } - else { - rinfo->pending_lvds_gen_cntl = target_val; - mod_timer(&rinfo->lvds_timer, - jiffies + - msecs_to_jiffies(rinfo->panel_info.pwr_delay)); - } - } - } else { - val |= LVDS_DISPLAY_DIS; - OUTREG(LVDS_GEN_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; - } - - return 0; -} - -static int radeonfb_blank (int blank, struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - - if (rinfo->asleep) - return 0; - - return radeon_screen_blank(rinfo, blank, 0); -} - -static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct radeonfb_info *rinfo) -{ - u32 pindex; - unsigned int i; - - - if (regno > 255) - return -EINVAL; - - 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->depth != 16 || regno < 32) { - OUTREG(PALETTE_INDEX, pindex); - OUTREG(PALETTE_DATA, (red << 16) | - (green << 8) | blue); - } - } - if (regno < 16) { - u32 *pal = rinfo->info->pseudo_palette; - switch (rinfo->depth) { - case 15: - pal[regno] = (regno << 10) | (regno << 5) | regno; - break; - case 16: - pal[regno] = (regno << 11) | (regno << 5) | regno; - break; - case 24: - pal[regno] = (regno << 16) | (regno << 8) | regno; - break; - case 32: - i = (regno << 8) | regno; - pal[regno] = (i << 16) | i; - break; - } - } - return 0; -} - -static int radeonfb_setcolreg (unsigned regno, unsigned red, unsigned green, - unsigned blue, unsigned transp, - struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - u32 dac_cntl2, vclk_cntl = 0; - int rc; - - 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); - } - } - - rc = radeon_setcolreg (regno, red, green, blue, transp, rinfo); - - if (!rinfo->asleep && rinfo->is_mobility) - OUTPLL(VCLK_ECP_CNTL, vclk_cntl); - - return rc; -} - -static int radeonfb_setcmap(struct fb_cmap *cmap, struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - u16 *red, *green, *blue, *transp; - u32 dac_cntl2, vclk_cntl = 0; - int i, start, rc = 0; - - 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; - - hred = *red++; - hgreen = *green++; - hblue = *blue++; - if (transp) - htransp = *transp++; - rc = radeon_setcolreg (start++, hred, hgreen, hblue, htransp, - rinfo); - if (rc) - break; - } - - if (!rinfo->asleep && rinfo->is_mobility) - OUTPLL(VCLK_ECP_CNTL, vclk_cntl); - - return rc; -} - -static void radeon_save_state (struct radeonfb_info *rinfo, - struct radeon_regs *save) -{ - /* CRTC regs */ - save->crtc_gen_cntl = INREG(CRTC_GEN_CNTL); - save->crtc_ext_cntl = INREG(CRTC_EXT_CNTL); - save->crtc_more_cntl = INREG(CRTC_MORE_CNTL); - save->dac_cntl = INREG(DAC_CNTL); - save->crtc_h_total_disp = INREG(CRTC_H_TOTAL_DISP); - save->crtc_h_sync_strt_wid = INREG(CRTC_H_SYNC_STRT_WID); - save->crtc_v_total_disp = INREG(CRTC_V_TOTAL_DISP); - save->crtc_v_sync_strt_wid = INREG(CRTC_V_SYNC_STRT_WID); - save->crtc_pitch = INREG(CRTC_PITCH); - save->surface_cntl = INREG(SURFACE_CNTL); - - /* FP regs */ - save->fp_crtc_h_total_disp = INREG(FP_CRTC_H_TOTAL_DISP); - save->fp_crtc_v_total_disp = INREG(FP_CRTC_V_TOTAL_DISP); - save->fp_gen_cntl = INREG(FP_GEN_CNTL); - save->fp_h_sync_strt_wid = INREG(FP_H_SYNC_STRT_WID); - save->fp_horz_stretch = INREG(FP_HORZ_STRETCH); - save->fp_v_sync_strt_wid = INREG(FP_V_SYNC_STRT_WID); - save->fp_vert_stretch = INREG(FP_VERT_STRETCH); - save->lvds_gen_cntl = INREG(LVDS_GEN_CNTL); - save->lvds_pll_cntl = INREG(LVDS_PLL_CNTL); - save->tmds_crc = INREG(TMDS_CRC); - save->tmds_transmitter_cntl = INREG(TMDS_TRANSMITTER_CNTL); - save->vclk_ecp_cntl = INPLL(VCLK_ECP_CNTL); - - /* PLL regs */ - save->clk_cntl_index = INREG(CLOCK_CNTL_INDEX) & ~0x3f; - radeon_pll_errata_after_index(rinfo); - save->ppll_div_3 = INPLL(PPLL_DIV_3); - save->ppll_ref_div = INPLL(PPLL_REF_DIV); -} - - -static void 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); - - /* Reset PPLL & enable atomic update */ - OUTPLLP(PPLL_CNTL, - PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN, - ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN)); - - /* Switch to selected PPLL divider */ - 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); - - /* Set PPLL ref. div */ - if (IS_R300_VARIANT(rinfo) || - rinfo->family == CHIP_FAMILY_RS300 || - rinfo->family == CHIP_FAMILY_RS400 || - rinfo->family == CHIP_FAMILY_RS480) { - if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) { - /* When restoring console mode, use saved PPLL_REF_DIV - * setting. - */ - OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0); - } else { - /* R300 uses ref_div_acc field as real ref divider */ - OUTPLLP(PPLL_REF_DIV, - (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT), - ~R300_PPLL_REF_DIV_ACC_MASK); - } - } else - OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK); - - /* Set PPLL divider 3 & post divider*/ - OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK); - OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK); - - /* Write update */ - while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R) - ; - OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W); - - /* 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++) - ; - - OUTPLL(HTOTAL_CNTL, 0); - - /* Clear reset & atomic update */ - OUTPLLP(PPLL_CNTL, 0, - ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN)); - - /* We may want some locking ... oh well */ - radeon_msleep(5); - - /* Switch back VCLK source to PPLL */ - OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK); -} - -/* - * Timer function for delayed LVDS panel power up/down - */ -static void radeon_lvds_timer_func(unsigned long data) -{ - struct radeonfb_info *rinfo = (struct radeonfb_info *)data; - - radeon_engine_idle(); - - OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); -} - -/* - * 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); - - /* Apply surface registers */ - for (i=0; i<8; i++) { - OUTREG(SURFACE0_LOWER_BOUND + 0x10*i, mode->surf_lower_bound[i]); - OUTREG(SURFACE0_UPPER_BOUND + 0x10*i, mode->surf_upper_bound[i]); - OUTREG(SURFACE0_INFO + 0x10*i, mode->surf_info[i]); - } - - OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl); - OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl, - ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS)); - OUTREG(CRTC_MORE_CNTL, mode->crtc_more_cntl); - OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING); - OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp); - OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid); - OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp); - OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid); - OUTREG(CRTC_OFFSET, 0); - OUTREG(CRTC_OFFSET_CNTL, 0); - OUTREG(CRTC_PITCH, mode->crtc_pitch); - OUTREG(SURFACE_CNTL, mode->surface_cntl); - - radeon_write_pll_regs(rinfo, mode); - - if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { - radeon_fifo_wait(10); - OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); - OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); - OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); - OUTREG(FP_V_SYNC_STRT_WID, mode->fp_v_sync_strt_wid); - OUTREG(FP_HORZ_STRETCH, mode->fp_horz_stretch); - OUTREG(FP_VERT_STRETCH, mode->fp_vert_stretch); - OUTREG(FP_GEN_CNTL, mode->fp_gen_cntl); - OUTREG(TMDS_CRC, mode->tmds_crc); - OUTREG(TMDS_TRANSMITTER_CNTL, mode->tmds_transmitter_cntl); - } - - if (!regs_only) - radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); - - radeon_fifo_wait(2); - OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); - - return; -} - -/* - * Calculate the PLL values for a given mode - */ -static void radeon_calc_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *regs, - unsigned long freq) -{ - const struct { - 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); - - fb_div = round_div(rinfo->pll.ref_div*pll_output_freq, - rinfo->pll.ref_clk); - regs->ppll_ref_div = rinfo->pll.ref_div; - regs->ppll_div_3 = fb_div | (post_div->bitvalue << 16); - - pr_debug("post div = 0x%x\n", post_div->bitvalue); - pr_debug("fb_div = 0x%x\n", fb_div); - pr_debug("ppll_div_3 = 0x%x\n", regs->ppll_div_3); -} - -static int radeonfb_set_par(struct fb_info *info) -{ - struct radeonfb_info *rinfo = info->par; - struct fb_var_screeninfo *mode = &info->var; - struct radeon_regs *newmode; - int hTotal, vTotal, hSyncStart, hSyncEnd, - hSyncPol, vSyncStart, vSyncEnd, vSyncPol, cSync; - u8 hsync_adj_tab[] = {0, 0x12, 9, 9, 6, 5}; - u8 hsync_fudge_fp[] = {2, 2, 0, 0, 5, 5}; - u32 sync, h_sync_pol, v_sync_pol, dotClock, pixClock; - int i, freq; - int format = 0; - int nopllcalc = 0; - int hsync_start, hsync_fudge, bytpp, hsync_wid, vsync_wid; - int primary_mon = PRIMARY_MONITOR(rinfo); - int depth = var_to_depth(mode); - int use_rmx = 0; - - newmode = kmalloc(sizeof(struct radeon_regs), GFP_KERNEL); - if (!newmode) - return -ENOMEM; - - /* We always want engine to be idle on a mode switch, even - * if we won't actually change the mode - */ - radeon_engine_idle(); - - hSyncStart = mode->xres + mode->right_margin; - hSyncEnd = hSyncStart + mode->hsync_len; - hTotal = hSyncEnd + mode->left_margin; - - vSyncStart = mode->yres + mode->lower_margin; - vSyncEnd = vSyncStart + mode->vsync_len; - vTotal = vSyncEnd + mode->upper_margin; - pixClock = mode->pixclock; - - sync = mode->sync; - h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; - v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - - if (primary_mon == MT_DFP || primary_mon == MT_LCD) { - if (rinfo->panel_info.xres < mode->xres) - mode->xres = rinfo->panel_info.xres; - if (rinfo->panel_info.yres < mode->yres) - mode->yres = rinfo->panel_info.yres; - - hTotal = mode->xres + rinfo->panel_info.hblank; - hSyncStart = mode->xres + rinfo->panel_info.hOver_plus; - hSyncEnd = hSyncStart + rinfo->panel_info.hSync_width; - - vTotal = mode->yres + rinfo->panel_info.vblank; - vSyncStart = mode->yres + rinfo->panel_info.vOver_plus; - vSyncEnd = vSyncStart + rinfo->panel_info.vSync_width; - - h_sync_pol = !rinfo->panel_info.hAct_high; - v_sync_pol = !rinfo->panel_info.vAct_high; - - pixClock = 100000000 / rinfo->panel_info.clock; - - if (rinfo->panel_info.use_bios_dividers) { - nopllcalc = 1; - newmode->ppll_div_3 = rinfo->panel_info.fbk_divider | - (rinfo->panel_info.post_divider << 16); - newmode->ppll_ref_div = rinfo->panel_info.ref_divider; - } - } - dotClock = 1000000000 / pixClock; - freq = dotClock / 10; /* x100 */ - - pr_debug("hStart = %d, hEnd = %d, hTotal = %d\n", - hSyncStart, hSyncEnd, hTotal); - pr_debug("vStart = %d, vEnd = %d, vTotal = %d\n", - vSyncStart, vSyncEnd, vTotal); - - hsync_wid = (hSyncEnd - hSyncStart) / 8; - vsync_wid = vSyncEnd - vSyncStart; - if (hsync_wid == 0) - hsync_wid = 1; - else if (hsync_wid > 0x3f) /* max */ - hsync_wid = 0x3f; - - if (vsync_wid == 0) - vsync_wid = 1; - else if (vsync_wid > 0x1f) /* max */ - vsync_wid = 0x1f; - - hSyncPol = mode->sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; - vSyncPol = mode->sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - - cSync = mode->sync & FB_SYNC_COMP_HIGH_ACT ? (1 << 4) : 0; - - format = radeon_get_dstbpp(depth); - bytpp = mode->bits_per_pixel >> 3; - - if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) - hsync_fudge = hsync_fudge_fp[format-1]; - else - hsync_fudge = hsync_adj_tab[format-1]; - - hsync_start = hSyncStart - 8 + hsync_fudge; - - newmode->crtc_gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | - (format << 8); - - /* Clear auto-center etc... */ - newmode->crtc_more_cntl = rinfo->init_state.crtc_more_cntl; - newmode->crtc_more_cntl &= 0xfffffff0; - - if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { - newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN; - if (mirror) - newmode->crtc_ext_cntl |= CRTC_CRT_ON; - - newmode->crtc_gen_cntl &= ~(CRTC_DBL_SCAN_EN | - CRTC_INTERLACE_EN); - } else { - newmode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | - CRTC_CRT_ON; - } - - newmode->dac_cntl = /* INREG(DAC_CNTL) | */ DAC_MASK_ALL | DAC_VGA_ADR_EN | - DAC_8BIT_EN; - - newmode->crtc_h_total_disp = ((((hTotal / 8) - 1) & 0x3ff) | - (((mode->xres / 8) - 1) << 16)); - - newmode->crtc_h_sync_strt_wid = ((hsync_start & 0x1fff) | - (hsync_wid << 16) | (h_sync_pol << 23)); - - newmode->crtc_v_total_disp = ((vTotal - 1) & 0xffff) | - ((mode->yres - 1) << 16); - - newmode->crtc_v_sync_strt_wid = (((vSyncStart - 1) & 0xfff) | - (vsync_wid << 16) | (v_sync_pol << 23)); - - if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { - /* We first calculate the engine pitch */ - rinfo->pitch = ((mode->xres_virtual * ((mode->bits_per_pixel + 1) / 8) + 0x3f) - & ~(0x3f)) >> 6; - - /* Then, re-multiply it to get the CRTC pitch */ - newmode->crtc_pitch = (rinfo->pitch << 3) / ((mode->bits_per_pixel + 1) / 8); - } else - newmode->crtc_pitch = (mode->xres_virtual >> 3); - - newmode->crtc_pitch |= (newmode->crtc_pitch << 16); - - /* - * 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; - -#if defined(__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 - - /* Clear surface registers */ - for (i=0; i<8; i++) { - newmode->surf_lower_bound[i] = 0; - newmode->surf_upper_bound[i] = 0x1f; - newmode->surf_info[i] = 0; - } - - pr_debug("h_total_disp = 0x%x\t hsync_strt_wid = 0x%x\n", - newmode->crtc_h_total_disp, newmode->crtc_h_sync_strt_wid); - pr_debug("v_total_disp = 0x%x\t vsync_strt_wid = 0x%x\n", - newmode->crtc_v_total_disp, newmode->crtc_v_sync_strt_wid); - - rinfo->bpp = mode->bits_per_pixel; - rinfo->depth = depth; - - pr_debug("pixclock = %lu\n", (unsigned long)pixClock); - pr_debug("freq = %lu\n", (unsigned long)freq); - - /* We use PPLL_DIV_3 */ - newmode->clk_cntl_index = 0x300; - - /* Calculate PPLL value if necessary */ - if (!nopllcalc) - radeon_calc_pll_regs(rinfo, newmode, freq); - - newmode->vclk_ecp_cntl = rinfo->init_state.vclk_ecp_cntl; - - if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { - unsigned int hRatio, vRatio; - - if (mode->xres > rinfo->panel_info.xres) - mode->xres = rinfo->panel_info.xres; - if (mode->yres > rinfo->panel_info.yres) - mode->yres = rinfo->panel_info.yres; - - newmode->fp_horz_stretch = (((rinfo->panel_info.xres / 8) - 1) - << HORZ_PANEL_SHIFT); - newmode->fp_vert_stretch = ((rinfo->panel_info.yres - 1) - << VERT_PANEL_SHIFT); - - if (mode->xres != rinfo->panel_info.xres) { - hRatio = round_div(mode->xres * HORZ_STRETCH_RATIO_MAX, - rinfo->panel_info.xres); - newmode->fp_horz_stretch = (((((unsigned long)hRatio) & HORZ_STRETCH_RATIO_MASK)) | - (newmode->fp_horz_stretch & - (HORZ_PANEL_SIZE | HORZ_FP_LOOP_STRETCH | - HORZ_AUTO_RATIO_INC))); - newmode->fp_horz_stretch |= (HORZ_STRETCH_BLEND | - HORZ_STRETCH_ENABLE); - use_rmx = 1; - } - newmode->fp_horz_stretch &= ~HORZ_AUTO_RATIO; - - if (mode->yres != rinfo->panel_info.yres) { - vRatio = round_div(mode->yres * VERT_STRETCH_RATIO_MAX, - rinfo->panel_info.yres); - newmode->fp_vert_stretch = (((((unsigned long)vRatio) & VERT_STRETCH_RATIO_MASK)) | - (newmode->fp_vert_stretch & - (VERT_PANEL_SIZE | VERT_STRETCH_RESERVED))); - newmode->fp_vert_stretch |= (VERT_STRETCH_BLEND | - VERT_STRETCH_ENABLE); - use_rmx = 1; - } - newmode->fp_vert_stretch &= ~VERT_AUTO_RATIO_EN; - - newmode->fp_gen_cntl = (rinfo->init_state.fp_gen_cntl & (u32) - ~(FP_SEL_CRTC2 | - FP_RMX_HVSYNC_CONTROL_EN | - FP_DFP_SYNC_SEL | - FP_CRT_SYNC_SEL | - FP_CRTC_LOCK_8DOT | - FP_USE_SHADOW_EN | - FP_CRTC_USE_SHADOW_VEND | - FP_CRT_SYNC_ALT)); - - newmode->fp_gen_cntl |= (FP_CRTC_DONT_SHADOW_VPAR | - FP_CRTC_DONT_SHADOW_HEND | - FP_PANEL_FORMAT); - - if (IS_R300_VARIANT(rinfo) || - (rinfo->family == CHIP_FAMILY_R200)) { - newmode->fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; - if (use_rmx) - newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; - else - newmode->fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; - } else - newmode->fp_gen_cntl |= FP_SEL_CRTC1; - - newmode->lvds_gen_cntl = rinfo->init_state.lvds_gen_cntl; - newmode->lvds_pll_cntl = rinfo->init_state.lvds_pll_cntl; - newmode->tmds_crc = rinfo->init_state.tmds_crc; - newmode->tmds_transmitter_cntl = rinfo->init_state.tmds_transmitter_cntl; - - if (primary_mon == MT_LCD) { - newmode->lvds_gen_cntl |= (LVDS_ON | LVDS_BLON); - newmode->fp_gen_cntl &= ~(FP_FPON | FP_TMDS_EN); - } else { - /* DFP */ - newmode->fp_gen_cntl |= (FP_FPON | FP_TMDS_EN); - newmode->tmds_transmitter_cntl &= ~(TMDS_PLLRST); - /* TMDS_PLL_EN bit is reversed on RV (and mobility) chips */ - if (IS_R300_VARIANT(rinfo) || - (rinfo->family == CHIP_FAMILY_R200) || !rinfo->has_CRTC2) - newmode->tmds_transmitter_cntl &= ~TMDS_PLL_EN; - else - newmode->tmds_transmitter_cntl |= TMDS_PLL_EN; - newmode->crtc_ext_cntl &= ~CRTC_CRT_ON; - } - - newmode->fp_crtc_h_total_disp = (((rinfo->panel_info.hblank / 8) & 0x3ff) | - (((mode->xres / 8) - 1) << 16)); - newmode->fp_crtc_v_total_disp = (rinfo->panel_info.vblank & 0xffff) | - ((mode->yres - 1) << 16); - newmode->fp_h_sync_strt_wid = ((rinfo->panel_info.hOver_plus & 0x1fff) | - (hsync_wid << 16) | (h_sync_pol << 23)); - newmode->fp_v_sync_strt_wid = ((rinfo->panel_info.vOver_plus & 0xfff) | - (vsync_wid << 16) | (v_sync_pol << 23)); - } - - /* do it! */ - if (!rinfo->asleep) { - memcpy(&rinfo->state, newmode, sizeof(*newmode)); - radeon_write_mode (rinfo, newmode, 0); - /* (re)initialize the engine */ - if (!(info->flags & FBINFO_HWACCEL_DISABLED)) - radeonfb_engine_init (rinfo); - } - /* Update fix */ - if (!(info->flags & FBINFO_HWACCEL_DISABLED)) - info->fix.line_length = rinfo->pitch*64; - else - info->fix.line_length = mode->xres_virtual - * ((mode->bits_per_pixel + 1) / 8); - info->fix.visual = rinfo->depth == 8 ? FB_VISUAL_PSEUDOCOLOR - : FB_VISUAL_DIRECTCOLOR; - -#ifdef CONFIG_BOOTX_TEXT - /* Update debug text engine */ - btext_update_display(rinfo->fb_base_phys, mode->xres, mode->yres, - rinfo->depth, info->fix.line_length); -#endif - - kfree(newmode); - return 0; -} - - -static struct fb_ops radeonfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = radeonfb_check_var, - .fb_set_par = radeonfb_set_par, - .fb_setcolreg = radeonfb_setcolreg, - .fb_setcmap = radeonfb_setcmap, - .fb_pan_display = radeonfb_pan_display, - .fb_blank = radeonfb_blank, - .fb_ioctl = radeonfb_ioctl, - .fb_sync = radeonfb_sync, - .fb_fillrect = radeonfb_fillrect, - .fb_copyarea = radeonfb_copyarea, - .fb_imageblit = radeonfb_imageblit, -}; - - -static int radeon_set_fbinfo(struct radeonfb_info *rinfo) -{ - struct fb_info *info = rinfo->info; - - info->par = rinfo; - info->pseudo_palette = rinfo->pseudo_palette; - info->flags = FBINFO_DEFAULT - | FBINFO_HWACCEL_COPYAREA - | FBINFO_HWACCEL_FILLRECT - | FBINFO_HWACCEL_XPAN - | FBINFO_HWACCEL_YPAN; - info->fbops = &radeonfb_ops; - info->screen_base = rinfo->fb_base; - info->screen_size = rinfo->mapped_vram; - /* Fill fix common fields */ - strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); - info->fix.smem_start = rinfo->fb_base_phys; - info->fix.smem_len = rinfo->video_ram; - info->fix.type = FB_TYPE_PACKED_PIXELS; - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - info->fix.xpanstep = 8; - info->fix.ypanstep = 1; - info->fix.ywrapstep = 0; - info->fix.type_aux = 0; - info->fix.mmio_start = rinfo->mmio_base_phys; - info->fix.mmio_len = RADEON_REGSIZE; - info->fix.accel = FB_ACCEL_ATI_RADEON; - - fb_alloc_cmap(&info->cmap, 256, 0); - - 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_OF -#undef SET_MC_FB_FROM_APERTURE -static void 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); - - OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl | CRTC_DISPLAY_DIS); - OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl | CRTC_DISP_REQ_EN_B); - mdelay(100); - - aper_base = INREG(CNFG_APER_0_BASE); - aper_size = INREG(CNFG_APER_SIZE); - -#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); - - /* Restore display settings */ - OUTREG(CRTC_GEN_CNTL, save_crtc_gen_cntl); - OUTREG(CRTC_EXT_CNTL, save_crtc_ext_cntl); - if (rinfo->has_CRTC2) - OUTREG(CRTC2_GEN_CNTL, save_crtc2_gen_cntl); - - pr_debug("aper_base: %08x MC_FB_LOC to: %08x, MC_AGP_LOC to: %08x\n", - aper_base, - ((aper_base + aper_size - 1) & 0xffff0000) | (aper_base >> 16), - 0xffff0000 | (agp_base >> 16)); -} -#endif /* CONFIG_PPC_OF */ - - -static void radeon_identify_vram(struct radeonfb_info *rinfo) -{ - u32 tmp; - - /* framebuffer size */ - if ((rinfo->family == CHIP_FAMILY_RS100) || - (rinfo->family == CHIP_FAMILY_RS200) || - (rinfo->family == CHIP_FAMILY_RS300) || - (rinfo->family == CHIP_FAMILY_RC410) || - (rinfo->family == CHIP_FAMILY_RS400) || - (rinfo->family == CHIP_FAMILY_RS480) ) { - u32 tom = INREG(NB_TOM); - tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); - - radeon_fifo_wait(6); - OUTREG(MC_FB_LOCATION, tom); - OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); - OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16); - - /* 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; - - tmp = INREG(MEM_CNTL); - if (IS_R300_VARIANT(rinfo)) { - tmp &= R300_MEM_NUM_CHANNELS_MASK; - switch (tmp) { - case 0: rinfo->vram_width = 64; break; - case 1: rinfo->vram_width = 128; break; - case 2: rinfo->vram_width = 256; break; - default: rinfo->vram_width = 128; break; - } - } else if ((rinfo->family == CHIP_FAMILY_RV100) || - (rinfo->family == CHIP_FAMILY_RS100) || - (rinfo->family == CHIP_FAMILY_RS200)){ - if (tmp & RV100_MEM_HALF_MODE) - rinfo->vram_width = 32; - else - rinfo->vram_width = 64; - } else { - if (tmp & MEM_NUM_CHANNELS_MASK) - rinfo->vram_width = 128; - else - rinfo->vram_width = 64; - } - - /* This may not be correct, as some cards can have half of channel disabled - * ToDo: identify these cases - */ - - pr_debug("radeonfb (%s): Found %ldk of %s %d bits wide videoram\n", - pci_name(rinfo->pdev), - rinfo->video_ram / 1024, - rinfo->vram_ddr ? "DDR" : "SDRAM", - rinfo->vram_width); -} - -/* - * Sysfs - */ - -static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u8 *edid) -{ - return memory_read_from_buffer(buf, count, &off, edid, EDID_LENGTH); -} - - -static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct pci_dev *pdev = to_pci_dev(dev); - struct fb_info *info = pci_get_drvdata(pdev); - struct radeonfb_info *rinfo = info->par; - - return radeon_show_one_edid(buf, off, count, rinfo->mon1_EDID); -} - - -static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct pci_dev *pdev = to_pci_dev(dev); - struct fb_info *info = pci_get_drvdata(pdev); - struct radeonfb_info *rinfo = info->par; - - return radeon_show_one_edid(buf, off, count, rinfo->mon2_EDID); -} - -static struct bin_attribute edid1_attr = { - .attr = { - .name = "edid1", - .mode = 0444, - }, - .size = EDID_LENGTH, - .read = radeon_show_edid1, -}; - -static struct bin_attribute edid2_attr = { - .attr = { - .name = "edid2", - .mode = 0444, - }, - .size = EDID_LENGTH, - .read = radeon_show_edid2, -}; - - -static int radeonfb_pci_register(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct fb_info *info; - struct radeonfb_info *rinfo; - int ret; - unsigned char c1, c2; - int err = 0; - - pr_debug("radeonfb_pci_register BEGIN\n"); - - /* Enable device in PCI config */ - ret = pci_enable_device(pdev); - if (ret < 0) { - printk(KERN_ERR "radeonfb (%s): Cannot enable PCI device\n", - pci_name(pdev)); - goto err_out; - } - - info = framebuffer_alloc(sizeof(struct radeonfb_info), &pdev->dev); - if (!info) { - printk (KERN_ERR "radeonfb (%s): could not allocate memory\n", - pci_name(pdev)); - ret = -ENOMEM; - goto err_disable; - } - rinfo = info->par; - rinfo->info = info; - rinfo->pdev = pdev; - - spin_lock_init(&rinfo->reg_lock); - init_timer(&rinfo->lvds_timer); - rinfo->lvds_timer.function = radeon_lvds_timer_func; - rinfo->lvds_timer.data = (unsigned long)rinfo; - - c1 = ent->device >> 8; - c2 = ent->device & 0xff; - if (isprint(c1) && isprint(c2)) - snprintf(rinfo->name, sizeof(rinfo->name), - "ATI Radeon %x \"%c%c\"", ent->device & 0xffff, c1, c2); - else - snprintf(rinfo->name, sizeof(rinfo->name), - "ATI Radeon %x", ent->device & 0xffff); - - rinfo->family = ent->driver_data & CHIP_FAMILY_MASK; - rinfo->chipset = pdev->device; - rinfo->has_CRTC2 = (ent->driver_data & CHIP_HAS_CRTC2) != 0; - rinfo->is_mobility = (ent->driver_data & CHIP_IS_MOBILITY) != 0; - rinfo->is_IGP = (ent->driver_data & CHIP_IS_IGP) != 0; - - /* Set base addrs */ - rinfo->fb_base_phys = pci_resource_start (pdev, 0); - rinfo->mmio_base_phys = pci_resource_start (pdev, 2); - - /* request the mem regions */ - ret = pci_request_region(pdev, 0, "radeonfb framebuffer"); - if (ret < 0) { - printk( KERN_ERR "radeonfb (%s): cannot request region 0.\n", - pci_name(rinfo->pdev)); - goto err_release_fb; - } - - ret = pci_request_region(pdev, 2, "radeonfb mmio"); - if (ret < 0) { - printk( KERN_ERR "radeonfb (%s): cannot request region 2.\n", - pci_name(rinfo->pdev)); - goto err_release_pci0; - } - - /* map the regions */ - rinfo->mmio_base = ioremap(rinfo->mmio_base_phys, RADEON_REGSIZE); - if (!rinfo->mmio_base) { - printk(KERN_ERR "radeonfb (%s): cannot map MMIO\n", - pci_name(rinfo->pdev)); - ret = -EIO; - goto err_release_pci2; - } - - rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; - - /* - * Check for errata - */ - rinfo->errata = 0; - if (rinfo->family == CHIP_FAMILY_R300 && - (INREG(CNFG_CNTL) & CFG_ATI_REV_ID_MASK) - == CFG_ATI_REV_A11) - rinfo->errata |= CHIP_ERRATA_R300_CG; - - if (rinfo->family == CHIP_FAMILY_RV200 || - rinfo->family == CHIP_FAMILY_RS200) - rinfo->errata |= CHIP_ERRATA_PLL_DUMMYREADS; - - if (rinfo->family == CHIP_FAMILY_RV100 || - rinfo->family == CHIP_FAMILY_RS100 || - rinfo->family == CHIP_FAMILY_RS200) - rinfo->errata |= CHIP_ERRATA_PLL_DELAY; - -#if defined(CONFIG_PPC_OF) || defined(CONFIG_SPARC) - /* On PPC, we obtain the OF device-node pointer to the firmware - * data for this chip - */ - rinfo->of_node = pci_device_to_OF_node(pdev); - if (rinfo->of_node == NULL) - printk(KERN_WARNING "radeonfb (%s): Cannot match card to OF node !\n", - pci_name(rinfo->pdev)); - -#endif /* CONFIG_PPC_OF || CONFIG_SPARC */ -#ifdef CONFIG_PPC_OF - /* On PPC, the firmware sets up a memory mapping that tends - * to cause lockups when enabling the engine. We reconfigure - * the card internal memory mappings properly - */ - fixup_memory_mappings(rinfo); -#endif /* CONFIG_PPC_OF */ - - /* Get VRAM size and type */ - radeon_identify_vram(rinfo); - - rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM, rinfo->video_ram); - - do { - rinfo->fb_base = ioremap (rinfo->fb_base_phys, - rinfo->mapped_vram); - } while (rinfo->fb_base == NULL && - ((rinfo->mapped_vram /= 2) >= MIN_MAPPED_VRAM)); - - if (rinfo->fb_base == NULL) { - printk (KERN_ERR "radeonfb (%s): cannot map FB\n", - pci_name(rinfo->pdev)); - ret = -EIO; - goto err_unmap_rom; - } - - pr_debug("radeonfb (%s): mapped %ldk videoram\n", pci_name(rinfo->pdev), - rinfo->mapped_vram/1024); - - /* - * Map the BIOS ROM if any and retrieve PLL parameters from - * the BIOS. We skip that on mobility chips as the real panel - * values we need aren't in the ROM but in the BIOS image in - * memory. This is definitely not the best meacnism though, - * we really need the arch code to tell us which is the "primary" - * video adapter to use the memory image (or better, the arch - * should provide us a copy of the BIOS image to shield us from - * archs who would store that elsewhere and/or could initialize - * more than one adapter during boot). - */ - if (!rinfo->is_mobility) - radeon_map_ROM(rinfo, pdev); - - /* - * On x86, the primary display on laptop may have it's BIOS - * ROM elsewhere, try to locate it at the legacy memory hole. - * We probably need to make sure this is the primary display, - * but that is difficult without some arch support. - */ -#ifdef CONFIG_X86 - if (rinfo->bios_seg == NULL) - radeon_find_mem_vbios(rinfo); -#endif - - /* If both above failed, try the BIOS ROM again for mobility - * chips - */ - if (rinfo->bios_seg == NULL && rinfo->is_mobility) - radeon_map_ROM(rinfo, pdev); - - /* Get informations about the board's PLL */ - radeon_get_pllinfo(rinfo); - -#ifdef CONFIG_FB_RADEON_I2C - /* Register I2C bus */ - radeon_create_i2c_busses(rinfo); -#endif - - /* set all the vital stuff */ - radeon_set_fbinfo (rinfo); - - /* Probe screen types */ - radeon_probe_screens(rinfo, monitor_layout, ignore_edid); - - /* Build mode list, check out panel native model */ - radeon_check_modes(rinfo, mode_option); - - /* Register some sysfs stuff (should be done better) */ - if (rinfo->mon1_EDID) - err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj, - &edid1_attr); - if (rinfo->mon2_EDID) - err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj, - &edid2_attr); - if (err) - pr_warning("%s() Creating sysfs files failed, continuing\n", - __func__); - - /* save current mode regs before we switch into the new one - * so we can restore this upon __exit - */ - radeon_save_state (rinfo, &rinfo->init_state); - memcpy(&rinfo->state, &rinfo->init_state, sizeof(struct radeon_regs)); - - /* Setup Power Management capabilities */ - if (default_dynclk < -1) { - /* -2 is special: means ON on mobility chips and do not - * change on others - */ - radeonfb_pm_init(rinfo, rinfo->is_mobility ? 1 : -1, ignore_devlist, force_sleep); - } else - radeonfb_pm_init(rinfo, default_dynclk, ignore_devlist, force_sleep); - - pci_set_drvdata(pdev, info); - - /* Register with fbdev layer */ - ret = register_framebuffer(info); - if (ret < 0) { - printk (KERN_ERR "radeonfb (%s): could not register framebuffer\n", - pci_name(rinfo->pdev)); - goto err_unmap_fb; - } - -#ifdef CONFIG_MTRR - rinfo->mtrr_hdl = nomtrr ? -1 : mtrr_add(rinfo->fb_base_phys, - rinfo->video_ram, - MTRR_TYPE_WRCOMB, 1); -#endif - - if (backlight) - radeonfb_bl_init(rinfo); - - printk ("radeonfb (%s): %s\n", pci_name(rinfo->pdev), rinfo->name); - - if (rinfo->bios_seg) - radeon_unmap_ROM(rinfo, pdev); - pr_debug("radeonfb_pci_register END\n"); - - return 0; -err_unmap_fb: - iounmap(rinfo->fb_base); -err_unmap_rom: - kfree(rinfo->mon1_EDID); - kfree(rinfo->mon2_EDID); - if (rinfo->mon1_modedb) - fb_destroy_modedb(rinfo->mon1_modedb); - fb_dealloc_cmap(&info->cmap); -#ifdef CONFIG_FB_RADEON_I2C - radeon_delete_i2c_busses(rinfo); -#endif - if (rinfo->bios_seg) - radeon_unmap_ROM(rinfo, pdev); - iounmap(rinfo->mmio_base); -err_release_pci2: - pci_release_region(pdev, 2); -err_release_pci0: - pci_release_region(pdev, 0); -err_release_fb: - framebuffer_release(info); -err_disable: -err_out: - return ret; -} - - - -static void radeonfb_pci_unregister(struct pci_dev *pdev) -{ - struct fb_info *info = pci_get_drvdata(pdev); - struct radeonfb_info *rinfo = info->par; - - if (!rinfo) - return; - - radeonfb_pm_exit(rinfo); - - if (rinfo->mon1_EDID) - sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid1_attr); - if (rinfo->mon2_EDID) - sysfs_remove_bin_file(&rinfo->pdev->dev.kobj, &edid2_attr); - -#if 0 - /* restore original state - * - * Doesn't quite work yet, I suspect if we come from a legacy - * VGA mode (or worse, text mode), we need to do some VGA black - * magic here that I know nothing about. --BenH - */ - radeon_write_mode (rinfo, &rinfo->init_state, 1); - #endif - - del_timer_sync(&rinfo->lvds_timer); - -#ifdef CONFIG_MTRR - if (rinfo->mtrr_hdl >= 0) - mtrr_del(rinfo->mtrr_hdl, 0, 0); -#endif - - unregister_framebuffer(info); - - radeonfb_bl_exit(rinfo); - - iounmap(rinfo->mmio_base); - iounmap(rinfo->fb_base); - - pci_release_region(pdev, 2); - pci_release_region(pdev, 0); - - kfree(rinfo->mon1_EDID); - kfree(rinfo->mon2_EDID); - if (rinfo->mon1_modedb) - fb_destroy_modedb(rinfo->mon1_modedb); -#ifdef CONFIG_FB_RADEON_I2C - radeon_delete_i2c_busses(rinfo); -#endif - fb_dealloc_cmap(&info->cmap); - framebuffer_release(info); -} - - -static struct pci_driver radeonfb_driver = { - .name = "radeonfb", - .id_table = radeonfb_pci_table, - .probe = radeonfb_pci_register, - .remove = radeonfb_pci_unregister, -#ifdef CONFIG_PM - .suspend = radeonfb_pci_suspend, - .resume = radeonfb_pci_resume, -#endif /* CONFIG_PM */ -}; - -#ifndef MODULE -static int __init radeonfb_setup (char *options) -{ - char *this_opt; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep (&options, ",")) != NULL) { - if (!*this_opt) - continue; - - if (!strncmp(this_opt, "noaccel", 7)) { - noaccel = 1; - } else if (!strncmp(this_opt, "mirror", 6)) { - mirror = 1; - } else if (!strncmp(this_opt, "force_dfp", 9)) { - force_dfp = 1; - } else if (!strncmp(this_opt, "panel_yres:", 11)) { - 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 - } else if (!strncmp(this_opt, "nomtrr", 6)) { - nomtrr = 1; -#endif - } else if (!strncmp(this_opt, "nomodeset", 9)) { - nomodeset = 1; - } else if (!strncmp(this_opt, "force_measure_pll", 17)) { - force_measure_pll = 1; - } else if (!strncmp(this_opt, "ignore_edid", 11)) { - ignore_edid = 1; -#if defined(CONFIG_PM) && defined(CONFIG_X86) - } else if (!strncmp(this_opt, "force_sleep", 11)) { - force_sleep = 1; - } else if (!strncmp(this_opt, "ignore_devlist", 14)) { - ignore_devlist = 1; -#endif - } else - mode_option = this_opt; - } - return 0; -} -#endif /* MODULE */ - -static int __init radeonfb_init (void) -{ -#ifndef MODULE - char *option = NULL; - - if (fb_get_options("radeonfb", &option)) - return -ENODEV; - radeonfb_setup(option); -#endif - return pci_register_driver (&radeonfb_driver); -} - - -static void __exit radeonfb_exit (void) -{ - pci_unregister_driver (&radeonfb_driver); -} - -module_init(radeonfb_init); -module_exit(radeonfb_exit); - -MODULE_AUTHOR("Ani Joshi"); -MODULE_DESCRIPTION("framebuffer driver for ATI Radeon chipset"); -MODULE_LICENSE("GPL"); -module_param(noaccel, bool, 0); -module_param(default_dynclk, int, 0); -MODULE_PARM_DESC(default_dynclk, "int: -2=enable on mobility only,-1=do not change,0=off,1=on"); -MODULE_PARM_DESC(noaccel, "bool: disable acceleration"); -module_param(nomodeset, bool, 0); -MODULE_PARM_DESC(nomodeset, "bool: disable actual setting of video mode"); -module_param(mirror, bool, 0); -MODULE_PARM_DESC(mirror, "bool: mirror the display to both monitors"); -module_param(force_dfp, bool, 0); -MODULE_PARM_DESC(force_dfp, "bool: force display to dfp"); -module_param(ignore_edid, bool, 0); -MODULE_PARM_DESC(ignore_edid, "bool: Ignore EDID data when doing DDC probe"); -module_param(monitor_layout, charp, 0); -MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); -module_param(force_measure_pll, bool, 0); -MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); -#ifdef CONFIG_MTRR -module_param(nomtrr, bool, 0); -MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); -#endif -module_param(panel_yres, int, 0); -MODULE_PARM_DESC(panel_yres, "int: set panel yres"); -module_param(mode_option, charp, 0); -MODULE_PARM_DESC(mode_option, "Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" "); -#if defined(CONFIG_PM) && defined(CONFIG_X86) -module_param(force_sleep, bool, 0); -MODULE_PARM_DESC(force_sleep, "bool: force D2 sleep mode on all hardware"); -module_param(ignore_devlist, bool, 0); -MODULE_PARM_DESC(ignore_devlist, "bool: ignore workarounds for bugs in specific laptops"); -#endif |