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

📄 offb.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  linux/drivers/video/offb.c -- Open Firmware based frame buffer device * *	Copyright (C) 1997 Geert Uytterhoeven * *  This driver is partly based on the PowerMac console driver: * *	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/ioport.h>#ifdef CONFIG_FB_COMPAT_XPMAC#include <asm/vc_ioctl.h>#endif#include <asm/io.h>#include <asm/prom.h>#ifdef CONFIG_BOOTX_TEXT#include <asm/bootx.h>#endif#include <video/fbcon.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>#include <video/fbcon-cfb32.h>#include <video/macmodes.h>static int currcon = 0;/* Supported palette hacks */enum {	cmap_unknown,	cmap_m64,	/* ATI Mach64 */	cmap_r128,	/* ATI Rage128 */	cmap_M3A,	/* ATI Rage Mobility M3 Head A */	cmap_M3B,	/* ATI Rage Mobility M3 Head B */	cmap_radeon,	/* ATI Radeon */	cmap_gxt2000	/* IBM GXT2000 */};struct fb_info_offb {    struct fb_info info;    struct fb_fix_screeninfo fix;    struct fb_var_screeninfo var;    struct display disp;    struct { u_char red, green, blue, pad; } palette[256];    volatile unsigned char *cmap_adr;    volatile unsigned char *cmap_data;    int cmap_type;    int blanked;    union {#ifdef FBCON_HAS_CFB16	u16 cfb16[16];#endif#ifdef FBCON_HAS_CFB32	u32 cfb32[16];#endif    } fbcon_cmap;};#ifdef __powerpc__#define mach_eieio()	eieio()#else#define mach_eieio()	do {} while (0)#endif    /*     *  Interface used by the world     */int offb_init(void);static int offb_get_fix(struct fb_fix_screeninfo *fix, int con,			struct fb_info *info);static int offb_get_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int offb_set_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info);static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			struct fb_info *info);#ifdef CONFIG_BOOTX_TEXTextern boot_infos_t *boot_infos;#endifstatic void offb_init_nodriver(struct device_node *);static void offb_init_fb(const char *name, const char *full_name, int width,		      int height, int depth, int pitch, unsigned long address,		      struct device_node *dp);    /*     *  Interface to the low level console driver     */static int offbcon_switch(int con, struct fb_info *info);static int offbcon_updatevar(int con, struct fb_info *info);static void offbcon_blank(int blank, struct fb_info *info);    /*     *  Internal routines     */static int offb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue,			 u_int *transp, struct fb_info *info);static int offb_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 offb_ops = {	owner:		THIS_MODULE,	fb_get_fix:	offb_get_fix,	fb_get_var:	offb_get_var,	fb_set_var:	offb_set_var,	fb_get_cmap:	offb_get_cmap,	fb_set_cmap:	offb_set_cmap,};    /*     *  Get the Fixed Part of the Display     */static int offb_get_fix(struct fb_fix_screeninfo *fix, int con,			struct fb_info *info){    struct fb_info_offb *info2 = (struct fb_info_offb *)info;    memcpy(fix, &info2->fix, sizeof(struct fb_fix_screeninfo));    return 0;}    /*     *  Get the User Defined Part of the Display     */static int offb_get_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info){    struct fb_info_offb *info2 = (struct fb_info_offb *)info;    memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo));    return 0;}    /*     *  Set the User Defined Part of the Display     */static int offb_set_var(struct fb_var_screeninfo *var, int con,			struct fb_info *info){    struct display *display;    unsigned int oldbpp = 0;    int err;    int activate = var->activate;    struct fb_info_offb *info2 = (struct fb_info_offb *)info;    if (con >= 0)	display = &fb_display[con];    else	display = &info2->disp;	/* used during initialization */    if (var->xres > info2->var.xres || var->yres > info2->var.yres ||	var->xres_virtual > info2->var.xres_virtual ||	var->yres_virtual > info2->var.yres_virtual ||	var->bits_per_pixel > info2->var.bits_per_pixel ||	var->nonstd ||	(var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED)	return -EINVAL;    memcpy(var, &info2->var, sizeof(struct fb_var_screeninfo));    if ((activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {	oldbpp = display->var.bits_per_pixel;	display->var = *var;    }    if ((oldbpp != var->bits_per_pixel) || (display->cmap.len == 0)) {	if ((err = fb_alloc_cmap(&display->cmap, 0, 0)))	    return err;	do_install_cmap(con, info);    }    return 0;}    /*     *  Get the Colormap     */static int offb_get_cmap(struct fb_cmap *cmap, int kspc, int con,			 struct fb_info *info){    struct fb_info_offb *info2 = (struct fb_info_offb *)info;    if (con == currcon && !info2->blanked) /* current console? */	return fb_get_cmap(cmap, kspc, offb_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;}    /*     *  Set the Colormap     */static int offb_set_cmap(struct fb_cmap *cmap, int kspc, int con,			 struct fb_info *info){    struct fb_info_offb *info2 = (struct fb_info_offb *)info;    int err;    if (!info2->cmap_adr)	return -ENOSYS;    if (!fb_display[con].cmap.len) {	/* no colormap allocated? */	int size = fb_display[con].var.bits_per_pixel == 16 ? 32 : 256;	if ((err = fb_alloc_cmap(&fb_display[con].cmap, size, 0)))	    return err;    }    if (con == currcon && !info2->blanked)		/* current console? */	return fb_set_cmap(cmap, kspc, offb_setcolreg, info);    else	fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1);    return 0;}    /*     *  Initialisation     */int __init offb_init(void){    struct device_node *dp;    unsigned int dpy;#ifdef CONFIG_BOOTX_TEXT    struct device_node *displays = find_type_devices("display");    struct device_node *macos_display = NULL;    /* If we're booted from BootX... */    if (prom_num_displays == 0 && boot_infos != 0) {	unsigned long addr = (unsigned long) boot_infos->dispDeviceBase;	/* find the device node corresponding to the macos display */	for (dp = displays; dp != NULL; dp = dp->next) {	    int i;	    /*	     * Grrr...  It looks like the MacOS ATI driver	     * munges the assigned-addresses property (but	     * the AAPL,address value is OK).	     */	    if (strncmp(dp->name, "ATY,", 4) == 0 && dp->n_addrs == 1) {		unsigned int *ap = (unsigned int *)		    get_property(dp, "AAPL,address", NULL);		if (ap != NULL) {		    dp->addrs[0].address = *ap;		    dp->addrs[0].size = 0x01000000;		}	    }	    /*	     * The LTPro on the Lombard powerbook has no addresses	     * on the display nodes, they are on their parent.	     */	    if (dp->n_addrs == 0 && device_is_compatible(dp, "ATY,264LTPro")) {		int na;		unsigned int *ap = (unsigned int *)		    get_property(dp, "AAPL,address", &na);		if (ap != 0)		    for (na /= sizeof(unsigned int); na > 0; --na, ++ap)			if (*ap <= addr && addr < *ap + 0x1000000)			    goto foundit;	    }	    /*	     * See if the display address is in one of the address	     * ranges for this display.	     */	    for (i = 0; i < dp->n_addrs; ++i) {		if (dp->addrs[i].address <= addr		    && addr < dp->addrs[i].address + dp->addrs[i].size)		    break;	    }	    if (i < dp->n_addrs) {	    foundit:		printk(KERN_INFO "MacOS display is %s\n", dp->full_name);		macos_display = dp;		break;	    }	}	/* initialize it */	offb_init_fb(macos_display? macos_display->name: "MacOS display",		     macos_display? macos_display->full_name: "MacOS display",		     boot_infos->dispDeviceRect[2],		     boot_infos->dispDeviceRect[3],		     boot_infos->dispDeviceDepth,		     boot_infos->dispDeviceRowBytes, addr, NULL);    }#endif    for (dpy = 0; dpy < prom_num_displays; dpy++) {	if ((dp = find_path_device(prom_display_paths[dpy])))	    offb_init_nodriver(dp);    }    return 0;}static void __init offb_init_nodriver(struct device_node *dp){    int *pp, i;    unsigned int len;    int width = 640, height = 480, depth = 8, pitch;    unsigned *up, address;    if ((pp = (int *)get_property(dp, "depth", &len)) != NULL	&& len == sizeof(int))	depth = *pp;    if ((pp = (int *)get_property(dp, "width", &len)) != NULL	&& len == sizeof(int))	width = *pp;    if ((pp = (int *)get_property(dp, "height", &len)) != NULL	&& len == sizeof(int))	height = *pp;    if ((pp = (int *)get_property(dp, "linebytes", &len)) != NULL	&& len == sizeof(int)) {	pitch = *pp;	if (pitch == 1)	    pitch = 0x1000;    } else	pitch = width;    if ((up = (unsigned *)get_property(dp, "address", &len)) != NULL	&& len == sizeof(unsigned))	address = (u_long)*up;    else {	for (i = 0; i < dp->n_addrs; ++i)	    if (dp->addrs[i].size >= pitch*height*depth/8)		break;	if (i >= dp->n_addrs) {	    printk(KERN_ERR "no framebuffer address found for %s\n", dp->full_name);	    return;	}	address = (u_long)dp->addrs[i].address;	/* kludge for valkyrie */	if (strcmp(dp->name, "valkyrie") == 0) 	    address += 0x1000;    }    offb_init_fb(dp->name, dp->full_name, width, height, depth,		 pitch, address, dp);    }static void __init offb_init_fb(const char *name, const char *full_name,				    int width, int height, int depth,				    int pitch, unsigned long address,				    struct device_node *dp){    int i;    struct fb_fix_screeninfo *fix;    struct fb_var_screeninfo *var;    struct display *disp;    struct fb_info_offb *info;    unsigned long res_start = address;    unsigned long res_size = pitch*height*depth/8;    if (!request_mem_region(res_start, res_size, "offb"))	return;    printk(KERN_INFO "Using unsupported %dx%d %s at %lx, depth=%d, pitch=%d\n",	   width, height, name, address, depth, pitch);    if (depth != 8 && depth != 16 && depth != 32) {	printk(KERN_ERR "%s: can't use depth = %d\n", full_name, depth);	release_mem_region(res_start, res_size);	return;    }    info = kmalloc(sizeof(struct fb_info_offb), GFP_ATOMIC);    if (info == 0) {	release_mem_region(res_start, res_size);	return;    }    memset(info, 0, sizeof(*info));    fix = &info->fix;    var = &info->var;    disp = &info->disp;    strcpy(fix->id, "OFfb ");    strncat(fix->id, name, sizeof(fix->id));    fix->id[sizeof(fix->id)-1] = '\0';

⌨️ 快捷键说明

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