?? sstfb.c
字號:
/* * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer * * Copyright (c) 2000-2002 Ghozlane Toumi <gtoumi@laposte.net> * * Created 15 Jan 2000 by Ghozlane Toumi * * Contributions (and many thanks) : * * 03/2001 James Simmons <jsimmons@linux-fbdev.org> * 04/2001 Paul Mundt <lethal@chaoticdreams.org> * 05/2001 Urs Ganse <ursg@uni.de> * (initial work on voodoo2 port, interlace) * * * $Id: sstfb.c,v 1.26.4.1 2001/08/29 01:30:37 ghoz Exp $ *//* * The voodoo1 has the following memory mapped adress space: * 0x000000 - 0x3fffff : registers (4Mb) * 0x400000 - 0x7fffff : linear frame buffer (4Mb) * 0x800000 - 0xffffff : texture memory (8Mb) *//* * misc notes, TODOs, toASKs, and deep thoughts-TODO: at one time or another test that the mode is acceptable by the monitor-ASK: I can choose different ordering for the color bitfields (rgba argb ...) wich one should i use ? is there any preferred one ? It seems ARGB is the one ...-ASK: later: how to cope with endianness ? the fbi chip has builtin functions to do byte swizling /swapping, maybe use that ...-TODO: check the error paths . if something get wrong, the error doesn't seem to be very well handled...if handled at all.. not good.-TODO: in set_var check the validity of timings (hsync vsync)...-TODO: check and recheck the use of sst_wait_idle : we dont flush the fifo via a nop command . so it's ok as long as the commands we pass don't go through the fifo. warning: issuing a nop command seems to need pci_fifo-FIXME: in case of failure in the init sequence, be sure we return to a safe state.-FIXME: 4MB boards have banked memory (FbiInit2 bits 1 & 20)-ASK: I stole "inverse" but seems it doesn't work... check what it realy does...-TODO: change struct sst_info fb_info from static to array/dynamic * *//* * debug info * SST_DEBUG : enable debugging * SST_DEBUG_REG : debug registers * 0 : no debug * 1 : dac calls, [un]set_bits, FbiInit * 2 : insane debug level (log every register read/write) * SST_DEBUG_FUNC : functions * 0 : no debug * 1 : function call / debug ioctl * 2 : variables * 3 : flood . you don't want to do that. trust me. * SST_DEBUG_VAR : debug display/var structs * 0 : no debug * 1 : dumps display, fb_var * SST_DEBUG_IOCTL : enable sstfb specific ioctls * 0 : disable * 1 : enable debug ioctls : * toggle vga (0x46db) : toggle vga_pass_through * fill fb (0x46dc) : fills fb * dump var (0x46dd) : logs display[0-5].var * test disp (0x46de) : draws a test motif *//* #define SST_DEBUG */#undef SST_DEBUG#define SST_DEBUG_REG 0#define SST_DEBUG_FUNC 0#define SST_DEBUG_VAR 0#define SST_DEBUG_IOCTL 1/* #define EN_24_32_BPP *//* enable 24/32 bpp functions for testing only */#undef EN_24_32_BPP/* Default video mode . 0 800x600@60 took from glide 1 640x480@75 took from glide 2 1024x768@76 std fb.mode 3 640x480@60 glide default */#define DEFAULT_MODE 1/* * Includes */#include <linux/string.h>#include <linux/config.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/tty.h>#include <linux/fb.h>#include <linux/pci.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/version.h>#include <linux/slab.h>#include <asm/io.h>#include <asm/ioctl.h>#include <video/fbcon.h>#include <video/fbcon-cfb16.h>#ifdef EN_24_32_BPP# include <video/fbcon-cfb24.h># include <video/fbcon-cfb32.h>#endif#include "sstfb.h"/* void __Dump_regs(struct sstfb_info *);#define Dump_regs __Dump_regs(sst_info) *//********//* initialized by setup */static int inverse; /* =0 */ /* invert colormap */static int vgapass; /* =0 */ /* enable Vga passthrough cable */static int mem; /* =0 */ /* mem size in Mb , 0 = autodetect */static int clipping = 1; /* use clipping (slower, safer) */static int gfxclk; /* =0 */ /* force FBI freq in Mhz . Dangerous */static int slowpci; /* =0 */ /* slow PCI settings */static int dev = -2; /* specify device (0..n) -2=all -1=none*/static char * mode_option ;/********/int sstfb_init(void);int sstfb_setup(char *options);static int __devinit sstfb_probe(struct pci_dev *pdev, const struct pci_device_id *id);static void __devexit sstfb_remove(struct pci_dev *pdev);/* Framebuffer API */static int sstfb_open(struct fb_info *info, int user);static int sstfb_release(struct fb_info *info, int user);static int sstfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int sstfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sstfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sstfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int sstfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int sstfb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sstfb_ioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg, int con, struct fb_info *info);/* Interface to the low level console driver */static int sstfbcon_switch(int con, struct fb_info *info);static int sstfbcon_updatevar(int con, struct fb_info *info);static void sstfbcon_blank(int blank, struct fb_info *info);/* Internal routines */static void sstfb_install_cmap(int con, struct fb_info *info);static int sstfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info);static int sstfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info);static int sstfb_set_par(const struct sstfb_par *par, struct sstfb_info *sst_info);static int sstfb_decode_var (const struct fb_var_screeninfo *var, struct sstfb_par *par, const struct sstfb_info *sst_info);static int sstfb_encode_var (struct fb_var_screeninfo *var, const struct sstfb_par *par, const struct sstfb_info *sst_info);static void sstfb_test16(struct sstfb_info *sst_info);#ifdef EN_24_32_BPPstatic void sstfb_test32(struct sstfb_info *sst_info);#endif/* Low level routines */static int sst_get_memsize(struct sstfb_info *sst_info, u_long *memsize);static int __sst_wait_idle(u_long vbase);#define sst_wait_idle() __sst_wait_idle(sst_info->mmio.vbase)static int sst_detect_dactype(struct sstfb_info *sst_info);static int sst_detect_att(struct sstfb_info *sst_info);static int sst_detect_ti(struct sstfb_info *sst_info);static int sst_detect_ics(struct sstfb_info *sst_info);static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t);static int sst_set_pll_att_ti(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);static int sst_set_pll_ics(struct sstfb_info *sst_info, const struct pll_timing *t, const int clock);static void sst_set_vidmod_att_ti(struct sstfb_info *sst_info, const int bpp);static void sst_set_vidmod_ics(struct sstfb_info *sst_info, const int bpp);static int sst_init(struct sstfb_info *sst_info);static void sst_shutdown(struct sstfb_info *sst_info);static struct fb_ops sstfb_ops = { owner : THIS_MODULE, fb_open: sstfb_open, fb_release: sstfb_release, fb_get_fix: sstfb_get_fix, fb_get_var: sstfb_get_var, fb_set_var: sstfb_set_var, fb_get_cmap: sstfb_get_cmap, fb_set_cmap: sstfb_set_cmap, fb_pan_display: sstfb_pan_display, fb_ioctl: sstfb_ioctl,};enum { ID_VOODOO1 = 0, ID_VOODOO2 = 1,};#define IS_VOODOO2(info) ((info)->type == ID_VOODOO2 )static struct sst_spec voodoo_spec[] __devinitdata = { { name : "Voodoo Graphics", default_gfx_clock : 50000, max_gfxclk : 60, }, { name : "Voodoo2", default_gfx_clock : 75000, max_gfxclk : 85, },};static struct pci_device_id sstfb_id_tbl[] __devinitdata = { { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO1 }, { PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ID_VOODOO2 }, { 0 },};static struct pci_driver sstfb_driver = { name: "sstfb", id_table: sstfb_id_tbl, probe: sstfb_probe, remove: __devexit_p(sstfb_remove),};static struct fb_var_screeninfo sstfb_default =#if ( DEFAULT_MODE == 0 ) { /* 800x600@60, 16 bpp .borowed from glide/sst1/include/sst1init.h */ 800, 600, 800, 600, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 25000, 86, 41, 23, 1, 127, 4, 0, FB_VMODE_NONINTERLACED };#endif#if ( DEFAULT_MODE == 1 ) {/* 640x480@75, 16 bpp .borowed from glide/sst1/include/sst1init.h */ 640, 480, 640, 480, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 31746, 118, 17, 16, 1, 63, 3, 0, FB_VMODE_NONINTERLACED };#endif#if ( DEFAULT_MODE == 2 ) { /* 1024x768@76 took from my /etc/fb.modes */ 1024, 768, 1024, 768,0, 0, 16,0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 11764, 208, 8, 36, 16, 120, 3 , 0, FB_VMODE_NONINTERLACED };#endif#if ( DEFAULT_MODE == 3 ) { /* 640x480@60 , 16bpp glide default ?*/ 640, 480, 640, 480, 0, 0, 16, 0, {11, 5, 0}, {5, 6, 0}, {0, 5, 0}, {0, 0, 0}, 0, 0, -1, -1, 0, 39721 , 38, 26 , 25 ,18 , 96 ,2, 0, FB_VMODE_NONINTERLACED };#endifstatic struct dac_switch dacs[] __devinitdata = { { name: "TI TVP3409", detect: sst_detect_ti, set_pll: sst_set_pll_att_ti, set_vidmod: sst_set_vidmod_att_ti }, { name: "AT&T ATT20C409", detect: sst_detect_att, set_pll: sst_set_pll_att_ti, set_vidmod: sst_set_vidmod_att_ti }, { name: "ICS ICS5342", detect: sst_detect_ics, set_pll: sst_set_pll_ics, set_vidmod: sst_set_vidmod_ics },};/* * * Definitions * */#if (SST_DEBUG_VAR > 0)/* debug info / dump a fb_var_screeninfo */static void sst_dbg_print_var(struct fb_var_screeninfo *var) { dprintk(" {%d, %d, %d, %d, %d, %d, %d, %d,\n", var->xres, var->yres, var->xres_virtual, var->yres_virtual, var->xoffset, var->yoffset, var->bits_per_pixel, var->grayscale); dprintk(" {%d, %d, %d}, {%d, %d, %d}, {%d, %d, %d}, {%d, %d, %d},\n", var->red.offset, var->red.length, var->red.msb_right, var->green.offset, var->green.length, var->green.msb_right, var->blue.offset, var->blue.length, var->blue.msb_right, var->transp.offset, var->transp.length, var->transp.msb_right); dprintk(" %d, %d, %d, %d, %d,\n", var->nonstd, var->activate, var->height, var->width, var->accel_flags); dprintk(" %d, %d, %d, %d, %d, %d, %d,\n", var->pixclock, var->left_margin, var->right_margin, var->upper_margin, var->lower_margin, var->hsync_len, var->vsync_len); dprintk(" %#x, %#x}\n",var->sync, var->vmode);}#endif /* (SST_DEBUG_VAR > 0) */#if (SST_DEBUG_REG > 0)static void sst_dbg_print_read_reg (u32 reg, u32 val) { char * regname =NULL; switch (reg) { case FBIINIT0: regname="FbiInit0"; break; case FBIINIT1: regname="FbiInit1"; break; case FBIINIT2: regname="FbiInit2"; break; case FBIINIT3: regname="FbiInit3"; break; case FBIINIT4: regname="FbiInit4"; break; case FBIINIT5: regname="FbiInit5"; break; case FBIINIT6: regname="FbiInit6"; break; } if (regname == NULL) r_ddprintk("sst_read(%#x): %#x\n", reg, val); else r_dprintk(" sst_read(%s): %#x\n", regname, val);}static void sst_dbg_print_write_reg (u32 reg, u32 val) { char * regname = NULL; switch (reg) { case FBIINIT0: regname="FbiInit0"; break; case FBIINIT1: regname="FbiInit1"; break; case FBIINIT2: regname="FbiInit2"; break; case FBIINIT3: regname="FbiInit3"; break; case FBIINIT4: regname="FbiInit4"; break; case FBIINIT5: regname="FbiInit5"; break; case FBIINIT6: regname="FbiInit6"; break; } if (regname == NULL) r_ddprintk("sst_write(%#x, %#x)\n", reg, val); else r_dprintk(" sst_write(%s, %#x)\n", regname, val);}#else /* (SST_DEBUG_REG > 0) */# define sst_dbg_print_read_reg(reg, val) do {}while(0)# define sst_dbg_print_write_reg(reg, val) do {}while(0)#endif /* (SST_DEBUG_REG > 0) *//* register access */#define sst_read(reg) __sst_read(sst_info->mmio.vbase, reg)#define sst_write(reg,val) __sst_write(sst_info->mmio.vbase, reg, val)#define sst_set_bits(reg,val) __sst_set_bits(sst_info->mmio.vbase, reg, val)#define sst_unset_bits(reg,val) __sst_unset_bits(sst_info->mmio.vbase, reg, val)#define sst_dac_read(reg) __sst_dac_read(sst_info->mmio.vbase, reg)#define sst_dac_write(reg,val) __sst_dac_write(sst_info->mmio.vbase, reg, val)#define dac_i_read(reg) __dac_i_read(sst_info->mmio.vbase, reg)#define dac_i_write(reg,val) __dac_i_write(sst_info->mmio.vbase, reg, val)static inline u32 __sst_read(u_long vbase, u32 reg){ u32 ret; ret = readl(vbase + reg); sst_dbg_print_read_reg(reg, ret); return ret;}static inline void __sst_write(u_long vbase, u32 reg, u32 val){ sst_dbg_print_write_reg(reg, val); writel(val, vbase + reg);}static inline void __sst_set_bits(u_long vbase, u32 reg, u32 val){ r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val); __sst_write(vbase, reg, __sst_read(vbase, reg) | val);}static inline void __sst_unset_bits(u_long vbase, u32 reg, u32 val){ r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val); __sst_write(vbase, reg, __sst_read(vbase, reg) & ~val);}/* dac access *//* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */static u8 __sst_dac_read(u_long vbase, u8 reg){ u8 ret;#ifdef SST_DEBUG if ((reg & 0x07) != reg) { dprintk("bug line %d: register adress '%d' is too high\n", __LINE__,reg); }#endif reg &= 0x07; __sst_write(vbase, DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD ); __sst_wait_idle(vbase); /*udelay(10);*/ ret=(__sst_read(vbase, DAC_READ) & 0xff); r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret); return (u8)ret;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -