📄 pvr2fb.c
字号:
display->inverse = pvr2fb_inverse; switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB16 case 16: display->dispsw = &fbcon_cfb16; display->dispsw_data = fbcon_cmap.cfb16; break;#endif#ifdef FBCON_HAS_CFB24 case 24: display->dispsw = &fbcon_cfb24; display->dispsw_data = fbcon_cmap.cfb24; break;#endif#ifdef FBCON_HAS_CFB32 case 32: display->dispsw = &fbcon_cfb32; display->dispsw_data = fbcon_cmap.cfb32; break;#endif default: display->dispsw = &fbcon_dummy; break; } if (fb_info.changevar) (*fb_info.changevar)(con); } if (oldbpp != var->bits_per_pixel) { if ((err = fb_alloc_cmap(&display->cmap, 0, 0))) return err; do_install_cmap(con, info); } if (con == currcon) pvr2_set_var(&display->var); } return 0;}/* * Pan or wrap the display. * This call looks only at xoffset, yoffset and the FB_VMODE_YRAP flag */static int pvr2fb_pan_display(struct fb_var_screeninfo *var, int con, struct fb_info *info){ if (var->vmode & FB_VMODE_YWRAP) { if (var->yoffset<0 || var->yoffset >= fb_display[con].var.yres_virtual || var->xoffset) return -EINVAL; } else { if (var->xoffset+fb_display[con].var.xres > fb_display[con].var.xres_virtual || var->yoffset+fb_display[con].var.yres > fb_display[con].var.yres_virtual) return -EINVAL; } if (con == currcon) pvr2_pan_var(var); fb_display[con].var.xoffset = var->xoffset; fb_display[con].var.yoffset = var->yoffset; if (var->vmode & FB_VMODE_YWRAP) fb_display[con].var.vmode |= FB_VMODE_YWRAP; else fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; return 0;}/* Get the colormap */static int pvr2fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, pvr2_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0;}/* Set the colormap */static int pvr2fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0))) return err; } if (con == currcon) /* current console? */ return fb_set_cmap(cmap, kspc, pvr2_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}static int pvr2fbcon_switch(int con, struct fb_info *info){ /* Do we have to save the colormap? */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, pvr2_getcolreg, info); currcon = con; pvr2_set_var(&fb_display[con].var); /* Install new colormap */ do_install_cmap(con, info); return 0;}static int pvr2fbcon_updatevar(int con, struct fb_info *info){ pvr2_pan_var(&fb_display[con].var); return 0;}static void pvr2fbcon_blank(int blank, struct fb_info *info){ do_blank = blank ? blank : -1;}/* Setup the colormap */static void do_install_cmap(int con, struct fb_info *info){ if (con != currcon) return; if (fb_display[con].cmap.len) fb_set_cmap(&fb_display[con].cmap, 1, pvr2_setcolreg, info); else fb_set_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), 1, pvr2_setcolreg, info);}static inline u_long get_line_length(int xres_virtual, int bpp){ return (u_long)((((xres_virtual*bpp)+31)&~31) >> 3);}static void set_color_bitfields(struct fb_var_screeninfo *var){ switch (var->bits_per_pixel) { case 16: /* RGB 565 */ var->red.offset = 11; var->red.length = 5; var->green.offset = 5; var->green.length = 6; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 0; var->transp.length = 0; break; case 24: /* RGB 888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; break; case 32: /* ARGB 8888 */ var->red.offset = 16; var->red.length = 8; var->green.offset = 8; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 24; var->transp.length = 8; break; }}static int pvr2_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info){ if (regno > 255) return 1; *red = palette[regno].red; *green = palette[regno].green; *blue = palette[regno].blue; *transp = 0; return 0;} static int pvr2_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info){ if (regno > 255) return 1; palette[regno].red = red; palette[regno].green = green; palette[regno].blue = blue; if (regno < 16) { switch (currbpp) {#ifdef FBCON_HAS_CFB16 case 16: /* RGB 565 */ fbcon_cmap.cfb16[regno] = (red & 0xf800) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break;#endif#ifdef FBCON_HAS_CFB24 case 24: /* RGB 888 */ red >>= 8; green >>= 8; blue >>= 8; fbcon_cmap.cfb24[regno] = (red << 16) | (green << 8) | blue; break;#endif#ifdef FBCON_HAS_CFB32 case 32: /* ARGB 8888 */ red >>= 8; green >>= 8; blue >>= 8; fbcon_cmap.cfb32[regno] = (red << 16) | (green << 8) | blue; break;#endif default: DPRINTK("Invalid bit depth %d?!?\n", currbpp); return 1; } } return 0;}static int pvr2_encode_fix(struct fb_fix_screeninfo *fix, struct pvr2fb_par *par){ memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, pvr2fb_name); fix->smem_start = videomemory; fix->smem_len = videomemorysize; fix->type = FB_TYPE_PACKED_PIXELS; fix->type_aux = 0; fix->visual = FB_VISUAL_TRUECOLOR; if (par->vmode & FB_VMODE_YWRAP) { fix->ywrapstep = 1; fix->xpanstep = fix->ypanstep = 0; } else { fix->ywrapstep = 0; fix->xpanstep = 1; fix->ypanstep = 1; } fix->line_length = par->next_line; return 0;}/* * Create a hardware video mode using the framebuffer values. If a value needs * to be clipped or constrained it's done here. This routine needs a bit more * work to make sure we're doing the right tests at the right time. */static int pvr2_decode_var(struct fb_var_screeninfo *var, struct pvr2fb_par *par){ u_long line_length; u_short vtotal; if (var->pixclock != TV_CLK && var->pixclock != VGA_CLK) { DPRINTK("Invalid pixclock value %d\n", var->pixclock); return -EINVAL; } par->pixclock = var->pixclock; if ((par->xres = var->xres) < 320) par->xres = 320; if ((par->yres = var->yres) < 240) par->yres = 240; if ((par->vxres = var->xres_virtual) < par->xres) par->vxres = par->xres; if ((par->vyres = var->yres_virtual) < par->yres) par->vyres = par->yres; if ((par->bpp = var->bits_per_pixel) <= 16) par->bpp = 16; else if ((par->bpp = var->bits_per_pixel) <= 24) par->bpp = 24; else if ((par->bpp = var->bits_per_pixel) <= 32) par->bpp = 32; currbpp = par->bpp; /* * XXX: It's possible that a user could use a VGA box, change the cable * type in hardware (i.e. switch from VGA<->composite), then change modes * (i.e. switching to another VT). If that happens we should automagically * change the output format to cope, but currently I don't have a VGA box * to make sure this works properly. */ cable_type = pvr2_init_cable(); if (cable_type == CT_VGA && video_output != VO_VGA) video_output = VO_VGA; par->vmode = var->vmode & FB_VMODE_MASK; if (par->vmode & FB_VMODE_INTERLACED && video_output != VO_VGA) par->is_interlaced = 1; /* * XXX: Need to be more creative with this (i.e. allow doublecan for * PAL/NTSC output). */ par->is_doublescan = (par->yres < 480 && video_output == VO_VGA); par->hsync_total = var->left_margin + var->xres + var->right_margin + var->hsync_len; par->vsync_total = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; if (var->sync & FB_SYNC_BROADCAST) { vtotal = par->vsync_total; if (par->is_interlaced) vtotal /= 2; if (vtotal > (PAL_VTOTAL + NTSC_VTOTAL)/2) { /* PAL video output */ /* XXX: Should be using a range here ... ? */ if (par->hsync_total != PAL_HTOTAL) { DPRINTK("invalid hsync total for PAL\n"); return -EINVAL; } /* XXX: Check for start values here... */ /* XXX: Check hardware for PAL-compatibility */ par->borderstart_h = 116; par->borderstart_v = 44; } else { /* NTSC video output */ if (par->hsync_total != NTSC_HTOTAL) { DPRINTK("invalid hsync total for NTSC\n"); return -EINVAL; } par->borderstart_h = 126; par->borderstart_v = 18; } } else { /* VGA mode */ /* XXX: What else needs to be checked? */ /* * XXX: We have a little freedom in VGA modes, what ranges should * be here (i.e. hsync/vsync totals, etc.)? */ par->borderstart_h = 126; par->borderstart_v = 40; } /* Calculate the remainding offsets */ par->borderstop_h = par->borderstart_h + par->hsync_total - var->hsync_len; par->borderstop_v = par->borderstart_v + par->vsync_total - var->vsync_len; par->diwstart_h = par->borderstart_h + var->left_margin; par->diwstart_v = par->borderstart_v + var->upper_margin; if (!par->is_interlaced) par->borderstop_v /= 2; if (par->xres < 640) par->is_lowres = 1; /* XXX: Needs testing. */ if (!((par->vmode ^ var->vmode) & FB_VMODE_YWRAP)) { par->xoffset = var->xoffset; par->yoffset = var->yoffset; if (par->vmode & FB_VMODE_YWRAP) { if (par->xoffset || par->yoffset < 0 || par->yoffset >= par->vyres) par->xoffset = par->yoffset = 0; } else { if (par->xoffset < 0 || par->xoffset > par->vxres-par->xres || par->yoffset < 0 || par->yoffset > par->vyres-par->yres) par->xoffset = par->yoffset = 0; } } else par->xoffset = par->yoffset = 0; /* Check memory sizes */ line_length = get_line_length(var->xres_virtual, var->bits_per_pixel); if (line_length * var->yres_virtual > videomemorysize) return -ENOMEM; par->disp_start = videomemory + (get_line_length(par->vxres, par->bpp) * par->yoffset) * get_line_length(par->xoffset, par->bpp); par->next_line = line_length; return 0;}static int pvr2_encode_var(struct fb_var_screeninfo *var, struct pvr2fb_par *par){ memset(var, 0, sizeof(struct fb_var_screeninfo)); var->xres = par->xres; var->yres = par->yres;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -