📄 svgalib.c
字号:
vga_wcrt(NULL, 0x0E, pos >> 8); vga_wcrt(NULL, 0x0F, pos & 0xFF); vga_wcrt(NULL, 0x0B, ce); /* set cursor end */ vga_wcrt(NULL, 0x0A, cs); /* set cursor start and enable it */}int svga_get_tilemax(struct fb_info *info){ return 256;}/* Get capabilities of accelerator based on the mode */void svga_get_caps(struct fb_info *info, struct fb_blit_caps *caps, struct fb_var_screeninfo *var){ if (var->bits_per_pixel == 0) { /* can only support 256 8x16 bitmap */ caps->x = 1 << (8 - 1); caps->y = 1 << (16 - 1); caps->len = 256; } else { caps->x = (var->bits_per_pixel == 4) ? 1 << (8 - 1) : ~(u32)0; caps->y = ~(u32)0; caps->len = ~(u32)0; }}EXPORT_SYMBOL(svga_get_caps);/* ------------------------------------------------------------------------- *//* * Compute PLL settings (M, N, R) * F_VCO = (F_BASE * M) / N * F_OUT = F_VCO / (2^R) */static inline u32 abs_diff(u32 a, u32 b){ return (a > b) ? (a - b) : (b - a);}int svga_compute_pll(const struct svga_pll *pll, u32 f_wanted, u16 *m, u16 *n, u16 *r, int node){ u16 am, an, ar; u32 f_vco, f_current, delta_current, delta_best; pr_debug("fb%d: ideal frequency: %d kHz\n", node, (unsigned int) f_wanted); ar = pll->r_max; f_vco = f_wanted << ar; /* overflow check */ if ((f_vco >> ar) != f_wanted) return -EINVAL; /* It is usually better to have greater VCO clock because of better frequency stability. So first try r_max, then r smaller. */ while ((ar > pll->r_min) && (f_vco > pll->f_vco_max)) { ar--; f_vco = f_vco >> 1; } /* VCO bounds check */ if ((f_vco < pll->f_vco_min) || (f_vco > pll->f_vco_max)) return -EINVAL; delta_best = 0xFFFFFFFF; *m = 0; *n = 0; *r = ar; am = pll->m_min; an = pll->n_min; while ((am <= pll->m_max) && (an <= pll->n_max)) { f_current = (pll->f_base * am) / an; delta_current = abs_diff (f_current, f_vco); if (delta_current < delta_best) { delta_best = delta_current; *m = am; *n = an; } if (f_current <= f_vco) { am ++; } else { an ++; } } f_current = (pll->f_base * *m) / *n; pr_debug("fb%d: found frequency: %d kHz (VCO %d kHz)\n", node, (int) (f_current >> ar), (int) f_current); pr_debug("fb%d: m = %d n = %d r = %d\n", node, (unsigned int) *m, (unsigned int) *n, (unsigned int) *r); return 0;}/* ------------------------------------------------------------------------- *//* Check CRT timing values */int svga_check_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, int node){ u32 value; var->xres = (var->xres+7)&~7; var->left_margin = (var->left_margin+7)&~7; var->right_margin = (var->right_margin+7)&~7; var->hsync_len = (var->hsync_len+7)&~7; /* Check horizontal total */ value = var->xres + var->left_margin + var->right_margin + var->hsync_len; if (((value / 8) - 5) >= svga_regset_size (tm->h_total_regs)) return -EINVAL; /* Check horizontal display and blank start */ value = var->xres; if (((value / 8) - 1) >= svga_regset_size (tm->h_display_regs)) return -EINVAL; if (((value / 8) - 1) >= svga_regset_size (tm->h_blank_start_regs)) return -EINVAL; /* Check horizontal sync start */ value = var->xres + var->right_margin; if (((value / 8) - 1) >= svga_regset_size (tm->h_sync_start_regs)) return -EINVAL; /* Check horizontal blank end (or length) */ value = var->left_margin + var->right_margin + var->hsync_len; if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_blank_end_regs))) return -EINVAL; /* Check horizontal sync end (or length) */ value = var->hsync_len; if ((value == 0) || ((value / 8) >= svga_regset_size (tm->h_sync_end_regs))) return -EINVAL; /* Check vertical total */ value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; if ((value - 1) >= svga_regset_size(tm->v_total_regs)) return -EINVAL; /* Check vertical display and blank start */ value = var->yres; if ((value - 1) >= svga_regset_size(tm->v_display_regs)) return -EINVAL; if ((value - 1) >= svga_regset_size(tm->v_blank_start_regs)) return -EINVAL; /* Check vertical sync start */ value = var->yres + var->lower_margin; if ((value - 1) >= svga_regset_size(tm->v_sync_start_regs)) return -EINVAL; /* Check vertical blank end (or length) */ value = var->upper_margin + var->lower_margin + var->vsync_len; if ((value == 0) || (value >= svga_regset_size (tm->v_blank_end_regs))) return -EINVAL; /* Check vertical sync end (or length) */ value = var->vsync_len; if ((value == 0) || (value >= svga_regset_size (tm->v_sync_end_regs))) return -EINVAL; return 0;}/* Set CRT timing registers */void svga_set_timings(const struct svga_timing_regs *tm, struct fb_var_screeninfo *var, u32 hmul, u32 hdiv, u32 vmul, u32 vdiv, u32 hborder, int node){ u8 regval; u32 value; value = var->xres + var->left_margin + var->right_margin + var->hsync_len; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal total : %d\n", node, value); svga_wcrt_multi(tm->h_total_regs, (value / 8) - 5); value = var->xres; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal display : %d\n", node, value); svga_wcrt_multi(tm->h_display_regs, (value / 8) - 1); value = var->xres; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal blank start: %d\n", node, value); svga_wcrt_multi(tm->h_blank_start_regs, (value / 8) - 1 + hborder); value = var->xres + var->left_margin + var->right_margin + var->hsync_len; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal blank end : %d\n", node, value); svga_wcrt_multi(tm->h_blank_end_regs, (value / 8) - 1 - hborder); value = var->xres + var->right_margin; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal sync start : %d\n", node, value); svga_wcrt_multi(tm->h_sync_start_regs, (value / 8)); value = var->xres + var->right_margin + var->hsync_len; value = (value * hmul) / hdiv; pr_debug("fb%d: horizontal sync end : %d\n", node, value); svga_wcrt_multi(tm->h_sync_end_regs, (value / 8)); value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical total : %d\n", node, value); svga_wcrt_multi(tm->v_total_regs, value - 2); value = var->yres; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical display : %d\n", node, value); svga_wcrt_multi(tm->v_display_regs, value - 1); value = var->yres; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical blank start : %d\n", node, value); svga_wcrt_multi(tm->v_blank_start_regs, value); value = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical blank end : %d\n", node, value); svga_wcrt_multi(tm->v_blank_end_regs, value - 2); value = var->yres + var->lower_margin; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical sync start : %d\n", node, value); svga_wcrt_multi(tm->v_sync_start_regs, value); value = var->yres + var->lower_margin + var->vsync_len; value = (value * vmul) / vdiv; pr_debug("fb%d: vertical sync end : %d\n", node, value); svga_wcrt_multi(tm->v_sync_end_regs, value); /* Set horizontal and vertical sync pulse polarity in misc register */ regval = vga_r(NULL, VGA_MIS_R); if (var->sync & FB_SYNC_HOR_HIGH_ACT) { pr_debug("fb%d: positive horizontal sync\n", node); regval = regval & ~0x80; } else { pr_debug("fb%d: negative horizontal sync\n", node); regval = regval | 0x80; } if (var->sync & FB_SYNC_VERT_HIGH_ACT) { pr_debug("fb%d: positive vertical sync\n", node); regval = regval & ~0x40; } else { pr_debug("fb%d: negative vertical sync\n\n", node); regval = regval | 0x40; } vga_w(NULL, VGA_MIS_W, regval);}/* ------------------------------------------------------------------------- */static inline int match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var){ int i = 0; int stored = -EINVAL; while (frm->bits_per_pixel != SVGA_FORMAT_END_VAL) { if ((var->bits_per_pixel == frm->bits_per_pixel) && (var->red.length <= frm->red.length) && (var->green.length <= frm->green.length) && (var->blue.length <= frm->blue.length) && (var->transp.length <= frm->transp.length) && (var->nonstd == frm->nonstd)) return i; if (var->bits_per_pixel == frm->bits_per_pixel) stored = i; i++; frm++; } return stored;}int svga_match_format(const struct svga_fb_format *frm, struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix){ int i = match_format(frm, var); if (i >= 0) { var->bits_per_pixel = frm[i].bits_per_pixel; var->red = frm[i].red; var->green = frm[i].green; var->blue = frm[i].blue; var->transp = frm[i].transp; var->nonstd = frm[i].nonstd; if (fix != NULL) { fix->type = frm[i].type; fix->type_aux = frm[i].type_aux; fix->visual = frm[i].visual; fix->xpanstep = frm[i].xpanstep; } } return i;}EXPORT_SYMBOL(svga_wcrt_multi);EXPORT_SYMBOL(svga_wseq_multi);EXPORT_SYMBOL(svga_set_default_gfx_regs);EXPORT_SYMBOL(svga_set_default_atc_regs);EXPORT_SYMBOL(svga_set_default_seq_regs);EXPORT_SYMBOL(svga_set_default_crt_regs);EXPORT_SYMBOL(svga_set_textmode_vga_regs);EXPORT_SYMBOL(svga_settile);EXPORT_SYMBOL(svga_tilecopy);EXPORT_SYMBOL(svga_tilefill);EXPORT_SYMBOL(svga_tileblit);EXPORT_SYMBOL(svga_tilecursor);EXPORT_SYMBOL(svga_get_tilemax);EXPORT_SYMBOL(svga_compute_pll);EXPORT_SYMBOL(svga_check_timings);EXPORT_SYMBOL(svga_set_timings);EXPORT_SYMBOL(svga_match_format);MODULE_AUTHOR("Ondrej Zajicek <santiago@crfreenet.org>");MODULE_DESCRIPTION("Common utility functions for VGA-based graphics cards");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -