📄 sa1100fb.c
字号:
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; *dvar = *var; dvar->activate &= ~FB_ACTIVATE_ALL; /* * Copy the RGB parameters for this display * from the machine specific parameters. */ dvar->red = fbi->rgb[rgbidx]->red; dvar->green = fbi->rgb[rgbidx]->green; dvar->blue = fbi->rgb[rgbidx]->blue; dvar->transp = fbi->rgb[rgbidx]->transp; DPRINTK("RGBT length = %d:%d:%d:%d\n", dvar->red.length, dvar->green.length, dvar->blue.length, dvar->transp.length); DPRINTK("RGBT offset = %d:%d:%d:%d\n", dvar->red.offset, dvar->green.offset, dvar->blue.offset, dvar->transp.offset); /* * Update the old var. The fbcon drivers still use this. * Once they are using fbi->fb.var, this can be dropped. */ display->var = *dvar; /* * If we are setting all the virtual consoles, also set the * defaults used to create new consoles. */ if (var->activate & FB_ACTIVATE_ALL) fbi->fb.disp->var = *dvar; /* * If the console has changed and the console has defined * a changevar function, call that function. */ if (chgvar && info && fbi->fb.changevar) fbi->fb.changevar(con); /* If the current console is selected, activate the new var. */ if (con != fbi->currcon) return 0; sa1100fb_hw_set_var(dvar, fbi); return 0;}static int__do_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; struct fb_cmap *dcmap = get_con_cmap(info, con); int err = 0; if (con == -1) con = fbi->currcon; /* no colormap allocated? (we always have "this" colour map allocated) */ if (con >= 0) err = fb_alloc_cmap(&fb_display[con].cmap, fbi->palette_size, 0); if (!err && con == fbi->currcon) err = fb_set_cmap(cmap, kspc, sa1100fb_setcolreg, info); if (!err) fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); return err;}static intsa1100fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct display *disp = get_con_display(info, con); if (disp->visual == FB_VISUAL_TRUECOLOR || disp->visual == FB_VISUAL_STATIC_PSEUDOCOLOR) return -EINVAL; return __do_set_cmap(cmap, kspc, con, info);}static intsa1100fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ struct display *display = get_con_display(info, con); *fix = info->fix; fix->line_length = display->line_length; fix->visual = display->visual; return 0;}static intsa1100fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ *var = *get_con_var(info, con); return 0;}static intsa1100fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ struct fb_cmap *dcmap = get_con_cmap(info, con); fb_copy_cmap(dcmap, cmap, kspc ? 0 : 2); return 0;}static struct fb_ops sa1100fb_ops = { owner: THIS_MODULE, fb_get_fix: sa1100fb_get_fix, fb_get_var: sa1100fb_get_var, fb_set_var: sa1100fb_set_var, fb_get_cmap: sa1100fb_get_cmap, fb_set_cmap: sa1100fb_set_cmap,};/* * sa1100fb_switch(): * Change to the specified console. Palette and video mode * are changed to the console's stored parameters. * * Uh oh, this can be called from a tasklet (IRQ) */static int sa1100fb_switch(int con, struct fb_info *info){ struct sa1100fb_info *fbi = (struct sa1100fb_info *)info; struct display *disp; struct fb_cmap *cmap; DPRINTK("con=%d info->modename=%s\n", con, fbi->fb.modename); if (con == fbi->currcon) return 0; if (fbi->currcon >= 0) { disp = fb_display + fbi->currcon; /* * Save the old colormap and video mode. */ disp->var = fbi->fb.var; if (disp->cmap.len) fb_copy_cmap(&fbi->fb.cmap, &disp->cmap, 0); } fbi->currcon = con; disp = fb_display + con; /* * Make sure that our colourmap contains 256 entries. */ fb_alloc_cmap(&fbi->fb.cmap, 256, 0); if (disp->cmap.len) cmap = &disp->cmap; else cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); fb_copy_cmap(cmap, &fbi->fb.cmap, 0); fbi->fb.var = disp->var; fbi->fb.var.activate = FB_ACTIVATE_NOW; sa1100fb_set_var(&fbi->fb.var, con, info); return 0;}/* * Formal definition of the VESA spec: * On * This refers to the state of the display when it is in full operation * Stand-By * This defines an optional operating state of minimal power reduction with * the shortest recovery time * Suspend * This refers to a level of power management in which substantial power * reduction is achieved by the display. The display can have a longer * recovery time from this state than from the Stand-by state * Off * This indicates that the display is consuming the lowest level of power * and is non-operational. Recovery from this state may optionally require * the user to manually power on the monitor * * Now, the fbdev driver adds an additional state, (blank), where they * turn off the video (maybe by colormap tricks), but don't mess with the * video itself: think of it semantically between on and Stand-By. * * So here's what we should do in our fbdev blank routine: * * VESA_NO_BLANKING (mode 0) Video on, front/back light on * VESA_VSYNC_SUSPEND (mode 1) Video on, front/back light off * VESA_HSYNC_SUSPEND (mode 2) Video on, front/back light off * VESA_POWERDOWN (mode 3) Video off, front/back light off * * This will match the matrox implementation. *//* * sa1100fb_blank(): * Blank the display by setting all palette values to zero. Note, the * 12 and 16 bpp modes don't really use the palette, so this will not * blank the display in all modes.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -