📄 s3c44b0xfb.c~
字号:
/* * linux/drivers/video/s3c44b0fb.c * * tpu. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Framebuffer driver for the S3C44B0X processors. *///#define LCD_GRAY_16#define FBCON_HAS_CFB8#include <linux/module.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/init.h>#include <video/fbcon.h>#ifdef LCD_GRAY_16#include <video/fbcon-cfb4.h>#else#include <video/fbcon-cfb8.h>#endif#include <asm/hardware.h>#include <asm/mach-types.h>#include <asm/uaccess.h>static struct s3c44b0fb_info { struct fb_info fb; int currcon;} *cfb;#define CMAP_SIZE 256/* * Set a single color register. Return != 0 for invalid regno. */static ints3c44b0fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ //TODO return 0;} /* * Set the colormap */static ints3c44b0fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct s3c44b0fb_info *cfb = (struct s3c44b0fb_info *)info; struct fb_cmap *dcmap = &fb_display[con].cmap; int err = 0; /* no colormap allocated? */ if (!dcmap->len) err = fb_alloc_cmap(dcmap, CMAP_SIZE, 0); if (!err && con == cfb->currcon) { err = fb_set_cmap(cmap, kspc, s3c44b0fb_setcolreg, &cfb->fb); dcmap = &cfb->fb.cmap; } if (!err) fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); return err;}/* * Set the User Defined Part of the Display */static ints3c44b0fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct display *display; unsigned int lcdcon, syscon; int chgvar = 0; if (var->activate & FB_ACTIVATE_TEST) return 0; if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return -EINVAL; if (cfb->fb.var.xres != var->xres) chgvar = 1; if (cfb->fb.var.yres != var->yres) chgvar = 1; if (cfb->fb.var.xres_virtual != var->xres_virtual) chgvar = 1; if (cfb->fb.var.yres_virtual != var->yres_virtual) chgvar = 1; if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) chgvar = 1; if (con < 0) { display = cfb->fb.disp; chgvar = 0; } else { display = fb_display + con; } var->transp.msb_right = 0; var->transp.offset = 0; var->transp.length = 0; var->red.msb_right = 0; var->red.offset = 5; var->red.length = 3; var->green.msb_right = 0; var->green.offset = 2; var->green.length = 3; var->blue.msb_right = 0; var->blue.offset = 0; var->blue.length = 2; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_MFB case 1: cfb->fb.fix.visual = FB_VISUAL_MONO01; display->dispsw = &fbcon_mfb; display->dispsw_data = NULL; break;#endif#ifdef FBCON_HAS_CFB2 case 2: cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; display->dispsw = &fbcon_cfb2; display->dispsw_data = NULL; break;#endif#ifdef FBCON_HAS_CFB4 case 4: cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; display->dispsw = &fbcon_cfb4; display->dispsw_data = NULL; break;#endif#ifdef FBCON_HAS_CFB8 case 8: cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; display->dispsw = &fbcon_cfb8; display->dispsw_data = NULL; break;#endif default: return -EINVAL; } display->next_line = var->xres_virtual * var->bits_per_pixel / 8; cfb->fb.fix.line_length = display->next_line; display->screen_base = cfb->fb.screen_base; display->line_length = cfb->fb.fix.line_length; display->visual = cfb->fb.fix.visual; display->type = cfb->fb.fix.type; display->type_aux = cfb->fb.fix.type_aux; display->ypanstep = cfb->fb.fix.ypanstep; display->ywrapstep = cfb->fb.fix.ywrapstep; display->can_soft_blank = 1; display->inverse = 0; cfb->fb.var = *var; cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; /* * Update the old var. The fbcon drivers still use this. * Once they are using cfb->fb.var, this can be dropped. * --rmk */ display->var = cfb->fb.var; /* * If we are setting all the virtual consoles, also set the * defaults used to create new consoles. */ if (var->activate & FB_ACTIVATE_ALL) cfb->fb.disp->var = cfb->fb.var; if (chgvar && info && cfb->fb.changevar) cfb->fb.changevar(con); fb_set_cmap(&cfb->fb.cmap, 1, s3c44b0fb_setcolreg, &cfb->fb); return 0;}/* * Get the currently displayed virtual consoles colormap. */static intgen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2); return 0;}/* * Get the currently displayed virtual consoles fixed part of the display. */static intgen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ *fix = info->fix; return 0;}/* * Get the current user defined part of the display. */static intgen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ *var = info->var; return 0;}static struct fb_ops s3c44b0fb_ops = { owner: THIS_MODULE, fb_set_var: s3c44b0fb_set_var, fb_set_cmap: s3c44b0fb_set_cmap, fb_get_fix: gen_get_fix, fb_get_var: gen_get_var, fb_get_cmap: gen_get_cmap,};static int s3c44b0fb_updatevar(int con, struct fb_info *info){ return -EINVAL;}static void s3c44b0fb_blank(int blank, struct fb_info *info){ //TODO if (blank) { } else { }}/********************************************************************************/#define U8 __u8#define U16 __u16 #define U32 __u32#define MAX749_CTRL 0x80#define MAX749_ADJ 0x40#define Max749AdjHi() outl(inl(S3C44B0X_PDATC)|MAX749_ADJ, S3C44B0X_PDATC)#define Max749AdjLo() outl(inl(S3C44B0X_PDATC)&~MAX749_ADJ, S3C44B0X_PDATC)#define Max749CtrlHi() outl(inl(S3C44B0X_PDATC)|MAX749_CTRL, S3C44B0X_PDATC)#define Max749CtrlLo() outl(inl(S3C44B0X_PDATC)&~MAX749_CTRL, S3C44B0X_PDATC)static void Max749Rst(void){ unsigned char i; Max749AdjHi(); Max749CtrlLo(); i = 100; while(i--); Max749CtrlHi(); }static void Max749Up(U16 cnt){ unsigned char i; Max749Rst(); for(; cnt; cnt--) { Max749AdjLo(); i = 10; while(i--); Max749AdjHi(); i = 10; while(i--); }}#define SCR_XSIZE 320#define SCR_YSIZE 240#define LCD_XSIZE 320#define LCD_YSIZE 240#ifdef LCD_GRAY_16#define LCD_DEPTH 4#define LCD_BUF_SIZE ((SCR_XSIZE*SCR_YSIZE)>>1)#else#define LCD_DEPTH 8#define LCD_BUF_SIZE ((SCR_XSIZE*SCR_YSIZE))#endif///////////////////// LCDCON1#define CLKVAL (10<<12) //VCLK = MCLK/(2*CLKVAL)#define WLH (1<<10) //16 clock#define WDLY (1<<8) //16 clock#define MMODE (0<<7) //VM = ecah frame, not use MVAL#define DISMODE (2<<5) //4bit single scan#define INVCLK (0<<4) //falling edge fetch data#define INVLINE (0<<3) //normal, non inverse#define INVFRAME (0<<2) //normal#define INVVD (0<<1) //normal#define ENVID 1#define DSVID 0#define LCD_MODE_DS (CLKVAL|WLH|WDLY|MMODE|DISMODE|INVCLK|INVLINE|INVFRAME|INVVD|DSVID)#define LCD_MODE_EN (CLKVAL|WLH|WDLY|MMODE|DISMODE|INVCLK|INVLINE|INVFRAME|INVVD|ENVID)///////////////////// LCDCON2#define LINEBLINK 10///////////////////// LCDCON3#define SELFREF_EN 1#define SELFREF_DS 0///////////////////// LCDSADDR1#define MONO_MODE 0#define G4_MODE 1#define G16_MODE 2#define C8_MODE 3#define BankOfDisMem(addr) (((U32)(addr)>>22)<<21)#define BaseOfDisMem(addr) (((U32)(addr)>>1)&0x1fffff)///////////////////// LCDSADDR2#define BSWP_EN 1#define BSWP_DS 0#define MVAL 1///////////////////// LCDSADDR3#define MONO_VS_SIZE (LCD_XSIZE/16)|(((SCR_XSIZE-LCD_XSIZE)/16)<<9)#define G4_VS_SIZE (LCD_XSIZE/8)|(((SCR_XSIZE-LCD_XSIZE)/8)<<9)#define G16_VS_SIZE (LCD_XSIZE/4)|(((SCR_XSIZE-LCD_XSIZE)/4)<<9)#define C8_VS_SIZE (LCD_XSIZE/2)|(((SCR_XSIZE-LCD_XSIZE)/2)<<9)int __init s3c44b0xfb_init(void){ int err = -ENOMEM; char *fbuf; cfb = kmalloc(sizeof(*cfb) + sizeof(struct display), GFP_KERNEL); if (!cfb) goto out; memset(cfb, 0, sizeof(*cfb) + sizeof(struct display)); fbuf = kmalloc(LCD_BUF_SIZE, GFP_KERNEL); if(!fbuf){ kfree(cfb); goto out; } memset(fbuf, 0, LCD_BUF_SIZE); cfb->currcon = -1; strcpy(cfb->fb.fix.id, "s3c44b0"); cfb->fb.screen_base = fbuf; cfb->fb.fix.smem_start = fbuf; cfb->fb.fix.smem_len = LCD_BUF_SIZE; cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; cfb->fb.var.xres = LCD_XSIZE; cfb->fb.var.xres_virtual = SCR_XSIZE; cfb->fb.var.yres = LCD_YSIZE; cfb->fb.var.yres_virtual = SCR_YSIZE; cfb->fb.var.bits_per_pixel = LCD_DEPTH; cfb->fb.var.grayscale = 1; cfb->fb.var.activate = FB_ACTIVATE_NOW; cfb->fb.var.height = -1; cfb->fb.var.width = -1; cfb->fb.fbops = &s3c44b0fb_ops; cfb->fb.changevar = NULL;// cfb->fb.switch_con = s3c44b0fb_switch; cfb->fb.updatevar = s3c44b0fb_updatevar; cfb->fb.blank = s3c44b0fb_blank; cfb->fb.flags = FBINFO_FLAG_DEFAULT; cfb->fb.disp = (struct display *)(cfb + 1); fb_alloc_cmap(&cfb->fb.cmap, CMAP_SIZE, 0); /* * Power up the LCD */#ifdef LCD_GRAY_16 Max749Up(23); outl(0xaaaa, S3C44B0X_PCOND); //VFRAME,VM,VLINE,VCLK,VD3-VD0 enable outl(LCD_MODE_DS, S3C44B0X_LCDCON1); outl((LINEBLINK<<21)|(((LCD_XSIZE>>2)-1)<<10)|(LCD_YSIZE-1), S3C44B0X_LCDCON2); outl((G16_MODE<<27)|BankOfDisMem(fbuf)|BaseOfDisMem(fbuf), S3C44B0X_LCDSADDR1); outl((BSWP_EN<<29)|(MVAL<<21)|BaseOfDisMem((U32)fbuf+SCR_XSIZE*LCD_YSIZE/2), S3C44B0X_LCDSADDR2); outl(G16_VS_SIZE, S3C44B0X_LCDSADDR3); outl(inl(S3C44B0X_PDATC)&~0x100, S3C44B0X_PDATC); // set GPC8 low#else/* Max749Up(23); PCOND = 0xaaaa; //VFRAME,VM,VLINE,VCLK,VD3-VD0 enable LCDCON1 = LCD_MODE_DS; LCDCON2 = (LINEBLINK<<21)|((LCD_XSIZE/4-1)<<10)|(LCD_YSIZE-1); LCDSADDR1 = (G16_MODE<<27)|BankOfDisMem(fbuf)|BaseOfDisMem(fbuf); LCDSADDR2 = (BSWP_EN<<29)|(MVAL<<21)|BaseOfDisMem((U32)fbuf+SCR_XSIZE*LCD_YSIZE/2); LCDSADDR3 = G16_VS_SIZE;*/ outl(inl(S3C44B0X_PCONC)&~0xff00, S3C44B0X_PCONC); outl(inl(S3C44B0X_PCONC)|0xff00, S3C44B0X_PCONC); //GPC4-GPC7 as VD7-VD4 outl(0xaaaa, S3C44B0X_PCOND); //VFRAME,VM,VLINE,VCLK,VD3-VD0 outl(inl(S3C44B0X_PDATC)|0x100, S3C44B0X_PDATC); // set GPC8 low //outl(0x4f40, S3C44B0X_LCDCON1); outl(LCD_MODE_DS, S3C44B0X_LCDCON1); outl((LINEBLINK<<21)|(((LCD_XSIZE>>1)-1)<<10)|(LCD_YSIZE-1), S3C44B0X_LCDCON2); outl((3<<27)|((int)fbuf>>1), S3C44B0X_LCDSADDR1); outl(((((int)fbuf+LCD_XSIZE*LCD_YSIZE)>>1)&0x1fffff)|(13<<21)|(1<<29), S3C44B0X_LCDSADDR2); outl(C8_VS_SIZE, S3C44B0X_LCDSADDR3); outl(0xfdb96420, S3C44B0X_REDLUT); outl(0xfdb96420, S3C44B0X_GREENLUT); outl(0xfb40, S3C44B0X_BLUELUT);#endif outl(inl(S3C44B0X_LCDCON1)|ENVID, S3C44B0X_LCDCON1); printk("LCD buffer : %p\n", fbuf); s3c44b0fb_set_var(&cfb->fb.var, -1, &cfb->fb); err = register_framebuffer(&cfb->fb);// printk("err=%d\n", err);out: return err;}static void __exit s3c44b0xfb_exit(void){ unregister_framebuffer(&cfb->fb); kfree(cfb);}int __init s3c44b0xfb_setup(char *options){ return 0;}#ifdef MODULEmodule_init(s3c44b0xfb_init);module_exit(s3c44b0xfb_exit);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -