📄 sa1100fb.c
字号:
};#endif#ifdef CONFIG_SA1100_STORK#if STORK_TFT /* ie the NEC TFT *//* * pixclock is ps per clock. say 72Hz, 800x600 clocks => (1/72)/(800*600) * = 28935 and a bit * NB likely to be increased to ease bus timings wrt pcmcia interface */static struct sa1100fb_mach_info stork_tft_info __initdata = { pixclock: 28935, bpp: 16, xres: 640, yres: 480, hsync_len: 64, vsync_len: 2, left_margin: 48, upper_margin: 12, right_margin: 48, lower_margin: 31, sync: 0, lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg,};static struct sa1100fb_rgb stork_tft_rgb_16 = { red: { offset: 11, length: 5, }, green: { offset: 5, length: 6, }, blue: { offset: 0, length: 5, }, transp: { offset: 0, length: 0, },};#else /* Kyocera DSTN */static struct sa1100fb_mach_info stork_dstn_info __initdata = { pixclock: 0, bpp: 16, xres: 640, yres: 480, hsync_len: 2, vsync_len: 2, left_margin: 2, upper_margin: 0, right_margin: 2, lower_margin: 0, sync: FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT , lccr0: LCCR0_Color | LCCR0_Dual | LCCR0_Pas,#error Fixme lccr3: 0xff00 | 0x18 /* ought to be 0x14 but DMA isn't up to that as yet */};static struct sa1100fb_rgb stork_dstn_rgb_16 = { red: { offset: 8, length: 4, }, green: { offset: 4, length: 4, }, blue: { offset: 0, length: 4, }, transp: { offset: 0, length: 0, },};#endif#endif#ifdef CONFIG_SA1100_XP860static struct sa1100fb_mach_info xp860_info __initdata = { pixclock: 0, bpp: 8, xres: 1024, yres: 768, hsync_len: 3, vsync_len: 3, left_margin: 3, upper_margin: 2, right_margin: 2, lower_margin: 1, sync: 0, lccr0: LCCR0_Color | LCCR0_Sngl | LCCR0_Act, lccr3: LCCR3_OutEnH | LCCR3_PixRsEdg | LCCR3_PixClkDiv(6),};#endifstatic struct sa1100fb_mach_info * __initsa1100fb_get_machine_info(struct sa1100fb_info *fbi){ struct sa1100fb_mach_info *inf = NULL; /* * R G B T * default {11,5}, { 5,6}, { 0,5}, { 0,0} * h3600 {12,4}, { 7,4}, { 1,4}, { 0,0} * freebird { 8,4}, { 4,4}, { 0,4}, {12,4} */#ifdef CONFIG_SA1100_ASSABET if (machine_is_assabet()) {#ifndef ASSABET_PAL_VIDEO inf = &lq039q2ds54_info;#else inf = &pal_info;#endif }#endif#ifdef CONFIG_SA1100_H3XXX if (machine_is_h3600()) { inf = &h3600_info; fbi->rgb[RGB_16] = &h3600_rgb_16; } if (machine_is_h3100()) { inf = &h3100_info; } if (machine_is_h3800()) { inf = &h3800_info; }#endif#ifdef CONFIG_SA1100_BRUTUS if (machine_is_brutus()) { inf = &brutus_info; }#endif#ifdef CONFIG_SA1100_CERF if (machine_is_cerf()) { inf = &cerf_info; }#endif#ifdef CONFIG_SA1100_FREEBIRD if (machine_is_freebird()) { inf = &freebird_info; fbi->rgb[RGB_16] = &freebird_rgb16; }#endif#ifdef CONFIG_SA1100_GRAPHICSCLIENT if (machine_is_graphicsclient()) { inf = &graphicsclient_info; }#endif#ifdef CONFIG_SA1100_HUW_WEBPANEL if (machine_is_huw_webpanel()) { inf = &huw_webpanel_info; }#endif#ifdef CONFIG_SA1100_LART if (machine_is_lart()) {#ifdef LART_GREY_LCD inf = &lart_grey_info;#endif#ifdef LART_COLOR_LCD inf = &lart_color_info;#endif#ifdef LART_VIDEO_OUT inf = &lart_video_info;#endif#ifdef KIT01_LCD inf = &kit01_info;#endif }#endif#ifdef CONFIG_SA1100_FRODO if (machine_is_frodo()) {#ifdef KIT01_LCD inf = &kit01_info;#endif }#endif#ifdef CONFIG_SA1100_SHANNON if (machine_is_shannon()) { inf = &shannon_info; }#endif#ifdef CONFIG_SA1100_OMNIMETER if (machine_is_omnimeter()) { inf = &omnimeter_info; }#endif#ifdef CONFIG_SA1100_PANGOLIN if (machine_is_pangolin()) { inf = &pangolin_info; }#endif#ifdef CONFIG_SA1100_XP860 if (machine_is_xp860()) { inf = &xp860_info; }#endif#ifdef CONFIG_SA1100_STORK if (machine_is_stork()) {#if STORK_TFT inf = &stork_tft_info; fbi->rgb[RGB_16] = &stork_tft_rgb_16;#else inf = &stork_dstn_info; fbi->rgb[RGB_16] = &stork_dstn_rgb_16;#endif }#endif return inf;}static int sa1100fb_activate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *);static void set_ctrlr_state(struct sa1100fb_info *fbi, u_int state);static inline void sa1100fb_schedule_task(struct sa1100fb_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 sa1100fb_info *fbi = (struct sa1100fb_info *)info; return (con == fbi->currcon || con == -1) ? &fbi->fb.var : &fb_display[con].var;}/* * Get the DISPLAY structure pointer for the specified console */static inline struct display *get_con_display(struct fb_info *info, int con){ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; return (con < 0) ? fbi->fb.disp : &fb_display[con];}/* * Get the CMAP pointer for the specified console */static inline struct fb_cmap *get_con_cmap(struct fb_info *info, int con){ struct sa1100fb_info *fbi = (struct sa1100fb_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;}static intsa1100fb_setpalettereg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info){ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; u_int val, ret = 1; if (regno < fbi->palette_size) { val = ((red >> 4) & 0xf00); val |= ((green >> 8) & 0x0f0); val |= ((blue >> 12) & 0x00f); if (regno == 0) val |= palette_pbs(&fbi->fb.var); fbi->palette_cpu[regno] = val; ret = 0; } return ret;}static intsa1100fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int trans, struct fb_info *info){ struct sa1100fb_info *fbi = (struct sa1100fb_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 = sa1100fb_setpalettereg(regno, red, green, blue, trans, info); break; } return ret;}/* * sa1100fb_display_dma_period() * Calculate the minimum period (in picoseconds) between two DMA * requests for the LCD controller. */static unsigned intsa1100fb_display_dma_period(struct fb_var_screeninfo *var){ unsigned int mem_bits_per_pixel; mem_bits_per_pixel = var->bits_per_pixel; if (mem_bits_per_pixel == 12) mem_bits_per_pixel = 16; /* * Period = pixclock * bits_per_byte * bytes_per_transfer * / memory_bits_per_pixel; */ return var->pixclock * 8 * 16 / mem_bits_per_pixel;}/* * sa1100fb_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 intsa1100fb_validate_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi){ int ret = -EINVAL; if (var->xres < MIN_XRES) var->xres = MIN_XRES; if (var->yres < MIN_YRES) var->yres = MIN_YRES; if (var->xres > fbi->max_xres) var->xres = fbi->max_xres; if (var->yres > fbi->max_yres) var->yres = fbi->max_yres; var->xres_virtual = var->xres_virtual < var->xres ? var->xres : var->xres_virtual; var->yres_virtual = var->yres_virtual < var->yres ? var->yres : var->yres_virtual; DPRINTK("var->bits_per_pixel=%d\n", var->bits_per_pixel); switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4 case 4: ret = 0; break;#endif#ifdef FBCON_HAS_CFB8 case 8: ret = 0; break;#endif#ifdef FBCON_HAS_CFB16 case 16: ret = 0; break;#endif default: break; }#ifdef CONFIG_CPU_FREQ printk(KERN_DEBUG "dma period = %d ps, clock = %d kHz\n", sa1100fb_display_dma_period(var), cpufreq_get(smp_processor_id()));#endif return ret;}static inline void sa1100fb_set_truecolor(u_int is_true_color){ DPRINTK("true_color = %d\n", is_true_color); if (machine_is_assabet()) {#if 1 // phase 4 or newer Assabet's if (is_true_color) ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB); else ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB);#else // older Assabet's if (is_true_color) ASSABET_BCR_clear(ASSABET_BCR_LCD_12RGB); else ASSABET_BCR_set(ASSABET_BCR_LCD_12RGB);#endif }}static voidsa1100fb_hw_set_var(struct fb_var_screeninfo *var, struct sa1100fb_info *fbi){ u_long palette_mem_size; fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16; palette_mem_size = fbi->palette_size * sizeof(u16); DPRINTK("palette_mem_size = 0x%08lx\n", (u_long) palette_mem_size); fbi->palette_cpu = (u16 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size); fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size; fb_set_cmap(&fbi->fb.cmap, 1, sa1100fb_setcolreg, &fbi->fb); /* Set board control register to handle new color depth */ sa1100fb_set_truecolor(var->bits_per_pixel >= 16);#ifdef CONFIG_SA1100_OMNIMETER#error Do we have to do this here? We already do it at init time. if (machine_is_omnimeter()) SetLCDContrast(DefaultLCDContrast);#endif sa1100fb_activate_var(var, fbi); fbi->palette_cpu[0] = (fbi->palette_cpu[0] & 0xcfff) | palette_pbs(var);}/* * sa1100fb_set_var(): * Set the user defined part of the display for the specified console */static intsa1100fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; struct fb_var_screeninfo *dvar = get_con_var(&fbi->fb, con); struct display *display = get_con_display(&fbi->fb, con); int err, chgvar = 0, rgbidx; DPRINTK("set_var\n"); /* * Decode var contents into a par structure, adjusting any * out of range values. */ err = sa1100fb_validate_var(var, fbi); if (err) return err; if (var->activate & FB_ACTIVATE_TEST) return 0; if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return -EINVAL; if (dvar->xres != var->xres) chgvar = 1; if (dvar->yres != var->yres) chgvar = 1; if (dvar->xres_virtual != var->xres_virtual) chgvar = 1; if (dvar->yres_virtual != var->yres_virtual) chgvar = 1; if (dvar->bits_per_pixel != var->bits_per_pixel) chgvar = 1; if (con < 0) chgvar = 0; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB4 case 4: if (fbi->cmap_static) display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; else display->visual = FB_VISUAL_PSEUDOCOLOR; display->line_length = var->xres / 2; display->dispsw = &fbcon_cfb4; rgbidx = RGB_8; break;#endif#ifdef FBCON_HAS_CFB8 case 8: if (fbi->cmap_static) display->visual = FB_VISUAL_STATIC_PSEUDOCOLOR; else display->visual = FB_VISUAL_PSEUDOCOLOR; display->line_length = var->xres; display->dispsw = &fbcon_cfb8; rgbidx = RGB_8; break;#endif#ifdef FBCON_HAS_CFB16 case 16: display->visual = FB_VISUAL_TRUECOLOR; display->line_length = var->xres * 2; display->dispsw = &fbcon_cfb16; display->dispsw_data = fbi->fb.pseudo_palette; rgbidx = RGB_16; break;#endif default: rgbidx = 0; display->dispsw = &fbcon_dummy; break; } display->screen_base = fbi->screen_cpu; display->next_line = display->line_length; display->type = fbi->fb.fix.type; display->type_aux = fbi->fb.fix.type_aux; display->ypanstep = fbi->fb.fix.ypanstep; display->ywrapstep = fbi->fb.fix.ywrapstep; display->can_soft_blank = 1; display->inverse = fbi->cmap_inverse;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -