📄 atyfb_base.c
字号:
/* * ATI Frame Buffer Device Driver Core * * Copyright (C) 2004 Alex Kern <alex.kern@gmx.de> * Copyright (C) 1997-2001 Geert Uytterhoeven * Copyright (C) 1998 Bernd Harries * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) * * This driver supports the following ATI graphics chips: * - ATI Mach64 * * To do: add support for * - ATI Rage128 (from aty128fb.c) * - ATI Radeon (from radeonfb.c) * * This driver is partly based on the PowerMac console driver: * * Copyright (C) 1996 Paul Mackerras * * and on the PowerMac ATI/mach64 display driver: * * Copyright (C) 1997 Michael AK Tesch * * with work by Jon Howell * Harry AC Eaton * Anthony Tong <atong@uiuc.edu> * * Generic LCD support written by Daniel Mantione, ported from 2.4.20 by Alex Kern * Many Thanks to Ville Syrjälä for patches and fixing nasting 16 bit color bug. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. * * Many thanks to Nitya from ATI devrel for support and patience ! *//****************************************************************************** TODO: - cursor support on all cards and all ramdacs. - cursor parameters controlable via ioctl()s. - guess PLL and MCLK based on the original PLL register values initialized by Open Firmware (if they are initialized). BIOS is done (Anyone with Mac to help with this?)******************************************************************************/#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/console.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/spinlock.h>#include <linux/wait.h>#include <linux/backlight.h>#include <asm/io.h>#include <linux/uaccess.h>#include <video/mach64.h>#include "atyfb.h"#include "ati_ids.h"#ifdef __powerpc__#include <asm/machdep.h>#include <asm/prom.h>#include "../macmodes.h"#endif#ifdef __sparc__#include <asm/fbio.h>#include <asm/oplib.h>#include <asm/prom.h>#endif#ifdef CONFIG_ADB_PMU#include <linux/adb.h>#include <linux/pmu.h>#endif#ifdef CONFIG_BOOTX_TEXT#include <asm/btext.h>#endif#ifdef CONFIG_PMAC_BACKLIGHT#include <asm/backlight.h>#endif#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif/* * Debug flags. */#undef DEBUG/*#define DEBUG*//* Make sure n * PAGE_SIZE is protected at end of Aperture for GUI-regs *//* - must be large enough to catch all GUI-Regs *//* - must be aligned to a PAGE boundary */#define GUI_RESERVE (1 * PAGE_SIZE)/* FIXME: remove the FAIL definition */#define FAIL(msg) do { \ if (!(var->activate & FB_ACTIVATE_TEST)) \ printk(KERN_CRIT "atyfb: " msg "\n"); \ return -EINVAL; \} while (0)#define FAIL_MAX(msg, x, _max_) do { \ if (x > _max_) { \ if (!(var->activate & FB_ACTIVATE_TEST)) \ printk(KERN_CRIT "atyfb: " msg " %x(%x)\n", x, _max_); \ return -EINVAL; \ } \} while (0)#ifdef DEBUG#define DPRINTK(fmt, args...) printk(KERN_DEBUG "atyfb: " fmt, ## args)#else#define DPRINTK(fmt, args...)#endif#define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args)#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args)#if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT)static const u32 lt_lcd_regs[] = { CNFG_PANEL_LG, LCD_GEN_CNTL_LG, DSTN_CONTROL_LG, HFB_PITCH_ADDR_LG, HORZ_STRETCHING_LG, VERT_STRETCHING_LG, 0, /* EXT_VERT_STRETCH */ LT_GIO_LG, POWER_MANAGEMENT_LG};void aty_st_lcd(int index, u32 val, const struct atyfb_par *par){ if (M64_HAS(LT_LCD_REGS)) { aty_st_le32(lt_lcd_regs[index], val, par); } else { unsigned long temp; /* write addr byte */ temp = aty_ld_le32(LCD_INDEX, par); aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par); /* write the register value */ aty_st_le32(LCD_DATA, val, par); }}u32 aty_ld_lcd(int index, const struct atyfb_par *par){ if (M64_HAS(LT_LCD_REGS)) { return aty_ld_le32(lt_lcd_regs[index], par); } else { unsigned long temp; /* write addr byte */ temp = aty_ld_le32(LCD_INDEX, par); aty_st_le32(LCD_INDEX, (temp & ~LCD_INDEX_MASK) | index, par); /* read the register value */ return aty_ld_le32(LCD_DATA, par); }}#endif /* defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || defined (CONFIG_FB_ATY_GENERIC_LCD) */#ifdef CONFIG_FB_ATY_GENERIC_LCD/* * ATIReduceRatio -- * * Reduce a fraction by factoring out the largest common divider of the * fraction's numerator and denominator. */static void ATIReduceRatio(int *Numerator, int *Denominator){ int Multiplier, Divider, Remainder; Multiplier = *Numerator; Divider = *Denominator; while ((Remainder = Multiplier % Divider)) { Multiplier = Divider; Divider = Remainder; } *Numerator /= Divider; *Denominator /= Divider;}#endif /* * The Hardware parameters for each card */struct pci_mmap_map { unsigned long voff; unsigned long poff; unsigned long size; unsigned long prot_flag; unsigned long prot_mask;};static struct fb_fix_screeninfo atyfb_fix __devinitdata = { .id = "ATY Mach64", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_PSEUDOCOLOR, .xpanstep = 8, .ypanstep = 1,}; /* * Frame buffer device API */static int atyfb_open(struct fb_info *info, int user);static int atyfb_release(struct fb_info *info, int user);static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);static int atyfb_set_par(struct fb_info *info);static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info);static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);static int atyfb_blank(int blank, struct fb_info *info);static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg);#ifdef __sparc__static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma);#endifstatic int atyfb_sync(struct fb_info *info); /* * Internal routines */static int aty_init(struct fb_info *info);#ifdef CONFIG_ATARIstatic int store_video_par(char *videopar, unsigned char m64_num);#endifstatic struct crtc saved_crtc;static union aty_pll saved_pll;static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc);static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc);static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc);static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var);static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info);#ifdef CONFIG_PPCstatic int read_aty_sense(const struct atyfb_par *par);#endif /* * Interface used by the world */static struct fb_var_screeninfo default_var = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ 640, 480, 640, 480, 0, 0, 8, 0, {0, 8, 0}, {0, 8, 0}, {0, 8, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 39722, 48, 16, 33, 10, 96, 2, 0, FB_VMODE_NONINTERLACED};static struct fb_videomode defmode = { /* 640x480 @ 60 Hz, 31.5 kHz hsync */ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, FB_VMODE_NONINTERLACED};static struct fb_ops atyfb_ops = { .owner = THIS_MODULE, .fb_open = atyfb_open, .fb_release = atyfb_release, .fb_check_var = atyfb_check_var, .fb_set_par = atyfb_set_par, .fb_setcolreg = atyfb_setcolreg, .fb_pan_display = atyfb_pan_display, .fb_blank = atyfb_blank, .fb_ioctl = atyfb_ioctl, .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit,#ifdef __sparc__ .fb_mmap = atyfb_mmap,#endif .fb_sync = atyfb_sync,};static int noaccel;#ifdef CONFIG_MTRRstatic int nomtrr;#endifstatic int vram;static int pll;static int mclk;static int xclk;static int comp_sync __devinitdata = -1;static char *mode;#ifdef CONFIG_PMAC_BACKLIGHTstatic int backlight __devinitdata = 1;#elsestatic int backlight __devinitdata = 0;#endif#ifdef CONFIG_PPCstatic int default_vmode __devinitdata = VMODE_CHOOSE;static int default_cmode __devinitdata = CMODE_CHOOSE;module_param_named(vmode, default_vmode, int, 0);MODULE_PARM_DESC(vmode, "int: video mode for mac");module_param_named(cmode, default_cmode, int, 0);MODULE_PARM_DESC(cmode, "int: color mode for mac");#endif#ifdef CONFIG_ATARIstatic unsigned int mach64_count __devinitdata = 0;static unsigned long phys_vmembase[FB_MAX] __devinitdata = { 0, };static unsigned long phys_size[FB_MAX] __devinitdata = { 0, };static unsigned long phys_guiregbase[FB_MAX] __devinitdata = { 0, };#endif/* top -> down is an evolution of mach64 chipset, any corrections? */#define ATI_CHIP_88800GX (M64F_GX)#define ATI_CHIP_88800CX (M64F_GX)#define ATI_CHIP_264CT (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)#define ATI_CHIP_264ET (M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO)#define ATI_CHIP_264VT (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO)#define ATI_CHIP_264GT (M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_EXTRA_BRIGHT)#define ATI_CHIP_264VTB (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP)#define ATI_CHIP_264VT3 (M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL)#define ATI_CHIP_264VT4 (M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP)/* FIXME what is this chip? */#define ATI_CHIP_264LT (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP)/* make sets shorter */#define ATI_MODERN_SET (M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_EXTRA_BRIGHT)#define ATI_CHIP_264GTB (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)/*#define ATI_CHIP_264GTDVD ?*/#define ATI_CHIP_264LTG (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL)#define ATI_CHIP_264GT2C (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE)#define ATI_CHIP_264GTPRO (ATI_MODERN_SET | M64F_SDRAM_MAGIC_PLL | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)#define ATI_CHIP_264LTPRO (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D)#define ATI_CHIP_264XL (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4)#define ATI_CHIP_MOBILITY (ATI_MODERN_SET | M64F_HW_TRIPLE | M64F_FIFO_32 | M64F_RESET_3D | M64F_XL_DLL | M64F_MFB_FORCE_4 | M64F_MOBIL_BUS)static struct { u16 pci_id; const char *name; int pll, mclk, xclk, ecp_max; u32 features;} aty_chips[] __devinitdata = {#ifdef CONFIG_FB_ATY_GX /* Mach64 GX */ { PCI_CHIP_MACH64GX, "ATI888GX00 (Mach64 GX)", 135, 50, 50, 0, ATI_CHIP_88800GX }, { PCI_CHIP_MACH64CX, "ATI888CX00 (Mach64 CX)", 135, 50, 50, 0, ATI_CHIP_88800CX },#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CT { PCI_CHIP_MACH64CT, "ATI264CT (Mach64 CT)", 135, 60, 60, 0, ATI_CHIP_264CT }, { PCI_CHIP_MACH64ET, "ATI264ET (Mach64 ET)", 135, 60, 60, 0, ATI_CHIP_264ET }, /* FIXME what is this chip? */ { PCI_CHIP_MACH64LT, "ATI264LT (Mach64 LT)", 135, 63, 63, 0, ATI_CHIP_264LT }, { PCI_CHIP_MACH64VT, "ATI264VT (Mach64 VT)", 170, 67, 67, 80, ATI_CHIP_264VT }, { PCI_CHIP_MACH64GT, "3D RAGE (Mach64 GT)", 135, 63, 63, 80, ATI_CHIP_264GT }, { PCI_CHIP_MACH64VU, "ATI264VT3 (Mach64 VU)", 200, 67, 67, 80, ATI_CHIP_264VT3 }, { PCI_CHIP_MACH64GU, "3D RAGE II+ (Mach64 GU)", 200, 67, 67, 100, ATI_CHIP_264GTB }, { PCI_CHIP_MACH64LG, "3D RAGE LT (Mach64 LG)", 230, 63, 63, 100, ATI_CHIP_264LTG | M64F_LT_LCD_REGS | M64F_G3_PB_1024x768 }, { PCI_CHIP_MACH64VV, "ATI264VT4 (Mach64 VV)", 230, 83, 83, 100, ATI_CHIP_264VT4 }, { PCI_CHIP_MACH64GV, "3D RAGE IIC (Mach64 GV, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, { PCI_CHIP_MACH64GW, "3D RAGE IIC (Mach64 GW, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, { PCI_CHIP_MACH64GY, "3D RAGE IIC (Mach64 GY, PCI)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, { PCI_CHIP_MACH64GZ, "3D RAGE IIC (Mach64 GZ, AGP)", 230, 83, 83, 100, ATI_CHIP_264GT2C }, { PCI_CHIP_MACH64GB, "3D RAGE PRO (Mach64 GB, BGA, AGP)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, { PCI_CHIP_MACH64GD, "3D RAGE PRO (Mach64 GD, BGA, AGP 1x)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, { PCI_CHIP_MACH64GI, "3D RAGE PRO (Mach64 GI, BGA, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO | M64F_MAGIC_VRAM_SIZE }, { PCI_CHIP_MACH64GP, "3D RAGE PRO (Mach64 GP, PQFP, PCI)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, { PCI_CHIP_MACH64GQ, "3D RAGE PRO (Mach64 GQ, PQFP, PCI, limited 3D)", 230, 100, 100, 125, ATI_CHIP_264GTPRO }, { PCI_CHIP_MACH64LB, "3D RAGE LT PRO (Mach64 LB, AGP)", 236, 75, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LD, "3D RAGE LT PRO (Mach64 LD, AGP)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64LI, "3D RAGE LT PRO (Mach64 LI, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 }, { PCI_CHIP_MACH64LP, "3D RAGE LT PRO (Mach64 LP, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO | M64F_G3_PB_1024x768 }, { PCI_CHIP_MACH64LQ, "3D RAGE LT PRO (Mach64 LQ, PCI)", 230, 100, 100, 135, ATI_CHIP_264LTPRO }, { PCI_CHIP_MACH64GM, "3D RAGE XL (Mach64 GM, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL }, { PCI_CHIP_MACH64GN, "3D RAGE XC (Mach64 GN, AGP 2x)", 230, 83, 63, 135, ATI_CHIP_264XL }, { PCI_CHIP_MACH64GO, "3D RAGE XL (Mach64 GO, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL }, { PCI_CHIP_MACH64GL, "3D RAGE XC (Mach64 GL, PCI-66)", 230, 83, 63, 135, ATI_CHIP_264XL }, { PCI_CHIP_MACH64GR, "3D RAGE XL (Mach64 GR, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL | M64F_SDRAM_MAGIC_PLL }, { PCI_CHIP_MACH64GS, "3D RAGE XC (Mach64 GS, PCI-33)", 230, 83, 63, 135, ATI_CHIP_264XL }, { PCI_CHIP_MACH64LM, "3D RAGE Mobility P/M (Mach64 LM, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, { PCI_CHIP_MACH64LN, "3D RAGE Mobility L (Mach64 LN, AGP 2x)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, { PCI_CHIP_MACH64LR, "3D RAGE Mobility P/M (Mach64 LR, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY }, { PCI_CHIP_MACH64LS, "3D RAGE Mobility L (Mach64 LS, PCI)", 230, 83, 125, 135, ATI_CHIP_MOBILITY },#endif /* CONFIG_FB_ATY_CT */};static int __devinit correct_chipset(struct atyfb_par *par){ u8 rev; u16 type; u32 chip_id; const char *name; int i; for (i = ARRAY_SIZE(aty_chips) - 1; i >= 0; i--) if (par->pci_id == aty_chips[i].pci_id) break; if (i < 0) return -ENODEV; name = aty_chips[i].name; par->pll_limits.pll_max = aty_chips[i].pll; par->pll_limits.mclk = aty_chips[i].mclk; par->pll_limits.xclk = aty_chips[i].xclk; par->pll_limits.ecp_max = aty_chips[i].ecp_max; par->features = aty_chips[i].features;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -