📄 s3c2410fb.c
字号:
/* * linux/drivers/video/s3c2410fb.c * * CopyRight (C) 2002 SAMSUNG ELECTRONICS * SW.LEE <hitchcar@sec.samsung.com> * * 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/sched.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/interrupt.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/delay.h>#include <linux/pm.h>#include <linux/init.h>#include <linux/cpufreq.h>#include <asm/hardware.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/mach-types.h>#include <asm/uaccess.h>#include <video/fbcon.h>#include <video/fbcon-mfb.h>#include <video/fbcon-cfb4.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-cfb16.h>/* * enable this if your panel appears to have broken */#undef CHECK_COMPAT/* * debugging? */#define DEBUG 1/* * Complain if VAR is out of range. */#define DEBUG_VAR 1#include "s3c2410fb.h"void (*s3c2410fb_blank_helper)(int blank);/* EXPORT_SYMBOL(s3c2410fb_blank_helper); *//* * IMHO this looks wrong. In 8BPP, length should be 8. */static struct s3c2410fb_rgb rgb_8 = { red: { offset: 0, length: 4, }, green: { offset: 0, length: 4, }, blue: { offset: 0, length: 4, }, transp: { offset: 0, length: 0, },};/* S3C2410 * 256 Palette Usage (TFT) * 256 color palette consist of 256(depth) * 16 bit SPSRAM */ static struct s3c2410fb_rgb def_rgb_16 = { red: { offset: 11, length: 5, }, green: { offset: 5, length: 6, }, blue: { offset: 0, length: 5, }, transp: { offset: 0, length: 0, },};/******* * role : Fill Machine dependant data ,according to STN or TFT * */static void __init s3c2410fb_get_machine_info(struct s3c2410fb_info *fbi){ static struct s3c2410fb_mach_info inf __initdata = {#if (LCD_TYPE == TFT240_320) pixclock: 174757, bpp: 16, xres: 240, yres: 320,#endif#if (LCD_TYPE == TFT640_480) pixclock: 174757, bpp: 16, xres: 640, yres: 480,#endif#if defined(CONFIG_SOMETHING_OHTERS) /* Not Tested .. */ pixclock: 0, bpp: 8, xres: 320, yres: 240,#endif // hsync_len: 5, vsync_len: 1, // left_margin: 7, upper_margin: 1, // right_margin: 3, lower_margin: 3, //070903-zjm hsync_len: 64, vsync_len: 2, //1<=hsync,vsync<=64; left_margin: 40, upper_margin: 24, //{1,255} right_margin: 32, lower_margin: 11, //[1,255] sync: 0, cmap_static: 1, //FB_ACTIVATE_NOW , /* value 0 */ /*reg : { rLCDCON1 : (CLKVAL_TFT<<8) | (3<<5) | (1<<8) , rLCDCON2 : (32<<24) | (9<<6) | (1), rLCDCON3 : (47<<19) | (15), rLCDCON4 : (95) | (13<<18), rLCDCON5 : (1<<11) | (1<<9) | (1<<8) | (1) | (1<<3), }, */ }; fbi->max_xres = inf.xres; fbi->fb.var.xres = inf.xres; fbi->fb.var.xres_virtual = inf.xres; fbi->max_yres = inf.yres; fbi->fb.var.yres = inf.yres; fbi->fb.var.yres_virtual = inf.yres; fbi->max_bpp = inf.bpp; fbi->fb.var.bits_per_pixel = inf.bpp; fbi->fb.var.pixclock = inf.pixclock; fbi->fb.var.hsync_len = inf.hsync_len; fbi->fb.var.left_margin = inf.left_margin; fbi->fb.var.right_margin = inf.right_margin; fbi->fb.var.vsync_len = inf.vsync_len; fbi->fb.var.upper_margin = inf.upper_margin; fbi->fb.var.lower_margin = inf.lower_margin; fbi->fb.var.sync = inf.sync; fbi->fb.var.grayscale = inf.cmap_greyscale; fbi->cmap_inverse = inf.cmap_inverse; fbi->cmap_static = inf.cmap_static; }static void s3c2410fb_lcd_port_init(void );static int s3c2410fb_activate_var(struct fb_var_screeninfo *var, struct s3c2410fb_info *);static void set_ctrlr_state(struct s3c2410fb_info *fbi, u_int state);#if (LCD_TYPE == TFT240_320)#define FR_WIDTH 240#define FR_HEIGHT 320#endif#if (LCD_TYPE == TFT640_480)#define FR_WIDTH 640#define FR_HEIGHT 480#endifstruct FrameBuffer { unsigned short pixel[FR_HEIGHT][FR_WIDTH];};struct FrameBuffer *FBuf;#ifdef YOU_WANT_TO_DRAW_TETRAGONstatic void lcd_demo(void){ // Test LCD Initialization. by displaying R.G.B and White. int i,j; for(i=0 ;i<FR_HEIGHT/2;i++) { for(j=0;j<FR_WIDTH;j++) { if(j<FR_WIDTH/2) FBuf->pixel[i][j]= 0xffff; else FBuf->pixel[i][j]= 0xf800; } } for(i=FR_HEIGHT/2 ;i<FR_HEIGHT;i++) { for(j=0;j<FR_WIDTH;j++) { if(j<FR_WIDTH/2) FBuf->pixel[i][j]= 0x07e0; else FBuf->pixel[i][j]= 0x001f; } } }#endifstatic void s3c2410fb_lcd_port_init(void){ rGPCUP=0xffffffff; // Disable Pull-up register rGPCCON=0xaaaaaaaa; //Initialize VD[7:0],LCDVF[2:0],VM,VFRAME,VLINE,VCLK,LEND rGPDUP=0xffffffff; // Disable Pull-up register rGPDCON=0xaaaaaaaa; //Initialize VD[23:8]} static inline void s3c2410fb_schedule_task(struct s3c2410fb_info *fbi, u_int state){ unsigned long flags; local_irq_save(flags); /* * We need to handle two requests being made at the same time. * There are two important cases: * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE) * We must perform the unblanking, which will do our REENABLE for us. * 2. When we are blanking, but immediately unblank before we have * blanked. We do the "REENABLE" thing here as well, just to be sure. */ if (fbi->task_state == C_ENABLE && state == C_REENABLE) state = (u_int) -1; if (fbi->task_state == C_DISABLE && state == C_ENABLE) state = C_REENABLE; if (state != (u_int)-1) { fbi->task_state = state; schedule_task(&fbi->task); } local_irq_restore(flags);}/* * Get the VAR structure pointer for the specified console */static inline struct fb_var_screeninfo *get_con_var(struct fb_info *info, int con){ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info; return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;}/* * Get the DISPLAY structure pointer for the specified console * * struct display fb_display[MAX_NR_CONSOLES]; from fbcon.c */static inline struct display *get_con_display(struct fb_info *info, int con){ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info; return (con < 0) ? fbi->fb.disp : &fb_display[con];}/* * Get the CMAP pointer for the specified console * * struct fb_cmap { * __u32 start; First entry * __u32 len; Number of entries * __u16 *red; Red values * __u16 *green; * __u16 *blue; * __u16 *transp; transparency, can be NULL * }; * */static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con){ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info; return (con == fbi->currcon || con == -1) ? &fbi->fb.cmap : &fb_display[con].cmap;}static inline u_intchan_to_field(u_int chan, struct fb_bitfield *bf){ chan &= 0xffff; chan >>= 16 - bf->length; return chan << bf->offset;}/* * Convert bits-per-pixel to a hardware palette PBS value. */static inline u_intpalette_pbs(struct fb_var_screeninfo *var){ int ret = 0; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4 case 4: ret = 0 << 12; break;#endif#ifdef FBCON_HAS_CFB8 case 8: ret = 1 << 12; break;#endif#ifdef FBCON_HAS_CFB16 case 16: ret = 2 << 12; break;#endif } return ret;}/****** * bit mask RGB=565 -> RRRR RGGG GGGB BBBB * 1111 1000 0000 0000 0xf800 * 0000 0111 1110 0000 0x07e0 * 0000 0000 0001 1111 0x001f *******************************************************/static ints3c2410fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info){ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info; u_int val, ret = 1; if (regno < fbi->palette_size) { val = ((blue >> 16) & 0x001f); val |= ((green >> 11) & 0x07e0); val |= ((red >> 5) & 0x0f800); if (regno == 0) val |= palette_pbs(&fbi->fb.var); fbi->palette_cpu[regno] = val; ret = 0; } return ret;}static ints3c2410fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info){ struct s3c2410fb_info *fbi = (struct s3c2410fb_info *)info; struct display *disp = get_con_display(info, fbi->currcon); u_int val; int ret = 1; /* * If inverse mode was selected, invert all the colours * rather than the register number. The register number * is what you poke into the framebuffer to produce the * colour you requested. */ //if (disp->inverse) //{ // red = 0xffff - red; // green = 0xffff - green; // blue = 0xffff - blue; //} /* * If greyscale is true, then we convert the RGB value * to greyscale no mater what visual we are using. */ if (fbi->fb.var.grayscale) red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16; switch (fbi->fb.disp->visual) { case FB_VISUAL_TRUECOLOR: /* * 12 or 16-bit True Colour. We encode the RGB value * according to the RGB bitfield information. */ if (regno < 16) { u16 *pal = fbi->fb.pseudo_palette; val = chan_to_field(red, &fbi->fb.var.red); val |= chan_to_field(green, &fbi->fb.var.green); val |= chan_to_field(blue, &fbi->fb.var.blue); pal[regno] = val; ret = 0; } break; case FB_VISUAL_STATIC_PSEUDOCOLOR: case FB_VISUAL_PSEUDOCOLOR: ret = s3c2410fb_setpalettereg(regno, red, green, blue, trans, info); break; } return ret;}/* * s3c2410fb_decode_var(): * Get the video params out of 'var'. If a value doesn't fit, round it up, * if it's too big, return -EINVAL. * * Suggestion: Round up in the following order: bits_per_pixel, xres, * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale, * bitfields, horizontal timing, vertical timing. */static ints3c2410fb_validate_var(struct fb_var_screeninfo *var, struct s3c2410fb_info *fbi)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -