📄 i810_main.c
字号:
/*-*- linux-c -*- * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device * * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net> * All Rights Reserved * * Contributors: * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets * and enabling the power-on state of * external VGA connectors for * secondary displays * * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of * the VESA GTF * * Brad Corrion <bcorrion@web-co.com> - alpha testing of customized * timings support * * The code framework is a modification of vfb.c by Geert Uytterhoeven. * DotClock and PLL calculations are partly based on i810_driver.c * in xfree86 v4.0.3 by Precision Insight. * Watermark calculation and tables are based on i810_wmark.c * in xfre86 v4.0.3 by Precision Insight. Slight modifications * only to allow for integer operations instead of floating point. * * 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. */#include <linux/module.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/pci.h>#include <linux/pci_ids.h>#include <linux/resource.h>#include <linux/unistd.h>#include <asm/io.h>#include <asm/div64.h>#ifdef CONFIG_MTRR#include <asm/mtrr.h>#endif #include <asm/page.h>#include "i810_regs.h"#include "i810.h"#include "i810_main.h"/* PCI */static const char *i810_pci_list[] __devinitdata = { "Intel(R) 810 Framebuffer Device" , "Intel(R) 810-DC100 Framebuffer Device" , "Intel(R) 810E Framebuffer Device" , "Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device" , "Intel(R) 815 (Internal Graphics only) Framebuffer Device" , "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device"};static struct pci_device_id i810fb_pci_tbl[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, /* mvo: added i815 PCI-ID */ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, { 0 },};static struct pci_driver i810fb_driver = { .name = "i810fb", .id_table = i810fb_pci_tbl, .probe = i810fb_init_pci, .remove = __exit_p(i810fb_remove_pci), .suspend = i810fb_suspend, .resume = i810fb_resume,};static char *mode_option __devinitdata = NULL;static int vram __devinitdata = 4;static int bpp __devinitdata = 8;static int mtrr __devinitdata;static int accel __devinitdata;static int hsync1 __devinitdata;static int hsync2 __devinitdata;static int vsync1 __devinitdata;static int vsync2 __devinitdata;static int xres __devinitdata;static int yres __devinitdata;static int vyres __devinitdata;static int sync __devinitdata;static int extvga __devinitdata;static int dcolor __devinitdata;/*------------------------------------------------------------*//************************************************************** * Hardware Low Level Routines * **************************************************************//** * i810_screen_off - turns off/on display * @mmio: address of register space * @mode: on or off * * DESCRIPTION: * Blanks/unblanks the display */static void i810_screen_off(u8 __iomem *mmio, u8 mode){ u32 count = WAIT_COUNT; u8 val; i810_writeb(SR_INDEX, mmio, SR01); val = i810_readb(SR_DATA, mmio); val = (mode == OFF) ? val | SCR_OFF : val & ~SCR_OFF; while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--); i810_writeb(SR_INDEX, mmio, SR01); i810_writeb(SR_DATA, mmio, val);}/** * i810_dram_off - turns off/on dram refresh * @mmio: address of register space * @mode: on or off * * DESCRIPTION: * Turns off DRAM refresh. Must be off for only 2 vsyncs * before data becomes corrupt */static void i810_dram_off(u8 __iomem *mmio, u8 mode){ u8 val; val = i810_readb(DRAMCH, mmio); val &= DRAM_OFF; val = (mode == OFF) ? val : val | DRAM_ON; i810_writeb(DRAMCH, mmio, val);}/** * i810_protect_regs - allows rw/ro mode of certain VGA registers * @mmio: address of register space * @mode: protect/unprotect * * DESCRIPTION: * The IBM VGA standard allows protection of certain VGA registers. * This will protect or unprotect them. */static void i810_protect_regs(u8 __iomem *mmio, int mode){ u8 reg; i810_writeb(CR_INDEX_CGA, mmio, CR11); reg = i810_readb(CR_DATA_CGA, mmio); reg = (mode == OFF) ? reg & ~0x80 : reg | 0x80; i810_writeb(CR_INDEX_CGA, mmio, CR11); i810_writeb(CR_DATA_CGA, mmio, reg);}/** * i810_load_pll - loads values for the hardware PLL clock * @par: pointer to i810fb_par structure * * DESCRIPTION: * Loads the P, M, and N registers. */static void i810_load_pll(struct i810fb_par *par){ u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->regs.M | par->regs.N << 16; tmp2 = i810_readl(DCLK_2D, mmio); tmp2 &= ~MN_MASK; i810_writel(DCLK_2D, mmio, tmp1 | tmp2); tmp1 = par->regs.P; tmp2 = i810_readl(DCLK_0DS, mmio); tmp2 &= ~(P_OR << 16); i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2); i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1);}/** * i810_load_vga - load standard VGA registers * @par: pointer to i810fb_par structure * * DESCRIPTION: * Load values to VGA registers */static void i810_load_vga(struct i810fb_par *par){ u8 __iomem *mmio = par->mmio_start_virtual; /* interlace */ i810_writeb(CR_INDEX_CGA, mmio, CR70); i810_writeb(CR_DATA_CGA, mmio, par->interlace); i810_writeb(CR_INDEX_CGA, mmio, CR00); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00); i810_writeb(CR_INDEX_CGA, mmio, CR01); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01); i810_writeb(CR_INDEX_CGA, mmio, CR02); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02); i810_writeb(CR_INDEX_CGA, mmio, CR03); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03); i810_writeb(CR_INDEX_CGA, mmio, CR04); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04); i810_writeb(CR_INDEX_CGA, mmio, CR05); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05); i810_writeb(CR_INDEX_CGA, mmio, CR06); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06); i810_writeb(CR_INDEX_CGA, mmio, CR09); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09); i810_writeb(CR_INDEX_CGA, mmio, CR10); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10); i810_writeb(CR_INDEX_CGA, mmio, CR11); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11); i810_writeb(CR_INDEX_CGA, mmio, CR12); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12); i810_writeb(CR_INDEX_CGA, mmio, CR15); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15); i810_writeb(CR_INDEX_CGA, mmio, CR16); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16);}/** * i810_load_vgax - load extended VGA registers * @par: pointer to i810fb_par structure * * DESCRIPTION: * Load values to extended VGA registers */static void i810_load_vgax(struct i810fb_par *par){ u8 __iomem *mmio = par->mmio_start_virtual; i810_writeb(CR_INDEX_CGA, mmio, CR30); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30); i810_writeb(CR_INDEX_CGA, mmio, CR31); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31); i810_writeb(CR_INDEX_CGA, mmio, CR32); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32); i810_writeb(CR_INDEX_CGA, mmio, CR33); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33); i810_writeb(CR_INDEX_CGA, mmio, CR35); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35); i810_writeb(CR_INDEX_CGA, mmio, CR39); i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39);}/** * i810_load_2d - load grahics registers * @par: pointer to i810fb_par structure * * DESCRIPTION: * Load values to graphics registers */static void i810_load_2d(struct i810fb_par *par){ u32 tmp; u8 tmp8; u8 __iomem *mmio = par->mmio_start_virtual; i810_writel(FW_BLC, mmio, par->watermark); tmp = i810_readl(PIXCONF, mmio); tmp |= 1 | 1 << 20; i810_writel(PIXCONF, mmio, tmp); i810_writel(OVRACT, mmio, par->ovract); i810_writeb(GR_INDEX, mmio, GR10); tmp8 = i810_readb(GR_DATA, mmio); tmp8 |= 2; i810_writeb(GR_INDEX, mmio, GR10); i810_writeb(GR_DATA, mmio, tmp8);} /** * i810_hires - enables high resolution mode * @mmio: address of register space */static void i810_hires(u8 __iomem *mmio){ u8 val; i810_writeb(CR_INDEX_CGA, mmio, CR80); val = i810_readb(CR_DATA_CGA, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR80); i810_writeb(CR_DATA_CGA, mmio, val | 1); /* Stop LCD displays from flickering */ i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4);}/** * i810_load_pitch - loads the characters per line of the display * @par: pointer to i810fb_par structure * * DESCRIPTION: * Loads the characters per line */ static void i810_load_pitch(struct i810fb_par *par){ u32 tmp, pitch; u8 val; u8 __iomem *mmio = par->mmio_start_virtual; pitch = par->pitch >> 3; i810_writeb(SR_INDEX, mmio, SR01); val = i810_readb(SR_DATA, mmio); val &= 0xE0; val |= 1 | 1 << 2; i810_writeb(SR_INDEX, mmio, SR01); i810_writeb(SR_DATA, mmio, val); tmp = pitch & 0xFF; i810_writeb(CR_INDEX_CGA, mmio, CR13); i810_writeb(CR_DATA_CGA, mmio, (u8) tmp); tmp = pitch >> 8; i810_writeb(CR_INDEX_CGA, mmio, CR41); val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F; i810_writeb(CR_INDEX_CGA, mmio, CR41); i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val);}/** * i810_load_color - loads the color depth of the display * @par: pointer to i810fb_par structure * * DESCRIPTION: * Loads the color depth of the display and the graphics engine */static void i810_load_color(struct i810fb_par *par){ u8 __iomem *mmio = par->mmio_start_virtual; u32 reg1; u16 reg2; reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27); reg2 = i810_readw(BLTCNTL, mmio) & ~0x30; reg1 |= 0x8000 | par->pixconf; reg2 |= par->bltcntl; i810_writel(PIXCONF, mmio, reg1); i810_writew(BLTCNTL, mmio, reg2);}/** * i810_load_regs - loads all registers for the mode * @par: pointer to i810fb_par structure * * DESCRIPTION: * Loads registers */static void i810_load_regs(struct i810fb_par *par){ u8 __iomem *mmio = par->mmio_start_virtual; i810_screen_off(mmio, OFF); i810_protect_regs(mmio, OFF); i810_dram_off(mmio, OFF); i810_load_pll(par); i810_load_vga(par); i810_load_vgax(par); i810_dram_off(mmio, ON); i810_load_2d(par); i810_hires(mmio); i810_screen_off(mmio, ON); i810_protect_regs(mmio, ON); i810_load_color(par); i810_load_pitch(par);}static void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue, u8 __iomem *mmio){ i810_writeb(CLUT_INDEX_WRITE, mmio, regno); i810_writeb(CLUT_DATA, mmio, red); i810_writeb(CLUT_DATA, mmio, green); i810_writeb(CLUT_DATA, mmio, blue); }static void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, u8 __iomem *mmio){ i810_writeb(CLUT_INDEX_READ, mmio, regno); *red = i810_readb(CLUT_DATA, mmio); *green = i810_readb(CLUT_DATA, mmio); *blue = i810_readb(CLUT_DATA, mmio);}/************************************************************ * VGA State Restore * ************************************************************/static void i810_restore_pll(struct i810fb_par *par){ u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->hw_state.dclk_2d; tmp2 = i810_readl(DCLK_2D, mmio); tmp1 &= ~MN_MASK; tmp2 &= MN_MASK; i810_writel(DCLK_2D, mmio, tmp1 | tmp2); tmp1 = par->hw_state.dclk_1d; tmp2 = i810_readl(DCLK_1D, mmio); tmp1 &= ~MN_MASK; tmp2 &= MN_MASK; i810_writel(DCLK_1D, mmio, tmp1 | tmp2); i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds);}static void i810_restore_dac(struct i810fb_par *par){ u32 tmp1, tmp2; u8 __iomem *mmio = par->mmio_start_virtual; tmp1 = par->hw_state.pixconf; tmp2 = i810_readl(PIXCONF, mmio); tmp1 &= DAC_BIT; tmp2 &= ~DAC_BIT; i810_writel(PIXCONF, mmio, tmp1 | tmp2);}static void i810_restore_vgax(struct i810fb_par *par){ u8 i, j; u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 4; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR30+i); i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i)); } i810_writeb(CR_INDEX_CGA, mmio, CR35); i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35); i810_writeb(CR_INDEX_CGA, mmio, CR39); i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39); i810_writeb(CR_INDEX_CGA, mmio, CR41); i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39); /*restore interlace*/ i810_writeb(CR_INDEX_CGA, mmio, CR70); i = par->hw_state.cr70; i &= INTERLACE_BIT; j = i810_readb(CR_DATA_CGA, mmio); i810_writeb(CR_INDEX_CGA, mmio, CR70); i810_writeb(CR_DATA_CGA, mmio, j | i); i810_writeb(CR_INDEX_CGA, mmio, CR80); i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80); i810_writeb(MSR_WRITE, mmio, par->hw_state.msr); i810_writeb(SR_INDEX, mmio, SR01); i = (par->hw_state.sr01) & ~0xE0 ; j = i810_readb(SR_DATA, mmio) & 0xE0; i810_writeb(SR_INDEX, mmio, SR01); i810_writeb(SR_DATA, mmio, i | j);}static void i810_restore_vga(struct i810fb_par *par){ u8 i; u8 __iomem *mmio = par->mmio_start_virtual; for (i = 0; i < 10; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i)); } for (i = 0; i < 8; i++) { i810_writeb(CR_INDEX_CGA, mmio, CR10 + i); i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i)); }}static void i810_restore_addr_map(struct i810fb_par *par){ u8 tmp; u8 __iomem *mmio = par->mmio_start_virtual; i810_writeb(GR_INDEX, mmio, GR10); tmp = i810_readb(GR_DATA, mmio); tmp &= ADDR_MAP_MASK; tmp |= par->hw_state.gr10; i810_writeb(GR_INDEX, mmio, GR10); i810_writeb(GR_DATA, mmio, tmp);}static void i810_restore_2d(struct i810fb_par *par){ u32 tmp_long; u16 tmp_word; u8 __iomem *mmio = par->mmio_start_virtual; tmp_word = i810_readw(BLTCNTL, mmio); tmp_word &= ~(3 << 4); tmp_word |= par->hw_state.bltcntl; i810_writew(BLTCNTL, mmio, tmp_word); i810_dram_off(mmio, OFF); i810_writel(PIXCONF, mmio, par->hw_state.pixconf); i810_dram_off(mmio, ON); tmp_word = i810_readw(HWSTAM, mmio); tmp_word &= 3 << 13; tmp_word |= par->hw_state.hwstam; i810_writew(HWSTAM, mmio, tmp_word); tmp_long = i810_readl(FW_BLC, mmio); tmp_long &= FW_BLC_MASK; tmp_long |= par->hw_state.fw_blc; i810_writel(FW_BLC, mmio, tmp_long); i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); i810_writew(IER, mmio, par->hw_state.ier); i810_writew(IMR, mmio, par->hw_state.imr); i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -