162306a36Sopenharmony_ci /*-*- linux-c -*- 262306a36Sopenharmony_ci * linux/drivers/video/i810_main.c -- Intel 810 frame buffer device 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2001 Antonino Daplas<adaplas@pol.net> 562306a36Sopenharmony_ci * All Rights Reserved 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Contributors: 862306a36Sopenharmony_ci * Michael Vogt <mvogt@acm.org> - added support for Intel 815 chipsets 962306a36Sopenharmony_ci * and enabling the power-on state of 1062306a36Sopenharmony_ci * external VGA connectors for 1162306a36Sopenharmony_ci * secondary displays 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Fredrik Andersson <krueger@shell.linux.se> - alpha testing of 1462306a36Sopenharmony_ci * the VESA GTF 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * Brad Corrion <bcorrion@web-co.com> - alpha testing of customized 1762306a36Sopenharmony_ci * timings support 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * The code framework is a modification of vfb.c by Geert Uytterhoeven. 2062306a36Sopenharmony_ci * DotClock and PLL calculations are partly based on i810_driver.c 2162306a36Sopenharmony_ci * in xfree86 v4.0.3 by Precision Insight. 2262306a36Sopenharmony_ci * Watermark calculation and tables are based on i810_wmark.c 2362306a36Sopenharmony_ci * in xfre86 v4.0.3 by Precision Insight. Slight modifications 2462306a36Sopenharmony_ci * only to allow for integer operations instead of floating point. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 2762306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 2862306a36Sopenharmony_ci * more details. 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <linux/aperture.h> 3262306a36Sopenharmony_ci#include <linux/module.h> 3362306a36Sopenharmony_ci#include <linux/kernel.h> 3462306a36Sopenharmony_ci#include <linux/errno.h> 3562306a36Sopenharmony_ci#include <linux/string.h> 3662306a36Sopenharmony_ci#include <linux/mm.h> 3762306a36Sopenharmony_ci#include <linux/slab.h> 3862306a36Sopenharmony_ci#include <linux/fb.h> 3962306a36Sopenharmony_ci#include <linux/init.h> 4062306a36Sopenharmony_ci#include <linux/pci.h> 4162306a36Sopenharmony_ci#include <linux/pci_ids.h> 4262306a36Sopenharmony_ci#include <linux/resource.h> 4362306a36Sopenharmony_ci#include <linux/unistd.h> 4462306a36Sopenharmony_ci#include <linux/console.h> 4562306a36Sopenharmony_ci#include <linux/io.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#include <asm/io.h> 4862306a36Sopenharmony_ci#include <asm/div64.h> 4962306a36Sopenharmony_ci#include <asm/page.h> 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#include "i810_regs.h" 5262306a36Sopenharmony_ci#include "i810.h" 5362306a36Sopenharmony_ci#include "i810_main.h" 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* 5662306a36Sopenharmony_ci * voffset - framebuffer offset in MiB from aperture start address. In order for 5762306a36Sopenharmony_ci * the driver to work with X, we must try to use memory holes left untouched by X. The 5862306a36Sopenharmony_ci * following table lists where X's different surfaces start at. 5962306a36Sopenharmony_ci * 6062306a36Sopenharmony_ci * --------------------------------------------- 6162306a36Sopenharmony_ci * : : 64 MiB : 32 MiB : 6262306a36Sopenharmony_ci * ---------------------------------------------- 6362306a36Sopenharmony_ci * : FrontBuffer : 0 : 0 : 6462306a36Sopenharmony_ci * : DepthBuffer : 48 : 16 : 6562306a36Sopenharmony_ci * : BackBuffer : 56 : 24 : 6662306a36Sopenharmony_ci * ---------------------------------------------- 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci * So for chipsets with 64 MiB Aperture sizes, 32 MiB for v_offset is okay, allowing up to 6962306a36Sopenharmony_ci * 15 + 1 MiB of Framebuffer memory. For 32 MiB Aperture sizes, a v_offset of 8 MiB should 7062306a36Sopenharmony_ci * work, allowing 7 + 1 MiB of Framebuffer memory. 7162306a36Sopenharmony_ci * Note, the size of the hole may change depending on how much memory you allocate to X, 7262306a36Sopenharmony_ci * and how the memory is split up between these surfaces. 7362306a36Sopenharmony_ci * 7462306a36Sopenharmony_ci * Note: Anytime the DepthBuffer or FrontBuffer is overlapped, X would still run but with 7562306a36Sopenharmony_ci * DRI disabled. But if the Frontbuffer is overlapped, X will fail to load. 7662306a36Sopenharmony_ci * 7762306a36Sopenharmony_ci * Experiment with v_offset to find out which works best for you. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_cistatic u32 v_offset_default; /* For 32 MiB Aper size, 8 should be the default */ 8062306a36Sopenharmony_cistatic u32 voffset; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); 8362306a36Sopenharmony_cistatic int i810fb_init_pci(struct pci_dev *dev, 8462306a36Sopenharmony_ci const struct pci_device_id *entry); 8562306a36Sopenharmony_cistatic void i810fb_remove_pci(struct pci_dev *dev); 8662306a36Sopenharmony_cistatic int i810fb_resume(struct pci_dev *dev); 8762306a36Sopenharmony_cistatic int i810fb_suspend(struct pci_dev *dev, pm_message_t state); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci/* Chipset Specific Functions */ 9062306a36Sopenharmony_cistatic int i810fb_set_par (struct fb_info *info); 9162306a36Sopenharmony_cistatic int i810fb_getcolreg (u8 regno, u8 *red, u8 *green, u8 *blue, 9262306a36Sopenharmony_ci u8 *transp, struct fb_info *info); 9362306a36Sopenharmony_cistatic int i810fb_setcolreg (unsigned regno, unsigned red, unsigned green, unsigned blue, 9462306a36Sopenharmony_ci unsigned transp, struct fb_info *info); 9562306a36Sopenharmony_cistatic int i810fb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); 9662306a36Sopenharmony_cistatic int i810fb_blank (int blank_mode, struct fb_info *info); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/* Initialization */ 9962306a36Sopenharmony_cistatic void i810fb_release_resource (struct fb_info *info, struct i810fb_par *par); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci/* PCI */ 10262306a36Sopenharmony_cistatic const char * const i810_pci_list[] = { 10362306a36Sopenharmony_ci "Intel(R) 810 Framebuffer Device" , 10462306a36Sopenharmony_ci "Intel(R) 810-DC100 Framebuffer Device" , 10562306a36Sopenharmony_ci "Intel(R) 810E Framebuffer Device" , 10662306a36Sopenharmony_ci "Intel(R) 815 (Internal Graphics 100Mhz FSB) Framebuffer Device" , 10762306a36Sopenharmony_ci "Intel(R) 815 (Internal Graphics only) Framebuffer Device" , 10862306a36Sopenharmony_ci "Intel(R) 815 (Internal Graphics with AGP) Framebuffer Device" 10962306a36Sopenharmony_ci}; 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_cistatic const struct pci_device_id i810fb_pci_tbl[] = { 11262306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1, 11362306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 11462306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3, 11562306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 }, 11662306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG, 11762306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 }, 11862306a36Sopenharmony_ci /* mvo: added i815 PCI-ID */ 11962306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_100, 12062306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 }, 12162306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_NOAGP, 12262306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, 12362306a36Sopenharmony_ci { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, 12462306a36Sopenharmony_ci PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, 12562306a36Sopenharmony_ci { 0 }, 12662306a36Sopenharmony_ci}; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic struct pci_driver i810fb_driver = { 12962306a36Sopenharmony_ci .name = "i810fb", 13062306a36Sopenharmony_ci .id_table = i810fb_pci_tbl, 13162306a36Sopenharmony_ci .probe = i810fb_init_pci, 13262306a36Sopenharmony_ci .remove = i810fb_remove_pci, 13362306a36Sopenharmony_ci .suspend = i810fb_suspend, 13462306a36Sopenharmony_ci .resume = i810fb_resume, 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic char *mode_option = NULL; 13862306a36Sopenharmony_cistatic int vram = 4; 13962306a36Sopenharmony_cistatic int bpp = 8; 14062306a36Sopenharmony_cistatic bool mtrr; 14162306a36Sopenharmony_cistatic bool accel; 14262306a36Sopenharmony_cistatic int hsync1; 14362306a36Sopenharmony_cistatic int hsync2; 14462306a36Sopenharmony_cistatic int vsync1; 14562306a36Sopenharmony_cistatic int vsync2; 14662306a36Sopenharmony_cistatic int xres; 14762306a36Sopenharmony_cistatic int yres; 14862306a36Sopenharmony_cistatic int vyres; 14962306a36Sopenharmony_cistatic bool sync; 15062306a36Sopenharmony_cistatic bool extvga; 15162306a36Sopenharmony_cistatic bool dcolor; 15262306a36Sopenharmony_cistatic bool ddc3; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci/*------------------------------------------------------------*/ 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci/************************************************************** 15762306a36Sopenharmony_ci * Hardware Low Level Routines * 15862306a36Sopenharmony_ci **************************************************************/ 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci/** 16162306a36Sopenharmony_ci * i810_screen_off - turns off/on display 16262306a36Sopenharmony_ci * @mmio: address of register space 16362306a36Sopenharmony_ci * @mode: on or off 16462306a36Sopenharmony_ci * 16562306a36Sopenharmony_ci * DESCRIPTION: 16662306a36Sopenharmony_ci * Blanks/unblanks the display 16762306a36Sopenharmony_ci */ 16862306a36Sopenharmony_cistatic void i810_screen_off(u8 __iomem *mmio, u8 mode) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci u32 count = WAIT_COUNT; 17162306a36Sopenharmony_ci u8 val; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 17462306a36Sopenharmony_ci val = i810_readb(SR_DATA, mmio); 17562306a36Sopenharmony_ci val = (mode == OFF) ? val | SCR_OFF : 17662306a36Sopenharmony_ci val & ~SCR_OFF; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci while((i810_readw(DISP_SL, mmio) & 0xFFF) && count--); 17962306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 18062306a36Sopenharmony_ci i810_writeb(SR_DATA, mmio, val); 18162306a36Sopenharmony_ci} 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci/** 18462306a36Sopenharmony_ci * i810_dram_off - turns off/on dram refresh 18562306a36Sopenharmony_ci * @mmio: address of register space 18662306a36Sopenharmony_ci * @mode: on or off 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * DESCRIPTION: 18962306a36Sopenharmony_ci * Turns off DRAM refresh. Must be off for only 2 vsyncs 19062306a36Sopenharmony_ci * before data becomes corrupt 19162306a36Sopenharmony_ci */ 19262306a36Sopenharmony_cistatic void i810_dram_off(u8 __iomem *mmio, u8 mode) 19362306a36Sopenharmony_ci{ 19462306a36Sopenharmony_ci u8 val; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci val = i810_readb(DRAMCH, mmio); 19762306a36Sopenharmony_ci val &= DRAM_OFF; 19862306a36Sopenharmony_ci val = (mode == OFF) ? val : val | DRAM_ON; 19962306a36Sopenharmony_ci i810_writeb(DRAMCH, mmio, val); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/** 20362306a36Sopenharmony_ci * i810_protect_regs - allows rw/ro mode of certain VGA registers 20462306a36Sopenharmony_ci * @mmio: address of register space 20562306a36Sopenharmony_ci * @mode: protect/unprotect 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * DESCRIPTION: 20862306a36Sopenharmony_ci * The IBM VGA standard allows protection of certain VGA registers. 20962306a36Sopenharmony_ci * This will protect or unprotect them. 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_cistatic void i810_protect_regs(u8 __iomem *mmio, int mode) 21262306a36Sopenharmony_ci{ 21362306a36Sopenharmony_ci u8 reg; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR11); 21662306a36Sopenharmony_ci reg = i810_readb(CR_DATA_CGA, mmio); 21762306a36Sopenharmony_ci reg = (mode == OFF) ? reg & ~0x80 : 21862306a36Sopenharmony_ci reg | 0x80; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR11); 22162306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, reg); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci/** 22562306a36Sopenharmony_ci * i810_load_pll - loads values for the hardware PLL clock 22662306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 22762306a36Sopenharmony_ci * 22862306a36Sopenharmony_ci * DESCRIPTION: 22962306a36Sopenharmony_ci * Loads the P, M, and N registers. 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_cistatic void i810_load_pll(struct i810fb_par *par) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci u32 tmp1, tmp2; 23462306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci tmp1 = par->regs.M | par->regs.N << 16; 23762306a36Sopenharmony_ci tmp2 = i810_readl(DCLK_2D, mmio); 23862306a36Sopenharmony_ci tmp2 &= ~MN_MASK; 23962306a36Sopenharmony_ci i810_writel(DCLK_2D, mmio, tmp1 | tmp2); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci tmp1 = par->regs.P; 24262306a36Sopenharmony_ci tmp2 = i810_readl(DCLK_0DS, mmio); 24362306a36Sopenharmony_ci tmp2 &= ~(P_OR << 16); 24462306a36Sopenharmony_ci i810_writel(DCLK_0DS, mmio, (tmp1 << 16) | tmp2); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci i810_writeb(MSR_WRITE, mmio, par->regs.msr | 0xC8 | 1); 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci/** 25162306a36Sopenharmony_ci * i810_load_vga - load standard VGA registers 25262306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 25362306a36Sopenharmony_ci * 25462306a36Sopenharmony_ci * DESCRIPTION: 25562306a36Sopenharmony_ci * Load values to VGA registers 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_cistatic void i810_load_vga(struct i810fb_par *par) 25862306a36Sopenharmony_ci{ 25962306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* interlace */ 26262306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR70); 26362306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->interlace); 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR00); 26662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr00); 26762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR01); 26862306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr01); 26962306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR02); 27062306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr02); 27162306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR03); 27262306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr03); 27362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR04); 27462306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr04); 27562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR05); 27662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr05); 27762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR06); 27862306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr06); 27962306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR09); 28062306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr09); 28162306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR10); 28262306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr10); 28362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR11); 28462306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr11); 28562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR12); 28662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr12); 28762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR15); 28862306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr15); 28962306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR16); 29062306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr16); 29162306a36Sopenharmony_ci} 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci/** 29462306a36Sopenharmony_ci * i810_load_vgax - load extended VGA registers 29562306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * DESCRIPTION: 29862306a36Sopenharmony_ci * Load values to extended VGA registers 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_cistatic void i810_load_vgax(struct i810fb_par *par) 30162306a36Sopenharmony_ci{ 30262306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR30); 30562306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr30); 30662306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR31); 30762306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr31); 30862306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR32); 30962306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr32); 31062306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR33); 31162306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr33); 31262306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR35); 31362306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr35); 31462306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR39); 31562306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->regs.cr39); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/** 31962306a36Sopenharmony_ci * i810_load_2d - load grahics registers 32062306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci * DESCRIPTION: 32362306a36Sopenharmony_ci * Load values to graphics registers 32462306a36Sopenharmony_ci */ 32562306a36Sopenharmony_cistatic void i810_load_2d(struct i810fb_par *par) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci u32 tmp; 32862306a36Sopenharmony_ci u8 tmp8; 32962306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci i810_writel(FW_BLC, mmio, par->watermark); 33262306a36Sopenharmony_ci tmp = i810_readl(PIXCONF, mmio); 33362306a36Sopenharmony_ci tmp |= 1 | 1 << 20; 33462306a36Sopenharmony_ci i810_writel(PIXCONF, mmio, tmp); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci i810_writel(OVRACT, mmio, par->ovract); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci i810_writeb(GR_INDEX, mmio, GR10); 33962306a36Sopenharmony_ci tmp8 = i810_readb(GR_DATA, mmio); 34062306a36Sopenharmony_ci tmp8 |= 2; 34162306a36Sopenharmony_ci i810_writeb(GR_INDEX, mmio, GR10); 34262306a36Sopenharmony_ci i810_writeb(GR_DATA, mmio, tmp8); 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci/** 34662306a36Sopenharmony_ci * i810_hires - enables high resolution mode 34762306a36Sopenharmony_ci * @mmio: address of register space 34862306a36Sopenharmony_ci */ 34962306a36Sopenharmony_cistatic void i810_hires(u8 __iomem *mmio) 35062306a36Sopenharmony_ci{ 35162306a36Sopenharmony_ci u8 val; 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR80); 35462306a36Sopenharmony_ci val = i810_readb(CR_DATA_CGA, mmio); 35562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR80); 35662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, val | 1); 35762306a36Sopenharmony_ci /* Stop LCD displays from flickering */ 35862306a36Sopenharmony_ci i810_writel(MEM_MODE, mmio, i810_readl(MEM_MODE, mmio) | 4); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci/** 36262306a36Sopenharmony_ci * i810_load_pitch - loads the characters per line of the display 36362306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 36462306a36Sopenharmony_ci * 36562306a36Sopenharmony_ci * DESCRIPTION: 36662306a36Sopenharmony_ci * Loads the characters per line 36762306a36Sopenharmony_ci */ 36862306a36Sopenharmony_cistatic void i810_load_pitch(struct i810fb_par *par) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci u32 tmp, pitch; 37162306a36Sopenharmony_ci u8 val; 37262306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci pitch = par->pitch >> 3; 37562306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 37662306a36Sopenharmony_ci val = i810_readb(SR_DATA, mmio); 37762306a36Sopenharmony_ci val &= 0xE0; 37862306a36Sopenharmony_ci val |= 1 | 1 << 2; 37962306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 38062306a36Sopenharmony_ci i810_writeb(SR_DATA, mmio, val); 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci tmp = pitch & 0xFF; 38362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR13); 38462306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, (u8) tmp); 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci tmp = pitch >> 8; 38762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR41); 38862306a36Sopenharmony_ci val = i810_readb(CR_DATA_CGA, mmio) & ~0x0F; 38962306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR41); 39062306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, (u8) tmp | val); 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci/** 39462306a36Sopenharmony_ci * i810_load_color - loads the color depth of the display 39562306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 39662306a36Sopenharmony_ci * 39762306a36Sopenharmony_ci * DESCRIPTION: 39862306a36Sopenharmony_ci * Loads the color depth of the display and the graphics engine 39962306a36Sopenharmony_ci */ 40062306a36Sopenharmony_cistatic void i810_load_color(struct i810fb_par *par) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 40362306a36Sopenharmony_ci u32 reg1; 40462306a36Sopenharmony_ci u16 reg2; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci reg1 = i810_readl(PIXCONF, mmio) & ~(0xF0000 | 1 << 27); 40762306a36Sopenharmony_ci reg2 = i810_readw(BLTCNTL, mmio) & ~0x30; 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci reg1 |= 0x8000 | par->pixconf; 41062306a36Sopenharmony_ci reg2 |= par->bltcntl; 41162306a36Sopenharmony_ci i810_writel(PIXCONF, mmio, reg1); 41262306a36Sopenharmony_ci i810_writew(BLTCNTL, mmio, reg2); 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/** 41662306a36Sopenharmony_ci * i810_load_regs - loads all registers for the mode 41762306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 41862306a36Sopenharmony_ci * 41962306a36Sopenharmony_ci * DESCRIPTION: 42062306a36Sopenharmony_ci * Loads registers 42162306a36Sopenharmony_ci */ 42262306a36Sopenharmony_cistatic void i810_load_regs(struct i810fb_par *par) 42362306a36Sopenharmony_ci{ 42462306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci i810_screen_off(mmio, OFF); 42762306a36Sopenharmony_ci i810_protect_regs(mmio, OFF); 42862306a36Sopenharmony_ci i810_dram_off(mmio, OFF); 42962306a36Sopenharmony_ci i810_load_pll(par); 43062306a36Sopenharmony_ci i810_load_vga(par); 43162306a36Sopenharmony_ci i810_load_vgax(par); 43262306a36Sopenharmony_ci i810_dram_off(mmio, ON); 43362306a36Sopenharmony_ci i810_load_2d(par); 43462306a36Sopenharmony_ci i810_hires(mmio); 43562306a36Sopenharmony_ci i810_screen_off(mmio, ON); 43662306a36Sopenharmony_ci i810_protect_regs(mmio, ON); 43762306a36Sopenharmony_ci i810_load_color(par); 43862306a36Sopenharmony_ci i810_load_pitch(par); 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic void i810_write_dac(u8 regno, u8 red, u8 green, u8 blue, 44262306a36Sopenharmony_ci u8 __iomem *mmio) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci i810_writeb(CLUT_INDEX_WRITE, mmio, regno); 44562306a36Sopenharmony_ci i810_writeb(CLUT_DATA, mmio, red); 44662306a36Sopenharmony_ci i810_writeb(CLUT_DATA, mmio, green); 44762306a36Sopenharmony_ci i810_writeb(CLUT_DATA, mmio, blue); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic void i810_read_dac(u8 regno, u8 *red, u8 *green, u8 *blue, 45162306a36Sopenharmony_ci u8 __iomem *mmio) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci i810_writeb(CLUT_INDEX_READ, mmio, regno); 45462306a36Sopenharmony_ci *red = i810_readb(CLUT_DATA, mmio); 45562306a36Sopenharmony_ci *green = i810_readb(CLUT_DATA, mmio); 45662306a36Sopenharmony_ci *blue = i810_readb(CLUT_DATA, mmio); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci/************************************************************ 46062306a36Sopenharmony_ci * VGA State Restore * 46162306a36Sopenharmony_ci ************************************************************/ 46262306a36Sopenharmony_cistatic void i810_restore_pll(struct i810fb_par *par) 46362306a36Sopenharmony_ci{ 46462306a36Sopenharmony_ci u32 tmp1, tmp2; 46562306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci tmp1 = par->hw_state.dclk_2d; 46862306a36Sopenharmony_ci tmp2 = i810_readl(DCLK_2D, mmio); 46962306a36Sopenharmony_ci tmp1 &= ~MN_MASK; 47062306a36Sopenharmony_ci tmp2 &= MN_MASK; 47162306a36Sopenharmony_ci i810_writel(DCLK_2D, mmio, tmp1 | tmp2); 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci tmp1 = par->hw_state.dclk_1d; 47462306a36Sopenharmony_ci tmp2 = i810_readl(DCLK_1D, mmio); 47562306a36Sopenharmony_ci tmp1 &= ~MN_MASK; 47662306a36Sopenharmony_ci tmp2 &= MN_MASK; 47762306a36Sopenharmony_ci i810_writel(DCLK_1D, mmio, tmp1 | tmp2); 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci i810_writel(DCLK_0DS, mmio, par->hw_state.dclk_0ds); 48062306a36Sopenharmony_ci} 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_cistatic void i810_restore_dac(struct i810fb_par *par) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci u32 tmp1, tmp2; 48562306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci tmp1 = par->hw_state.pixconf; 48862306a36Sopenharmony_ci tmp2 = i810_readl(PIXCONF, mmio); 48962306a36Sopenharmony_ci tmp1 &= DAC_BIT; 49062306a36Sopenharmony_ci tmp2 &= ~DAC_BIT; 49162306a36Sopenharmony_ci i810_writel(PIXCONF, mmio, tmp1 | tmp2); 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_cistatic void i810_restore_vgax(struct i810fb_par *par) 49562306a36Sopenharmony_ci{ 49662306a36Sopenharmony_ci u8 i, j; 49762306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 50062306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR30+i); 50162306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, *(&(par->hw_state.cr30) + i)); 50262306a36Sopenharmony_ci } 50362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR35); 50462306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr35); 50562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR39); 50662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39); 50762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR41); 50862306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr39); 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci /*restore interlace*/ 51162306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR70); 51262306a36Sopenharmony_ci i = par->hw_state.cr70; 51362306a36Sopenharmony_ci i &= INTERLACE_BIT; 51462306a36Sopenharmony_ci j = i810_readb(CR_DATA_CGA, mmio); 51562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR70); 51662306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, j | i); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR80); 51962306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, par->hw_state.cr80); 52062306a36Sopenharmony_ci i810_writeb(MSR_WRITE, mmio, par->hw_state.msr); 52162306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 52262306a36Sopenharmony_ci i = (par->hw_state.sr01) & ~0xE0 ; 52362306a36Sopenharmony_ci j = i810_readb(SR_DATA, mmio) & 0xE0; 52462306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 52562306a36Sopenharmony_ci i810_writeb(SR_DATA, mmio, i | j); 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic void i810_restore_vga(struct i810fb_par *par) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci u8 i; 53162306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 53462306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); 53562306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr00) + i)); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 53862306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR10 + i); 53962306a36Sopenharmony_ci i810_writeb(CR_DATA_CGA, mmio, *((&par->hw_state.cr10) + i)); 54062306a36Sopenharmony_ci } 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ci 54362306a36Sopenharmony_cistatic void i810_restore_addr_map(struct i810fb_par *par) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci u8 tmp; 54662306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci i810_writeb(GR_INDEX, mmio, GR10); 54962306a36Sopenharmony_ci tmp = i810_readb(GR_DATA, mmio); 55062306a36Sopenharmony_ci tmp &= ADDR_MAP_MASK; 55162306a36Sopenharmony_ci tmp |= par->hw_state.gr10; 55262306a36Sopenharmony_ci i810_writeb(GR_INDEX, mmio, GR10); 55362306a36Sopenharmony_ci i810_writeb(GR_DATA, mmio, tmp); 55462306a36Sopenharmony_ci} 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_cistatic void i810_restore_2d(struct i810fb_par *par) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci u32 tmp_long; 55962306a36Sopenharmony_ci u16 tmp_word; 56062306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci tmp_word = i810_readw(BLTCNTL, mmio); 56362306a36Sopenharmony_ci tmp_word &= ~(3 << 4); 56462306a36Sopenharmony_ci tmp_word |= par->hw_state.bltcntl; 56562306a36Sopenharmony_ci i810_writew(BLTCNTL, mmio, tmp_word); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci i810_dram_off(mmio, OFF); 56862306a36Sopenharmony_ci i810_writel(PIXCONF, mmio, par->hw_state.pixconf); 56962306a36Sopenharmony_ci i810_dram_off(mmio, ON); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci tmp_word = i810_readw(HWSTAM, mmio); 57262306a36Sopenharmony_ci tmp_word &= 3 << 13; 57362306a36Sopenharmony_ci tmp_word |= par->hw_state.hwstam; 57462306a36Sopenharmony_ci i810_writew(HWSTAM, mmio, tmp_word); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci tmp_long = i810_readl(FW_BLC, mmio); 57762306a36Sopenharmony_ci tmp_long &= FW_BLC_MASK; 57862306a36Sopenharmony_ci tmp_long |= par->hw_state.fw_blc; 57962306a36Sopenharmony_ci i810_writel(FW_BLC, mmio, tmp_long); 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci i810_writel(HWS_PGA, mmio, par->hw_state.hws_pga); 58262306a36Sopenharmony_ci i810_writew(IER, mmio, par->hw_state.ier); 58362306a36Sopenharmony_ci i810_writew(IMR, mmio, par->hw_state.imr); 58462306a36Sopenharmony_ci i810_writel(DPLYSTAS, mmio, par->hw_state.dplystas); 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_cistatic void i810_restore_vga_state(struct i810fb_par *par) 58862306a36Sopenharmony_ci{ 58962306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci i810_screen_off(mmio, OFF); 59262306a36Sopenharmony_ci i810_protect_regs(mmio, OFF); 59362306a36Sopenharmony_ci i810_dram_off(mmio, OFF); 59462306a36Sopenharmony_ci i810_restore_pll(par); 59562306a36Sopenharmony_ci i810_restore_dac(par); 59662306a36Sopenharmony_ci i810_restore_vga(par); 59762306a36Sopenharmony_ci i810_restore_vgax(par); 59862306a36Sopenharmony_ci i810_restore_addr_map(par); 59962306a36Sopenharmony_ci i810_dram_off(mmio, ON); 60062306a36Sopenharmony_ci i810_restore_2d(par); 60162306a36Sopenharmony_ci i810_screen_off(mmio, ON); 60262306a36Sopenharmony_ci i810_protect_regs(mmio, ON); 60362306a36Sopenharmony_ci} 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci/*********************************************************************** 60662306a36Sopenharmony_ci * VGA State Save * 60762306a36Sopenharmony_ci ***********************************************************************/ 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_cistatic void i810_save_vgax(struct i810fb_par *par) 61062306a36Sopenharmony_ci{ 61162306a36Sopenharmony_ci u8 i; 61262306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 61562306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR30 + i); 61662306a36Sopenharmony_ci *(&(par->hw_state.cr30) + i) = i810_readb(CR_DATA_CGA, mmio); 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR35); 61962306a36Sopenharmony_ci par->hw_state.cr35 = i810_readb(CR_DATA_CGA, mmio); 62062306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR39); 62162306a36Sopenharmony_ci par->hw_state.cr39 = i810_readb(CR_DATA_CGA, mmio); 62262306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR41); 62362306a36Sopenharmony_ci par->hw_state.cr41 = i810_readb(CR_DATA_CGA, mmio); 62462306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR70); 62562306a36Sopenharmony_ci par->hw_state.cr70 = i810_readb(CR_DATA_CGA, mmio); 62662306a36Sopenharmony_ci par->hw_state.msr = i810_readb(MSR_READ, mmio); 62762306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR80); 62862306a36Sopenharmony_ci par->hw_state.cr80 = i810_readb(CR_DATA_CGA, mmio); 62962306a36Sopenharmony_ci i810_writeb(SR_INDEX, mmio, SR01); 63062306a36Sopenharmony_ci par->hw_state.sr01 = i810_readb(SR_DATA, mmio); 63162306a36Sopenharmony_ci} 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_cistatic void i810_save_vga(struct i810fb_par *par) 63462306a36Sopenharmony_ci{ 63562306a36Sopenharmony_ci u8 i; 63662306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 63962306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR00 + i); 64062306a36Sopenharmony_ci *((&par->hw_state.cr00) + i) = i810_readb(CR_DATA_CGA, mmio); 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 64362306a36Sopenharmony_ci i810_writeb(CR_INDEX_CGA, mmio, CR10 + i); 64462306a36Sopenharmony_ci *((&par->hw_state.cr10) + i) = i810_readb(CR_DATA_CGA, mmio); 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_cistatic void i810_save_2d(struct i810fb_par *par) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci par->hw_state.dclk_2d = i810_readl(DCLK_2D, mmio); 65362306a36Sopenharmony_ci par->hw_state.dclk_1d = i810_readl(DCLK_1D, mmio); 65462306a36Sopenharmony_ci par->hw_state.dclk_0ds = i810_readl(DCLK_0DS, mmio); 65562306a36Sopenharmony_ci par->hw_state.pixconf = i810_readl(PIXCONF, mmio); 65662306a36Sopenharmony_ci par->hw_state.fw_blc = i810_readl(FW_BLC, mmio); 65762306a36Sopenharmony_ci par->hw_state.bltcntl = i810_readw(BLTCNTL, mmio); 65862306a36Sopenharmony_ci par->hw_state.hwstam = i810_readw(HWSTAM, mmio); 65962306a36Sopenharmony_ci par->hw_state.hws_pga = i810_readl(HWS_PGA, mmio); 66062306a36Sopenharmony_ci par->hw_state.ier = i810_readw(IER, mmio); 66162306a36Sopenharmony_ci par->hw_state.imr = i810_readw(IMR, mmio); 66262306a36Sopenharmony_ci par->hw_state.dplystas = i810_readl(DPLYSTAS, mmio); 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_cistatic void i810_save_vga_state(struct i810fb_par *par) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci i810_save_vga(par); 66862306a36Sopenharmony_ci i810_save_vgax(par); 66962306a36Sopenharmony_ci i810_save_2d(par); 67062306a36Sopenharmony_ci} 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci/************************************************************ 67362306a36Sopenharmony_ci * Helpers * 67462306a36Sopenharmony_ci ************************************************************/ 67562306a36Sopenharmony_ci/** 67662306a36Sopenharmony_ci * get_line_length - calculates buffer pitch in bytes 67762306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 67862306a36Sopenharmony_ci * @xres_virtual: virtual resolution of the frame 67962306a36Sopenharmony_ci * @bpp: bits per pixel 68062306a36Sopenharmony_ci * 68162306a36Sopenharmony_ci * DESCRIPTION: 68262306a36Sopenharmony_ci * Calculates buffer pitch in bytes. 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_cistatic u32 get_line_length(struct i810fb_par *par, int xres_virtual, int bpp) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci u32 length; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci length = xres_virtual*bpp; 68962306a36Sopenharmony_ci length = (length+31)&-32; 69062306a36Sopenharmony_ci length >>= 3; 69162306a36Sopenharmony_ci return length; 69262306a36Sopenharmony_ci} 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci/** 69562306a36Sopenharmony_ci * i810_calc_dclk - calculates the P, M, and N values of a pixelclock value 69662306a36Sopenharmony_ci * @freq: target pixelclock in picoseconds 69762306a36Sopenharmony_ci * @m: where to write M register 69862306a36Sopenharmony_ci * @n: where to write N register 69962306a36Sopenharmony_ci * @p: where to write P register 70062306a36Sopenharmony_ci * 70162306a36Sopenharmony_ci * DESCRIPTION: 70262306a36Sopenharmony_ci * Based on the formula Freq_actual = (4*M*Freq_ref)/(N^P) 70362306a36Sopenharmony_ci * Repeatedly computes the Freq until the actual Freq is equal to 70462306a36Sopenharmony_ci * the target Freq or until the loop count is zero. In the latter 70562306a36Sopenharmony_ci * case, the actual frequency nearest the target will be used. 70662306a36Sopenharmony_ci */ 70762306a36Sopenharmony_cistatic void i810_calc_dclk(u32 freq, u32 *m, u32 *n, u32 *p) 70862306a36Sopenharmony_ci{ 70962306a36Sopenharmony_ci u32 m_reg, n_reg, p_divisor, n_target_max; 71062306a36Sopenharmony_ci u32 m_target, n_target, p_target, n_best, m_best, mod; 71162306a36Sopenharmony_ci u32 f_out, target_freq, diff = 0, mod_min, diff_min; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci diff_min = mod_min = 0xFFFFFFFF; 71462306a36Sopenharmony_ci n_best = m_best = m_target = f_out = 0; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci target_freq = freq; 71762306a36Sopenharmony_ci n_target_max = 30; 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ci /* 72062306a36Sopenharmony_ci * find P such that target freq is 16x reference freq (Hz). 72162306a36Sopenharmony_ci */ 72262306a36Sopenharmony_ci p_divisor = 1; 72362306a36Sopenharmony_ci p_target = 0; 72462306a36Sopenharmony_ci while(!((1000000 * p_divisor)/(16 * 24 * target_freq)) && 72562306a36Sopenharmony_ci p_divisor <= 32) { 72662306a36Sopenharmony_ci p_divisor <<= 1; 72762306a36Sopenharmony_ci p_target++; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci n_reg = m_reg = n_target = 3; 73162306a36Sopenharmony_ci while (diff_min && mod_min && (n_target < n_target_max)) { 73262306a36Sopenharmony_ci f_out = (p_divisor * n_reg * 1000000)/(4 * 24 * m_reg); 73362306a36Sopenharmony_ci mod = (p_divisor * n_reg * 1000000) % (4 * 24 * m_reg); 73462306a36Sopenharmony_ci m_target = m_reg; 73562306a36Sopenharmony_ci n_target = n_reg; 73662306a36Sopenharmony_ci if (f_out <= target_freq) { 73762306a36Sopenharmony_ci n_reg++; 73862306a36Sopenharmony_ci diff = target_freq - f_out; 73962306a36Sopenharmony_ci } else { 74062306a36Sopenharmony_ci m_reg++; 74162306a36Sopenharmony_ci diff = f_out - target_freq; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci if (diff_min > diff) { 74562306a36Sopenharmony_ci diff_min = diff; 74662306a36Sopenharmony_ci n_best = n_target; 74762306a36Sopenharmony_ci m_best = m_target; 74862306a36Sopenharmony_ci } 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci if (!diff && mod_min > mod) { 75162306a36Sopenharmony_ci mod_min = mod; 75262306a36Sopenharmony_ci n_best = n_target; 75362306a36Sopenharmony_ci m_best = m_target; 75462306a36Sopenharmony_ci } 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci if (m) *m = (m_best - 2) & 0x3FF; 75762306a36Sopenharmony_ci if (n) *n = (n_best - 2) & 0x3FF; 75862306a36Sopenharmony_ci if (p) *p = (p_target << 4); 75962306a36Sopenharmony_ci} 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci/************************************************************* 76262306a36Sopenharmony_ci * Hardware Cursor Routines * 76362306a36Sopenharmony_ci *************************************************************/ 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci/** 76662306a36Sopenharmony_ci * i810_enable_cursor - show or hide the hardware cursor 76762306a36Sopenharmony_ci * @mmio: address of register space 76862306a36Sopenharmony_ci * @mode: show (1) or hide (0) 76962306a36Sopenharmony_ci * 77062306a36Sopenharmony_ci * Description: 77162306a36Sopenharmony_ci * Shows or hides the hardware cursor 77262306a36Sopenharmony_ci */ 77362306a36Sopenharmony_cistatic void i810_enable_cursor(u8 __iomem *mmio, int mode) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci u32 temp; 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci temp = i810_readl(PIXCONF, mmio); 77862306a36Sopenharmony_ci temp = (mode == ON) ? temp | CURSOR_ENABLE_MASK : 77962306a36Sopenharmony_ci temp & ~CURSOR_ENABLE_MASK; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci i810_writel(PIXCONF, mmio, temp); 78262306a36Sopenharmony_ci} 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_cistatic void i810_reset_cursor_image(struct i810fb_par *par) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci u8 __iomem *addr = par->cursor_heap.virtual; 78762306a36Sopenharmony_ci int i, j; 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ci for (i = 64; i--; ) { 79062306a36Sopenharmony_ci for (j = 0; j < 8; j++) { 79162306a36Sopenharmony_ci i810_writeb(j, addr, 0xff); 79262306a36Sopenharmony_ci i810_writeb(j+8, addr, 0x00); 79362306a36Sopenharmony_ci } 79462306a36Sopenharmony_ci addr +=16; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci} 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_cistatic void i810_load_cursor_image(int width, int height, u8 *data, 79962306a36Sopenharmony_ci struct i810fb_par *par) 80062306a36Sopenharmony_ci{ 80162306a36Sopenharmony_ci u8 __iomem *addr = par->cursor_heap.virtual; 80262306a36Sopenharmony_ci int i, j, w = width/8; 80362306a36Sopenharmony_ci int mod = width % 8, t_mask, d_mask; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci t_mask = 0xff >> mod; 80662306a36Sopenharmony_ci d_mask = ~(0xff >> mod); 80762306a36Sopenharmony_ci for (i = height; i--; ) { 80862306a36Sopenharmony_ci for (j = 0; j < w; j++) { 80962306a36Sopenharmony_ci i810_writeb(j+0, addr, 0x00); 81062306a36Sopenharmony_ci i810_writeb(j+8, addr, *data++); 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci if (mod) { 81362306a36Sopenharmony_ci i810_writeb(j+0, addr, t_mask); 81462306a36Sopenharmony_ci i810_writeb(j+8, addr, *data++ & d_mask); 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci addr += 16; 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci} 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_cistatic void i810_load_cursor_colors(int fg, int bg, struct fb_info *info) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci struct i810fb_par *par = info->par; 82362306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 82462306a36Sopenharmony_ci u8 red, green, blue, trans, temp; 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci i810fb_getcolreg(bg, &red, &green, &blue, &trans, info); 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci temp = i810_readb(PIXCONF1, mmio); 82962306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci i810_write_dac(4, red, green, blue, mmio); 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci i810fb_getcolreg(fg, &red, &green, &blue, &trans, info); 83662306a36Sopenharmony_ci temp = i810_readb(PIXCONF1, mmio); 83762306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp | EXTENDED_PALETTE); 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci i810_write_dac(5, red, green, blue, mmio); 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp); 84262306a36Sopenharmony_ci} 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci/** 84562306a36Sopenharmony_ci * i810_init_cursor - initializes the cursor 84662306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 84762306a36Sopenharmony_ci * 84862306a36Sopenharmony_ci * DESCRIPTION: 84962306a36Sopenharmony_ci * Initializes the cursor registers 85062306a36Sopenharmony_ci */ 85162306a36Sopenharmony_cistatic void i810_init_cursor(struct i810fb_par *par) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci i810_enable_cursor(mmio, OFF); 85662306a36Sopenharmony_ci i810_writel(CURBASE, mmio, par->cursor_heap.physical); 85762306a36Sopenharmony_ci i810_writew(CURCNTR, mmio, COORD_ACTIVE | CURSOR_MODE_64_XOR); 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci/********************************************************************* 86162306a36Sopenharmony_ci * Framebuffer hook helpers * 86262306a36Sopenharmony_ci *********************************************************************/ 86362306a36Sopenharmony_ci/** 86462306a36Sopenharmony_ci * i810_round_off - Round off values to capability of hardware 86562306a36Sopenharmony_ci * @var: pointer to fb_var_screeninfo structure 86662306a36Sopenharmony_ci * 86762306a36Sopenharmony_ci * DESCRIPTION: 86862306a36Sopenharmony_ci * @var contains user-defined information for the mode to be set. 86962306a36Sopenharmony_ci * This will try modify those values to ones nearest the 87062306a36Sopenharmony_ci * capability of the hardware 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_cistatic void i810_round_off(struct fb_var_screeninfo *var) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci u32 xres, yres, vxres, vyres; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci /* 87762306a36Sopenharmony_ci * Presently supports only these configurations 87862306a36Sopenharmony_ci */ 87962306a36Sopenharmony_ci 88062306a36Sopenharmony_ci xres = var->xres; 88162306a36Sopenharmony_ci yres = var->yres; 88262306a36Sopenharmony_ci vxres = var->xres_virtual; 88362306a36Sopenharmony_ci vyres = var->yres_virtual; 88462306a36Sopenharmony_ci 88562306a36Sopenharmony_ci var->bits_per_pixel += 7; 88662306a36Sopenharmony_ci var->bits_per_pixel &= ~7; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci if (var->bits_per_pixel < 8) 88962306a36Sopenharmony_ci var->bits_per_pixel = 8; 89062306a36Sopenharmony_ci if (var->bits_per_pixel > 32) 89162306a36Sopenharmony_ci var->bits_per_pixel = 32; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci round_off_xres(&xres); 89462306a36Sopenharmony_ci if (xres < 40) 89562306a36Sopenharmony_ci xres = 40; 89662306a36Sopenharmony_ci if (xres > 2048) 89762306a36Sopenharmony_ci xres = 2048; 89862306a36Sopenharmony_ci xres = (xres + 7) & ~7; 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci if (vxres < xres) 90162306a36Sopenharmony_ci vxres = xres; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci round_off_yres(&xres, &yres); 90462306a36Sopenharmony_ci if (yres < 1) 90562306a36Sopenharmony_ci yres = 1; 90662306a36Sopenharmony_ci if (yres >= 2048) 90762306a36Sopenharmony_ci yres = 2048; 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci if (vyres < yres) 91062306a36Sopenharmony_ci vyres = yres; 91162306a36Sopenharmony_ci 91262306a36Sopenharmony_ci if (var->bits_per_pixel == 32) 91362306a36Sopenharmony_ci var->accel_flags = 0; 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_ci /* round of horizontal timings to nearest 8 pixels */ 91662306a36Sopenharmony_ci var->left_margin = (var->left_margin + 4) & ~7; 91762306a36Sopenharmony_ci var->right_margin = (var->right_margin + 4) & ~7; 91862306a36Sopenharmony_ci var->hsync_len = (var->hsync_len + 4) & ~7; 91962306a36Sopenharmony_ci 92062306a36Sopenharmony_ci if (var->vmode & FB_VMODE_INTERLACED) { 92162306a36Sopenharmony_ci if (!((yres + var->upper_margin + var->vsync_len + 92262306a36Sopenharmony_ci var->lower_margin) & 1)) 92362306a36Sopenharmony_ci var->upper_margin++; 92462306a36Sopenharmony_ci } 92562306a36Sopenharmony_ci 92662306a36Sopenharmony_ci var->xres = xres; 92762306a36Sopenharmony_ci var->yres = yres; 92862306a36Sopenharmony_ci var->xres_virtual = vxres; 92962306a36Sopenharmony_ci var->yres_virtual = vyres; 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_ci/** 93362306a36Sopenharmony_ci * set_color_bitfields - sets rgba fields 93462306a36Sopenharmony_ci * @var: pointer to fb_var_screeninfo 93562306a36Sopenharmony_ci * 93662306a36Sopenharmony_ci * DESCRIPTION: 93762306a36Sopenharmony_ci * The length, offset and ordering for each color field 93862306a36Sopenharmony_ci * (red, green, blue) will be set as specified 93962306a36Sopenharmony_ci * by the hardware 94062306a36Sopenharmony_ci */ 94162306a36Sopenharmony_cistatic void set_color_bitfields(struct fb_var_screeninfo *var) 94262306a36Sopenharmony_ci{ 94362306a36Sopenharmony_ci switch (var->bits_per_pixel) { 94462306a36Sopenharmony_ci case 8: 94562306a36Sopenharmony_ci var->red.offset = 0; 94662306a36Sopenharmony_ci var->red.length = 8; 94762306a36Sopenharmony_ci var->green.offset = 0; 94862306a36Sopenharmony_ci var->green.length = 8; 94962306a36Sopenharmony_ci var->blue.offset = 0; 95062306a36Sopenharmony_ci var->blue.length = 8; 95162306a36Sopenharmony_ci var->transp.offset = 0; 95262306a36Sopenharmony_ci var->transp.length = 0; 95362306a36Sopenharmony_ci break; 95462306a36Sopenharmony_ci case 16: 95562306a36Sopenharmony_ci var->green.length = (var->green.length == 5) ? 5 : 6; 95662306a36Sopenharmony_ci var->red.length = 5; 95762306a36Sopenharmony_ci var->blue.length = 5; 95862306a36Sopenharmony_ci var->transp.length = 6 - var->green.length; 95962306a36Sopenharmony_ci var->blue.offset = 0; 96062306a36Sopenharmony_ci var->green.offset = 5; 96162306a36Sopenharmony_ci var->red.offset = 5 + var->green.length; 96262306a36Sopenharmony_ci var->transp.offset = (5 + var->red.offset) & 15; 96362306a36Sopenharmony_ci break; 96462306a36Sopenharmony_ci case 24: /* RGB 888 */ 96562306a36Sopenharmony_ci case 32: /* RGBA 8888 */ 96662306a36Sopenharmony_ci var->red.offset = 16; 96762306a36Sopenharmony_ci var->red.length = 8; 96862306a36Sopenharmony_ci var->green.offset = 8; 96962306a36Sopenharmony_ci var->green.length = 8; 97062306a36Sopenharmony_ci var->blue.offset = 0; 97162306a36Sopenharmony_ci var->blue.length = 8; 97262306a36Sopenharmony_ci var->transp.length = var->bits_per_pixel - 24; 97362306a36Sopenharmony_ci var->transp.offset = (var->transp.length) ? 24 : 0; 97462306a36Sopenharmony_ci break; 97562306a36Sopenharmony_ci } 97662306a36Sopenharmony_ci var->red.msb_right = 0; 97762306a36Sopenharmony_ci var->green.msb_right = 0; 97862306a36Sopenharmony_ci var->blue.msb_right = 0; 97962306a36Sopenharmony_ci var->transp.msb_right = 0; 98062306a36Sopenharmony_ci} 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci/** 98362306a36Sopenharmony_ci * i810_check_params - check if contents in var are valid 98462306a36Sopenharmony_ci * @var: pointer to fb_var_screeninfo 98562306a36Sopenharmony_ci * @info: pointer to fb_info 98662306a36Sopenharmony_ci * 98762306a36Sopenharmony_ci * DESCRIPTION: 98862306a36Sopenharmony_ci * This will check if the framebuffer size is sufficient 98962306a36Sopenharmony_ci * for the current mode and if the user's monitor has the 99062306a36Sopenharmony_ci * required specifications to display the current mode. 99162306a36Sopenharmony_ci */ 99262306a36Sopenharmony_cistatic int i810_check_params(struct fb_var_screeninfo *var, 99362306a36Sopenharmony_ci struct fb_info *info) 99462306a36Sopenharmony_ci{ 99562306a36Sopenharmony_ci struct i810fb_par *par = info->par; 99662306a36Sopenharmony_ci int line_length, vidmem, mode_valid = 0, retval = 0; 99762306a36Sopenharmony_ci u32 vyres = var->yres_virtual, vxres = var->xres_virtual; 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci /* 100062306a36Sopenharmony_ci * Memory limit 100162306a36Sopenharmony_ci */ 100262306a36Sopenharmony_ci line_length = get_line_length(par, vxres, var->bits_per_pixel); 100362306a36Sopenharmony_ci vidmem = line_length*vyres; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci if (vidmem > par->fb.size) { 100662306a36Sopenharmony_ci vyres = par->fb.size/line_length; 100762306a36Sopenharmony_ci if (vyres < var->yres) { 100862306a36Sopenharmony_ci vyres = info->var.yres; 100962306a36Sopenharmony_ci vxres = par->fb.size/vyres; 101062306a36Sopenharmony_ci vxres /= var->bits_per_pixel >> 3; 101162306a36Sopenharmony_ci line_length = get_line_length(par, vxres, 101262306a36Sopenharmony_ci var->bits_per_pixel); 101362306a36Sopenharmony_ci vidmem = line_length * info->var.yres; 101462306a36Sopenharmony_ci if (vxres < var->xres) { 101562306a36Sopenharmony_ci printk("i810fb: required video memory, " 101662306a36Sopenharmony_ci "%d bytes, for %dx%d-%d (virtual) " 101762306a36Sopenharmony_ci "is out of range\n", 101862306a36Sopenharmony_ci vidmem, vxres, vyres, 101962306a36Sopenharmony_ci var->bits_per_pixel); 102062306a36Sopenharmony_ci return -ENOMEM; 102162306a36Sopenharmony_ci } 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci } 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci var->xres_virtual = vxres; 102662306a36Sopenharmony_ci var->yres_virtual = vyres; 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci /* 102962306a36Sopenharmony_ci * Monitor limit 103062306a36Sopenharmony_ci */ 103162306a36Sopenharmony_ci switch (var->bits_per_pixel) { 103262306a36Sopenharmony_ci case 8: 103362306a36Sopenharmony_ci info->monspecs.dclkmax = 234000000; 103462306a36Sopenharmony_ci break; 103562306a36Sopenharmony_ci case 16: 103662306a36Sopenharmony_ci info->monspecs.dclkmax = 229000000; 103762306a36Sopenharmony_ci break; 103862306a36Sopenharmony_ci case 24: 103962306a36Sopenharmony_ci case 32: 104062306a36Sopenharmony_ci info->monspecs.dclkmax = 204000000; 104162306a36Sopenharmony_ci break; 104262306a36Sopenharmony_ci } 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci info->monspecs.dclkmin = 15000000; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci if (!fb_validate_mode(var, info)) 104762306a36Sopenharmony_ci mode_valid = 1; 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci#ifdef CONFIG_FB_I810_I2C 105062306a36Sopenharmony_ci if (!mode_valid && info->monspecs.gtf && 105162306a36Sopenharmony_ci !fb_get_mode(FB_MAXTIMINGS, 0, var, info)) 105262306a36Sopenharmony_ci mode_valid = 1; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci if (!mode_valid && info->monspecs.modedb_len) { 105562306a36Sopenharmony_ci const struct fb_videomode *mode; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci mode = fb_find_best_mode(var, &info->modelist); 105862306a36Sopenharmony_ci if (mode) { 105962306a36Sopenharmony_ci fb_videomode_to_var(var, mode); 106062306a36Sopenharmony_ci mode_valid = 1; 106162306a36Sopenharmony_ci } 106262306a36Sopenharmony_ci } 106362306a36Sopenharmony_ci#endif 106462306a36Sopenharmony_ci if (!mode_valid && info->monspecs.modedb_len == 0) { 106562306a36Sopenharmony_ci if (fb_get_mode(FB_MAXTIMINGS, 0, var, info)) { 106662306a36Sopenharmony_ci int default_sync = (info->monspecs.hfmin-HFMIN) 106762306a36Sopenharmony_ci |(info->monspecs.hfmax-HFMAX) 106862306a36Sopenharmony_ci |(info->monspecs.vfmin-VFMIN) 106962306a36Sopenharmony_ci |(info->monspecs.vfmax-VFMAX); 107062306a36Sopenharmony_ci printk("i810fb: invalid video mode%s\n", 107162306a36Sopenharmony_ci default_sync ? "" : ". Specifying " 107262306a36Sopenharmony_ci "vsyncN/hsyncN parameters may help"); 107362306a36Sopenharmony_ci retval = -EINVAL; 107462306a36Sopenharmony_ci } 107562306a36Sopenharmony_ci } 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci return retval; 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci/** 108162306a36Sopenharmony_ci * encode_fix - fill up fb_fix_screeninfo structure 108262306a36Sopenharmony_ci * @fix: pointer to fb_fix_screeninfo 108362306a36Sopenharmony_ci * @info: pointer to fb_info 108462306a36Sopenharmony_ci * 108562306a36Sopenharmony_ci * DESCRIPTION: 108662306a36Sopenharmony_ci * This will set up parameters that are unmodifiable by the user. 108762306a36Sopenharmony_ci */ 108862306a36Sopenharmony_cistatic int encode_fix(struct fb_fix_screeninfo *fix, struct fb_info *info) 108962306a36Sopenharmony_ci{ 109062306a36Sopenharmony_ci struct i810fb_par *par = info->par; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci memset(fix, 0, sizeof(struct fb_fix_screeninfo)); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci strcpy(fix->id, "I810"); 109562306a36Sopenharmony_ci mutex_lock(&info->mm_lock); 109662306a36Sopenharmony_ci fix->smem_start = par->fb.physical; 109762306a36Sopenharmony_ci fix->smem_len = par->fb.size; 109862306a36Sopenharmony_ci mutex_unlock(&info->mm_lock); 109962306a36Sopenharmony_ci fix->type = FB_TYPE_PACKED_PIXELS; 110062306a36Sopenharmony_ci fix->type_aux = 0; 110162306a36Sopenharmony_ci fix->xpanstep = 8; 110262306a36Sopenharmony_ci fix->ypanstep = 1; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci switch (info->var.bits_per_pixel) { 110562306a36Sopenharmony_ci case 8: 110662306a36Sopenharmony_ci fix->visual = FB_VISUAL_PSEUDOCOLOR; 110762306a36Sopenharmony_ci break; 110862306a36Sopenharmony_ci case 16: 110962306a36Sopenharmony_ci case 24: 111062306a36Sopenharmony_ci case 32: 111162306a36Sopenharmony_ci if (info->var.nonstd) 111262306a36Sopenharmony_ci fix->visual = FB_VISUAL_DIRECTCOLOR; 111362306a36Sopenharmony_ci else 111462306a36Sopenharmony_ci fix->visual = FB_VISUAL_TRUECOLOR; 111562306a36Sopenharmony_ci break; 111662306a36Sopenharmony_ci default: 111762306a36Sopenharmony_ci return -EINVAL; 111862306a36Sopenharmony_ci } 111962306a36Sopenharmony_ci fix->ywrapstep = 0; 112062306a36Sopenharmony_ci fix->line_length = par->pitch; 112162306a36Sopenharmony_ci fix->mmio_start = par->mmio_start_phys; 112262306a36Sopenharmony_ci fix->mmio_len = MMIO_SIZE; 112362306a36Sopenharmony_ci fix->accel = FB_ACCEL_I810; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci return 0; 112662306a36Sopenharmony_ci} 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci/** 112962306a36Sopenharmony_ci * decode_var - modify par according to contents of var 113062306a36Sopenharmony_ci * @var: pointer to fb_var_screeninfo 113162306a36Sopenharmony_ci * @par: pointer to i810fb_par 113262306a36Sopenharmony_ci * 113362306a36Sopenharmony_ci * DESCRIPTION: 113462306a36Sopenharmony_ci * Based on the contents of @var, @par will be dynamically filled up. 113562306a36Sopenharmony_ci * @par contains all information necessary to modify the hardware. 113662306a36Sopenharmony_ci*/ 113762306a36Sopenharmony_cistatic void decode_var(const struct fb_var_screeninfo *var, 113862306a36Sopenharmony_ci struct i810fb_par *par) 113962306a36Sopenharmony_ci{ 114062306a36Sopenharmony_ci u32 xres, yres, vxres, vyres; 114162306a36Sopenharmony_ci 114262306a36Sopenharmony_ci xres = var->xres; 114362306a36Sopenharmony_ci yres = var->yres; 114462306a36Sopenharmony_ci vxres = var->xres_virtual; 114562306a36Sopenharmony_ci vyres = var->yres_virtual; 114662306a36Sopenharmony_ci 114762306a36Sopenharmony_ci switch (var->bits_per_pixel) { 114862306a36Sopenharmony_ci case 8: 114962306a36Sopenharmony_ci par->pixconf = PIXCONF8; 115062306a36Sopenharmony_ci par->bltcntl = 0; 115162306a36Sopenharmony_ci par->depth = 1; 115262306a36Sopenharmony_ci par->blit_bpp = BPP8; 115362306a36Sopenharmony_ci break; 115462306a36Sopenharmony_ci case 16: 115562306a36Sopenharmony_ci if (var->green.length == 5) 115662306a36Sopenharmony_ci par->pixconf = PIXCONF15; 115762306a36Sopenharmony_ci else 115862306a36Sopenharmony_ci par->pixconf = PIXCONF16; 115962306a36Sopenharmony_ci par->bltcntl = 16; 116062306a36Sopenharmony_ci par->depth = 2; 116162306a36Sopenharmony_ci par->blit_bpp = BPP16; 116262306a36Sopenharmony_ci break; 116362306a36Sopenharmony_ci case 24: 116462306a36Sopenharmony_ci par->pixconf = PIXCONF24; 116562306a36Sopenharmony_ci par->bltcntl = 32; 116662306a36Sopenharmony_ci par->depth = 3; 116762306a36Sopenharmony_ci par->blit_bpp = BPP24; 116862306a36Sopenharmony_ci break; 116962306a36Sopenharmony_ci case 32: 117062306a36Sopenharmony_ci par->pixconf = PIXCONF32; 117162306a36Sopenharmony_ci par->bltcntl = 0; 117262306a36Sopenharmony_ci par->depth = 4; 117362306a36Sopenharmony_ci par->blit_bpp = 3 << 24; 117462306a36Sopenharmony_ci break; 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci if (var->nonstd && var->bits_per_pixel != 8) 117762306a36Sopenharmony_ci par->pixconf |= 1 << 27; 117862306a36Sopenharmony_ci 117962306a36Sopenharmony_ci i810_calc_dclk(var->pixclock, &par->regs.M, 118062306a36Sopenharmony_ci &par->regs.N, &par->regs.P); 118162306a36Sopenharmony_ci i810fb_encode_registers(var, par, xres, yres); 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci par->watermark = i810_get_watermark(var, par); 118462306a36Sopenharmony_ci par->pitch = get_line_length(par, vxres, var->bits_per_pixel); 118562306a36Sopenharmony_ci} 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci/** 118862306a36Sopenharmony_ci * i810fb_getcolreg - gets red, green and blue values of the hardware DAC 118962306a36Sopenharmony_ci * @regno: DAC index 119062306a36Sopenharmony_ci * @red: red 119162306a36Sopenharmony_ci * @green: green 119262306a36Sopenharmony_ci * @blue: blue 119362306a36Sopenharmony_ci * @transp: transparency (alpha) 119462306a36Sopenharmony_ci * @info: pointer to fb_info 119562306a36Sopenharmony_ci * 119662306a36Sopenharmony_ci * DESCRIPTION: 119762306a36Sopenharmony_ci * Gets the red, green and blue values of the hardware DAC as pointed by @regno 119862306a36Sopenharmony_ci * and writes them to @red, @green and @blue respectively 119962306a36Sopenharmony_ci */ 120062306a36Sopenharmony_cistatic int i810fb_getcolreg(u8 regno, u8 *red, u8 *green, u8 *blue, 120162306a36Sopenharmony_ci u8 *transp, struct fb_info *info) 120262306a36Sopenharmony_ci{ 120362306a36Sopenharmony_ci struct i810fb_par *par = info->par; 120462306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 120562306a36Sopenharmony_ci u8 temp; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 120862306a36Sopenharmony_ci if ((info->var.green.length == 5 && regno > 31) || 120962306a36Sopenharmony_ci (info->var.green.length == 6 && regno > 63)) 121062306a36Sopenharmony_ci return 1; 121162306a36Sopenharmony_ci } 121262306a36Sopenharmony_ci 121362306a36Sopenharmony_ci temp = i810_readb(PIXCONF1, mmio); 121462306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 121762306a36Sopenharmony_ci info->var.green.length == 5) 121862306a36Sopenharmony_ci i810_read_dac(regno * 8, red, green, blue, mmio); 121962306a36Sopenharmony_ci 122062306a36Sopenharmony_ci else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 122162306a36Sopenharmony_ci info->var.green.length == 6) { 122262306a36Sopenharmony_ci u8 tmp; 122362306a36Sopenharmony_ci 122462306a36Sopenharmony_ci i810_read_dac(regno * 8, red, &tmp, blue, mmio); 122562306a36Sopenharmony_ci i810_read_dac(regno * 4, &tmp, green, &tmp, mmio); 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci else 122862306a36Sopenharmony_ci i810_read_dac(regno, red, green, blue, mmio); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci *transp = 0; 123162306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp); 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci return 0; 123462306a36Sopenharmony_ci} 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci/****************************************************************** 123762306a36Sopenharmony_ci * Framebuffer device-specific hooks * 123862306a36Sopenharmony_ci ******************************************************************/ 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic int i810fb_open(struct fb_info *info, int user) 124162306a36Sopenharmony_ci{ 124262306a36Sopenharmony_ci struct i810fb_par *par = info->par; 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci mutex_lock(&par->open_lock); 124562306a36Sopenharmony_ci if (par->use_count == 0) { 124662306a36Sopenharmony_ci memset(&par->state, 0, sizeof(struct vgastate)); 124762306a36Sopenharmony_ci par->state.flags = VGA_SAVE_CMAP; 124862306a36Sopenharmony_ci par->state.vgabase = par->mmio_start_virtual; 124962306a36Sopenharmony_ci save_vga(&par->state); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci i810_save_vga_state(par); 125262306a36Sopenharmony_ci } 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci par->use_count++; 125562306a36Sopenharmony_ci mutex_unlock(&par->open_lock); 125662306a36Sopenharmony_ci 125762306a36Sopenharmony_ci return 0; 125862306a36Sopenharmony_ci} 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_cistatic int i810fb_release(struct fb_info *info, int user) 126162306a36Sopenharmony_ci{ 126262306a36Sopenharmony_ci struct i810fb_par *par = info->par; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci mutex_lock(&par->open_lock); 126562306a36Sopenharmony_ci if (par->use_count == 0) { 126662306a36Sopenharmony_ci mutex_unlock(&par->open_lock); 126762306a36Sopenharmony_ci return -EINVAL; 126862306a36Sopenharmony_ci } 126962306a36Sopenharmony_ci 127062306a36Sopenharmony_ci if (par->use_count == 1) { 127162306a36Sopenharmony_ci i810_restore_vga_state(par); 127262306a36Sopenharmony_ci restore_vga(&par->state); 127362306a36Sopenharmony_ci } 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci par->use_count--; 127662306a36Sopenharmony_ci mutex_unlock(&par->open_lock); 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_ci return 0; 127962306a36Sopenharmony_ci} 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_cistatic int i810fb_setcolreg(unsigned regno, unsigned red, unsigned green, 128362306a36Sopenharmony_ci unsigned blue, unsigned transp, 128462306a36Sopenharmony_ci struct fb_info *info) 128562306a36Sopenharmony_ci{ 128662306a36Sopenharmony_ci struct i810fb_par *par = info->par; 128762306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 128862306a36Sopenharmony_ci u8 temp; 128962306a36Sopenharmony_ci int i; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci if (regno > 255) return 1; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 129462306a36Sopenharmony_ci if ((info->var.green.length == 5 && regno > 31) || 129562306a36Sopenharmony_ci (info->var.green.length == 6 && regno > 63)) 129662306a36Sopenharmony_ci return 1; 129762306a36Sopenharmony_ci } 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (info->var.grayscale) 130062306a36Sopenharmony_ci red = green = blue = (19595 * red + 38470 * green + 130162306a36Sopenharmony_ci 7471 * blue) >> 16; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci temp = i810_readb(PIXCONF1, mmio); 130462306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp & ~EXTENDED_PALETTE); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 130762306a36Sopenharmony_ci info->var.green.length == 5) { 130862306a36Sopenharmony_ci for (i = 0; i < 8; i++) 130962306a36Sopenharmony_ci i810_write_dac((u8) (regno * 8) + i, (u8) red, 131062306a36Sopenharmony_ci (u8) green, (u8) blue, mmio); 131162306a36Sopenharmony_ci } else if (info->fix.visual == FB_VISUAL_DIRECTCOLOR && 131262306a36Sopenharmony_ci info->var.green.length == 6) { 131362306a36Sopenharmony_ci u8 r, g, b; 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci if (regno < 32) { 131662306a36Sopenharmony_ci for (i = 0; i < 8; i++) 131762306a36Sopenharmony_ci i810_write_dac((u8) (regno * 8) + i, 131862306a36Sopenharmony_ci (u8) red, (u8) green, 131962306a36Sopenharmony_ci (u8) blue, mmio); 132062306a36Sopenharmony_ci } 132162306a36Sopenharmony_ci i810_read_dac((u8) (regno*4), &r, &g, &b, mmio); 132262306a36Sopenharmony_ci for (i = 0; i < 4; i++) 132362306a36Sopenharmony_ci i810_write_dac((u8) (regno*4) + i, r, (u8) green, 132462306a36Sopenharmony_ci b, mmio); 132562306a36Sopenharmony_ci } else if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR) { 132662306a36Sopenharmony_ci i810_write_dac((u8) regno, (u8) red, (u8) green, 132762306a36Sopenharmony_ci (u8) blue, mmio); 132862306a36Sopenharmony_ci } 132962306a36Sopenharmony_ci 133062306a36Sopenharmony_ci i810_writeb(PIXCONF1, mmio, temp); 133162306a36Sopenharmony_ci 133262306a36Sopenharmony_ci if (regno < 16) { 133362306a36Sopenharmony_ci switch (info->var.bits_per_pixel) { 133462306a36Sopenharmony_ci case 16: 133562306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) { 133662306a36Sopenharmony_ci if (info->var.green.length == 5) 133762306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 133862306a36Sopenharmony_ci (regno << 10) | (regno << 5) | 133962306a36Sopenharmony_ci regno; 134062306a36Sopenharmony_ci else 134162306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 134262306a36Sopenharmony_ci (regno << 11) | (regno << 5) | 134362306a36Sopenharmony_ci regno; 134462306a36Sopenharmony_ci } else { 134562306a36Sopenharmony_ci if (info->var.green.length == 5) { 134662306a36Sopenharmony_ci /* RGB 555 */ 134762306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 134862306a36Sopenharmony_ci ((red & 0xf800) >> 1) | 134962306a36Sopenharmony_ci ((green & 0xf800) >> 6) | 135062306a36Sopenharmony_ci ((blue & 0xf800) >> 11); 135162306a36Sopenharmony_ci } else { 135262306a36Sopenharmony_ci /* RGB 565 */ 135362306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 135462306a36Sopenharmony_ci (red & 0xf800) | 135562306a36Sopenharmony_ci ((green & 0xf800) >> 5) | 135662306a36Sopenharmony_ci ((blue & 0xf800) >> 11); 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci break; 136062306a36Sopenharmony_ci case 24: /* RGB 888 */ 136162306a36Sopenharmony_ci case 32: /* RGBA 8888 */ 136262306a36Sopenharmony_ci if (info->fix.visual == FB_VISUAL_DIRECTCOLOR) 136362306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 136462306a36Sopenharmony_ci (regno << 16) | (regno << 8) | 136562306a36Sopenharmony_ci regno; 136662306a36Sopenharmony_ci else 136762306a36Sopenharmony_ci ((u32 *)info->pseudo_palette)[regno] = 136862306a36Sopenharmony_ci ((red & 0xff00) << 8) | 136962306a36Sopenharmony_ci (green & 0xff00) | 137062306a36Sopenharmony_ci ((blue & 0xff00) >> 8); 137162306a36Sopenharmony_ci break; 137262306a36Sopenharmony_ci } 137362306a36Sopenharmony_ci } 137462306a36Sopenharmony_ci return 0; 137562306a36Sopenharmony_ci} 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_cistatic int i810fb_pan_display(struct fb_var_screeninfo *var, 137862306a36Sopenharmony_ci struct fb_info *info) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci struct i810fb_par *par = info->par; 138162306a36Sopenharmony_ci u32 total; 138262306a36Sopenharmony_ci 138362306a36Sopenharmony_ci total = var->xoffset * par->depth + 138462306a36Sopenharmony_ci var->yoffset * info->fix.line_length; 138562306a36Sopenharmony_ci i810fb_load_front(total, info); 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_ci return 0; 138862306a36Sopenharmony_ci} 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_cistatic int i810fb_blank (int blank_mode, struct fb_info *info) 139162306a36Sopenharmony_ci{ 139262306a36Sopenharmony_ci struct i810fb_par *par = info->par; 139362306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 139462306a36Sopenharmony_ci int mode = 0, pwr, scr_off = 0; 139562306a36Sopenharmony_ci 139662306a36Sopenharmony_ci pwr = i810_readl(PWR_CLKC, mmio); 139762306a36Sopenharmony_ci 139862306a36Sopenharmony_ci switch (blank_mode) { 139962306a36Sopenharmony_ci case FB_BLANK_UNBLANK: 140062306a36Sopenharmony_ci mode = POWERON; 140162306a36Sopenharmony_ci pwr |= 1; 140262306a36Sopenharmony_ci scr_off = ON; 140362306a36Sopenharmony_ci break; 140462306a36Sopenharmony_ci case FB_BLANK_NORMAL: 140562306a36Sopenharmony_ci mode = POWERON; 140662306a36Sopenharmony_ci pwr |= 1; 140762306a36Sopenharmony_ci scr_off = OFF; 140862306a36Sopenharmony_ci break; 140962306a36Sopenharmony_ci case FB_BLANK_VSYNC_SUSPEND: 141062306a36Sopenharmony_ci mode = STANDBY; 141162306a36Sopenharmony_ci pwr |= 1; 141262306a36Sopenharmony_ci scr_off = OFF; 141362306a36Sopenharmony_ci break; 141462306a36Sopenharmony_ci case FB_BLANK_HSYNC_SUSPEND: 141562306a36Sopenharmony_ci mode = SUSPEND; 141662306a36Sopenharmony_ci pwr |= 1; 141762306a36Sopenharmony_ci scr_off = OFF; 141862306a36Sopenharmony_ci break; 141962306a36Sopenharmony_ci case FB_BLANK_POWERDOWN: 142062306a36Sopenharmony_ci mode = POWERDOWN; 142162306a36Sopenharmony_ci pwr &= ~1; 142262306a36Sopenharmony_ci scr_off = OFF; 142362306a36Sopenharmony_ci break; 142462306a36Sopenharmony_ci default: 142562306a36Sopenharmony_ci return -EINVAL; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci 142862306a36Sopenharmony_ci i810_screen_off(mmio, scr_off); 142962306a36Sopenharmony_ci i810_writel(HVSYNC, mmio, mode); 143062306a36Sopenharmony_ci i810_writel(PWR_CLKC, mmio, pwr); 143162306a36Sopenharmony_ci 143262306a36Sopenharmony_ci return 0; 143362306a36Sopenharmony_ci} 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_cistatic int i810fb_set_par(struct fb_info *info) 143662306a36Sopenharmony_ci{ 143762306a36Sopenharmony_ci struct i810fb_par *par = info->par; 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci decode_var(&info->var, par); 144062306a36Sopenharmony_ci i810_load_regs(par); 144162306a36Sopenharmony_ci i810_init_cursor(par); 144262306a36Sopenharmony_ci encode_fix(&info->fix, info); 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci if (info->var.accel_flags && !(par->dev_flags & LOCKUP)) { 144562306a36Sopenharmony_ci info->flags = FBINFO_HWACCEL_YPAN | 144662306a36Sopenharmony_ci FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT | 144762306a36Sopenharmony_ci FBINFO_HWACCEL_IMAGEBLIT; 144862306a36Sopenharmony_ci info->pixmap.scan_align = 2; 144962306a36Sopenharmony_ci } else { 145062306a36Sopenharmony_ci info->pixmap.scan_align = 1; 145162306a36Sopenharmony_ci info->flags = FBINFO_HWACCEL_YPAN; 145262306a36Sopenharmony_ci } 145362306a36Sopenharmony_ci return 0; 145462306a36Sopenharmony_ci} 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_cistatic int i810fb_check_var(struct fb_var_screeninfo *var, 145762306a36Sopenharmony_ci struct fb_info *info) 145862306a36Sopenharmony_ci{ 145962306a36Sopenharmony_ci int err; 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci if (IS_DVT) { 146262306a36Sopenharmony_ci var->vmode &= ~FB_VMODE_MASK; 146362306a36Sopenharmony_ci var->vmode |= FB_VMODE_NONINTERLACED; 146462306a36Sopenharmony_ci } 146562306a36Sopenharmony_ci if (var->vmode & FB_VMODE_DOUBLE) { 146662306a36Sopenharmony_ci var->vmode &= ~FB_VMODE_MASK; 146762306a36Sopenharmony_ci var->vmode |= FB_VMODE_NONINTERLACED; 146862306a36Sopenharmony_ci } 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci i810_round_off(var); 147162306a36Sopenharmony_ci if ((err = i810_check_params(var, info))) 147262306a36Sopenharmony_ci return err; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci i810fb_fill_var_timings(var); 147562306a36Sopenharmony_ci set_color_bitfields(var); 147662306a36Sopenharmony_ci return 0; 147762306a36Sopenharmony_ci} 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_cistatic int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor) 148062306a36Sopenharmony_ci{ 148162306a36Sopenharmony_ci struct i810fb_par *par = info->par; 148262306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci if (par->dev_flags & LOCKUP) 148562306a36Sopenharmony_ci return -ENXIO; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci if (cursor->image.width > 64 || cursor->image.height > 64) 148862306a36Sopenharmony_ci return -ENXIO; 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_ci if ((i810_readl(CURBASE, mmio) & 0xf) != par->cursor_heap.physical) { 149162306a36Sopenharmony_ci i810_init_cursor(par); 149262306a36Sopenharmony_ci cursor->set |= FB_CUR_SETALL; 149362306a36Sopenharmony_ci } 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_ci i810_enable_cursor(mmio, OFF); 149662306a36Sopenharmony_ci 149762306a36Sopenharmony_ci if (cursor->set & FB_CUR_SETPOS) { 149862306a36Sopenharmony_ci u32 tmp; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci tmp = (cursor->image.dx - info->var.xoffset) & 0xffff; 150162306a36Sopenharmony_ci tmp |= (cursor->image.dy - info->var.yoffset) << 16; 150262306a36Sopenharmony_ci i810_writel(CURPOS, mmio, tmp); 150362306a36Sopenharmony_ci } 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if (cursor->set & FB_CUR_SETSIZE) 150662306a36Sopenharmony_ci i810_reset_cursor_image(par); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci if (cursor->set & FB_CUR_SETCMAP) 150962306a36Sopenharmony_ci i810_load_cursor_colors(cursor->image.fg_color, 151062306a36Sopenharmony_ci cursor->image.bg_color, 151162306a36Sopenharmony_ci info); 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) { 151462306a36Sopenharmony_ci int size = ((cursor->image.width + 7) >> 3) * 151562306a36Sopenharmony_ci cursor->image.height; 151662306a36Sopenharmony_ci int i; 151762306a36Sopenharmony_ci u8 *data = kmalloc(64 * 8, GFP_ATOMIC); 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci if (data == NULL) 152062306a36Sopenharmony_ci return -ENOMEM; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci switch (cursor->rop) { 152362306a36Sopenharmony_ci case ROP_XOR: 152462306a36Sopenharmony_ci for (i = 0; i < size; i++) 152562306a36Sopenharmony_ci data[i] = cursor->image.data[i] ^ cursor->mask[i]; 152662306a36Sopenharmony_ci break; 152762306a36Sopenharmony_ci case ROP_COPY: 152862306a36Sopenharmony_ci default: 152962306a36Sopenharmony_ci for (i = 0; i < size; i++) 153062306a36Sopenharmony_ci data[i] = cursor->image.data[i] & cursor->mask[i]; 153162306a36Sopenharmony_ci break; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci i810_load_cursor_image(cursor->image.width, 153562306a36Sopenharmony_ci cursor->image.height, data, 153662306a36Sopenharmony_ci par); 153762306a36Sopenharmony_ci kfree(data); 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci if (cursor->enable) 154162306a36Sopenharmony_ci i810_enable_cursor(mmio, ON); 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci return 0; 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_cistatic const struct fb_ops i810fb_ops = { 154762306a36Sopenharmony_ci .owner = THIS_MODULE, 154862306a36Sopenharmony_ci .fb_open = i810fb_open, 154962306a36Sopenharmony_ci .fb_release = i810fb_release, 155062306a36Sopenharmony_ci .fb_check_var = i810fb_check_var, 155162306a36Sopenharmony_ci .fb_set_par = i810fb_set_par, 155262306a36Sopenharmony_ci .fb_setcolreg = i810fb_setcolreg, 155362306a36Sopenharmony_ci .fb_blank = i810fb_blank, 155462306a36Sopenharmony_ci .fb_pan_display = i810fb_pan_display, 155562306a36Sopenharmony_ci .fb_fillrect = i810fb_fillrect, 155662306a36Sopenharmony_ci .fb_copyarea = i810fb_copyarea, 155762306a36Sopenharmony_ci .fb_imageblit = i810fb_imageblit, 155862306a36Sopenharmony_ci .fb_cursor = i810fb_cursor, 155962306a36Sopenharmony_ci .fb_sync = i810fb_sync, 156062306a36Sopenharmony_ci}; 156162306a36Sopenharmony_ci 156262306a36Sopenharmony_ci/*********************************************************************** 156362306a36Sopenharmony_ci * Power Management * 156462306a36Sopenharmony_ci ***********************************************************************/ 156562306a36Sopenharmony_cistatic int i810fb_suspend(struct pci_dev *dev, pm_message_t mesg) 156662306a36Sopenharmony_ci{ 156762306a36Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 156862306a36Sopenharmony_ci struct i810fb_par *par = info->par; 156962306a36Sopenharmony_ci 157062306a36Sopenharmony_ci par->cur_state = mesg.event; 157162306a36Sopenharmony_ci 157262306a36Sopenharmony_ci switch (mesg.event) { 157362306a36Sopenharmony_ci case PM_EVENT_FREEZE: 157462306a36Sopenharmony_ci case PM_EVENT_PRETHAW: 157562306a36Sopenharmony_ci dev->dev.power.power_state = mesg; 157662306a36Sopenharmony_ci return 0; 157762306a36Sopenharmony_ci } 157862306a36Sopenharmony_ci 157962306a36Sopenharmony_ci console_lock(); 158062306a36Sopenharmony_ci fb_set_suspend(info, 1); 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci if (info->fbops->fb_sync) 158362306a36Sopenharmony_ci info->fbops->fb_sync(info); 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci i810fb_blank(FB_BLANK_POWERDOWN, info); 158662306a36Sopenharmony_ci agp_unbind_memory(par->i810_gtt.i810_fb_memory); 158762306a36Sopenharmony_ci agp_unbind_memory(par->i810_gtt.i810_cursor_memory); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci pci_save_state(dev); 159062306a36Sopenharmony_ci pci_disable_device(dev); 159162306a36Sopenharmony_ci pci_set_power_state(dev, pci_choose_state(dev, mesg)); 159262306a36Sopenharmony_ci console_unlock(); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_ci return 0; 159562306a36Sopenharmony_ci} 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_cistatic int i810fb_resume(struct pci_dev *dev) 159862306a36Sopenharmony_ci{ 159962306a36Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 160062306a36Sopenharmony_ci struct i810fb_par *par = info->par; 160162306a36Sopenharmony_ci int cur_state = par->cur_state; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci par->cur_state = PM_EVENT_ON; 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci if (cur_state == PM_EVENT_FREEZE) { 160662306a36Sopenharmony_ci pci_set_power_state(dev, PCI_D0); 160762306a36Sopenharmony_ci return 0; 160862306a36Sopenharmony_ci } 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci console_lock(); 161162306a36Sopenharmony_ci pci_set_power_state(dev, PCI_D0); 161262306a36Sopenharmony_ci pci_restore_state(dev); 161362306a36Sopenharmony_ci 161462306a36Sopenharmony_ci if (pci_enable_device(dev)) 161562306a36Sopenharmony_ci goto fail; 161662306a36Sopenharmony_ci 161762306a36Sopenharmony_ci pci_set_master(dev); 161862306a36Sopenharmony_ci agp_bind_memory(par->i810_gtt.i810_fb_memory, 161962306a36Sopenharmony_ci par->fb.offset); 162062306a36Sopenharmony_ci agp_bind_memory(par->i810_gtt.i810_cursor_memory, 162162306a36Sopenharmony_ci par->cursor_heap.offset); 162262306a36Sopenharmony_ci i810fb_set_par(info); 162362306a36Sopenharmony_ci fb_set_suspend (info, 0); 162462306a36Sopenharmony_ci info->fbops->fb_blank(VESA_NO_BLANKING, info); 162562306a36Sopenharmony_cifail: 162662306a36Sopenharmony_ci console_unlock(); 162762306a36Sopenharmony_ci return 0; 162862306a36Sopenharmony_ci} 162962306a36Sopenharmony_ci/*********************************************************************** 163062306a36Sopenharmony_ci * AGP resource allocation * 163162306a36Sopenharmony_ci ***********************************************************************/ 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_cistatic void i810_fix_pointers(struct i810fb_par *par) 163462306a36Sopenharmony_ci{ 163562306a36Sopenharmony_ci par->fb.physical = par->aperture.physical+(par->fb.offset << 12); 163662306a36Sopenharmony_ci par->fb.virtual = par->aperture.virtual+(par->fb.offset << 12); 163762306a36Sopenharmony_ci par->iring.physical = par->aperture.physical + 163862306a36Sopenharmony_ci (par->iring.offset << 12); 163962306a36Sopenharmony_ci par->iring.virtual = par->aperture.virtual + 164062306a36Sopenharmony_ci (par->iring.offset << 12); 164162306a36Sopenharmony_ci par->cursor_heap.virtual = par->aperture.virtual+ 164262306a36Sopenharmony_ci (par->cursor_heap.offset << 12); 164362306a36Sopenharmony_ci} 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_cistatic void i810_fix_offsets(struct i810fb_par *par) 164662306a36Sopenharmony_ci{ 164762306a36Sopenharmony_ci if (vram + 1 > par->aperture.size >> 20) 164862306a36Sopenharmony_ci vram = (par->aperture.size >> 20) - 1; 164962306a36Sopenharmony_ci if (v_offset_default > (par->aperture.size >> 20)) 165062306a36Sopenharmony_ci v_offset_default = (par->aperture.size >> 20); 165162306a36Sopenharmony_ci if (vram + v_offset_default + 1 > par->aperture.size >> 20) 165262306a36Sopenharmony_ci v_offset_default = (par->aperture.size >> 20) - (vram + 1); 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci par->fb.size = vram << 20; 165562306a36Sopenharmony_ci par->fb.offset = v_offset_default << 20; 165662306a36Sopenharmony_ci par->fb.offset >>= 12; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci par->iring.offset = par->fb.offset + (par->fb.size >> 12); 165962306a36Sopenharmony_ci par->iring.size = RINGBUFFER_SIZE; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci par->cursor_heap.offset = par->iring.offset + (RINGBUFFER_SIZE >> 12); 166262306a36Sopenharmony_ci par->cursor_heap.size = 4096; 166362306a36Sopenharmony_ci} 166462306a36Sopenharmony_ci 166562306a36Sopenharmony_cistatic int i810_alloc_agp_mem(struct fb_info *info) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci struct i810fb_par *par = info->par; 166862306a36Sopenharmony_ci int size; 166962306a36Sopenharmony_ci struct agp_bridge_data *bridge; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci i810_fix_offsets(par); 167262306a36Sopenharmony_ci size = par->fb.size + par->iring.size; 167362306a36Sopenharmony_ci 167462306a36Sopenharmony_ci if (!(bridge = agp_backend_acquire(par->dev))) { 167562306a36Sopenharmony_ci printk("i810fb_alloc_fbmem: cannot acquire agpgart\n"); 167662306a36Sopenharmony_ci return -ENODEV; 167762306a36Sopenharmony_ci } 167862306a36Sopenharmony_ci if (!(par->i810_gtt.i810_fb_memory = 167962306a36Sopenharmony_ci agp_allocate_memory(bridge, size >> 12, AGP_NORMAL_MEMORY))) { 168062306a36Sopenharmony_ci printk("i810fb_alloc_fbmem: can't allocate framebuffer " 168162306a36Sopenharmony_ci "memory\n"); 168262306a36Sopenharmony_ci agp_backend_release(bridge); 168362306a36Sopenharmony_ci return -ENOMEM; 168462306a36Sopenharmony_ci } 168562306a36Sopenharmony_ci if (agp_bind_memory(par->i810_gtt.i810_fb_memory, 168662306a36Sopenharmony_ci par->fb.offset)) { 168762306a36Sopenharmony_ci printk("i810fb_alloc_fbmem: can't bind framebuffer memory\n"); 168862306a36Sopenharmony_ci agp_backend_release(bridge); 168962306a36Sopenharmony_ci return -EBUSY; 169062306a36Sopenharmony_ci } 169162306a36Sopenharmony_ci 169262306a36Sopenharmony_ci if (!(par->i810_gtt.i810_cursor_memory = 169362306a36Sopenharmony_ci agp_allocate_memory(bridge, par->cursor_heap.size >> 12, 169462306a36Sopenharmony_ci AGP_PHYSICAL_MEMORY))) { 169562306a36Sopenharmony_ci printk("i810fb_alloc_cursormem: can't allocate " 169662306a36Sopenharmony_ci "cursor memory\n"); 169762306a36Sopenharmony_ci agp_backend_release(bridge); 169862306a36Sopenharmony_ci return -ENOMEM; 169962306a36Sopenharmony_ci } 170062306a36Sopenharmony_ci if (agp_bind_memory(par->i810_gtt.i810_cursor_memory, 170162306a36Sopenharmony_ci par->cursor_heap.offset)) { 170262306a36Sopenharmony_ci printk("i810fb_alloc_cursormem: cannot bind cursor memory\n"); 170362306a36Sopenharmony_ci agp_backend_release(bridge); 170462306a36Sopenharmony_ci return -EBUSY; 170562306a36Sopenharmony_ci } 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci par->cursor_heap.physical = par->i810_gtt.i810_cursor_memory->physical; 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci i810_fix_pointers(par); 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci agp_backend_release(bridge); 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci return 0; 171462306a36Sopenharmony_ci} 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci/*************************************************************** 171762306a36Sopenharmony_ci * Initialization * 171862306a36Sopenharmony_ci ***************************************************************/ 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci/** 172162306a36Sopenharmony_ci * i810_init_monspecs 172262306a36Sopenharmony_ci * @info: pointer to device specific info structure 172362306a36Sopenharmony_ci * 172462306a36Sopenharmony_ci * DESCRIPTION: 172562306a36Sopenharmony_ci * Sets the user monitor's horizontal and vertical 172662306a36Sopenharmony_ci * frequency limits 172762306a36Sopenharmony_ci */ 172862306a36Sopenharmony_cistatic void i810_init_monspecs(struct fb_info *info) 172962306a36Sopenharmony_ci{ 173062306a36Sopenharmony_ci if (!hsync1) 173162306a36Sopenharmony_ci hsync1 = HFMIN; 173262306a36Sopenharmony_ci if (!hsync2) 173362306a36Sopenharmony_ci hsync2 = HFMAX; 173462306a36Sopenharmony_ci if (!info->monspecs.hfmax) 173562306a36Sopenharmony_ci info->monspecs.hfmax = hsync2; 173662306a36Sopenharmony_ci if (!info->monspecs.hfmin) 173762306a36Sopenharmony_ci info->monspecs.hfmin = hsync1; 173862306a36Sopenharmony_ci if (hsync2 < hsync1) 173962306a36Sopenharmony_ci info->monspecs.hfmin = hsync2; 174062306a36Sopenharmony_ci 174162306a36Sopenharmony_ci if (!vsync1) 174262306a36Sopenharmony_ci vsync1 = VFMIN; 174362306a36Sopenharmony_ci if (!vsync2) 174462306a36Sopenharmony_ci vsync2 = VFMAX; 174562306a36Sopenharmony_ci if (IS_DVT && vsync1 < 60) 174662306a36Sopenharmony_ci vsync1 = 60; 174762306a36Sopenharmony_ci if (!info->monspecs.vfmax) 174862306a36Sopenharmony_ci info->monspecs.vfmax = vsync2; 174962306a36Sopenharmony_ci if (!info->monspecs.vfmin) 175062306a36Sopenharmony_ci info->monspecs.vfmin = vsync1; 175162306a36Sopenharmony_ci if (vsync2 < vsync1) 175262306a36Sopenharmony_ci info->monspecs.vfmin = vsync2; 175362306a36Sopenharmony_ci} 175462306a36Sopenharmony_ci 175562306a36Sopenharmony_ci/** 175662306a36Sopenharmony_ci * i810_init_defaults - initializes default values to use 175762306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 175862306a36Sopenharmony_ci * @info: pointer to current fb_info structure 175962306a36Sopenharmony_ci */ 176062306a36Sopenharmony_cistatic void i810_init_defaults(struct i810fb_par *par, struct fb_info *info) 176162306a36Sopenharmony_ci{ 176262306a36Sopenharmony_ci mutex_init(&par->open_lock); 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci if (voffset) 176562306a36Sopenharmony_ci v_offset_default = voffset; 176662306a36Sopenharmony_ci else if (par->aperture.size > 32 * 1024 * 1024) 176762306a36Sopenharmony_ci v_offset_default = 16; 176862306a36Sopenharmony_ci else 176962306a36Sopenharmony_ci v_offset_default = 8; 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_ci if (!vram) 177262306a36Sopenharmony_ci vram = 1; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci if (accel) 177562306a36Sopenharmony_ci par->dev_flags |= HAS_ACCELERATION; 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ci if (sync) 177862306a36Sopenharmony_ci par->dev_flags |= ALWAYS_SYNC; 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci par->ddc_num = (ddc3 ? 3 : 2); 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci if (bpp < 8) 178362306a36Sopenharmony_ci bpp = 8; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_ci par->i810fb_ops = i810fb_ops; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci if (xres) 178862306a36Sopenharmony_ci info->var.xres = xres; 178962306a36Sopenharmony_ci else 179062306a36Sopenharmony_ci info->var.xres = 640; 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci if (yres) 179362306a36Sopenharmony_ci info->var.yres = yres; 179462306a36Sopenharmony_ci else 179562306a36Sopenharmony_ci info->var.yres = 480; 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci if (!vyres) 179862306a36Sopenharmony_ci vyres = (vram << 20)/(info->var.xres*bpp >> 3); 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci info->var.yres_virtual = vyres; 180162306a36Sopenharmony_ci info->var.bits_per_pixel = bpp; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci if (dcolor) 180462306a36Sopenharmony_ci info->var.nonstd = 1; 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci if (par->dev_flags & HAS_ACCELERATION) 180762306a36Sopenharmony_ci info->var.accel_flags = 1; 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci i810_init_monspecs(info); 181062306a36Sopenharmony_ci} 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci/** 181362306a36Sopenharmony_ci * i810_init_device - initialize device 181462306a36Sopenharmony_ci * @par: pointer to i810fb_par structure 181562306a36Sopenharmony_ci */ 181662306a36Sopenharmony_cistatic void i810_init_device(struct i810fb_par *par) 181762306a36Sopenharmony_ci{ 181862306a36Sopenharmony_ci u8 reg; 181962306a36Sopenharmony_ci u8 __iomem *mmio = par->mmio_start_virtual; 182062306a36Sopenharmony_ci 182162306a36Sopenharmony_ci if (mtrr) 182262306a36Sopenharmony_ci par->wc_cookie= arch_phys_wc_add((u32) par->aperture.physical, 182362306a36Sopenharmony_ci par->aperture.size); 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci i810_init_cursor(par); 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci /* mvo: enable external vga-connector (for laptops) */ 182862306a36Sopenharmony_ci if (extvga) { 182962306a36Sopenharmony_ci i810_writel(HVSYNC, mmio, 0); 183062306a36Sopenharmony_ci i810_writel(PWR_CLKC, mmio, 3); 183162306a36Sopenharmony_ci } 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_ci pci_read_config_byte(par->dev, 0x50, ®); 183462306a36Sopenharmony_ci reg &= FREQ_MASK; 183562306a36Sopenharmony_ci par->mem_freq = (reg) ? 133 : 100; 183662306a36Sopenharmony_ci 183762306a36Sopenharmony_ci} 183862306a36Sopenharmony_ci 183962306a36Sopenharmony_cistatic int i810_allocate_pci_resource(struct i810fb_par *par, 184062306a36Sopenharmony_ci const struct pci_device_id *entry) 184162306a36Sopenharmony_ci{ 184262306a36Sopenharmony_ci int err; 184362306a36Sopenharmony_ci 184462306a36Sopenharmony_ci if ((err = pci_enable_device(par->dev))) { 184562306a36Sopenharmony_ci printk("i810fb_init: cannot enable device\n"); 184662306a36Sopenharmony_ci return err; 184762306a36Sopenharmony_ci } 184862306a36Sopenharmony_ci par->res_flags |= PCI_DEVICE_ENABLED; 184962306a36Sopenharmony_ci 185062306a36Sopenharmony_ci if (pci_resource_len(par->dev, 0) > 512 * 1024) { 185162306a36Sopenharmony_ci par->aperture.physical = pci_resource_start(par->dev, 0); 185262306a36Sopenharmony_ci par->aperture.size = pci_resource_len(par->dev, 0); 185362306a36Sopenharmony_ci par->mmio_start_phys = pci_resource_start(par->dev, 1); 185462306a36Sopenharmony_ci } else { 185562306a36Sopenharmony_ci par->aperture.physical = pci_resource_start(par->dev, 1); 185662306a36Sopenharmony_ci par->aperture.size = pci_resource_len(par->dev, 1); 185762306a36Sopenharmony_ci par->mmio_start_phys = pci_resource_start(par->dev, 0); 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci if (!par->aperture.size) { 186062306a36Sopenharmony_ci printk("i810fb_init: device is disabled\n"); 186162306a36Sopenharmony_ci return -ENOMEM; 186262306a36Sopenharmony_ci } 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci if (!request_mem_region(par->aperture.physical, 186562306a36Sopenharmony_ci par->aperture.size, 186662306a36Sopenharmony_ci i810_pci_list[entry->driver_data])) { 186762306a36Sopenharmony_ci printk("i810fb_init: cannot request framebuffer region\n"); 186862306a36Sopenharmony_ci return -ENODEV; 186962306a36Sopenharmony_ci } 187062306a36Sopenharmony_ci par->res_flags |= FRAMEBUFFER_REQ; 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci par->aperture.virtual = ioremap_wc(par->aperture.physical, 187362306a36Sopenharmony_ci par->aperture.size); 187462306a36Sopenharmony_ci if (!par->aperture.virtual) { 187562306a36Sopenharmony_ci printk("i810fb_init: cannot remap framebuffer region\n"); 187662306a36Sopenharmony_ci return -ENODEV; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci 187962306a36Sopenharmony_ci if (!request_mem_region(par->mmio_start_phys, 188062306a36Sopenharmony_ci MMIO_SIZE, 188162306a36Sopenharmony_ci i810_pci_list[entry->driver_data])) { 188262306a36Sopenharmony_ci printk("i810fb_init: cannot request mmio region\n"); 188362306a36Sopenharmony_ci return -ENODEV; 188462306a36Sopenharmony_ci } 188562306a36Sopenharmony_ci par->res_flags |= MMIO_REQ; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci par->mmio_start_virtual = ioremap(par->mmio_start_phys, 188862306a36Sopenharmony_ci MMIO_SIZE); 188962306a36Sopenharmony_ci if (!par->mmio_start_virtual) { 189062306a36Sopenharmony_ci printk("i810fb_init: cannot remap mmio region\n"); 189162306a36Sopenharmony_ci return -ENODEV; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci 189462306a36Sopenharmony_ci return 0; 189562306a36Sopenharmony_ci} 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_cistatic void i810fb_find_init_mode(struct fb_info *info) 189862306a36Sopenharmony_ci{ 189962306a36Sopenharmony_ci struct fb_videomode mode; 190062306a36Sopenharmony_ci struct fb_var_screeninfo var; 190162306a36Sopenharmony_ci struct fb_monspecs *specs = &info->monspecs; 190262306a36Sopenharmony_ci int found = 0; 190362306a36Sopenharmony_ci#ifdef CONFIG_FB_I810_I2C 190462306a36Sopenharmony_ci int i; 190562306a36Sopenharmony_ci int err = 1; 190662306a36Sopenharmony_ci struct i810fb_par *par = info->par; 190762306a36Sopenharmony_ci#endif 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci INIT_LIST_HEAD(&info->modelist); 191062306a36Sopenharmony_ci memset(&mode, 0, sizeof(struct fb_videomode)); 191162306a36Sopenharmony_ci var = info->var; 191262306a36Sopenharmony_ci#ifdef CONFIG_FB_I810_I2C 191362306a36Sopenharmony_ci i810_create_i2c_busses(par); 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci for (i = 0; i < par->ddc_num + 1; i++) { 191662306a36Sopenharmony_ci err = i810_probe_i2c_connector(info, &par->edid, i); 191762306a36Sopenharmony_ci if (!err) 191862306a36Sopenharmony_ci break; 191962306a36Sopenharmony_ci } 192062306a36Sopenharmony_ci 192162306a36Sopenharmony_ci if (!err) 192262306a36Sopenharmony_ci printk("i810fb_init_pci: DDC probe successful\n"); 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci fb_edid_to_monspecs(par->edid, specs); 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci if (specs->modedb == NULL) 192762306a36Sopenharmony_ci printk("i810fb_init_pci: Unable to get Mode Database\n"); 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci fb_videomode_to_modelist(specs->modedb, specs->modedb_len, 193062306a36Sopenharmony_ci &info->modelist); 193162306a36Sopenharmony_ci if (specs->modedb != NULL) { 193262306a36Sopenharmony_ci const struct fb_videomode *m; 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci if (xres && yres) { 193562306a36Sopenharmony_ci if ((m = fb_find_best_mode(&var, &info->modelist))) { 193662306a36Sopenharmony_ci mode = *m; 193762306a36Sopenharmony_ci found = 1; 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci } 194062306a36Sopenharmony_ci 194162306a36Sopenharmony_ci if (!found) { 194262306a36Sopenharmony_ci m = fb_find_best_display(&info->monspecs, &info->modelist); 194362306a36Sopenharmony_ci mode = *m; 194462306a36Sopenharmony_ci found = 1; 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci 194762306a36Sopenharmony_ci fb_videomode_to_var(&var, &mode); 194862306a36Sopenharmony_ci } 194962306a36Sopenharmony_ci#endif 195062306a36Sopenharmony_ci if (mode_option) 195162306a36Sopenharmony_ci fb_find_mode(&var, info, mode_option, specs->modedb, 195262306a36Sopenharmony_ci specs->modedb_len, (found) ? &mode : NULL, 195362306a36Sopenharmony_ci info->var.bits_per_pixel); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci info->var = var; 195662306a36Sopenharmony_ci fb_destroy_modedb(specs->modedb); 195762306a36Sopenharmony_ci specs->modedb = NULL; 195862306a36Sopenharmony_ci} 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci#ifndef MODULE 196162306a36Sopenharmony_cistatic int i810fb_setup(char *options) 196262306a36Sopenharmony_ci{ 196362306a36Sopenharmony_ci char *this_opt, *suffix = NULL; 196462306a36Sopenharmony_ci 196562306a36Sopenharmony_ci if (!options || !*options) 196662306a36Sopenharmony_ci return 0; 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_ci while ((this_opt = strsep(&options, ",")) != NULL) { 196962306a36Sopenharmony_ci if (!strncmp(this_opt, "mtrr", 4)) 197062306a36Sopenharmony_ci mtrr = true; 197162306a36Sopenharmony_ci else if (!strncmp(this_opt, "accel", 5)) 197262306a36Sopenharmony_ci accel = true; 197362306a36Sopenharmony_ci else if (!strncmp(this_opt, "extvga", 6)) 197462306a36Sopenharmony_ci extvga = true; 197562306a36Sopenharmony_ci else if (!strncmp(this_opt, "sync", 4)) 197662306a36Sopenharmony_ci sync = true; 197762306a36Sopenharmony_ci else if (!strncmp(this_opt, "vram:", 5)) 197862306a36Sopenharmony_ci vram = (simple_strtoul(this_opt+5, NULL, 0)); 197962306a36Sopenharmony_ci else if (!strncmp(this_opt, "voffset:", 8)) 198062306a36Sopenharmony_ci voffset = (simple_strtoul(this_opt+8, NULL, 0)); 198162306a36Sopenharmony_ci else if (!strncmp(this_opt, "xres:", 5)) 198262306a36Sopenharmony_ci xres = simple_strtoul(this_opt+5, NULL, 0); 198362306a36Sopenharmony_ci else if (!strncmp(this_opt, "yres:", 5)) 198462306a36Sopenharmony_ci yres = simple_strtoul(this_opt+5, NULL, 0); 198562306a36Sopenharmony_ci else if (!strncmp(this_opt, "vyres:", 6)) 198662306a36Sopenharmony_ci vyres = simple_strtoul(this_opt+6, NULL, 0); 198762306a36Sopenharmony_ci else if (!strncmp(this_opt, "bpp:", 4)) 198862306a36Sopenharmony_ci bpp = simple_strtoul(this_opt+4, NULL, 0); 198962306a36Sopenharmony_ci else if (!strncmp(this_opt, "hsync1:", 7)) { 199062306a36Sopenharmony_ci hsync1 = simple_strtoul(this_opt+7, &suffix, 0); 199162306a36Sopenharmony_ci if (strncmp(suffix, "H", 1)) 199262306a36Sopenharmony_ci hsync1 *= 1000; 199362306a36Sopenharmony_ci } else if (!strncmp(this_opt, "hsync2:", 7)) { 199462306a36Sopenharmony_ci hsync2 = simple_strtoul(this_opt+7, &suffix, 0); 199562306a36Sopenharmony_ci if (strncmp(suffix, "H", 1)) 199662306a36Sopenharmony_ci hsync2 *= 1000; 199762306a36Sopenharmony_ci } else if (!strncmp(this_opt, "vsync1:", 7)) 199862306a36Sopenharmony_ci vsync1 = simple_strtoul(this_opt+7, NULL, 0); 199962306a36Sopenharmony_ci else if (!strncmp(this_opt, "vsync2:", 7)) 200062306a36Sopenharmony_ci vsync2 = simple_strtoul(this_opt+7, NULL, 0); 200162306a36Sopenharmony_ci else if (!strncmp(this_opt, "dcolor", 6)) 200262306a36Sopenharmony_ci dcolor = true; 200362306a36Sopenharmony_ci else if (!strncmp(this_opt, "ddc3", 4)) 200462306a36Sopenharmony_ci ddc3 = true; 200562306a36Sopenharmony_ci else 200662306a36Sopenharmony_ci mode_option = this_opt; 200762306a36Sopenharmony_ci } 200862306a36Sopenharmony_ci return 0; 200962306a36Sopenharmony_ci} 201062306a36Sopenharmony_ci#endif 201162306a36Sopenharmony_ci 201262306a36Sopenharmony_cistatic int i810fb_init_pci(struct pci_dev *dev, 201362306a36Sopenharmony_ci const struct pci_device_id *entry) 201462306a36Sopenharmony_ci{ 201562306a36Sopenharmony_ci struct fb_info *info; 201662306a36Sopenharmony_ci struct i810fb_par *par = NULL; 201762306a36Sopenharmony_ci struct fb_videomode mode; 201862306a36Sopenharmony_ci int err = -1, vfreq, hfreq, pixclock; 201962306a36Sopenharmony_ci 202062306a36Sopenharmony_ci err = aperture_remove_conflicting_pci_devices(dev, "i810fb"); 202162306a36Sopenharmony_ci if (err) 202262306a36Sopenharmony_ci return err; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci info = framebuffer_alloc(sizeof(struct i810fb_par), &dev->dev); 202562306a36Sopenharmony_ci if (!info) 202662306a36Sopenharmony_ci return -ENOMEM; 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci par = info->par; 202962306a36Sopenharmony_ci par->dev = dev; 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci if (!(info->pixmap.addr = kzalloc(8*1024, GFP_KERNEL))) { 203262306a36Sopenharmony_ci i810fb_release_resource(info, par); 203362306a36Sopenharmony_ci return -ENOMEM; 203462306a36Sopenharmony_ci } 203562306a36Sopenharmony_ci info->pixmap.size = 8*1024; 203662306a36Sopenharmony_ci info->pixmap.buf_align = 8; 203762306a36Sopenharmony_ci info->pixmap.access_align = 32; 203862306a36Sopenharmony_ci info->pixmap.flags = FB_PIXMAP_SYSTEM; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci if ((err = i810_allocate_pci_resource(par, entry))) { 204162306a36Sopenharmony_ci i810fb_release_resource(info, par); 204262306a36Sopenharmony_ci return err; 204362306a36Sopenharmony_ci } 204462306a36Sopenharmony_ci 204562306a36Sopenharmony_ci i810_init_defaults(par, info); 204662306a36Sopenharmony_ci 204762306a36Sopenharmony_ci if ((err = i810_alloc_agp_mem(info))) { 204862306a36Sopenharmony_ci i810fb_release_resource(info, par); 204962306a36Sopenharmony_ci return err; 205062306a36Sopenharmony_ci } 205162306a36Sopenharmony_ci 205262306a36Sopenharmony_ci i810_init_device(par); 205362306a36Sopenharmony_ci 205462306a36Sopenharmony_ci info->screen_base = par->fb.virtual; 205562306a36Sopenharmony_ci info->fbops = &par->i810fb_ops; 205662306a36Sopenharmony_ci info->pseudo_palette = par->pseudo_palette; 205762306a36Sopenharmony_ci fb_alloc_cmap(&info->cmap, 256, 0); 205862306a36Sopenharmony_ci i810fb_find_init_mode(info); 205962306a36Sopenharmony_ci 206062306a36Sopenharmony_ci if ((err = info->fbops->fb_check_var(&info->var, info))) { 206162306a36Sopenharmony_ci i810fb_release_resource(info, par); 206262306a36Sopenharmony_ci return err; 206362306a36Sopenharmony_ci } 206462306a36Sopenharmony_ci 206562306a36Sopenharmony_ci fb_var_to_videomode(&mode, &info->var); 206662306a36Sopenharmony_ci fb_add_videomode(&mode, &info->modelist); 206762306a36Sopenharmony_ci 206862306a36Sopenharmony_ci i810fb_init_ringbuffer(info); 206962306a36Sopenharmony_ci err = register_framebuffer(info); 207062306a36Sopenharmony_ci 207162306a36Sopenharmony_ci if (err < 0) { 207262306a36Sopenharmony_ci i810fb_release_resource(info, par); 207362306a36Sopenharmony_ci printk("i810fb_init: cannot register framebuffer device\n"); 207462306a36Sopenharmony_ci return err; 207562306a36Sopenharmony_ci } 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci pci_set_drvdata(dev, info); 207862306a36Sopenharmony_ci pixclock = 1000000000/(info->var.pixclock); 207962306a36Sopenharmony_ci pixclock *= 1000; 208062306a36Sopenharmony_ci hfreq = pixclock/(info->var.xres + info->var.left_margin + 208162306a36Sopenharmony_ci info->var.hsync_len + info->var.right_margin); 208262306a36Sopenharmony_ci vfreq = hfreq/(info->var.yres + info->var.upper_margin + 208362306a36Sopenharmony_ci info->var.vsync_len + info->var.lower_margin); 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci printk("I810FB: fb%d : %s v%d.%d.%d%s\n" 208662306a36Sopenharmony_ci "I810FB: Video RAM : %dK\n" 208762306a36Sopenharmony_ci "I810FB: Monitor : H: %d-%d KHz V: %d-%d Hz\n" 208862306a36Sopenharmony_ci "I810FB: Mode : %dx%d-%dbpp@%dHz\n", 208962306a36Sopenharmony_ci info->node, 209062306a36Sopenharmony_ci i810_pci_list[entry->driver_data], 209162306a36Sopenharmony_ci VERSION_MAJOR, VERSION_MINOR, VERSION_TEENIE, BRANCH_VERSION, 209262306a36Sopenharmony_ci (int) par->fb.size>>10, info->monspecs.hfmin/1000, 209362306a36Sopenharmony_ci info->monspecs.hfmax/1000, info->monspecs.vfmin, 209462306a36Sopenharmony_ci info->monspecs.vfmax, info->var.xres, 209562306a36Sopenharmony_ci info->var.yres, info->var.bits_per_pixel, vfreq); 209662306a36Sopenharmony_ci return 0; 209762306a36Sopenharmony_ci} 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci/*************************************************************** 210062306a36Sopenharmony_ci * De-initialization * 210162306a36Sopenharmony_ci ***************************************************************/ 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_cistatic void i810fb_release_resource(struct fb_info *info, 210462306a36Sopenharmony_ci struct i810fb_par *par) 210562306a36Sopenharmony_ci{ 210662306a36Sopenharmony_ci struct gtt_data *gtt = &par->i810_gtt; 210762306a36Sopenharmony_ci arch_phys_wc_del(par->wc_cookie); 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci i810_delete_i2c_busses(par); 211062306a36Sopenharmony_ci 211162306a36Sopenharmony_ci if (par->i810_gtt.i810_cursor_memory) 211262306a36Sopenharmony_ci agp_free_memory(gtt->i810_cursor_memory); 211362306a36Sopenharmony_ci if (par->i810_gtt.i810_fb_memory) 211462306a36Sopenharmony_ci agp_free_memory(gtt->i810_fb_memory); 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci if (par->mmio_start_virtual) 211762306a36Sopenharmony_ci iounmap(par->mmio_start_virtual); 211862306a36Sopenharmony_ci if (par->aperture.virtual) 211962306a36Sopenharmony_ci iounmap(par->aperture.virtual); 212062306a36Sopenharmony_ci kfree(par->edid); 212162306a36Sopenharmony_ci if (par->res_flags & FRAMEBUFFER_REQ) 212262306a36Sopenharmony_ci release_mem_region(par->aperture.physical, 212362306a36Sopenharmony_ci par->aperture.size); 212462306a36Sopenharmony_ci if (par->res_flags & MMIO_REQ) 212562306a36Sopenharmony_ci release_mem_region(par->mmio_start_phys, MMIO_SIZE); 212662306a36Sopenharmony_ci 212762306a36Sopenharmony_ci framebuffer_release(info); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci} 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_cistatic void i810fb_remove_pci(struct pci_dev *dev) 213262306a36Sopenharmony_ci{ 213362306a36Sopenharmony_ci struct fb_info *info = pci_get_drvdata(dev); 213462306a36Sopenharmony_ci struct i810fb_par *par = info->par; 213562306a36Sopenharmony_ci 213662306a36Sopenharmony_ci unregister_framebuffer(info); 213762306a36Sopenharmony_ci i810fb_release_resource(info, par); 213862306a36Sopenharmony_ci printk("cleanup_module: unloaded i810 framebuffer device\n"); 213962306a36Sopenharmony_ci} 214062306a36Sopenharmony_ci 214162306a36Sopenharmony_ci#ifndef MODULE 214262306a36Sopenharmony_cistatic int i810fb_init(void) 214362306a36Sopenharmony_ci{ 214462306a36Sopenharmony_ci char *option = NULL; 214562306a36Sopenharmony_ci 214662306a36Sopenharmony_ci if (fb_modesetting_disabled("i810fb")) 214762306a36Sopenharmony_ci return -ENODEV; 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci if (fb_get_options("i810fb", &option)) 215062306a36Sopenharmony_ci return -ENODEV; 215162306a36Sopenharmony_ci i810fb_setup(option); 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci return pci_register_driver(&i810fb_driver); 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci#endif 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci/********************************************************************* 215862306a36Sopenharmony_ci * Modularization * 215962306a36Sopenharmony_ci *********************************************************************/ 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci#ifdef MODULE 216262306a36Sopenharmony_ci 216362306a36Sopenharmony_cistatic int i810fb_init(void) 216462306a36Sopenharmony_ci{ 216562306a36Sopenharmony_ci if (fb_modesetting_disabled("i810fb")) 216662306a36Sopenharmony_ci return -ENODEV; 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci hsync1 *= 1000; 216962306a36Sopenharmony_ci hsync2 *= 1000; 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci return pci_register_driver(&i810fb_driver); 217262306a36Sopenharmony_ci} 217362306a36Sopenharmony_ci 217462306a36Sopenharmony_cimodule_param(vram, int, 0); 217562306a36Sopenharmony_ciMODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB" 217662306a36Sopenharmony_ci " (default=4)"); 217762306a36Sopenharmony_cimodule_param(voffset, int, 0); 217862306a36Sopenharmony_ciMODULE_PARM_DESC(voffset, "at what offset to place start of framebuffer " 217962306a36Sopenharmony_ci "memory (0 to maximum aperture size), in MiB (default = 48)"); 218062306a36Sopenharmony_cimodule_param(bpp, int, 0); 218162306a36Sopenharmony_ciMODULE_PARM_DESC(bpp, "Color depth for display in bits per pixel" 218262306a36Sopenharmony_ci " (default = 8)"); 218362306a36Sopenharmony_cimodule_param(xres, int, 0); 218462306a36Sopenharmony_ciMODULE_PARM_DESC(xres, "Horizontal resolution in pixels (default = 640)"); 218562306a36Sopenharmony_cimodule_param(yres, int, 0); 218662306a36Sopenharmony_ciMODULE_PARM_DESC(yres, "Vertical resolution in scanlines (default = 480)"); 218762306a36Sopenharmony_cimodule_param(vyres,int, 0); 218862306a36Sopenharmony_ciMODULE_PARM_DESC(vyres, "Virtual vertical resolution in scanlines" 218962306a36Sopenharmony_ci " (default = 480)"); 219062306a36Sopenharmony_cimodule_param(hsync1, int, 0); 219162306a36Sopenharmony_ciMODULE_PARM_DESC(hsync1, "Minimum horizontal frequency of monitor in KHz" 219262306a36Sopenharmony_ci " (default = 29)"); 219362306a36Sopenharmony_cimodule_param(hsync2, int, 0); 219462306a36Sopenharmony_ciMODULE_PARM_DESC(hsync2, "Maximum horizontal frequency of monitor in KHz" 219562306a36Sopenharmony_ci " (default = 30)"); 219662306a36Sopenharmony_cimodule_param(vsync1, int, 0); 219762306a36Sopenharmony_ciMODULE_PARM_DESC(vsync1, "Minimum vertical frequency of monitor in Hz" 219862306a36Sopenharmony_ci " (default = 50)"); 219962306a36Sopenharmony_cimodule_param(vsync2, int, 0); 220062306a36Sopenharmony_ciMODULE_PARM_DESC(vsync2, "Maximum vertical frequency of monitor in Hz" 220162306a36Sopenharmony_ci " (default = 60)"); 220262306a36Sopenharmony_cimodule_param(accel, bool, 0); 220362306a36Sopenharmony_ciMODULE_PARM_DESC(accel, "Use Acceleration (BLIT) engine (default = 0)"); 220462306a36Sopenharmony_cimodule_param(mtrr, bool, 0); 220562306a36Sopenharmony_ciMODULE_PARM_DESC(mtrr, "Use MTRR (default = 0)"); 220662306a36Sopenharmony_cimodule_param(extvga, bool, 0); 220762306a36Sopenharmony_ciMODULE_PARM_DESC(extvga, "Enable external VGA connector (default = 0)"); 220862306a36Sopenharmony_cimodule_param(sync, bool, 0); 220962306a36Sopenharmony_ciMODULE_PARM_DESC(sync, "wait for accel engine to finish drawing" 221062306a36Sopenharmony_ci " (default = 0)"); 221162306a36Sopenharmony_cimodule_param(dcolor, bool, 0); 221262306a36Sopenharmony_ciMODULE_PARM_DESC(dcolor, "use DirectColor visuals" 221362306a36Sopenharmony_ci " (default = 0 = TrueColor)"); 221462306a36Sopenharmony_cimodule_param(ddc3, bool, 0); 221562306a36Sopenharmony_ciMODULE_PARM_DESC(ddc3, "Probe DDC bus 3 (default = 0 = no)"); 221662306a36Sopenharmony_cimodule_param(mode_option, charp, 0); 221762306a36Sopenharmony_ciMODULE_PARM_DESC(mode_option, "Specify initial video mode"); 221862306a36Sopenharmony_ci 221962306a36Sopenharmony_ciMODULE_AUTHOR("Tony A. Daplas"); 222062306a36Sopenharmony_ciMODULE_DESCRIPTION("Framebuffer device for the Intel 810/815 and" 222162306a36Sopenharmony_ci " compatible cards"); 222262306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_cistatic void __exit i810fb_exit(void) 222562306a36Sopenharmony_ci{ 222662306a36Sopenharmony_ci pci_unregister_driver(&i810fb_driver); 222762306a36Sopenharmony_ci} 222862306a36Sopenharmony_cimodule_exit(i810fb_exit); 222962306a36Sopenharmony_ci 223062306a36Sopenharmony_ci#endif /* MODULE */ 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_cimodule_init(i810fb_init); 2233