📄 fbdev.c
字号:
* @p: pointer to display object * @width: font width in pixels * @height: font height in pixels * * DESCRIPTION: * Callback function called if font settings changed. * * RETURNS: * 1 (Always succeeds.) */static int rivafb_set_font(struct display *p, int width, int height){ struct rivafb_info *fb = (struct rivafb_info *)(p->fb_info); rivafb_create_cursor(fb, width, height); return 1;}/** * rivafb_cursor - cursor handler * @p: pointer to display object * @mode: cursor mode (see CM_*) * @x: cursor x coordinate in characters * @y: cursor y coordinate in characters * * DESCRIPTION: * Cursor handler. */static void rivafb_cursor(struct display *p, int mode, int x, int y){ struct rivafb_info *rinfo = (struct rivafb_info *)(p->fb_info); struct riva_cursor *c = rinfo->cursor; if (!c) return; x = x * fontwidth(p) - p->var.xoffset; y = y * fontheight(p) - p->var.yoffset; if (c->pos.x == x && c->pos.y == y && (mode == CM_ERASE) == !c->enable) return; c->enable = 0; if (c->on) rinfo->riva.ShowHideCursor(&rinfo->riva, 0); c->pos.x = x; c->pos.y = y; switch (mode) { case CM_ERASE: c->on = 0; break; case CM_DRAW: case CM_MOVE: if (c->last_move_delay <= 1) { /* rapid cursor movement */ c->vbl_cnt = CURSOR_SHOW_DELAY; } else { *(rinfo->riva.CURSORPOS) = (x & 0xFFFF) | (y << 16); rinfo->riva.ShowHideCursor(&rinfo->riva, 1); if (!noblink) c->vbl_cnt = CURSOR_HIDE_DELAY; c->on = 1; } c->last_move_delay = 0; c->enable = 1; break; }}/* ------------------------------------------------------------------------- * * * general utility functions * * ------------------------------------------------------------------------- *//** * riva_set_dispsw - sets dispsw * @rinfo: pointer to internal driver struct for a given Riva card * @disp: pointer to display object * * DESCRIPTION: * Sets up console low level operations depending on the current? color depth * of the display. * * CALLED FROM: * rivafb_set_var() * rivafb_switch() * riva_init_disp() */static void riva_set_dispsw(struct rivafb_info *rinfo, struct display *disp){ int accel = disp->var.accel_flags & FB_ACCELF_TEXT; DPRINTK("ENTER\n"); assert(rinfo != NULL); disp->dispsw_data = NULL; disp->screen_base = rinfo->fb_base; disp->type = FB_TYPE_PACKED_PIXELS; disp->type_aux = 0; disp->ypanstep = 1; disp->ywrapstep = 0; disp->can_soft_blank = 1; disp->inverse = 0; switch (disp->var.bits_per_pixel) {#ifdef FBCON_HAS_CFB8 case 8: rinfo->dispsw = accel ? fbcon_riva8 : fbcon_cfb8; disp->dispsw = &rinfo->dispsw; disp->line_length = disp->var.xres_virtual; disp->visual = FB_VISUAL_PSEUDOCOLOR; break;#endif#ifdef FBCON_HAS_CFB16 case 16: rinfo->dispsw = accel ? fbcon_riva16 : fbcon_cfb16; disp->dispsw_data = &rinfo->con_cmap.cfb16; disp->dispsw = &rinfo->dispsw; disp->line_length = disp->var.xres_virtual * 2; disp->visual = FB_VISUAL_DIRECTCOLOR; break;#endif#ifdef FBCON_HAS_CFB32 case 32: rinfo->dispsw = accel ? fbcon_riva32 : fbcon_cfb32; disp->dispsw_data = rinfo->con_cmap.cfb32; disp->dispsw = &rinfo->dispsw; disp->line_length = disp->var.xres_virtual * 4; disp->visual = FB_VISUAL_DIRECTCOLOR; break;#endif default: DPRINTK("Setting fbcon_dummy renderer\n"); rinfo->dispsw = fbcon_dummy; disp->dispsw = &rinfo->dispsw; } /* FIXME: verify that the above code sets dsp->* fields correctly */ if (rinfo->cursor) { rinfo->dispsw.cursor = rivafb_cursor; rinfo->dispsw.set_font = rivafb_set_font; } DPRINTK("EXIT\n");}/** * riva_wclut - set CLUT entry * @chip: pointer to RIVA_HW_INST object * @regnum: register number * @red: red component * @green: green component * @blue: blue component * * DESCRIPTION: * Sets color register @regnum. * * CALLED FROM: * riva_setcolreg() */static void riva_wclut(RIVA_HW_INST *chip, unsigned char regnum, unsigned char red, unsigned char green, unsigned char blue){ VGA_WR08(chip->PDIO, 0x3c8, regnum); VGA_WR08(chip->PDIO, 0x3c9, red); VGA_WR08(chip->PDIO, 0x3c9, green); VGA_WR08(chip->PDIO, 0x3c9, blue);}/** * riva_save_state - saves current chip state * @rinfo: pointer to rivafb_info object containing info for current riva board * @regs: pointer to riva_regs object * * DESCRIPTION: * Saves current chip state to @regs. * * CALLED FROM: * rivafb_init_one() *//* from GGI */static void riva_save_state(struct rivafb_info *rinfo, struct riva_regs *regs){ int i; rinfo->riva.LockUnlock(&rinfo->riva, 0); rinfo->riva.UnloadStateExt(&rinfo->riva, ®s->ext); regs->misc_output = MISCin(rinfo); for (i = 0; i < NUM_CRT_REGS; i++) { regs->crtc[i] = CRTCin(rinfo, i); } for (i = 0; i < NUM_ATC_REGS; i++) { regs->attr[i] = ATTRin(rinfo, i); } for (i = 0; i < NUM_GRC_REGS; i++) { regs->gra[i] = GRAin(rinfo, i); } for (i = 0; i < NUM_SEQ_REGS; i++) { regs->seq[i] = SEQin(rinfo, i); }}/** * riva_load_state - loads current chip state * @rinfo: pointer to rivafb_info object containing info for current riva board * @regs: pointer to riva_regs object * * DESCRIPTION: * Loads chip state from @regs. * * CALLED FROM: * riva_load_video_mode() * rivafb_init_one() * rivafb_remove_one() *//* from GGI */static void riva_load_state(struct rivafb_info *rinfo, struct riva_regs *regs){ int i; RIVA_HW_STATE *state = ®s->ext; CRTCout(rinfo, 0x11, 0x00); rinfo->riva.LockUnlock(&rinfo->riva, 0); rinfo->riva.LoadStateExt(&rinfo->riva, state); MISCout(rinfo, regs->misc_output); for (i = 0; i < NUM_CRT_REGS; i++) { switch (i) { case 0x19: case 0x20 ... 0x40: break; default: CRTCout(rinfo, i, regs->crtc[i]); } } for (i = 0; i < NUM_ATC_REGS; i++) { ATTRout(rinfo, i, regs->attr[i]); } for (i = 0; i < NUM_GRC_REGS; i++) { GRAout(rinfo, i, regs->gra[i]); } for (i = 0; i < NUM_SEQ_REGS; i++) { SEQout(rinfo, i, regs->seq[i]); }}/** * riva_load_video_mode - calculate timings * @rinfo: pointer to rivafb_info object containing info for current riva board * @video_mode: video mode to set * * DESCRIPTION: * Calculate some timings and then send em off to riva_load_state(). * * CALLED FROM: * rivafb_set_var() */static void riva_load_video_mode(struct rivafb_info *rinfo, struct fb_var_screeninfo *video_mode){ struct riva_regs newmode; int bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock; int hBlankStart, hBlankEnd, vBlankStart, vBlankEnd; /* time to calculate */ rivafb_blank(1, (struct fb_info *)rinfo); bpp = video_mode->bits_per_pixel; if (bpp == 16 && video_mode->green.length == 5) bpp = 15; width = video_mode->xres_virtual; hDisplaySize = video_mode->xres; hDisplay = (hDisplaySize / 8) - 1; hStart = (hDisplaySize + video_mode->right_margin) / 8 + 2; hEnd = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len) / 8 - 1; hTotal = (hDisplaySize + video_mode->right_margin + video_mode->hsync_len + video_mode->left_margin) / 8 - 1; hBlankStart = hDisplay; hBlankEnd = hTotal; height = video_mode->yres_virtual; vDisplay = video_mode->yres - 1; vStart = video_mode->yres + video_mode->lower_margin - 1; vEnd = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len - 1; vTotal = video_mode->yres + video_mode->lower_margin + video_mode->vsync_len + video_mode->upper_margin + 2; vBlankStart = vDisplay; vBlankEnd = vTotal; dotClock = 1000000000 / video_mode->pixclock; memcpy(&newmode, ®_template, sizeof(struct riva_regs)); newmode.ext.screen = SetBitField(hBlankEnd,6:6,4:4) | SetBitField(vBlankStart,10:10,3:3) | SetBitField(vStart,10:10,2:2) | SetBitField(vDisplay,10:10,1:1) | SetBitField(vTotal,10:10,0:0); newmode.ext.horiz = SetBitField(hTotal,8:8,0:0) | SetBitField(hDisplay,8:8,1:1) | SetBitField(hBlankStart,8:8,2:2) | SetBitField(hStart,8:8,3:3); newmode.ext.extra = SetBitField(vTotal,11:11,0:0) | SetBitField(vDisplay,11:11,2:2) | SetBitField(vStart,11:11,4:4) | SetBitField(vBlankStart,11:11,6:6); if (rinfo->riva.flatPanel) { vStart = vTotal - 3; vEnd = vTotal - 2; vBlankStart = vStart; hStart = hTotal - 3; hEnd = hTotal - 2; hBlankEnd = hTotal + 4; } newmode.crtc[0x0] = Set8Bits (hTotal - 4); newmode.crtc[0x1] = Set8Bits (hDisplay); newmode.crtc[0x2] = Set8Bits (hBlankStart); newmode.crtc[0x3] = SetBitField(hBlankEnd,4:0,4:0) | SetBit(7); newmode.crtc[0x4] = Set8Bits (hStart); newmode.crtc[0x5] = SetBitField (hBlankEnd, 5: 5, 7:7) | SetBitField (hEnd, 4: 0, 4:0); newmode.crtc[0x6] = SetBitField (vTotal, 7: 0, 7:0); newmode.crtc[0x7] = SetBitField (vTotal, 8: 8, 0:0) | SetBitField (vDisplay, 8: 8, 1:1) | SetBitField (vStart, 8: 8, 2:2) | SetBitField (vBlankStart, 8: 8, 3:3) | SetBit (4) | SetBitField (vTotal, 9: 9, 5:5) | SetBitField (vDisplay, 9: 9, 6:6) | SetBitField (vStart, 9: 9, 7:7); newmode.crtc[0x9] = SetBitField (vBlankStart, 9: 9, 5:5) | SetBit (6); newmode.crtc[0x10] = Set8Bits (vStart); newmode.crtc[0x11] = SetBitField (vEnd, 3: 0, 3:0) | SetBit (5); newmode.crtc[0x12] = Set8Bits (vDisplay); newmode.crtc[0x13] = ((width / 8) * ((bpp + 1) / 8)) & 0xFF; newmode.crtc[0x15] = Set8Bits (vBlankStart); newmode.crtc[0x16] = Set8Bits (vBlankEnd + 1); newmode.ext.bpp = bpp; newmode.ext.width = width; newmode.ext.height = height; rinfo->riva.CalcStateExt(&rinfo->riva, &newmode.ext, bpp, width, hDisplaySize, hDisplay, hStart, hEnd, hTotal, height, vDisplay, vStart, vEnd, vTotal, dotClock); newmode.ext.scale = rinfo->riva.PRAMDAC[0x00000848/4] & 0xfff000ff; if (rinfo->riva.flatPanel) { newmode.ext.pixel |= (1 << 7); newmode.ext.scale |= (1 << 8); } newmode.ext.vpll2 = rinfo->riva.PRAMDAC[0x00000520/4];#if defined(__powerpc__) /* * XXX only Mac cards use second DAC for flat panel */ if (rinfo->riva.flatPanel) { newmode.ext.pllsel |= 0x20000800; newmode.ext.vpll2 = newmode.ext.vpll; }#endif rinfo->current_state = newmode; riva_load_state(rinfo, &rinfo->current_state); rinfo->riva.LockUnlock(&rinfo->riva, 0); /* important for HW cursor */ rivafb_download_cursor(rinfo); rivafb_blank(0, (struct fb_info *)rinfo);}/** * riva_board_list_add - maintains board list * @board_list: root node of list of boards * @new_node: new node to be added * * DESCRIPTION: * Adds @new_node to the list referenced by @board_list. * * RETURNS: * New root node * * CALLED FROM: * rivafb_init_one() */static struct rivafb_info *riva_board_list_add(struct rivafb_info *board_list, struct rivafb_info *new_node){ struct rivafb_info *i_p = board_list; new_node->next = NULL; if (board_list == NULL) return new_node; while (i_p->next != NULL) i_p = i_p->next; i_p->next = new_node; return board_list;}/** * riva_board_list_del - maintains board list * @board_list: root node of list of boards * @del_node: node to be removed * * DESCRIPTION: * Removes @del_node from the list referenced by @board_list. * * RETURNS: * New root node * * CALLED FROM: * rivafb_remove_one() */static struct rivafb_info *riva_board_list_del(struct rivafb_info *board_list, struct rivafb_info *del_node){ struct rivafb_info *i_p = board_list; if (board_list == del_node) return del_node->next; while (i_p->next != del_node) i_p = i_p->next; i_p->next = del_node->next; return board_list;}/** * rivafb_do_maximize - * @rinfo: pointer to rivafb_info object containing info for current riva board * @var: * @v: * @nom: * @den: * * DESCRIPTION: * . * * RETURNS: * -EINVAL on failure, 0 on success * * * CALLED FROM: * rivafb_set_var() */static int rivafb_do_maximize(struct rivafb_info *rinfo, struct fb_var_screeninfo *var, struct fb_var_screeninfo *v, int nom, int den){ static struct { int xres, yres; } modes[] = { {1600, 1280}, {1280, 1024}, {1024, 768}, {800, 600}, {640, 480}, {-1, -1} }; int i; /* use highest possible virtual resolution */ if (v->xres_virtual == -1 && v->yres_virtual == -1) { printk(KERN_WARNING PFX "using maximum available virtual resolution\n"); for (i = 0; modes[i].xres != -1; i++) { if (modes[i].xres * nom / den * modes[i].yres < rinfo->ram_amount / 2) break; } if (modes[i].xres == -1) { printk(KERN_ERR PFX "could not find a virtual resolution that fits into video memory!!\n"); DPRINTK("EXIT - EINVAL error\n"); return -EINVAL; } v->xres_virtual = modes[i].xres; v->yres_virtual = modes[i].yres; printk(KERN_INFO PFX "virtual resolution set to maximum of %dx%d\n", v->xres_virtual, v->yres_virtual); } else if (v->xres_virtual == -1) { v->xres_virtual = (rinfo->ram_amount * den / (nom * v->yres_virtual * 2)) & ~15; printk(KERN_WARNING PFX "setting virtual X resolution to %d\n", v->xres_virtual); } else if (v->yres_virtual == -1) { v->xres_virtual = (v->xres_virtual + 15) & ~15; v->yres_virtual = rinfo->ram_amount * den / (nom * v->xres_virtual * 2); printk(KERN_WARNING PFX "setting virtual Y resolution to %d\n", v->yres_virtual); } else { v->xres_virtual = (v->xres_virtual + 15) & ~15; if (v->xres_virtual * nom / den * v->yres_virtual > rinfo->ram_amount) { printk(KERN_ERR PFX "mode %dx%dx%d rejected...resolution too high to fit into video memory!\n", var->xres, var->yres, var->bits_per_pixel); DPRINTK("EXIT - EINVAL error\n"); return -EINVAL; } } if (v->xres_virtual * nom / den >= 8192) { printk(KERN_WARNING PFX "virtual X resolution (%d) is too high, lowering to %d\n", v->xres_virtual, 8192 * den / nom - 16); v->xres_virtual = 8192 * den / nom - 16; } if (v->xres_virtual < v->xres) { printk(KERN_ERR PFX "virtual X resolution (%d) is smaller than real\n", v->xres_virtual); return -EINVAL; } if (v->yres_virtual < v->yres) { printk(KERN_ERR PFX "virtual Y resolution (%d) is smaller than real\n", v->yres_virtual); return -EINVAL; } return 0;}/* ------------------------------------------------------------------------- * * * internal fb_ops helper functions * * ------------------------------------------------------------------------- *//** * riva_get_cmap_len - query current color map length * @var: standard kernel fb changeable data * * DESCRIPTION: * Get current color map length. * * RETURNS: * Length of color map * * CALLED FROM: * riva_getcolreg() * riva_setcolreg() * rivafb_get_cmap() * rivafb_set_cmap() */static int riva_get_cmap_len(const struct fb_var_screeninfo *var){ int rc = 16; /* reasonable default */ assert(var != NULL); switch (var->bits_per_pixel) {#ifdef FBCON_HAS_CFB8
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -