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

📄 fbcon.c

📁 S3C44B0X下的LCD (framebuffer)驱动资料与相关代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}    } else if (w <= 24) {	for (i = 0; i < op->charcount; i++) {	    int j;	    for (j = 0; j < h; j++) {	        memcpy(p, data, 3);		p[3] = 0;		data += 3;		p += sizeof(u32);	    }	    data += 3*(32 - h);	}    } else {	h *= 4;	for (i = 0; i < op->charcount; i++) {	    memcpy(p, data, h);	    data += 128;	    p += h;	}    }#endif    /* we can do it in u32 chunks because of charcount is 256 or 512, so       font length must be multiple of 256, at least. And 256 is multiple       of 4 */    k = 0;    while (p > new_data) k += *--(u32 *)p;    FNTSUM(new_data) = k;    /* Check if the same font is on some other console already */    for (i = 0; i < MAX_NR_CONSOLES; i++) {    	if (fb_display[i].userfont &&    	    fb_display[i].fontdata &&    	    FNTSUM(fb_display[i].fontdata) == k &&    	    FNTSIZE(fb_display[i].fontdata) == size &&    	    fontwidth(&fb_display[i]) == w &&	    !memcmp(fb_display[i].fontdata, new_data, size)) {	    kfree(new_data - FONT_EXTRA_WORDS*sizeof(int));	    new_data = fb_display[i].fontdata;	    break;    	}    }    return fbcon_do_set_font(unit, op, new_data, 1);}static inline int fbcon_set_def_font(int unit, struct console_font_op *op){    char name[MAX_FONT_NAME];    struct fbcon_font_desc *f;    struct display *p = &fb_display[unit];    if (!op->data)	f = fbcon_get_default_font(p->var.xres, p->var.yres);    else if (strncpy_from_user(name, op->data, MAX_FONT_NAME-1) < 0)	return -EFAULT;    else {	name[MAX_FONT_NAME-1] = 0;	if (!(f = fbcon_find_font(name)))	    return -ENOENT;    }    op->width = f->width;    op->height = f->height;    return fbcon_do_set_font(unit, op, f->data, 0);}static int fbcon_font_op(struct vc_data *conp, struct console_font_op *op){    int unit = conp->vc_num;    switch (op->op) {	case KD_FONT_OP_SET:	    return fbcon_set_font(unit, op);	case KD_FONT_OP_GET:	    return fbcon_get_font(unit, op);	case KD_FONT_OP_SET_DEFAULT:	    return fbcon_set_def_font(unit, op);	case KD_FONT_OP_COPY:	    return fbcon_copy_font(unit, op);	default:	    return -ENOSYS;    }}static u16 palette_red[16];static u16 palette_green[16];static u16 palette_blue[16];static struct fb_cmap palette_cmap  = {    0, 16, palette_red, palette_green, palette_blue, NULL};static int fbcon_set_palette(struct vc_data *conp, unsigned char *table){    int unit = conp->vc_num;    struct display *p = &fb_display[unit];    int i, j, k;    u8 val;    if (!conp->vc_can_do_color || (!p->can_soft_blank && console_blanked))	return -EINVAL;    for (i = j = 0; i < 16; i++) {	k = table[i];	val = conp->vc_palette[j++];	palette_red[k] = (val<<8)|val;	val = conp->vc_palette[j++];	palette_green[k] = (val<<8)|val;	val = conp->vc_palette[j++];	palette_blue[k] = (val<<8)|val;    }    if (p->var.bits_per_pixel <= 4)	palette_cmap.len = 1<<p->var.bits_per_pixel;    else	palette_cmap.len = 16;    palette_cmap.start = 0;    return p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, unit, p->fb_info);}static u16 *fbcon_screen_pos(struct vc_data *conp, int offset){    int line;    unsigned long p;    if (conp->vc_num != fg_console || !softback_lines)    	return (u16 *)(conp->vc_origin + offset);    line = offset / conp->vc_size_row;    if (line >= softback_lines)    	return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);    p = softback_curr + offset;    if (p >= softback_end)    	p += softback_buf - softback_end;    return (u16 *)p;}static unsigned long fbcon_getxy(struct vc_data *conp, unsigned long pos, int *px, int *py){    int x, y;    unsigned long ret;    if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {    	unsigned long offset = (pos - conp->vc_origin) / 2;    	    	x = offset % conp->vc_cols;    	y = offset / conp->vc_cols;    	if (conp->vc_num == fg_console)    	    y += softback_lines;    	ret = pos + (conp->vc_cols - x) * 2;    } else if (conp->vc_num == fg_console && softback_lines) {    	unsigned long offset = pos - softback_curr;    	    	if (pos < softback_curr)    	    offset += softback_end - softback_buf;    	offset /= 2;    	x = offset % conp->vc_cols;    	y = offset / conp->vc_cols;	ret = pos + (conp->vc_cols - x) * 2;	if (ret == softback_end)	    ret = softback_buf;	if (ret == softback_in)	    ret = conp->vc_origin;    } else {    	/* Should not happen */    	x = y = 0;    	ret = conp->vc_origin;    }    if (px) *px = x;    if (py) *py = y;    return ret;}/* As we might be inside of softback, we may work with non-contiguous buffer,   that's why we have to use a separate routine. */static void fbcon_invert_region(struct vc_data *conp, u16 *p, int cnt){    while (cnt--) {	u16 a = scr_readw(p);	if (!conp->vc_can_do_color)	    a ^= 0x0800;	else if (conp->vc_hi_font_mask == 0x100)	    a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);	else	    a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);	scr_writew(a, p++);	if (p == (u16 *)softback_end)	    p = (u16 *)softback_buf;	if (p == (u16 *)softback_in)	    p = (u16 *)conp->vc_origin;    }}static int fbcon_scrolldelta(struct vc_data *conp, int lines){    int unit, offset, limit, scrollback_old;    struct display *p;        unit = fg_console;    p = &fb_display[unit];    if (softback_top) {    	if (conp->vc_num != unit)    	    return 0;    	if (vt_cons[unit]->vc_mode != KD_TEXT || !lines)    	    return 0;    	if (logo_shown >= 0) {		struct vc_data *conp2 = vc_cons[logo_shown].d;    			if (conp2->vc_top == logo_lines && conp2->vc_bottom == conp2->vc_rows)    		    conp2->vc_top = 0;    		if (logo_shown == unit) {    		    unsigned long p, q;    		    int i;    		        		    p = softback_in;    		    q = conp->vc_origin + logo_lines * conp->vc_size_row;    		    for (i = 0; i < logo_lines; i++) {    		    	if (p == softback_top) break;    		    	if (p == softback_buf) p = softback_end;    		    	p -= conp->vc_size_row;    		    	q -= conp->vc_size_row;    		    	scr_memcpyw((u16 *)q, (u16 *)p, conp->vc_size_row);    		    }    		    softback_in = p;    		    update_region(unit, conp->vc_origin, logo_lines * conp->vc_cols);    		}		logo_shown = -1;	}    	fbcon_cursor(conp, CM_ERASE|CM_SOFTBACK);    	fbcon_redraw_softback(conp, p, lines);    	fbcon_cursor(conp, CM_DRAW|CM_SOFTBACK);    	return 0;    }    if (!scrollback_phys_max)	return -ENOSYS;    scrollback_old = scrollback_current;    scrollback_current -= lines;    if (scrollback_current < 0)	scrollback_current = 0;    else if (scrollback_current > scrollback_max)	scrollback_current = scrollback_max;    if (scrollback_current == scrollback_old)	return 0;    if (!p->can_soft_blank &&	(console_blanked || vt_cons[unit]->vc_mode != KD_TEXT || !lines))	return 0;    fbcon_cursor(conp, CM_ERASE);    offset = p->yscroll-scrollback_current;    limit = p->vrows;    switch (p->scrollmode && __SCROLL_YMASK) {	case __SCROLL_YWRAP:	    p->var.vmode |= FB_VMODE_YWRAP;	    break;	case __SCROLL_YPAN:	    limit -= conp->vc_rows;	    p->var.vmode &= ~FB_VMODE_YWRAP;	    break;    }    if (offset < 0)	offset += limit;    else if (offset >= limit)	offset -= limit;    p->var.xoffset = 0;    p->var.yoffset = offset*fontheight(p);    p->fb_info->updatevar(unit, p->fb_info);    if (!scrollback_current)	fbcon_cursor(conp, CM_DRAW);    return 0;}static int fbcon_set_origin(struct vc_data *conp){    if (softback_lines && !console_blanked)        fbcon_scrolldelta(conp, softback_lines);    return 0;}static inline unsigned safe_shift(unsigned d,int n){    return n<0 ? d>>-n : d<<n;}static int __init fbcon_show_logo( void ){    struct display *p = &fb_display[fg_console]; /* draw to vt in foreground */    int depth = p->var.bits_per_pixel;    int line = p->next_line;    unsigned char *fb = p->screen_base;    unsigned char *logo;    unsigned char *dst, *src;    int i, j, n, x1, y1, x;    int logo_depth, done = 0;    /* Return if the frame buffer is not mapped */    if (!fb)	return 0;	    /*     * Set colors if visual is PSEUDOCOLOR and we have enough colors, or for     * DIRECTCOLOR     * We don't have to set the colors for the 16-color logo, since that logo     * uses the standard VGA text console palette     */    if ((p->visual == FB_VISUAL_PSEUDOCOLOR && depth >= 8) ||	(p->visual == FB_VISUAL_DIRECTCOLOR && depth >= 24))	for (i = 0; i < LINUX_LOGO_COLORS; i += n) {	    n = LINUX_LOGO_COLORS - i;	    if (n > 16)		/* palette_cmap provides space for only 16 colors at once */		n = 16;	    palette_cmap.start = 32 + i;	    palette_cmap.len   = n;	    for( j = 0; j < n; ++j ) {		palette_cmap.red[j]   = (linux_logo_red[i+j] << 8) |					linux_logo_red[i+j];		palette_cmap.green[j] = (linux_logo_green[i+j] << 8) |					linux_logo_green[i+j];		palette_cmap.blue[j]  = (linux_logo_blue[i+j] << 8) |					linux_logo_blue[i+j];	    }	    p->fb_info->fbops->fb_set_cmap(&palette_cmap, 1, fg_console,					   p->fb_info);	}	    if (depth >= 8) {	logo = linux_logo;	logo_depth = 8;    }    else if (depth >= 4) {	logo = linux_logo16;	logo_depth = 4;    }    else {	logo = linux_logo_bw;	logo_depth = 1;    }        if (p->fb_info->fbops->fb_rasterimg)    	p->fb_info->fbops->fb_rasterimg(p->fb_info, 1);    for (x = 0; x < smp_num_cpus * (LOGO_W + 8) &&    	 x < p->var.xres - (LOGO_W + 8); x += (LOGO_W + 8)) {    	 #if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \    defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)        if (p->visual == FB_VISUAL_DIRECTCOLOR) {	    unsigned int val;		/* max. depth 32! */	    int bdepth;	    int redshift, greenshift, blueshift;			    /* Bug: Doesn't obey msb_right ... (who needs that?) */	    redshift   = p->var.red.offset;	    greenshift = p->var.green.offset;	    blueshift  = p->var.blue.offset;	    if (depth >= 24 && (depth % 8) == 0) {		/* have at least 8 bits per color */		src = logo;		bdepth = depth/8;		for( y1 = 0; y1 < LOGO_H; y1++ ) {		    dst = fb + y1*line + x*bdepth;		    for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {			val = (*src << redshift) |			      (*src << greenshift) |			      (*src << blueshift);			if (bdepth == 4 && !((long)dst & 3)) {			    /* Some cards require 32bit access */			    fb_writel (val, dst);			    dst += 4;			} else if (bdepth == 2 && !((long)dst & 1)) {			    /* others require 16bit access */			    fb_writew (val,dst);			    dst +=2;			} else {#ifdef __LITTLE_ENDIAN			    for( i = 0; i < bdepth; ++i )#else			    for( i = bdepth-1; i >= 0; --i )#endif			        fb_writeb (val >> (i*8), dst++);			}		    }		}	    }	    else if (depth >= 12 && depth <= 23) {	        /* have 4..7 bits per color, using 16 color image */		unsigned int pix;		src = linux_logo16;		bdepth = (depth+7)/8;		for( y1 = 0; y1 < LOGO_H; y1++ ) {		    dst = fb + y1*line + x*bdepth;		    for( x1 = 0; x1 < LOGO_W/2; x1++, src++ ) {			pix = *src >> 4; /* upper nibble */			val = (pix << redshift) |			      (pix << greenshift) |			      (pix << blueshift);#ifdef __LITTLE_ENDIAN			for( i = 0; i < bdepth; ++i )#else			for( i = bdepth-1; i >= 0; --i )#endif			    fb_writeb (val >> (i*8), dst++);			pix = *src & 0x0f; /* lower nibble */			val = (pix << redshift) |			      (pix << greenshift) |			      (pix << blueshift);#ifdef __LITTLE_ENDIAN			for( i = 0; i < bdepth; ++i )#else			for( i = bdepth-1; i >= 0; --i )#endif			    fb_writeb (val >> (i*8), dst++);		    }		}	    }	    done = 1;        }#endif#if defined(CONFIG_FBCON_CFB16) || defined(CONFIG_FBCON_CFB24) || \    defined(CONFIG_FBCON_CFB32) || defined(CONFIG_FB_SBUS)	if ((depth % 8 == 0) && (p->visual == FB_VISUAL_TRUECOLOR)) {	    /* Modes without color mapping, needs special data transformation... */	    unsigned int val;		/* max. depth 32! */	    int bdepth = depth/8;	    unsigned char mask[9] = { 0,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff };	    unsigned char redmask, greenmask, bluemask;	    int redshift, greenshift, blueshift;			    /* Bug: Doesn't obey msb_right ... (who needs that?) */	    redmask   = mask[p->var.red.length   < 8 ? p->var.red.length   : 8];	    greenmask = mask[p->var.green.length < 8 ? p->var.green.length : 8];	    bluemask  = mask[p->var.blue.length  < 8 ? p->var.blue.length  : 8];	    redshift   = p->var.red.offset   - (8-p->var.red.length);	    greenshift = p->var.green.offset - (8-p->var.green.length);	    blueshift  = p->var.blue.offset  - (8-p->var.blue.length);	    src = logo;	    for( y1 = 0; y1 < LOGO_H; y1++ ) {		dst = fb + y1*line + x*bdepth;		for( x1 = 0; x1 < LOGO_W; x1++, src++ ) {		    val = safe_shift((linux_logo_red[*src-32]   & redmask), redshift) |		          safe_shift((linux_logo_green[*src-32] & greenmask), greenshift) |		          safe_shift((linux_logo_blue[*src-32]  & bluemask), blueshift);		    if (bdepth == 4 && !((long)dst & 3)) {			/* Some cards require 32bit access */			fb_writel (val, dst);			dst += 4;		    } else if (bdepth == 2 && !((long)dst & 1)) {			/* others require 16bit access */			fb_writew (val,dst);			dst +=2;		    } else {#ifdef __LITTLE_ENDIAN			for( i = 0; i < bdepth; ++i )#else			for( i = bdepth-1; i >= 0; --i )#endif			    fb_writeb (val >> (i*8), dst++);		    }		}	    }	    done = 1;	}#endif#if defined(CONFIG_FBCON_CFB4)	if (depth == 4 && p->type == FB_TYPE_PACKED_PIXELS) {		src = logo;		for( y1 =

⌨️ 快捷键说明

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