📄 s3c44b0xfb.c
字号:
/* * linux/drivers/video/s3c44b0xfb.c * * Copyright (C) 2003 Stefan Macher <macher@sympat.de> * Alexander Assel <assel@sympat.de> * * 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. *//* TODO (roughly in order of priority): * color gray / (monochrom) 2 bpp (8 bpp color) * configuration via modul parameters and i/o control */#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/delay.h>#include <linux/fb.h>#include <linux/init.h>#include "linux/config.h"#include <video/fbcon.h>//#include <video/fbcon-cfb4.h> /* add -- luzhl */#include "s3c44b0xfb.h"#include "asm-armnommu/arch-S3C44B0X/s3c44b0x.h"/*---------------------------------*//* global parameters *//*---------------------------------*/static int s3c44b0x_lcd_index; /*!< index within panels; will be set according to panel_name */#if MODULE /* in case of module the panel name is set as module parameter */static u8 panel_valid = 0;static unsigned char *panel_name = NULL;#else /* FIXME this should be similar to module but as linux boot line parameter */static u8 panel_valid = 1;static unsigned char *panel_name = "LCDBA7T11M4_320x240x4"; /* mod -- luzhl */#endifstatic u8 bootloader = 0; /* use bootloader settings for LCD controller setup */static struct fb_ops s3c44b0xfb_ops;struct fbgen_hwswitch s3c44b0xfb_switch;/*---------------------------------*//* parameter decleration *//*---------------------------------*/#if MODULEMODULE_PARM(panel_name, "s");MODULE_PARM_DESC(panel_name, "Name of the connected panel\nknown panels are: LCDBA7T11M4_320x240x8");MODULE_PARM(bootloader, "b");MODULE_PARM_DESC(bootloader, "Set it to 1 if you want the device driver to use the parameters that has the bootloader configured\n");MODULE_AUTHOR("Alexander Assel <asselv@sympat.de> Stefan Macher <macher@sympat.de>");MODULE_DESCRIPTION("S3C44B0X LCD framebuffer device driver");#endif/*--------------------------------*//************************************** * definition of the known displays **************************************//* if you add some new panels in the struct bellow change also the module description on the end of this file*/struct known_lcd_panels panels[] = { { /* holds the lcd panel name */ "LCDBA7T11M4_320x240x4", /* mod -- luzhl */ /* clkval */ 3, /* mod -- luzhl */ /* FIXME this is based on a cpu clock of 60,75 MHz */ /* Determine the VLINE pulses high level width [clocks] valid values 4, 8, 12 and 16 */ 16, /* Determine the delay between VLINE and VCLOCK [clocks] valid values 4, 8, 12 and 16 */ 16, /* Determine toggle rate of VM 0 -> each frame 1 -> defined by MVAL */ 0, /* display mode is 8 bit single scan */ 1, /* mod -- luzhl */ /* controls the poloarity of VCLOCK active edge 0 -> falling edge 1 -> rising edge */ 0, /* indicate the line pulse polarity 0 -> normal 1 -> inverted */ 0, /* indicate the frame pulse polarity 0 -> normal 1 -> inverted */ 0, /* indicates the video data polarity 0 -> normal 1 -> inverted */ 0, /* indicates the blank time in one horizontal line duration */ 10, /* LCD self refrash mode enable */ 0, /* byte swap control */#ifdef CONFIG_CPU_BIG_ENDIAN 0,#else 1,#endif /* defines the rate at which the vm signal will toggle */ 0x0D, /* display width in pixels */ 320, /* display height in pixels */ 240, /* bits per pixel valid is 1 (mono), 2 (gray), 4 (gray) and 8 (color) */ 4, /* mod -- luzhl */ 79, /* mod -- luzhl */ /* hozval */ 239, /* lineval */ S3C44B0X_PDATC, /* port register for enabling the display */ (1<<8), /* mask port c pin 8 */ (1<<8), /* set port c pin 8 to high */ S3C44B0X_PCONC, /* port control register for setting PORTC.8 to output */ (3<<16), /* mask port c pin8 control */ (1<<16) /* set port c pin 8 control to output */}}; static struct s3c44b0xfb_info fb_info;static struct s3c44b0xfb_par current_par;static int current_par_valid = 0;static struct display disp; /* add -- luzhl */int s3c44b0xfb_init(void);int s3c44b0xfb_setup(char*);/* ------------------- chipset specific functions -------------------------- */static void s3c44b0xfb_detect(void){ /* * Yeh, well, we're not going to change any settings so we're * always stuck with the default ... */}static int s3c44b0xfb_encode_fix(struct fb_fix_screeninfo *fix, const void *_par, struct fb_info_gen *_info){ /* * This function should fill in the 'fix' structure based on the values * in the `par' structure. */ struct s3c44b0xfb_info *info = (struct s3c44b0xfb_info *) _info; struct s3c44b0xfb_par *par = (struct s3c44b0xfb_par *) _par; struct fb_var_screeninfo *var = &par->var; memset(fix, 0, sizeof(struct fb_fix_screeninfo)); fix->smem_start = info->fb_phys; fix->smem_len = info->fb_size; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = (var->bits_per_pixel == 1) ? FB_VISUAL_MONO01 : FB_VISUAL_PSEUDOCOLOR; /* mod -- luzhl */ /* FB_VISUAL_TRUECOLOR; */ fix->ywrapstep = 0; fix->xpanstep = 0; fix->ypanstep = 0; fix->line_length = current_par.line_length; return 0;}static int s3c44b0xfb_decode_var(const struct fb_var_screeninfo *var, void *par, struct fb_info_gen *info){ /* * 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. */ struct known_lcd_panels *p_lcd = &panels[s3c44b0x_lcd_index]; if (var->xres != p_lcd->width || var->yres != p_lcd->height) { return -EINVAL; } if(var->bits_per_pixel != p_lcd->bpp) { return -EINVAL; } return 0;}static int s3c44b0xfb_encode_var(struct fb_var_screeninfo *var, const void *_par, struct fb_info_gen *info){ /* * Fill the 'var' structure based on the values in 'par' and maybe other * values read out of the hardware. */ struct s3c44b0xfb_par *par = (struct s3c44b0xfb_par*)_par; memcpy(var, &par->var, sizeof(struct fb_var_screeninfo)); return 0;}static void s3c44b0xfb_get_par(void *_par, struct fb_info_gen *info){ /* * Fill the hardware's 'par' structure. */ struct s3c44b0xfb_par *par = (struct s3c44b0xfb_par*)_par; if (current_par_valid) memcpy(par, ¤t_par, sizeof(struct s3c44b0xfb_par));}static void s3c44b0xfb_set_par(const void *par, struct fb_info_gen *info){ /* * Set the hardware according to 'par'. */ /* nothing to do: we don't change any settings */ }static int s3c44b0xfb_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *_info){ /* * Read a single color register and split it into colors/transparent. * The return values must have a 16 bit magnitude. * Return != 0 for invalid regno. */ struct s3c44b0xfb_info *info = (struct s3c44b0xfb_info *) _info; u32 blueval, redval, greenval; u8 helpvalue; blueval = inw(S3C44B0X_BLUELUT); redval = inw(S3C44B0X_REDLUT); greenval = inw(S3C44B0X_GREENLUT); switch(info->gen.info.var.bits_per_pixel) { case 1: if(regno > 1) return 1; /* error */ if(regno == 0) *red = *green = *blue = 0; else *red = *green = *blue = 0xFFFF; break; case 2: if(regno > 4) return 1; /* error */ blueval = (blueval >> (regno<<2)) & 0xF; *red = *green = *blue = 0x1111 * blueval; /* 0xFFFF / 0xF = 0x1111 */ break; case 4: if(regno > 16) return 1; /* error */ *red = *green = *blue = 0x1111 * regno; /* 0xFFFF / 0xF = 0x1111 */ break; case 8: if(regno > 256) return 1; helpvalue = regno >> 5; redval = (redval >> (helpvalue<<2)) & 0xF; *red = redval * 0x1111; helpvalue = (regno >> 2) & 0x7; greenval = (greenval >> (helpvalue<<2)) & 0xF; *green = greenval * 0x1111; helpvalue = regno & 0x03; blueval = (blueval >> (helpvalue<<2)) & 0xF; *blue = blueval * 0x1111; break; default: return 1; } return 0;}static int s3c44b0xfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *_info){ /* * Set a single color register. The values supplied have a 16 bit * magnitude. * Return != 0 for invalid regno. */ struct s3c44b0xfb_info *info = (struct s3c44b0xfb_info *) _info; unsigned int helpvalue; u32 blueval, redval, greenval; blueval = inw(S3C44B0X_BLUELUT); redval = inw(S3C44B0X_REDLUT); greenval = inw(S3C44B0X_GREENLUT); switch(info->gen.info.var.bits_per_pixel) { case 1: return -EINVAL; break; case 2: if((regno > 4) || (red != green) || (red != blue)) /* FIXME: maybe wrong */ return 1; helpvalue = (unsigned int)(blue / 0x1111) & 0xF; blueval &= ~(0xF << (regno<<2)); blueval |= (helpvalue << (regno<<2)); outl(blueval, S3C44B0X_BLUELUT); break; case 4: return -EINVAL; break; case 8: if(regno > 256) return 1; helpvalue = (unsigned int)(blue / 0x1111) & 0xF; blueval &= ~(0xF << ((regno&0x03)<<2)); blueval |= (helpvalue << ((regno&0x03)<<2)); outl(blueval, S3C44B0X_BLUELUT); helpvalue = (unsigned int)(red / 0x1111) & 0xF; redval &= ~(0xF << (((regno>>5)&0x7)<<2)); redval |= (helpvalue << (((regno>>5)&0x7)<<2)); outl(redval, S3C44B0X_BLUELUT); helpvalue = (unsigned int)(green / 0x1111) & 0xF; greenval &= ~(0xF << (((regno>>2)&0x7)<<2)); greenval |= (helpvalue << (((regno>>2)&0x7)<<2)); outl(greenval, S3C44B0X_BLUELUT); break; default: return 1; } return 0;}static int s3c44b0xfb_pan_display(const struct fb_var_screeninfo *var, struct fb_info_gen *info){ /* * Pan (or wrap, depending on the `vmode' field) the display using the * `xoffset' and `yoffset' fields of the `var' structure. * If the values don't fit, return -EINVAL. */ return -EINVAL;}static int s3c44b0xfb_blank(int blank_mode, struct fb_info_gen *info){ /* * Blank the screen if blank_mode != 0, else unblank. If blank == NULL * then the caller blanks by setting the CLUT (Color Look Up Table) to all * black. Return 0 if blanking succeeded, != 0 if un-/blanking failed due * to e.g. a video mode which doesn't support it. Implements VESA suspend * and powerdown modes on hardware that supports disabling hsync/vsync: * blank_mode == 2: suspend vsync * blank_mode == 3: suspend hsync * blank_mode == 4: powerdown */ u32 helpvalue; switch(blank_mode) { case 2: return -EINVAL; case 3: return -EINVAL; case 4: helpvalue = inw(S3C44B0X_LCDCON1); outl(helpvalue&~S3C44B0X_LCDCON1_ENVID, S3C44B0X_LCDCON1); /* disable video output */ break; default: return -EINVAL; } /* ... */ return 0;}static void s3c44b0xfb_gen_blank(int blank_mode, struct fb_info *info){ s3c44b0xfb_blank(blank_mode, &fb_info.gen); return;}#if 0 /* mod -- luzhl */static void s3c44b0xfb_set_disp(const void *par, struct display *disp, struct fb_info_gen *info){ /* * Fill in a pointer with the virtual address of the mapped frame buffer.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -