📄 s1d13706fb.c
字号:
/* * linux/drivers/video/s1d13706fb.c * -- Support for the Epson S1D13706 LCD/CRT controller * * Copyright (C) 2003 Heiko Degenhardt <linux@sentec-elektronik.de> * Michael Huhn <michael.huhn@sentec-elektronik.de> * * based on linux/drivers/video/skeletonfb.c, which was * Created 28 Dec 1997 by Geert Uytterhoeven * * Some ideas were "stolen" from * linux/drivers/video/epson1355fb.c * that is "Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>" * and from s1d13xxxfb.c and a file called "s1d13706.h" that was * generated by S1D13706CFG.EXE both are * "Copyright(c) 2000, 2001 Epson Research and Development, Inc" * * HINT: If someone feels that we used his code but didn't give him * credits here, please email us! It was a quite complicated thing to * get all that working, so may be we just forgot someone! Thanks! * * 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. * *//* * CHANGES * * 20030312 * Creation * (mihu, hede) *//* * * ATTENTION! * This stuff is _really_ experimental, currently! * Feedback is really welcome! * *//* define DBUG below if you want to get more verbose output of the driver *//*#define DBUG*/#include <asm/io.h>#include <linux/config.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fb.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/mm.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/tty.h>#include <video/fbcon-cfb8.h>#include <video/fbcon-mfb.h>#include <video/fbcon.h>#include <asm/coldfire.h>/* ----------------------------------------------------------------------------- Sanity checks -----------------------------------------------------------------------------*//* Are you compiling for our board? * If not I think you know how to solve the error. ;) */#ifdef CONFIG_COBRA5272/* S1D13706 supports 4Bpp, 8Bpp, 16Bpp */#ifdef CONFIG_FB_S1D13706 #if defined (FBCON_HAS_CFB4) && defined (FBCON_HAS_CFB8) #error More than one colordepth specified #endif #if defined (FBCON_HAS_CFB4) && defined (FBCON_HAS_CFB16) #error More than one colordepth specified #endif #if defined (FBCON_HAS_CFB8) && defined (FBCON_HAS_CFB16) #error More than one colordepth specified #endif#include "s1d13706fb.h"#else #error lcd controller not supported#endif/* Check if at least one supported colordepth was configured */#if !defined (FBCON_HAS_CFB4) && !defined (FBCON_HAS_CFB8) && \ !defined (FBCON_HAS_CFB16) #error No colordepth specified#endifstatic inline u8 s1d13706_read_reg(int index){ return readb(S1D13706_REG_OFFSET + index);}static inline void s1d13706_write_reg(u8 data, int index){ writeb(data, S1D13706_REG_OFFSET + index);}static inline u16 s1d13706_read_reg16(int index){ return s1d13706_read_reg(index) + (s1d13706_read_reg(index+1) << 8);}static inline void s1d13706_write_reg16(u16 data, int index){ s1d13706_write_reg((data&0xff), index); s1d13706_write_reg(((data>>8)&0xff), index + 1);}#else /* not on the COBRA5272 board */#error unknown architecture#endifstatic int current_par_valid = 0;static struct display disp;static struct fb_var_screeninfo default_var;static struct fb_fix_screeninfo current_fix = { id: "S1D13706", smem_start: (__u32)S1D13706_FB_BASE, /* initially, we'll fill it later */ smem_len: 320*240, /* initially, we'll fill it later */ type: FB_TYPE_PACKED_PIXELS, /* this should always be true for dragonballs */ visual: FB_VISUAL_PSEUDOCOLOR, /* this should depend on LCD used */ line_length: 320, accel: FB_ACCEL_NONE, /* but still like a breeze ;-) */};static int currcon = 0;/* ------------------- chipset specific functions -------------------------- */static void s1d13706_detect(void){ u8 rev; rev = s1d13706_read_reg(S1D13706_REVISION_CODE_REG); if ((rev & 0xfc) != 0x28) { printk(KERN_WARNING "Epson 13706 not detected\n"); } s1d13706_encode_var(&default_var, NULL, NULL);#ifdef DBUG printk("s1d13706_detect done\n");#endif}static int s1d13706_encode_fix(struct fb_fix_screeninfo *fix, const void *raw_par, struct fb_info_gen *info){ const struct s1d13706_par *par = raw_par; memset(fix, 0, sizeof *fix); fix->type= FB_TYPE_PACKED_PIXELS; if (!par) BUG(); if (par->bpp == 1) { fix->visual = FB_VISUAL_MONO10; } else if (par->bpp <= 8) { fix->visual = FB_VISUAL_PSEUDOCOLOR; } else { fix->visual = FB_VISUAL_TRUECOLOR; } fix->line_length = par->xres; fix->mmio_start = S1D13706_FB_BASE; fix->smem_start = S1D13706_FB_BASE; fix->mmio_len = S1D13706_SRAM_SIZE; fix->smem_len = S1D13706_SRAM_SIZE;#ifdef DBUG printk("s1d13706_encode_fix done\n");#endif return 0;}static int s1d13706_set_bpp(struct s1d13706_par *par, int bpp){ int code; u8 disp; u16 bytes_per_line; switch(bpp) { case 1: code = 0; break; case 2: code = 1; break; case 4: code = 2; break; case 8: code = 3; break; case 16: code = 4; break; default: return -EINVAL; break; } disp = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); disp &= ~0x07; /* Bits 2:0 */ disp |= code; s1d13706_write_reg(disp, S1D13706_DISPLAY_MODE_REG); bytes_per_line = ((par->xres * bpp) >> 3) - 1; /* horizontal displ. period reg */ s1d13706_write_reg16(bytes_per_line, S1D13706_HOR_DISPLAY_MODE_REG); par->bpp = bpp;#ifdef DBUG printk("s1d13706_set_bpp started\n");#endif return 0;}static int s1d13706_decode_var(const struct fb_var_screeninfo *var, void *raw_par, struct fb_info_gen *info){ struct s1d13706_par *par = raw_par; int ret;#ifdef DBUG printk("s1d13706_decode_var started\n");#endif if (!par) BUG(); /* * Don't allow setting any of these yet: xres and yres don't * make sense for LCD panels; xres_virtual and yres_virtual * should be supported fine by our hardware though. */ if (var->xres != par->xres || var->yres != par->yres || var->xres != var->xres_virtual || var->yres != var->yres_virtual || var->xoffset != 0 || var->yoffset != 0){#ifdef DBUG printk("s1d13706_decode_var returned -EINVAL\n");#endif return -EINVAL; } if(var->bits_per_pixel != par->bpp) { ret = s1d13706_set_bpp(par, var->bits_per_pixel); if (ret) goto out_err; }#ifdef DBUG printk("s1d13706_decode_var returned 0\n");#endif return 0; out_err:#ifdef DBUG printk("s1d13706_decode_var returned %i\n", ret);#endif return ret;}static void dump_panel_data(void){ u8 panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG); int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } }; char *type[] = {"STN", "TFT", "HR-TFT", "D-DFT"}; printk("%s %s panel, width %d bits\n", panel & 0x40 ? "color" : "mono", *(type[panel & 0x03]), (width[panel&1][(panel>>4)&3])); printk("resolution %d x %d\n", /* hor. display period reg.: */ (s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1) * 8, /* vert. displ. period reg.: */ ((s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0)+ 1) ));#ifdef DBUG printk("dump_panel_data done\n");#endif}static int s1d13706_bpp_to_var(int bpp, struct fb_var_screeninfo *var){ switch(bpp) { case 1: case 2: case 4: case 8: var->bits_per_pixel = bpp; var->red.offset = var->green.offset = var->blue.offset = 0; var->red.length = var->green.length = var->blue.length = bpp; break; case 16: var->bits_per_pixel = 16; var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; break; }#ifdef DBUG printk("s1d13706_bpp_to_var done\n");#endif return 0;}static int s1d13706_encode_var(struct fb_var_screeninfo *var, const void *raw_par, struct fb_info_gen *info){ u8 panel, display; u32 xres, xres_virtual, yres, yres_virtual; static int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 18, -1 } }; static int bpp_tab[8] = { 1, 2, 4, 8, 16, -1 }; int bpp, hw_bpp; int is_color, is_tft; int lcd_enabled; int xoffset, yoffset; display = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG); is_color = (panel & 0x40) != 0; is_tft = (panel & 0x03) == 0x01; bpp = bpp_tab[(display) & 0x07];/* BPP is in Bits 2:0 */ s1d13706_bpp_to_var(bpp, var); lcd_enabled = (display & 0x80) == 0;/* when disabled, data outputs are zero*/ hw_bpp = width[is_tft][(panel>>4)&0x03]; /* Horizontal display period register: */ xres = s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1; /* Vertical display period register: */ yres = s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0) + 1; xres *= 8; /* horizontal total resolution: */ xres_virtual = s1d13706_read_reg(S1D13706_HOR_TOTAL_REG); xres_virtual *= 8; /* vertical total resolution: */ yres_virtual = s1d13706_read_reg16(S1D13706_VERT_TOTAL_REG0); /* hor. display period start pos. reg. */ xoffset = s1d13706_read_reg16(S1D13706_HOR_DISP_PERIOD_START_POS_REG0); yoffset = s1d13706_read_reg16(S1D13706_VERT_DISP_PERIOD_START_POS_REG0); var->xres = xres; var->yres = yres; var->xres_virtual = xres_virtual; var->yres_virtual = yres_virtual; var->xoffset = xoffset; var->yoffset = yoffset; var->bits_per_pixel = bpp; var->grayscale = !is_color;#ifdef DBUG printk("s1d13706_encode_var done\n");#endif return 0;}static void get_panel_data(struct s1d13706_par *par){ u8 panel; u8 display; int width[2][4] = { { 4, 8, 16, -1 }, { 9, 12, 16, -1 } }; int bpp_tab[8] = { 1, 2, 4, 8, 16, -1 }; panel = s1d13706_read_reg(S1D13706_PANEL_TYPE_REG) & 0x3F; display = s1d13706_read_reg(S1D13706_DISPLAY_MODE_REG); par->panel_width = width[panel&1][(panel>>4)&3]; /* horiz. display period reg.: */ par->panel_xres = (s1d13706_read_reg(S1D13706_HOR_DISPLAY_MODE_REG) + 1) * 8; /* vert. displ. period reg.: */ par->panel_yres = (s1d13706_read_reg16(S1D13706_VERT_DISPLAY_MODE_REG0) + 1); par->bpp = bpp_tab[(display) & 0x07]; /* BPP is in Bits 2:0 */ par->mem_bpp = par->bpp; par->xres = par->panel_xres; par->yres = par->panel_yres;;#ifdef DBUG printk("get_panel_data done\n");#endif}static void s1d13706_get_par(void *raw_par, struct fb_info_gen *info){ struct s1d13706_par *par = raw_par; get_panel_data(par);#ifdef DBUG printk("s1d13706_get_par done\n");#endif}static void s1d13706_set_par(const void *par, struct fb_info_gen *info){#ifdef DBUG printk("s1d13706_set_par done\n");#endif}static int s1d13706_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -