📄 atyfb_base.c
字号:
/* * ATI Frame Buffer Device Driver Core * * 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> * * 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 the BIOS or Open Firmware (if they are initialized). (Anyone to help with this?)******************************************************************************/#include <linux/config.h>#include <linux/module.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/selection.h>#include <linux/console.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/vt_kern.h>#include <linux/kd.h>#include <asm/io.h>#include <asm/uaccess.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#include "mach64.h"#include "atyfb.h"#ifdef __powerpc__#include <asm/prom.h>#include <video/macmodes.h>#endif#ifdef __sparc__#include <asm/pbm.h>#include <asm/fbio.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_NVRAM#include <linux/nvram.h>#endif#ifdef CONFIG_FB_COMPAT_XPMAC#include <asm/vc_ioctl.h>#endif#ifdef CONFIG_PMAC_BACKLIGHT#include <asm/backlight.h>#endif/* * Debug flags. */#undef 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(x) do { printk(x "\n"); return -EINVAL; } while (0) /* * The Hardware parameters for each card */struct aty_cmap_regs { u8 windex; u8 lut; u8 mask; u8 rindex; u8 cntl;};struct pci_mmap_map { unsigned long voff; unsigned long poff; unsigned long size; unsigned long prot_flag; unsigned long prot_mask;}; /* * 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_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *fb);static int atyfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb);static int atyfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *fb);static int atyfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *fb);static int atyfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int atyfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int atyfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info);#ifdef __sparc__static int atyfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma);#endifstatic int atyfb_rasterimg(struct fb_info *info, int start); /* * Interface to the low level console driver */static int atyfbcon_switch(int con, struct fb_info *fb);static int atyfbcon_updatevar(int con, struct fb_info *fb);static void atyfbcon_blank(int blank, struct fb_info *fb); /* * Internal routines */static int aty_init(struct fb_info_aty *info, const char *name);#ifdef CONFIG_ATARIstatic int store_video_par(char *videopar, unsigned char m64_num);static char *strtoke(char *s, const char *ct);#endifstatic void aty_set_crtc(const struct fb_info_aty *info, const struct crtc *crtc);static int aty_var_to_crtc(const struct fb_info_aty *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 atyfb_set_par(const struct atyfb_par *par, struct fb_info_aty *info);static int atyfb_decode_var(const struct fb_var_screeninfo *var, struct atyfb_par *par, const struct fb_info_aty *info);static int atyfb_encode_var(struct fb_var_screeninfo *var, const struct atyfb_par *par, const struct fb_info_aty *info);static void set_off_pitch(struct atyfb_par *par, const struct fb_info_aty *info);static int encode_fix(struct fb_fix_screeninfo *fix, const struct atyfb_par *par, const struct fb_info_aty *info);static void atyfb_set_dispsw(struct display *disp, struct fb_info_aty *info, int bpp, int accel);static int atyfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *fb);static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *fb);static void do_install_cmap(int con, struct fb_info *info);#ifdef CONFIG_PPCstatic int read_aty_sense(const struct fb_info_aty *info);#endif /* * Interface used by the world */int atyfb_init(void);#ifndef MODULEint atyfb_setup(char*);#endifstatic int currcon = 0;static struct fb_ops atyfb_ops = { owner: THIS_MODULE, fb_open: atyfb_open, fb_release: atyfb_release, fb_get_fix: atyfb_get_fix, fb_get_var: atyfb_get_var, fb_set_var: atyfb_set_var, fb_get_cmap: atyfb_get_cmap, fb_set_cmap: atyfb_set_cmap, fb_pan_display: atyfb_pan_display, fb_ioctl: atyfb_ioctl,#ifdef __sparc__ fb_mmap: atyfb_mmap,#endif fb_rasterimg: atyfb_rasterimg,};static char atyfb_name[16] = "ATY Mach64";static char fontname[40] __initdata = { 0 };static char curblink __initdata = 1;static char noaccel __initdata = 0;static u32 default_vram __initdata = 0;static int default_pll __initdata = 0;static int default_mclk __initdata = 0;#ifndef MODULEstatic char *mode_option __initdata = NULL;#endif#ifdef CONFIG_PPC#ifndef CONFIG_NVRAMstatic int default_vmode __initdata = VMODE_NVRAM;static int default_cmode __initdata = CMODE_NVRAM;#elsestatic int default_vmode __initdata = VMODE_CHOOSE;static int default_cmode __initdata = CMODE_CHOOSE;#endif#endif#ifdef CONFIG_ATARIstatic unsigned int mach64_count __initdata = 0;static unsigned long phys_vmembase[FB_MAX] __initdata = { 0, };static unsigned long phys_size[FB_MAX] __initdata = { 0, };static unsigned long phys_guiregbase[FB_MAX] __initdata = { 0, };#endif#ifdef CONFIG_FB_ATY_GXstatic char m64n_gx[] __initdata = "mach64GX (ATI888GX00)";static char m64n_cx[] __initdata = "mach64CX (ATI888CX00)";#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CTstatic char m64n_ct[] __initdata = "mach64CT (ATI264CT)";static char m64n_et[] __initdata = "mach64ET (ATI264ET)";static char m64n_vta3[] __initdata = "mach64VTA3 (ATI264VT)";static char m64n_vta4[] __initdata = "mach64VTA4 (ATI264VT)";static char m64n_vtb[] __initdata = "mach64VTB (ATI264VTB)";static char m64n_vt4[] __initdata = "mach64VT4 (ATI264VT4)";static char m64n_gt[] __initdata = "3D RAGE (GT)";static char m64n_gtb[] __initdata = "3D RAGE II+ (GTB)";static char m64n_iic_p[] __initdata = "3D RAGE IIC (PCI)";static char m64n_iic_a[] __initdata = "3D RAGE IIC (AGP)";static char m64n_lt[] __initdata = "3D RAGE LT";static char m64n_ltg[] __initdata = "3D RAGE LT-G";static char m64n_gtc_ba[] __initdata = "3D RAGE PRO (BGA, AGP)";static char m64n_gtc_ba1[] __initdata = "3D RAGE PRO (BGA, AGP, 1x only)";static char m64n_gtc_bp[] __initdata = "3D RAGE PRO (BGA, PCI)";static char m64n_gtc_pp[] __initdata = "3D RAGE PRO (PQFP, PCI)";static char m64n_gtc_ppl[] __initdata = "3D RAGE PRO (PQFP, PCI, limited 3D)";static char m64n_xl[] __initdata = "3D RAGE (XL)";static char m64n_ltp_a[] __initdata = "3D RAGE LT PRO (AGP)";static char m64n_ltp_p[] __initdata = "3D RAGE LT PRO (PCI)";static char m64n_mob_p[] __initdata = "3D RAGE Mobility (PCI)";static char m64n_mob_a[] __initdata = "3D RAGE Mobility (AGP)";#endif /* CONFIG_FB_ATY_CT */static const struct { u16 pci_id, chip_type; u8 rev_mask, rev_val; const char *name; int pll, mclk; u32 features;} aty_chips[] __initdata = {#ifdef CONFIG_FB_ATY_GX /* Mach64 GX */ { 0x4758, 0x00d7, 0x00, 0x00, m64n_gx, 135, 50, M64F_GX }, { 0x4358, 0x0057, 0x00, 0x00, m64n_cx, 135, 50, M64F_GX },#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CT /* Mach64 CT */ { 0x4354, 0x4354, 0x00, 0x00, m64n_ct, 135, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO }, { 0x4554, 0x4554, 0x00, 0x00, m64n_et, 135, 60, M64F_CT | M64F_INTEGRATED | M64F_CT_BUS | M64F_MAGIC_FIFO }, /* Mach64 VT */ { 0x5654, 0x5654, 0xc7, 0x00, m64n_vta3, 170, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 }, { 0x5654, 0x5654, 0xc7, 0x40, m64n_vta4, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_MAGIC_POSTDIV }, { 0x5654, 0x5654, 0x00, 0x00, m64n_vtb, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 }, { 0x5655, 0x5655, 0x00, 0x00, m64n_vtb, 200, 67, M64F_VT | M64F_INTEGRATED | M64F_VT_BUS | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL }, { 0x5656, 0x5656, 0x00, 0x00, m64n_vt4, 230, 83, M64F_VT | M64F_INTEGRATED | M64F_GTB_DSP }, /* Mach64 GT (3D RAGE) */ { 0x4754, 0x4754, 0x07, 0x00, m64n_gt, 135, 63, M64F_GT | M64F_INTEGRATED | M64F_MAGIC_FIFO | M64F_FIFO_24 | M64F_EXTRA_BRIGHT }, { 0x4754, 0x4754, 0x07, 0x01, m64n_gt, 170, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4754, 0x4754, 0x07, 0x02, m64n_gt, 200, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4755, 0x4755, 0x00, 0x00, m64n_gtb, 200, 67, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4756, 0x4756, 0x00, 0x00, m64n_iic_p, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4757, 0x4757, 0x00, 0x00, m64n_iic_a, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x475a, 0x475a, 0x00, 0x00, m64n_iic_a, 230, 83, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_FIFO_24 | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, /* Mach64 LT */ { 0x4c54, 0x4c54, 0x00, 0x00, m64n_lt, 135, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP }, { 0x4c47, 0x4c47, 0x00, 0x00, m64n_ltg, 230, 63, M64F_GT | M64F_INTEGRATED | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_LT_SLEEP | M64F_G3_PB_1024x768 }, /* Mach64 GTC (3D RAGE PRO) */ { 0x4742, 0x4742, 0x00, 0x00, m64n_gtc_ba, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4744, 0x4744, 0x00, 0x00, m64n_gtc_ba1, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4749, 0x4749, 0x00, 0x00, m64n_gtc_bp, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_MAGIC_VRAM_SIZE }, { 0x4750, 0x4750, 0x00, 0x00, m64n_gtc_pp, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, { 0x4751, 0x4751, 0x00, 0x00, m64n_gtc_ppl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT }, /* 3D RAGE XL */ { 0x4752, 0x4752, 0x00, 0x00, m64n_xl, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_SDRAM_MAGIC_PLL | M64F_EXTRA_BRIGHT | M64F_XL_DLL }, /* Mach64 LT PRO */ { 0x4c42, 0x4c42, 0x00, 0x00, m64n_ltp_a, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, { 0x4c44, 0x4c44, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, { 0x4c49, 0x4c49, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_EXTRA_BRIGHT | M64F_G3_PB_1_1 | M64F_G3_PB_1024x768 }, { 0x4c50, 0x4c50, 0x00, 0x00, m64n_ltp_p, 230, 100, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP }, /* 3D RAGE Mobility */ { 0x4c4d, 0x4c4d, 0x00, 0x00, m64n_mob_p, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS }, { 0x4c4e, 0x4c4e, 0x00, 0x00, m64n_mob_a, 230, 50, M64F_GT | M64F_INTEGRATED | M64F_RESET_3D | M64F_GTB_DSP | M64F_MOBIL_BUS },#endif /* CONFIG_FB_ATY_CT */};#if defined(CONFIG_FB_ATY_GX) || defined(CONFIG_FB_ATY_CT)static char ram_dram[] __initdata = "DRAM";static char ram_resv[] __initdata = "RESV";#endif /* CONFIG_FB_ATY_GX || CONFIG_FB_ATY_CT */#ifdef CONFIG_FB_ATY_GXstatic char ram_vram[] __initdata = "VRAM";#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CTstatic char ram_edo[] __initdata = "EDO";static char ram_sdram[] __initdata = "SDRAM";static char ram_sgram[] __initdata = "SGRAM";static char ram_wram[] __initdata = "WRAM";static char ram_off[] __initdata = "OFF";#endif /* CONFIG_FB_ATY_CT */#ifdef CONFIG_FB_ATY_GXstatic char *aty_gx_ram[8] __initdata = { ram_dram, ram_vram, ram_vram, ram_dram, ram_dram, ram_vram, ram_vram, ram_resv};#endif /* CONFIG_FB_ATY_GX */#ifdef CONFIG_FB_ATY_CTstatic char *aty_ct_ram[8] __initdata = { ram_off, ram_dram, ram_edo, ram_edo, ram_sdram, ram_sgram, ram_wram, ram_resv};#endif /* CONFIG_FB_ATY_CT */#if defined(CONFIG_PPC) /* * Apple monitor sense */static int __init read_aty_sense(const struct fb_info_aty *info){ int sense, i; aty_st_le32(GP_IO, 0x31003100, info); /* drive outputs high */ __delay(200); aty_st_le32(GP_IO, 0, info); /* turn off outputs */ __delay(2000); i = aty_ld_le32(GP_IO, info); /* get primary sense value */ sense = ((i & 0x3000) >> 3) | (i & 0x100); /* drive each sense line low in turn and collect the other 2 */ aty_st_le32(GP_IO, 0x20000000, info); /* drive A low */ __delay(2000); i = aty_ld_le32(GP_IO, info); sense |= ((i & 0x1000) >> 7) | ((i & 0x100) >> 4); aty_st_le32(GP_IO, 0x20002000, info); /* drive A high again */ __delay(200); aty_st_le32(GP_IO, 0x10000000, info); /* drive B low */ __delay(2000); i = aty_ld_le32(GP_IO, info); sense |= ((i & 0x2000) >> 10) | ((i & 0x100) >> 6); aty_st_le32(GP_IO, 0x10001000, info); /* drive B high again */ __delay(200); aty_st_le32(GP_IO, 0x01000000, info); /* drive C low */ __delay(2000); sense |= (aty_ld_le32(GP_IO, info) & 0x3000) >> 12; aty_st_le32(GP_IO, 0, info); /* turn off outputs */ return sense;}#endif /* defined(CONFIG_PPC) */#if defined(CONFIG_PMAC_PBOOK) || defined(CONFIG_PMAC_BACKLIGHT)static void aty_st_lcd(int index, u32 val, const struct fb_info_aty *info){ unsigned long temp; /* write addr byte */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -