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

📄 pm2fb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Permedia2 framebuffer driver. * Copyright (c) 1998-1999 Ilario Nardinocchi (nardinoc@CS.UniBO.IT) * Copyright (c) 1999 Jakub Jelinek (jakub@redhat.com) * Based on linux/drivers/video/skeletonfb.c by Geert Uytterhoeven. * -------------------------------------------------------------------------- * $Id: pm2fb.c,v 1.163 1999/02/21 14:06:49 illo Exp $ * -------------------------------------------------------------------------- * TODO multiple boards support * -------------------------------------------------------------------------- * This file is subject to the terms and conditions of the GNU General Public * License.  See the file COPYING in the main directory of this archive * for more details. */#include <linux/config.h>#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/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/selection.h>#include <linux/console.h>#include <linux/init.h>#include <linux/pci.h>#include <asm/system.h>#include <asm/io.h>#include <asm/uaccess.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb24.h>#include <video/fbcon-cfb32.h>#include "pm2fb.h"#include "cvisionppc.h"#ifdef __sparc__#include <asm/pbm.h>#include <asm/fbio.h>#endif#if !defined(__LITTLE_ENDIAN) && !defined(__BIG_ENDIAN)#error	"The endianness of the target host has not been defined."#endif#if defined(__BIG_ENDIAN) && !defined(__sparc__)#define PM2FB_BE_APERTURE#endif/* Need to debug this some more */#undef PM2FB_HW_CURSOR#if defined(CONFIG_FB_PM2_PCI) && !defined(CONFIG_PCI)#undef CONFIG_FB_PM2_PCI#warning "support for Permedia2 PCI boards with no generic PCI support!"#endif#undef PM2FB_MASTER_DEBUG#ifdef PM2FB_MASTER_DEBUG#define DPRINTK(a,b...)	printk(KERN_DEBUG "pm2fb: %s: " a, __FUNCTION__ , ## b)#else#define DPRINTK(a,b...)#endif #define PICOS2KHZ(a) (1000000000UL/(a))#define KHZ2PICOS(a) (1000000000UL/(a))/* * The _DEFINITIVE_ memory mapping/unmapping functions. * This is due to the fact that they're changing soooo often... */#define MMAP(a,b)	ioremap((unsigned long )(a), b)#define UNMAP(a,b)	iounmap(a)/* * The _DEFINITIVE_ memory i/o barrier functions. * This is due to the fact that they're changing soooo often... */#define DEFW()		wmb()#define DEFR()		rmb()#define DEFRW()		mb()#ifndef MIN#define MIN(a,b) ((a)<(b)?(a):(b))#endif#ifndef MAX#define MAX(a,b) ((a)>(b)?(a):(b))#endifstruct pm2fb_par {	u32 pixclock;		/* pixclock in KHz */	u32 width;		/* width of virtual screen */	u32 height;		/* height of virtual screen */	u32 hsstart;		/* horiz. sync start */	u32 hsend;		/* horiz. sync end */	u32 hbend;		/* horiz. blank end (also gate end) */	u32 htotal;		/* total width (w/ sync & blank) */	u32 vsstart;		/* vert. sync start */	u32 vsend;		/* vert. sync end */	u32 vbend;		/* vert. blank end */	u32 vtotal;		/* total height (w/ sync & blank) */	u32 stride;		/* screen stride */	u32 base;		/* screen base (xoffset+yoffset) */	u32 depth;		/* screen depth (8, 16, 24 or 32) */	u32 video;		/* video control (hsync,vsync) */};#define OPTF_OLD_MEM		(1L<<0)#define OPTF_YPAN		(1L<<1)#define OPTF_VIRTUAL		(1L<<2)#define OPTF_USER		(1L<<3)static struct {	char font[40];	u32 flags;	struct pm2fb_par user_mode;} pm2fb_options =#ifdef __sparc__	/* For some reason Raptor is not happy with the low-end mode */	{"\0", 0L, {31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}};#else	{"\0", 0L, {25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}};#endifstatic char curblink __initdata = 1;static struct {	char name[16];	struct pm2fb_par par;} user_mode[] __initdata = {	{"640x480-60",		{25174,640,480,4,28,40,199,9,11,45,524,80,0,8,121}},	{"640x480-72",		{31199,640,480,6,16,48,207,8,10,39,518,80,0,8,121}},	{"640x480-75",		{31499,640,480,4,20,50,209,0,3,20,499,80,0,8,121}},	{"640x480-90",		{39909,640,480,8,18,48,207,24,38,53,532,80,0,8,121}},	{"640x480-100",		{44899,640,480,8,40,52,211,21,33,51,530,80,0,8,121}},	{"800x600-56",		{35999,800,600,6,24,56,255,0,2,25,624,100,0,8,41}},	{"800x600-60",		{40000,800,600,10,42,64,263,0,4,28,627,100,0,8,41}},	{"800x600-70",		{44899,800,600,6,42,52,251,8,20,36,635,100,0,8,105}},	{"800x600-72",		{50000,800,600,14,44,60,259,36,42,66,665,100,0,8,41}},	{"800x600-75",		{49497,800,600,4,24,64,263,0,3,25,624,100,0,8,41}},	{"800x600-90",		{56637,800,600,2,18,48,247,7,18,35,634,100,0,8,41}},	{"800x600-100",		{67499,800,600,0,16,70,269,6,10,25,624,100,0,8,41}},	{"1024x768-60",		{64998,1024,768,6,40,80,335,2,8,38,805,128,0,8,121}},	{"1024x768-70",		{74996,1024,768,6,40,76,331,2,8,38,805,128,0,8,121}},	{"1024x768-72",		{74996,1024,768,6,40,66,321,2,8,38,805,128,0,8,121}},	{"1024x768-75",		{78932,1024,768,4,28,72,327,0,3,32,799,128,0,8,41}},	{"1024x768-90",		{100000,1024,768,0,24,72,327,20,35,77,844,128,0,8,121}},	{"1024x768-100",		{109998,1024,768,0,22,92,347,0,7,24,791,128,0,8,121}},	{"1024x768-illo",		{120322,1024,768,12,48,120,375,3,7,32,799,128,0,8,41}},	{"1152x864-60",		{80000,1152,864,16,44,76,363,5,10,52,915,144,0,8,41}},	{"1152x864-70",		{100000,1152,864,10,48,90,377,12,23,81,944,144,0,8,41}},	{"1152x864-75",		{109998,1152,864,6,42,78,365,44,52,138,1001,144,0,8,41}},	{"1152x864-80",		{109998,1152,864,4,32,72,359,29,36,94,957,144,0,8,41}},	{"1280x1024-60",		{107991,1280,1024,12,40,102,421,0,3,42,1065,160,0,8,41}},	{"1280x1024-70",		{125992,1280,1024,20,48,102,421,0,5,42,1065,160,0,8,41}},	{"1280x1024-74",		{134989,1280,1024,8,44,108,427,0,29,40,1063,160,0,8,41}},	{"1280x1024-75",		{134989,1280,1024,4,40,102,421,0,3,42,1065,160,0,8,41}},	{"1600x1200-60",		{155981,1600,1200,8,48,112,511,9,17,70,1269,200,0,8,121}},	{"1600x1200-66",		{171998,1600,1200,10,44,120,519,2,5,53,1252,200,0,8,121}},	{"1600x1200-76",		{197980,1600,1200,10,44,120,519,2,7,50,1249,200,0,8,121}},	{"\0", },};#ifdef CONFIG_FB_PM2_PCIstruct pm2pci_par {	u32 mem_config;	u32 mem_control;	u32 boot_address;	struct pci_dev* dev;};#endif#define DEFAULT_CURSOR_BLINK_RATE       (20)#define CURSOR_DRAW_DELAY               (2)struct pm2_cursor {    int	enable;    int on;    int vbl_cnt;    int blink_rate;    struct {        u16 x, y;    } pos, hot, size;    u8 color[6];    u8 bits[8][64];    u8 mask[8][64];    struct timer_list *timer;};static const char permedia2_name[16]="Permedia2";static struct pm2fb_info {	struct fb_info_gen gen;	int board;			/* Permedia2 board index (see					   board_table[] below) */	pm2type_t type;	struct {		unsigned long  fb_base;	/* physical framebuffer memory base */		u32 fb_size;		/* framebuffer memory size */		unsigned long  rg_base;	/* physical register memory base */		unsigned long  p_fb;	/* physical address of frame buffer */		unsigned char* v_fb;	/* virtual address of frame buffer */		unsigned long  p_regs;	/* physical address of registers					   region, must be rg_base or					   rg_base+PM2_REGS_SIZE depending on					   the host endianness */		unsigned char* v_regs;	/* virtual address of p_regs */	} regions;	union {				/* here, the per-board par structs */#ifdef CONFIG_FB_PM2_CVPPC		struct cvppc_par cvppc;	/* CVisionPPC data */#endif#ifdef CONFIG_FB_PM2_PCI		struct pm2pci_par pci;	/* Permedia2 PCI boards data */#endif	} board_par;	struct pm2fb_par current_par;	/* displayed screen */	int current_par_valid;	u32 memclock;			/* memclock (set by the per-board					   		init routine) */	struct display disp;	struct {		u8 transp;		u8 red;		u8 green;		u8 blue;	} palette[256];	union {#ifdef FBCON_HAS_CFB16		u16 cmap16[16];#endif#ifdef FBCON_HAS_CFB24		u32 cmap24[16];#endif#ifdef FBCON_HAS_CFB32		u32 cmap32[16];#endif	} cmap;	struct pm2_cursor *cursor;} fb_info;#ifdef CONFIG_FB_PM2_CVPPCstatic int cvppc_detect(struct pm2fb_info*);static void cvppc_init(struct pm2fb_info*);#endif#ifdef CONFIG_FB_PM2_PCIstatic int pm2pci_detect(struct pm2fb_info*);static void pm2pci_init(struct pm2fb_info*);#endif#ifdef PM2FB_HW_CURSORstatic void pm2fb_cursor(struct display *p, int mode, int x, int y);static int pm2fb_set_font(struct display *d, int width, int height);static struct pm2_cursor *pm2_init_cursor(struct pm2fb_info *fb);static void pm2v_set_cursor_color(struct pm2fb_info *fb, u8 *red, u8 *green, u8 *blue);static void pm2v_set_cursor_shape(struct pm2fb_info *fb);static u8 cursor_color_map[2] = { 0, 0xff };#else#define pm2fb_cursor NULL#define pm2fb_set_font NULL#endif/* * Table of the supported Permedia2 based boards. * Three hooks are defined for each board: * detect(): should return 1 if the related board has been detected, 0 *           otherwise. It should also fill the fields 'regions.fb_base', *           'regions.fb_size', 'regions.rg_base' and 'memclock' in the *           passed pm2fb_info structure. * init(): called immediately after the reset of the Permedia2 chip. *         It should reset the memory controller if needed (the MClk *         is set shortly afterwards by the caller). * cleanup(): called after the driver has been unregistered. * * the init and cleanup pointers can be NULL. */static const struct {	int (*detect)(struct pm2fb_info*);	void (*init)(struct pm2fb_info*);	void (*cleanup)(struct pm2fb_info*);	char name[32];} board_table[] = {#ifdef CONFIG_FB_PM2_PCI	{ pm2pci_detect, pm2pci_init, NULL, "Permedia2 PCI board" },#endif#ifdef CONFIG_FB_PM2_CVPPC	{ cvppc_detect, cvppc_init, NULL, "CVisionPPC/BVisionPPC" },#endif	{ NULL, }};/* * partial products for the supported horizontal resolutions. */#define PACKPP(p0,p1,p2)	(((p2)<<6)|((p1)<<3)|(p0))static const struct {	u16 width;	u16 pp;} pp_table[] = {	{ 32,	PACKPP(1, 0, 0) }, { 64,	PACKPP(1, 1, 0) },	{ 96,	PACKPP(1, 1, 1) }, { 128,	PACKPP(2, 1, 1) },	{ 160,	PACKPP(2, 2, 1) }, { 192,	PACKPP(2, 2, 2) },	{ 224,	PACKPP(3, 2, 1) }, { 256,	PACKPP(3, 2, 2) },	{ 288,	PACKPP(3, 3, 1) }, { 320,	PACKPP(3, 3, 2) },	{ 384,	PACKPP(3, 3, 3) }, { 416,	PACKPP(4, 3, 1) },	{ 448,	PACKPP(4, 3, 2) }, { 512,	PACKPP(4, 3, 3) },	{ 544,	PACKPP(4, 4, 1) }, { 576,	PACKPP(4, 4, 2) },	{ 640,	PACKPP(4, 4, 3) }, { 768,	PACKPP(4, 4, 4) },	{ 800,	PACKPP(5, 4, 1) }, { 832,	PACKPP(5, 4, 2) },	{ 896,	PACKPP(5, 4, 3) }, { 1024,	PACKPP(5, 4, 4) },	{ 1056,	PACKPP(5, 5, 1) }, { 1088,	PACKPP(5, 5, 2) },	{ 1152,	PACKPP(5, 5, 3) }, { 1280,	PACKPP(5, 5, 4) },	{ 1536,	PACKPP(5, 5, 5) }, { 1568,	PACKPP(6, 5, 1) },	{ 1600,	PACKPP(6, 5, 2) }, { 1664,	PACKPP(6, 5, 3) },	{ 1792,	PACKPP(6, 5, 4) }, { 2048,	PACKPP(6, 5, 5) },	{ 0,	0 } };static void pm2fb_detect(void);static int pm2fb_encode_fix(struct fb_fix_screeninfo* fix,				const void* par, struct fb_info_gen* info);static int pm2fb_decode_var(const struct fb_var_screeninfo* var,					void* par, struct fb_info_gen* info);static int pm2fb_encode_var(struct fb_var_screeninfo* var,				const void* par, struct fb_info_gen* info);static void pm2fb_get_par(void* par, struct fb_info_gen* info);static void pm2fb_set_par(const void* par, struct fb_info_gen* info);static int pm2fb_getcolreg(unsigned regno,			unsigned* red, unsigned* green, unsigned* blue,				unsigned* transp, struct fb_info* info);static int pm2fb_setcolreg(unsigned regno,			unsigned red, unsigned green, unsigned blue,				unsigned transp, struct fb_info* info);static int pm2fb_blank(int blank_mode, struct fb_info_gen* info);static int pm2fb_pan_display(const struct fb_var_screeninfo* var,					struct fb_info_gen* info);static void pm2fb_set_disp(const void* par, struct display* disp,						struct fb_info_gen* info);static struct fbgen_hwswitch pm2fb_hwswitch={	pm2fb_detect, pm2fb_encode_fix, pm2fb_decode_var,	pm2fb_encode_var, pm2fb_get_par, pm2fb_set_par,	pm2fb_getcolreg, pm2fb_setcolreg, pm2fb_pan_display,	pm2fb_blank, pm2fb_set_disp};static struct fb_ops pm2fb_ops={	owner:		THIS_MODULE,	fb_get_fix:	fbgen_get_fix,	fb_get_var:	fbgen_get_var,	fb_set_var:	fbgen_set_var,	fb_get_cmap:	fbgen_get_cmap,	fb_set_cmap:	fbgen_set_cmap,	fb_pan_display:	fbgen_pan_display,};/*************************************************************************** * Begin of Permedia2 specific functions ***************************************************************************/inline static u32 RD32(unsigned char* base, s32 off) {	return readl(base+off);}inline static void WR32(unsigned char* base, s32 off, u32 v) {	writel(v, base+off);}inline static u32 pm2_RD(struct pm2fb_info* p, s32 off) {	return RD32(p->regions.v_regs, off);}inline static void pm2_WR(struct pm2fb_info* p, s32 off, u32 v) {	WR32(p->regions.v_regs, off, v);}inline static u32 pm2_RDAC_RD(struct pm2fb_info* p, s32 idx) {	int index = PM2R_RD_INDEXED_DATA;	switch (p->type) {	case PM2_TYPE_PERMEDIA2:		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);		break;	case PM2_TYPE_PERMEDIA2V:		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);		index = PM2VR_RD_INDEXED_DATA;		break;	}		DEFRW();	return pm2_RD(p, index);}inline static void pm2_RDAC_WR(struct pm2fb_info* p, s32 idx,						u32 v) {	int index = PM2R_RD_INDEXED_DATA;	switch (p->type) {	case PM2_TYPE_PERMEDIA2:		pm2_WR(p, PM2R_RD_PALETTE_WRITE_ADDRESS, idx);		break;	case PM2_TYPE_PERMEDIA2V:		pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);		index = PM2VR_RD_INDEXED_DATA;		break;	}		DEFRW();	pm2_WR(p, index, v);}inline static u32 pm2v_RDAC_RD(struct pm2fb_info* p, s32 idx) {	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);	DEFRW();	return pm2_RD(p, PM2VR_RD_INDEXED_DATA);}inline static void pm2v_RDAC_WR(struct pm2fb_info* p, s32 idx,						u32 v) {	pm2_WR(p, PM2VR_RD_INDEX_LOW, idx & 0xff);	DEFRW();	pm2_WR(p, PM2VR_RD_INDEXED_DATA, v);}#ifdef CONFIG_FB_PM2_FIFO_DISCONNECT#define WAIT_FIFO(p,a)#elseinline static void WAIT_FIFO(struct pm2fb_info* p, u32 a) {	while(pm2_RD(p, PM2R_IN_FIFO_SPACE)<a);	DEFRW();}#endifstatic u32 partprod(u32 xres) {	int i;	for (i=0; pp_table[i].width && pp_table[i].width!=xres; i++);	if (!pp_table[i].width)		DPRINTK("invalid width %u\n", xres);	return pp_table[i].pp;}static u32 to3264(u32 timing, int bpp, int is64) {	switch (bpp) {		case 8:			timing=timing>>(2+is64);			break;		case 16:			timing=timing>>(1+is64);			break;		case 24:			timing=(timing*3)>>(2+is64);			break;		case 32:			if (is64)				timing=timing>>1;			break;	}	return timing;}static u32 from3264(u32 timing, int bpp, int is64) {	switch (bpp) {		case 8:			timing=timing<<(2+is64);			break;		case 16:			timing=timing<<(1+is64);			break;		case 24:			timing=(timing<<(2+is64))/3;			break;		case 32:			if (is64)				timing=timing<<1;			break;	}	return timing;}static void pm2_mnp(u32 clk, unsigned char* mm, unsigned char* nn,		unsigned char* pp) {	unsigned char m;	unsigned char n;	unsigned char p;	u32 f;	s32 curr;	s32 delta=100000;	*mm=*nn=*pp=0;	for (n=2; n<15; n++) {		for (m=2; m; m++) {			f=PM2_REFERENCE_CLOCK*m/n;			if (f>=150000 && f<=300000) {				for (p=0; p<5; p++, f>>=1) {					curr=clk>f?clk-f:f-clk;					if (curr<delta) {						delta=curr;						*mm=m;						*nn=n;						*pp=p;					}

⌨️ 快捷键说明

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