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

📄 sbusfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  linux/drivers/video/sbusfb.c -- SBUS or UPA based frame buffer device * *	Copyright (C) 1998 Jakub Jelinek * *  This driver is partly based on the Open Firmware console driver * *	Copyright (C) 1997 Geert Uytterhoeven * *  and SPARC console subsystem * *      Copyright (C) 1995 Peter Zaitcev (zaitcev@yahoo.com) *      Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu) *      Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx) *      Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) *      Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) *      Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * *  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/init.h>#include <linux/console.h>#include <linux/kd.h>#include <linux/vt_kern.h>#include <asm/uaccess.h>#include <asm/pgtable.h>	/* io_remap_page_range() */#include <video/sbusfb.h>#define DEFAULT_CURSOR_BLINK_RATE       (2*HZ/5)#define CURSOR_SHAPE			1#define CURSOR_BLINK			2    /*     *  Interface used by the world     */int sbusfb_init(void);int sbusfb_setup(char*);static int currcon;static int defx_margin = -1, defy_margin = -1;static char fontname[40] __initdata = { 0 };static int curblink __initdata = 1;static struct {	int depth;	int xres, yres;	int x_margin, y_margin;} def_margins [] = {	{ 8, 1280, 1024, 64, 80 },	{ 8, 1152, 1024, 64, 80 },	{ 8, 1152, 900,  64, 18 },	{ 8, 1024, 768,  0,  0 },	{ 8, 800, 600, 16, 12 },	{ 8, 640, 480, 0, 0 },	{ 1, 1152, 900,  8,  18 },	{ 0 },};static int sbusfb_open(struct fb_info *info, int user);static int sbusfb_release(struct fb_info *info, int user);static int sbusfb_mmap(struct fb_info *info, struct file *file, 			struct vm_area_struct *vma);static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,			struct fb_info *info);static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int sbusfb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);static int sbusfb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);static int sbusfb_ioctl(struct inode *inode, struct file *file, u_int cmd,			    u_long arg, int con, struct fb_info *info);static void sbusfb_cursor(struct display *p, int mode, int x, int y);static void sbusfb_clear_margin(struct display *p, int s);			        /*     *  Interface to the low level console driver     */static int sbusfbcon_switch(int con, struct fb_info *info);static int sbusfbcon_updatevar(int con, struct fb_info *info);static void sbusfbcon_blank(int blank, struct fb_info *info);    /*     *  Internal routines     */static int sbusfb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,			    u_int *transp, struct fb_info *info);static int sbusfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,			    u_int transp, struct fb_info *info);static void do_install_cmap(int con, struct fb_info *info);static struct fb_ops sbusfb_ops = {	owner:		THIS_MODULE,	fb_open:	sbusfb_open,	fb_release:	sbusfb_release,	fb_get_fix:	sbusfb_get_fix,	fb_get_var:	sbusfb_get_var,	fb_set_var:	sbusfb_set_var,	fb_get_cmap:	sbusfb_get_cmap,	fb_set_cmap:	sbusfb_set_cmap,	fb_ioctl:	sbusfb_ioctl,	fb_mmap:	sbusfb_mmap,};    /*     *  Open/Release the frame buffer device     */static int sbusfb_open(struct fb_info *info, int user){	struct fb_info_sbusfb *fb = sbusfbinfo(info);		if (user) {		if (fb->open == 0) {			fb->mmaped = 0;			fb->vtconsole = -1;		}		fb->open++;	} else		fb->consolecnt++;	return 0;}static int sbusfb_release(struct fb_info *info, int user){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	if (user) {			fb->open--;		if (fb->open == 0) {			if (fb->vtconsole != -1) {				vt_cons[fb->vtconsole]->vc_mode = KD_TEXT;				if (fb->mmaped) {					fb->graphmode--;					sbusfb_clear_margin(&fb_display[fb->vtconsole], 0);				}			}			if (fb->reset)				fb->reset(fb);		}	} else		fb->consolecnt--;	return 0;}static unsigned long sbusfb_mmapsize(struct fb_info_sbusfb *fb, long size){	if (size == SBUS_MMAP_EMPTY) return 0;	if (size >= 0) return size;	return fb->type.fb_size * (-size);}static int sbusfb_mmap(struct fb_info *info, struct file *file, 			struct vm_area_struct *vma){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	unsigned int size, page, r, map_size;	unsigned long map_offset = 0;	unsigned long off;	int i;                                        	size = vma->vm_end - vma->vm_start;	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))		return -EINVAL;	off = vma->vm_pgoff << PAGE_SHIFT;	/* To stop the swapper from even considering these pages */	vma->vm_flags |= (VM_SHM| VM_LOCKED);		/* Each page, see which map applies */	for (page = 0; page < size; ){		map_size = 0;		for (i = 0; fb->mmap_map[i].size; i++)			if (fb->mmap_map[i].voff == off+page) {				map_size = sbusfb_mmapsize(fb,fb->mmap_map[i].size);#ifdef __sparc_v9__#define POFF_MASK	(PAGE_MASK|0x1UL)#else#define POFF_MASK	(PAGE_MASK)#endif								map_offset = (fb->physbase + fb->mmap_map[i].poff) & POFF_MASK;				break;			}		if (!map_size){			page += PAGE_SIZE;			continue;		}		if (page + map_size > size)			map_size = size - page;		r = io_remap_page_range (vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->iospace);		if (r)			return -EAGAIN;		page += map_size;	}		vma->vm_flags |= VM_IO;	if (!fb->mmaped) {		int lastconsole = 0;				if (info->display_fg)			lastconsole = info->display_fg->vc_num;		fb->mmaped = 1;		if (fb->consolecnt && fb_display[lastconsole].fb_info == info) {			fb->vtconsole = lastconsole;			fb->graphmode++;			vt_cons [lastconsole]->vc_mode = KD_GRAPHICS;			vc_cons[lastconsole].d->vc_sw->con_cursor(vc_cons[lastconsole].d,CM_ERASE);		} else if (fb->unblank && !fb->blanked)			(*fb->unblank)(fb);	}	return 0;}static void sbusfb_clear_margin(struct display *p, int s){	struct fb_info_sbusfb *fb = sbusfbinfod(p);	if (fb->switch_from_graph)		(*fb->switch_from_graph)(fb);	if (fb->fill) {		unsigned short rects [16];		rects [0] = 0;		rects [1] = 0;		rects [2] = fb->var.xres_virtual;		rects [3] = fb->y_margin;		rects [4] = 0;		rects [5] = fb->y_margin;		rects [6] = fb->x_margin;		rects [7] = fb->var.yres_virtual;		rects [8] = fb->var.xres_virtual - fb->x_margin;		rects [9] = fb->y_margin;		rects [10] = fb->var.xres_virtual;		rects [11] = fb->var.yres_virtual;		rects [12] = fb->x_margin;		rects [13] = fb->var.yres_virtual - fb->y_margin;		rects [14] = fb->var.xres_virtual - fb->x_margin;		rects [15] = fb->var.yres_virtual;		(*fb->fill)(fb, p, s, 4, rects);	} else {		unsigned char *fb_base = p->screen_base, *q;		int skip_bytes = fb->y_margin * fb->var.xres_virtual;		int scr_size = fb->var.xres_virtual * fb->var.yres_virtual;		int h, he, incr, size;		he = fb->var.yres;		if (fb->var.bits_per_pixel == 1) {			fb_base -= (skip_bytes + fb->x_margin) / 8;			skip_bytes /= 8;			scr_size /= 8;			fb_memset255 (fb_base, skip_bytes - fb->x_margin / 8);			fb_memset255 (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8);			incr = fb->var.xres_virtual / 8;			size = fb->x_margin / 8 * 2;			for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0;			     h <= he; q += incr, h++)				fb_memset255 (q, size);		} else {			fb_base -= (skip_bytes + fb->x_margin);			memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin);			memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin);			incr = fb->var.xres_virtual;			size = fb->x_margin * 2;			for (q = fb_base + skip_bytes - fb->x_margin, h = 0;			     h <= he; q += incr, h++)				memset (q, attr_bgcol(p,s), size);		}	}}static void sbusfb_disp_setup(struct display *p){	struct fb_info_sbusfb *fb = sbusfbinfod(p);	if (fb->setup)		fb->setup(p);		sbusfb_clear_margin(p, 0);}    /*     *  Get the Fixed Part of the Display     */static int sbusfb_get_fix(struct fb_fix_screeninfo *fix, int con,			  struct fb_info *info){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo));	return 0;}    /*     *  Get the User Defined Part of the Display     */static int sbusfb_get_var(struct fb_var_screeninfo *var, int con,			  struct fb_info *info){	struct fb_info_sbusfb *fb = sbusfbinfo(info);	memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo));	return 0;}    /*     *  Set the User Defined Part of the Display     */static int sbusfb_set_var(struct fb_var_screeninfo *var, int con,			  struct fb_info *info){       struct display *display;       int activate = var->activate;       if(con >= 0)               display = &fb_display[con];       else               display = info->disp;       /* simple check for equality until fully implemented -E */       if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {               if (display->var.xres != var->xres ||                       display->var.yres != var->yres ||                       display->var.xres_virtual != var->xres_virtual ||                       display->var.yres_virtual != var->yres_virtual ||                       display->var.bits_per_pixel != var->bits_per_pixel ||                       display->var.accel_flags != var->accel_flags) {                       return -EINVAL;               }       }       return 0;}    /*     *  Hardware cursor     */     static int sbus_hw_scursor (struct fbcursor *cursor, struct fb_info_sbusfb *fb){	int op;	int i, bytes = 0;	struct fbcursor f;	char red[2], green[2], blue[2];		if (copy_from_user (&f, cursor, sizeof(struct fbcursor)))		return -EFAULT;	op = f.set;	if (op & FB_CUR_SETSHAPE){		if ((u32) f.size.fbx > fb->cursor.hwsize.fbx)			return -EINVAL;		if ((u32) f.size.fby > fb->cursor.hwsize.fby)			return -EINVAL;		if (f.size.fbx > 32)			bytes = f.size.fby << 3;		else			bytes = f.size.fby << 2;	}	if (op & FB_CUR_SETCMAP){		if (f.cmap.index || f.cmap.count != 2)			return -EINVAL;		if (copy_from_user (red, f.cmap.red, 2) ||		    copy_from_user (green, f.cmap.green, 2) ||		    copy_from_user (blue, f.cmap.blue, 2))			return -EFAULT;	}	if (op & FB_CUR_SETCMAP)		(*fb->setcursormap) (fb, red, green, blue);	if (op & FB_CUR_SETSHAPE){		u32 u;				fb->cursor.size = f.size;		memset ((void *)&fb->cursor.bits, 0, sizeof (fb->cursor.bits));		if (copy_from_user (fb->cursor.bits [0], f.mask, bytes) ||		    copy_from_user (fb->cursor.bits [1], f.image, bytes))			return -EFAULT;		if (f.size.fbx <= 32) {			u = 0xffffffff << (32 - f.size.fbx);

⌨️ 快捷键说明

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