⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sstfb.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * linux/drivers/video/sstfb.c -- voodoo graphics frame buffer * *     Copyright (c) 2000,2001 Ghozlane Toumi <gtoumi@messel.emse.fr> * *     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       <urs.ganse@t-online.de> *     (initial work on voodoo2 port) * * * $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. -ASK: ioremap ou ioremap_nocache ? : nocache is safe-TODO: in  set_var check the validity of timings (hsync vsync)...-FIXME: I'm not sure i like all the functions with no parameters.. change them         to use a sstfb_par or sstfb_info or something like that.-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        enabled-ASK: the 24 bits mode is NOT packed . how do i differenciate from a packed mode ?      set a pseudo alpha value not used ?-ASK: how does the 32 bpp work ? should i enable the pipeline so alpha values       are used ?-TODO: check how the voodoo graphics can cope with 24/32 bpp (engine is 16bpp        only)-ASK: Do i ioremap the complete area devoted to the lfb (4Mb), or check the       real size, then unmap and remap to the real size of the lfb ?       ... map all the area.-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...Notes-TODO: change struct sst_info fb_info from static to array/dynamic  TTT comments is for code i've put there for debuging the "weird peinguin   	syndrome", it should disapear soon * *//* * 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 <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(void); *//* sst default init registers */#define FBIINIT0_DEFAULT EN_VGA_PASSTHROUGH#define FBIINIT1_DEFAULT 	\	(			\	  FAST_PCI_WRITES	\/*	  SLOW_PCI_WRITES*/	\	| VIDEO_RESET		\	| 10 << TILES_IN_X_SHIFT\	| SEL_SOURCE_VCLK_2X_SEL\	| EN_LFB_READ		\	)#define FBIINIT2_DEFAULT	\	(			\	 SWAP_DACVSYNC		\	| EN_DRAM_OE		\	| DRAM_REFRESH_16	\	| EN_DRAM_REFRESH	\	| EN_FAST_RAS_READ	\	| EN_RD_AHEAD_FIFO	\	| EN_FAST_RD_AHEAD_WR	\	)#define FBIINIT3_DEFAULT 	\	( DISABLE_TEXTURE )#define FBIINIT4_DEFAULT	\	(			\	  FAST_PCI_READS	\/*	  SLOW_PCI_READS*/	\	| LFB_READ_AHEAD	\	)/* Careful with this one : writing back the data just read will trash the DAC   reading some fields give logic value on pins, but setting this field will   set the source signal driving the pin. conclusion : just use the default   as a base before writing back .*/#define FBIINIT6_DEFAULT	(0x0)/********/int currcon; /* =0 */int num_sst; /* =0*/		/* number of initialized boards *//* 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 = -1;		/* specify device (0..n) */static char * mode_option ;#if defined(FBCON_HAS_CFB16) || defined(FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)union {#  ifdef FBCON_HAS_CFB16	u16 cfb16[16];#  endif#ifdef EN_24_32_BPP#  if defined (FBCON_HAS_CFB24) || defined(FBCON_HAS_CFB32)	u32 cfb32[16];#  endif#endif	} fbcon_cmap;#endifstatic struct { u_int red, green, blue, transp; } palette[16];static struct sstfb_info fb_info;static struct display disp;/********//* Interface to ze oueurld  */int sstfb_init(void);int sstfb_setup(char *options);/* 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(u_long *memsize);static int sst_wait_idle(void);static int sst_detect_dactype(void);static int sst_detect_att(void);static int sst_detect_ti(void);static int sst_detect_ics(void);static int sst_calc_pll(const int freq, int *freq_out, struct pll_timing *t);static int sst_set_pll_att_ti(const struct pll_timing *t, const int clock);static int sst_set_pll_ics(const struct pll_timing *t, const int clock);static void sst_set_vidmod_att_ti(const int bpp);static void sst_set_vidmod_ics(const int bpp);static int sst_init(void);#ifdef MODULEstatic void sst_shutdown(void);#endifstatic 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,};#ifndef DEFAULT_MODE#  define DEFAULT_MODE 0#endifstatic 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[] = {	{	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 },};static struct sst_spec voodoo1_spec = {	name : "Voodoo Graphics",	default_gfx_clock : 50000,	max_gfxclk : 60,};static struct sst_spec voodoo2_spec = {	name : "Voodoo2",	default_gfx_clock : 75000,	max_gfxclk : 85,};/* * *  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) */static void sst_dbg_print_read_reg (u32 reg, u32 val) {#if (SST_DEBUG_REG > 0) /* i need the init registers :) */	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 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);#endif /*  (SST_DEBUG_REG > 0) */}static void sst_dbg_print_write_reg (u32 reg, u32 val) {#if (SST_DEBUG_REG > 0) /* i need the init registers :) */	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 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);#endif /*  (SST_DEBUG_REG > 0) */}/* register access */static inline u32 sst_read(u32 reg){	u32 ret;	ret = readl(fb_info.mmio.vbase + reg);	sst_dbg_print_read_reg(reg, ret);	return ret;}static inline void sst_write(u32 reg, u32 val){	sst_dbg_print_write_reg(reg, val);	writel(val, fb_info.mmio.vbase + reg);}static inline void sst_set_bits(u32 reg, u32 val){	r_dprintk("sst_set_bits(%#x, %#x)\n", reg, val);	sst_write(reg, sst_read(reg) | val);}static inline void sst_unset_bits(u32 reg, u32 val){	r_dprintk("sst_unset_bits(%#x, %#x)\n", reg, val);	sst_write(reg, sst_read(reg) & ~val);}/* dac access *//* dac_read should be remaped to FbiInit2 (via the pci reg init_enable) */static u8 sst_dac_read(u8 reg){	u8 ret;#ifdef SST_DEBUG	if ((reg & 0x07) != reg) {		dprintk("bug line %d: register adress '%d' is to high\n",		         __LINE__,reg);	}#endif	reg &= 0x07;	sst_write(DAC_DATA, ((u32)reg << 8) | DAC_READ_CMD );	sst_wait_idle();	/*udelay(10);*/	ret=(sst_read(DAC_READ) & 0xff);	r_dprintk("sst_dac_read(%#x): %#x\n", reg, ret);	return (u8)ret;}static void sst_dac_write(u8 reg, u8 val){	r_dprintk("sst_dac_write(%#x, %#x)\n", reg, val);#ifdef SST_DEBUG	if ((reg & 0x07) != reg)		dprintk("bug line %d: register adress '%d' is to high\n",		         __LINE__,reg);#endif	reg &= 0x07;	sst_write(DAC_DATA,(((u32)reg << 8)) | (u32)val);}/* indexed access to ti/att dacs */static inline u32 dac_i_read(u8 reg){	u32 ret;	sst_dac_write(DACREG_ADDR_I, reg);	ret = sst_dac_read(DACREG_DATA_I);	r_dprintk("sst_dac_read_i(%#x): %#x\n", reg, ret);	return ret;}static inline void dac_i_write(u8 reg,u8 val){	r_dprintk("sst_dac_write_i(%#x, %#x)\n", reg, val);	sst_dac_write(DACREG_ADDR_I, reg);	sst_dac_write(DACREG_DATA_I, val);}/* * *  Internal routines * */static void sstfb_install_cmap(int con, struct fb_info *info){	f_dprintk("sstfb_install_cmap(con: %d)\n",con);	f_ddprintk("currcon: %d\n", currcon);	if (con != currcon)		return;	if (fb_display[con].cmap.len)		fb_set_cmap(&fb_display[con].cmap, 1, sstfb_setcolreg, info);	else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -