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

📄 pvr2fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* drivers/video/pvr2fb.c * * Frame buffer and fbcon support for the NEC PowerVR2 found within the Sega * Dreamcast. * * Copyright (c) 2001 M. R. Brown <mrbrown@0xd6.org> * Copyright (c) 2001 Paul Mundt  <lethal@chaoticdreams.org> * * This file is part of the LinuxDC project (linuxdc.sourceforge.net). * *//* * This driver is mostly based on the excellent amifb and vfb sources.  It uses * an odd scheme for converting hardware values to/from framebuffer values, here are * some hacked-up formulas: * *  The Dreamcast has screen offsets from each side of it's four borders and the start *  offsets of the display window.  I used these values to calculate 'pseudo' values *  (think of them as placeholders) for the fb video mode, so that when it came time *  to convert these values back into their hardware values, I could just add mode- *  specific offsets to get the correct mode settings: * *      left_margin = diwstart_h - borderstart_h; *      right_margin = borderstop_h - (diwstart_h + xres); *      upper_margin = diwstart_v - borderstart_v; *      lower_margin = borderstop_v - (diwstart_h + yres); * *      hsync_len = borderstart_h + (hsync_total - borderstop_h); *      vsync_len = borderstart_v + (vsync_total - borderstop_v); * *  Then, when it's time to convert back to hardware settings, the only constants *  are the borderstart_* offsets, all other values are derived from the fb video *  mode: *   *      // PAL *      borderstart_h = 116; *      borderstart_v = 44; *      ... *      borderstop_h = borderstart_h + hsync_total - hsync_len; *      ... *      diwstart_v = borderstart_v - upper_margin; * *  However, in the current implementation, the borderstart values haven't had *  the benefit of being fully researched, so some modes may be broken. */#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/delay.h>#include <linux/config.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/console.h>#ifdef CONFIG_SH_DREAMCAST#include <asm/io.h>#include <asm/machvec.h>#include <asm/dc_sysasic.h>#endif#ifdef CONFIG_MTRR  #include <asm/mtrr.h>#endif#include <video/fbcon.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#ifdef CONFIG_FB_PVR2_DEBUG#  define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)#else#  define DPRINTK(fmt, args...)#endif/* 2D video registers */#define DISP_BASE 0xa05f8000#define DISP_BRDRCOLR (DISP_BASE + 0x40)#define DISP_DIWMODE (DISP_BASE + 0x44)#define DISP_DIWADDRL (DISP_BASE + 0x50)#define DISP_DIWADDRS (DISP_BASE + 0x54)#define DISP_DIWSIZE (DISP_BASE + 0x5c)#define DISP_SYNCCONF (DISP_BASE + 0xd0)#define DISP_BRDRHORZ (DISP_BASE + 0xd4)#define DISP_SYNCSIZE (DISP_BASE + 0xd8)#define DISP_BRDRVERT (DISP_BASE + 0xdc)#define DISP_DIWCONF (DISP_BASE + 0xe8)#define DISP_DIWHSTRT (DISP_BASE + 0xec)#define DISP_DIWVSTRT (DISP_BASE + 0xf0)/* Pixel clocks, one for TV output, doubled for VGA output */#define TV_CLK 74239#define VGA_CLK 37119/* This is for 60Hz - the VTOTAL is doubled for interlaced modes */#define PAL_HTOTAL 863#define PAL_VTOTAL 312#define NTSC_HTOTAL 857#define NTSC_VTOTAL 262enum { CT_VGA, CT_NONE, CT_RGB, CT_COMPOSITE };enum { VO_PAL, VO_NTSC, VO_VGA };struct pvr2_params { u_short val; char *name; };static struct pvr2_params cables[] __initdata = {	{ CT_VGA, "VGA" }, { CT_RGB, "RGB" }, { CT_COMPOSITE, "COMPOSITE" },};static struct pvr2_params outputs[] __initdata = {	{ VO_PAL, "PAL" }, { VO_NTSC, "NTSC" }, { VO_VGA, "VGA" },};/* * This describes the current video mode */static struct pvr2fb_par {	int xres;	int yres;	int vxres;	int vyres;	int xoffset;	int yoffset;	u_short bpp;	u_long pixclock;	u_short hsync_total;	/* Clocks/line */	u_short vsync_total;	/* Lines/field */	u_short borderstart_h;	u_short borderstop_h;	u_short borderstart_v;	u_short borderstop_v;	u_short diwstart_h;	/* Horizontal offset of the display field */	u_short diwstart_v;	/* Vertical offset of the display field, for				   interlaced modes, this is the long field */	u_long disp_start;	/* Address of image within VRAM */	u_long next_line;	/* Modulo for next line */	u_char is_interlaced;	/* Is the display interlaced? */	u_char is_doublescan;	/* Are scanlines output twice? (doublescan) */	u_char is_lowres;	/* Is horizontal pixel-doubling enabled? */	u_long bordercolor;	/* RGB888 format border color */	u_long vmode;	} currentpar;static int currcon = 0;static int currbpp;static struct display disp;static struct fb_info fb_info;static int pvr2fb_inverse = 0;static struct { u_short red, green, blue, alpha; } palette[256];static union {#ifdef FBCON_HAS_CFB16	u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB24	u32 cfb24[16];#endif#ifdef FBCON_HAS_CFB32	u32 cfb32[16];#endif} fbcon_cmap;static char pvr2fb_name[16] = "NEC PowerVR2";#define VIDEOMEMSIZE (8*1024*1024)static u_long videomemory = 0xa5000000, videomemorysize = VIDEOMEMSIZE;static int cable_type = -1;static int video_output = -1;#ifdef CONFIG_MTRRstatic int enable_mtrr = 1;static int mtrr_handle;#endif/* * We do all updating, blanking, etc. during the vertical retrace period */static u_short do_vmode_full = 0;	/* Change the video mode */static u_short do_vmode_pan = 0;	/* Update the video mode */static short do_blank = 0;		/* (Un)Blank the screen */static u_short is_blanked = 0;		/* Is the screen blanked? *//* Interface used by the world */int pvr2fb_setup(char*);static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,                            struct fb_info *info);static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,                            struct fb_info *info);static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,                            struct fb_info *info);static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con,                                struct fb_info *info);static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con,                             struct fb_info *info);static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con,                             struct fb_info *info);	/*	 * Interface to the low level console driver	 */static int pvr2fbcon_switch(int con, struct fb_info *info);static int pvr2fbcon_updatevar(int con, struct fb_info *info);static void pvr2fbcon_blank(int blank, struct fb_info *info);	/*	 * Internal/hardware-specific routines	 */static void do_install_cmap(int con, struct fb_info *info);static u_long get_line_length(int xres_virtual, int bpp);static void set_color_bitfields(struct fb_var_screeninfo *var);static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,                            u_int *transp, struct fb_info *info);static int pvr2_setcolreg(u_int regno, u_int red, u_int green, u_int blue,                            u_int transp, struct fb_info *info);static int pvr2_encode_fix(struct fb_fix_screeninfo *fix,                             struct pvr2fb_par *par);static int pvr2_decode_var(struct fb_var_screeninfo *var,                          struct pvr2fb_par *par);static int pvr2_encode_var(struct fb_var_screeninfo *var,                          struct pvr2fb_par *par);static void pvr2_get_par(struct pvr2fb_par *par);static void pvr2_set_var(struct fb_var_screeninfo *var);static void pvr2_pan_var(struct fb_var_screeninfo *var);static int pvr2_update_par(void);static void pvr2_update_display(void);static void pvr2_init_display(void);static void pvr2_do_blank(void);static void pvr2fb_interrupt(int irq, void *dev_id, struct pt_regs *fp);static int pvr2_init_cable(void);static int pvr2_get_param(const struct pvr2_params *p, const char *s,                            int val, int size);static struct fb_ops pvr2fb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	pvr2fb_get_fix,	fb_get_var:	pvr2fb_get_var,	fb_set_var:	pvr2fb_set_var,	fb_get_cmap:	pvr2fb_get_cmap,	fb_set_cmap:	pvr2fb_set_cmap,	fb_pan_display: pvr2fb_pan_display,};static struct fb_videomode pvr2_modedb[] __initdata = {    /*     * Broadcast video modes (PAL and NTSC).  I'm unfamiliar with     * PAL-M and PAL-N, but from what I've read both modes parallel PAL and     * NTSC, so it shouldn't be a problem (I hope).     */    {	/* 640x480 @ 60Hz interlaced (NTSC) */	"ntsc_640x480i", 60, 640, 480, TV_CLK, 38, 33, 0, 18, 146, 26,	FB_SYNC_BROADCAST, FB_VMODE_INTERLACED | FB_VMODE_YWRAP    },    {	/* 640x240 @ 60Hz (NTSC) */	/* XXX: Broken! Don't use... */	"ntsc_640x240", 60, 640, 240, TV_CLK, 38, 33, 0, 0, 146, 22,	FB_SYNC_BROADCAST, FB_VMODE_YWRAP    },    {	/* 640x480 @ 60hz (VGA) */	"vga_640x480", 60, 640, 480, VGA_CLK, 38, 33, 0, 18, 146, 26,	0, FB_VMODE_YWRAP    },};#define NUM_TOTAL_MODES  ARRAY_SIZE(pvr2_modedb)#define DEFMODE_NTSC	0#define DEFMODE_PAL	0#define DEFMODE_VGA	2static int defmode = DEFMODE_NTSC;static char *mode_option __initdata = NULL;/* Get the fixed part of the display */static int pvr2fb_get_fix(struct fb_fix_screeninfo *fix, int con,                            struct fb_info *info){	struct pvr2fb_par par;	if (con == -1)		pvr2_get_par(&par);	else {		int err;		if ((err = pvr2_decode_var(&fb_display[con].var, &par)))			return err;	}	return pvr2_encode_fix(fix, &par);}/* Get the user-defined part of the display */static int pvr2fb_get_var(struct fb_var_screeninfo *var, int con,                            struct fb_info *info){	int err = 0;	if (con == -1) {		struct pvr2fb_par par;		pvr2_get_par(&par);		err = pvr2_encode_var(var, &par);	} else		*var = fb_display[con].var;		return err;}/* Set the user-defined part of the display */static int pvr2fb_set_var(struct fb_var_screeninfo *var, int con,                            struct fb_info *info){	int err, activate = var->activate;	int oldxres, oldyres, oldvxres, oldvyres, oldbpp;	struct pvr2fb_par par;	struct display *display;	if (con >= 0)		display = &fb_display[con];	else		display = &disp;        /* used during initialization */	/*	 * FB_VMODE_CONUPDATE and FB_VMODE_SMOOTH_XPAN are equal!	 * as FB_VMODE_SMOOTH_XPAN is only used internally	 */	if (var->vmode & FB_VMODE_CONUPDATE) {		var->vmode |= FB_VMODE_YWRAP;		var->xoffset = display->var.xoffset;		var->yoffset = display->var.yoffset;	}	if ((err = pvr2_decode_var(var, &par)))		return err;	pvr2_encode_var(var, &par);	/* Do memory check and bitfield set here?? */	if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {		oldxres = display->var.xres;		oldyres = display->var.yres;		oldvxres = display->var.xres_virtual;		oldvyres = display->var.yres_virtual;		oldbpp = display->var.bits_per_pixel;		display->var = *var;		if (oldxres != var->xres || oldyres != var->yres ||		    oldvxres != var->xres_virtual || oldvyres != var->yres_virtual ||		    oldbpp != var->bits_per_pixel) {			struct fb_fix_screeninfo fix;			pvr2_encode_fix(&fix, &par);			display->screen_base = (char *)fix.smem_start;			display->scrollmode = SCROLL_YREDRAW;			display->visual = fix.visual;			display->type = fix.type;			display->type_aux = fix.type_aux;			display->ypanstep = fix.ypanstep;			display->ywrapstep = fix.ywrapstep;			display->line_length = fix.line_length;			display->can_soft_blank = 1;

⌨️ 快捷键说明

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