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

📄 controlfb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  controlfb.c -- frame buffer device for the PowerMac 'control' display * *  Created 12 July 1998 by Dan Jacobowitz <dan@debian.org> *  Copyright (C) 1998 Dan Jacobowitz *  Copyright (C) 2001 Takashi Oe * *  Mmap code by Michel Lanners <mlan@cpu.lu> * *  Frame buffer structure from: *    drivers/video/chipsfb.c -- frame buffer device for *    Chips & Technologies 65550 chip. * *    Copyright (C) 1998 Paul Mackerras * *    This file is derived from the Powermac "chips" driver: *    Copyright (C) 1997 Fabio Riccardi. *    And from the frame buffer device for Open Firmware-initialized devices: *    Copyright (C) 1997 Geert Uytterhoeven. * *  Hardware information from: *    control.c: Console support for PowerMac "control" display adaptor. *    Copyright (C) 1996 Paul Mackerras * *  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/pci.h>#include <linux/nvram.h>#ifdef CONFIG_FB_COMPAT_XPMAC#include <asm/vc_ioctl.h>#endif#include <linux/adb.h>#include <linux/cuda.h>#include <asm/io.h>#include <asm/prom.h>#include <asm/pgtable.h>#include <asm/btext.h>#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb32.h>#include <video/macmodes.h>#include "controlfb.h"struct fb_par_control {	int	vmode, cmode;	int	xres, yres;	int	vxres, vyres;	int	xoffset, yoffset;	int	pitch;	struct control_regvals	regvals;	unsigned long sync;	unsigned char ctrl;};#define DIRTY(z) ((x)->z != (y)->z)#define DIRTY_CMAP(z) (memcmp(&((x)->z), &((y)->z), sizeof((y)->z)))static inline int PAR_EQUAL(struct fb_par_control *x, struct fb_par_control *y){	int i, results;	results = 1;	for (i = 0; i < 3; i++)		results &= !DIRTY(regvals.clock_params[i]);	if (!results)		return 0;	for (i = 0; i < 16; i++)		results &= !DIRTY(regvals.regs[i]);	if (!results)		return 0;	return (!DIRTY(cmode) && !DIRTY(xres) && !DIRTY(yres)		&& !DIRTY(vxres) && !DIRTY(vyres));}static inline int VAR_MATCH(struct fb_var_screeninfo *x, struct fb_var_screeninfo *y){	return (!DIRTY(bits_per_pixel) && !DIRTY(xres)		&& !DIRTY(yres) && !DIRTY(xres_virtual)		&& !DIRTY(yres_virtual)		&& !DIRTY_CMAP(red) && !DIRTY_CMAP(green) && !DIRTY_CMAP(blue));}struct fb_info_control {	struct fb_info			info;	struct display			display;	struct fb_par_control		par;	struct {		__u8 red, green, blue;	}			palette[256];		struct cmap_regs	*cmap_regs;	unsigned long		cmap_regs_phys;		struct control_regs	*control_regs;	unsigned long		control_regs_phys;	unsigned long		control_regs_size;		__u8			*frame_buffer;	unsigned long		frame_buffer_phys;	unsigned long		fb_orig_base;	unsigned long		fb_orig_size;	int			control_use_bank2;	unsigned long		total_vram;	unsigned char		vram_attr;	union {#ifdef FBCON_HAS_CFB16		u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB32		u32 cfb32[16];#endif	} fbcon_cmap;};/* control register access macro */#define CNTRL_REG(INFO,REG) (&(((INFO)->control_regs->REG).r))/******************** Prototypes for exported functions ********************//* * struct fb_ops */static int control_get_fix(struct fb_fix_screeninfo *fix, int con,	struct fb_info *info);static int control_get_var(struct fb_var_screeninfo *var, int con,	struct fb_info *info);static int control_set_var(struct fb_var_screeninfo *var, int con,	struct fb_info *info);static int control_pan_display(struct fb_var_screeninfo *var, int con,	struct fb_info *info);static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con,	struct fb_info *info);static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,	struct fb_info *info);static int control_mmap(struct fb_info *info, struct file *file,	struct vm_area_struct *vma);/* * low level fbcon ops */static int controlfb_switch(int con, struct fb_info *info);static int controlfb_updatevar(int con, struct fb_info *info);static void controlfb_blank(int blank_mode, struct fb_info *info);/* * low level cmap set/get ops */static int controlfb_getcolreg(u_int regno, u_int *red, u_int *green,	u_int *blue, u_int *transp, struct fb_info *info);static int controlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,	u_int transp, struct fb_info *info);/* * inititialization */int control_init(void);void control_setup(char *);/* * low level fbcon revc ops */static void control_cfb16_revc(struct display *p, int xx, int yy);static void control_cfb32_revc(struct display *p, int xx, int yy);/******************** Prototypes for internal functions **********************/static void do_install_cmap(struct display *disp, struct fb_info *info);static void set_control_clock(unsigned char *params);static int init_control(struct fb_info_control *p);static void control_set_hardware(struct fb_info_control *p,	struct fb_par_control *par);static int control_of_init(struct device_node *dp);static void control_par_to_fix(struct fb_par_control *par,	struct fb_fix_screeninfo *fix, struct fb_info_control *p);static void control_set_dispsw(struct display *disp, int cmode,	struct fb_info_control *p);static void find_vram_size(struct fb_info_control *p);static int read_control_sense(struct fb_info_control *p);static int calc_clock_params(unsigned long clk, unsigned char *param);static int control_var_to_par(struct fb_var_screeninfo *var,	struct fb_par_control *par, const struct fb_info *fb_info);static inline void control_par_to_var(struct fb_par_control *par,	struct fb_var_screeninfo *var);static void control_par_to_fix(struct fb_par_control *par,	struct fb_fix_screeninfo *fix, struct fb_info_control *p);static void control_par_to_display(struct fb_par_control *par,	struct display *disp, struct fb_fix_screeninfo *fix,	struct fb_info_control *p);static void control_set_dispsw(struct display *disp, int cmode,	struct fb_info_control *p);static void control_init_info(struct fb_info *info, struct fb_info_control *p);static void control_cleanup(void);/************************** Internal variables *******************************/static int currcon;static struct fb_info_control *control_fb;static char fontname[40] __initdata = { 0 };static int default_vmode __initdata = VMODE_NVRAM;static int default_cmode __initdata = CMODE_NVRAM;static struct fb_ops controlfb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	control_get_fix,	fb_get_var:	control_get_var,	fb_set_var:	control_set_var,	fb_get_cmap:	control_get_cmap,	fb_set_cmap:	control_set_cmap,	fb_pan_display:	control_pan_display,	fb_mmap:	control_mmap,};/********************  The functions for controlfb_ops ********************/#ifdef MODULEMODULE_LICENSE("GPL");int init_module(void){	struct device_node *dp;	dp = find_devices("control");	if (dp != 0 && !control_of_init(dp))		return 0;	return -ENXIO;}void cleanup_module(void){	control_cleanup();}#endif/*********** Providing our information to the user ************/static int control_get_fix(struct fb_fix_screeninfo *fix, int con,			 struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	if(con == -1) {		control_par_to_fix(&p->par, fix, p);	} else {		struct fb_par_control par;				control_var_to_par(&fb_display[con].var, &par, info);		control_par_to_fix(&par, fix, p);	}	return 0;}static int control_get_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	if(con == -1) {		control_par_to_var(&p->par, var);	} else {		*var = fb_display[con].var;	}	return 0;}/* * Sets everything according to var */static int control_set_var(struct fb_var_screeninfo *var, int con,			 struct fb_info *info){	struct fb_info_control *p = (struct fb_info_control *) info;	struct display *disp;	struct fb_par_control par;	int depthchange, err;	int activate = var->activate;	if((err = control_var_to_par(var, &par, info))) {		if (con < 0)			printk (KERN_ERR "control_set_var: error calling"					 " control_var_to_par: %d.\n", err);		return err;	}		control_par_to_var(&par, var);		if ((activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW)		return 0;	disp = (con >= 0) ? &fb_display[con] : info->disp;	depthchange = (disp->var.bits_per_pixel != var->bits_per_pixel);	if(!VAR_MATCH(&disp->var, var)) {		struct fb_fix_screeninfo	fix;		control_par_to_fix(&par, &fix, p);		control_par_to_display(&par, disp, &fix, p);		if(info->changevar)			(*info->changevar)(con);	} else		disp->var = *var;	if(con == currcon) {		control_set_hardware(p, &par);		if(depthchange) {			if((err = fb_alloc_cmap(&disp->cmap, 0, 0)))				return err;			do_install_cmap(disp, info);		}	}	return 0;}/* * Set screen start address according to var offset values */static inline void set_screen_start(int xoffset, int yoffset,	struct fb_info_control *p){	struct fb_par_control *par = &p->par;	par->xoffset = xoffset;	par->yoffset = yoffset;	out_le32(CNTRL_REG(p,start_addr),		 par->yoffset * par->pitch + (par->xoffset << par->cmode));}static int control_pan_display(struct fb_var_screeninfo *var, int con,			     struct fb_info *info){	unsigned int xoffset, hstep;	struct fb_info_control *p = (struct fb_info_control *)info;	struct fb_par_control *par = &p->par;	/*	 * make sure start addr will be 32-byte aligned	 */	hstep = 0x1f >> par->cmode;	xoffset = (var->xoffset + hstep) & ~hstep;	if (xoffset+par->xres > par->vxres ||	    var->yoffset+par->yres > par->vyres)		return -EINVAL;	set_screen_start(xoffset, var->yoffset, p);	return 0;}static int control_get_cmap(struct fb_cmap *cmap, int kspc, int con,			  struct fb_info *info){	if (con == currcon)		/* current console? */		return fb_get_cmap(cmap, kspc, controlfb_getcolreg, info);	if (fb_display[con].cmap.len)	/* non default colormap? */		fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0: 2);	else {		int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;		fb_copy_cmap(fb_default_cmap(size), cmap, kspc ? 0 : 2);	}	return 0;}static int control_set_cmap(struct fb_cmap *cmap, int kspc, int con,			 struct fb_info *info){	struct display *disp = (con < 0)? info->disp: &fb_display[con];	int err, size = disp->var.bits_per_pixel == 16 ? 32 : 256;	if (disp->cmap.len != size) {		err = fb_alloc_cmap(&disp->cmap, size, 0);		if (err)			return err;	}	if (con == currcon)		return fb_set_cmap(cmap, kspc, controlfb_setcolreg, info);	fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1);	return 0;}/* * Private mmap since we want to have a different caching on the framebuffer * for controlfb. * Note there's no locking in here; it's done in fb_mmap() in fbmem.c. */static int control_mmap(struct fb_info *info, struct file *file,                       struct vm_area_struct *vma){       struct fb_ops *fb = info->fbops;       struct fb_fix_screeninfo fix;       struct fb_var_screeninfo var;       unsigned long off, start;       u32 len;       fb->fb_get_fix(&fix, PROC_CONSOLE(info), info);       off = vma->vm_pgoff << PAGE_SHIFT;       /* frame buffer memory */       start = fix.smem_start;       len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.smem_len);       if (off >= len) {               /* memory mapped io */               off -= len;               fb->fb_get_var(&var, PROC_CONSOLE(info), info);               if (var.accel_flags)                       return -EINVAL;               start = fix.mmio_start;               len = PAGE_ALIGN((start & ~PAGE_MASK)+fix.mmio_len);               pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE|_PAGE_GUARDED;       } else {               /* framebuffer */               pgprot_val(vma->vm_page_prot) |= _PAGE_WRITETHRU;       }       start &= PAGE_MASK;       if ((vma->vm_end - vma->vm_start + off) > len)       		return -EINVAL;       off += start;       vma->vm_pgoff = off >> PAGE_SHIFT;       if (io_remap_page_range(vma->vm_start, off,           vma->vm_end - vma->vm_start, vma->vm_page_prot))               return -EAGAIN;       return 0;}/********************  End of controlfb_ops implementation  ******************//* * low level fbcon ops */static int controlfb_switch(int con, struct fb_info *info){	struct fb_info_control	*p = (struct fb_info_control *)info;	struct fb_par_control	par;	if (currcon >= 0 && fb_display[currcon].cmap.len)		fb_get_cmap(&fb_display[currcon].cmap, 1, controlfb_getcolreg,			    info);	currcon = con;	fb_display[con].var.activate = FB_ACTIVATE_NOW;	control_var_to_par(&fb_display[con].var, &par, info);	control_set_hardware(p, &par);	control_set_dispsw(&fb_display[con], par.cmode, p);	do_install_cmap(&fb_display[con], info);	return 1;}static int controlfb_updatevar(int con, struct fb_info *info){	struct fb_var_screeninfo *var = &fb_display[con].var;	struct fb_info_control *p = (struct fb_info_control *) info;	set_screen_start(var->xoffset, var->yoffset, p);	return 0;

⌨️ 快捷键说明

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