📄 matroxfb_base.c
字号:
var->xres_virtual = var->xres; if (var->bits_per_pixel) { var->xres_virtual = matroxfb_pitch_adjust(PMINFO var->xres_virtual, var->bits_per_pixel); memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; if (memlen > vramlen) { var->yres_virtual = vramlen * 8 / (var->xres_virtual * var->bits_per_pixel); memlen = var->xres_virtual * var->bits_per_pixel * var->yres_virtual / 8; } /* There is hardware bug that no line can cross 4MB boundary */ /* give up for CFB24, it is impossible to easy workaround it */ /* for other try to do something */ if (!ACCESS_FBINFO(capable.cross4MB) && (memlen > 0x400000)) { if (var->bits_per_pixel == 24) { /* sorry */ } else { unsigned int linelen; unsigned int m1 = linelen = var->xres_virtual * var->bits_per_pixel / 8; unsigned int m2 = PAGE_SIZE; /* or 128 if you do not need PAGE ALIGNED address */ unsigned int max_yres; while (m1) { int t; while (m2 >= m1) m2 -= m1; t = m1; m1 = m2; m2 = t; } m2 = linelen * PAGE_SIZE / m2; *ydstorg = m2 = 0x400000 % m2; max_yres = (vramlen - m2) / linelen; if (var->yres_virtual > max_yres) var->yres_virtual = max_yres; } } } else { matrox_text_round(PMINFO var, p);#if 0/* we must limit pixclock by mclk... Millennium I: 66 MHz = 15000 Millennium II: 61 MHz = 16300 Millennium G200: 83 MHz = 12000 */ if (var->pixclock < 15000) var->pixclock = 15000; /* limit for "normal" gclk & mclk */#endif } /* YDSTLEN contains only signed 16bit value */ if (var->yres_virtual > 32767) var->yres_virtual = 32767; /* we must round yres/xres down, we already rounded y/xres_virtual up if it was possible. We should return -EINVAL, but I disagree */ if (var->yres_virtual < var->yres) var->yres = var->yres_virtual; if (var->xres_virtual < var->xres) var->xres = var->xres_virtual; if (var->xoffset + var->xres > var->xres_virtual) var->xoffset = var->xres_virtual - var->xres; if (var->yoffset + var->yres > var->yres_virtual) var->yoffset = var->yres_virtual - var->yres; if (var->bits_per_pixel == 0) { var->red.offset = 0; var->red.length = 6; var->green.offset = 0; var->green.length = 6; var->blue.offset = 0; var->blue.length = 6; var->transp.offset = 0; var->transp.length = 0; *visual = MX_VISUAL_PSEUDOCOLOR; } else if (var->bits_per_pixel == 4) { var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; *visual = MX_VISUAL_PSEUDOCOLOR; } else if (var->bits_per_pixel <= 8) { var->red.offset = 0; var->red.length = 8; var->green.offset = 0; var->green.length = 8; var->blue.offset = 0; var->blue.length = 8; var->transp.offset = 0; var->transp.length = 0; *visual = MX_VISUAL_PSEUDOCOLOR; } else { if (var->bits_per_pixel <= 16) { if (var->green.length == 5) { var->red.offset = 10; var->red.length = 5; var->green.offset = 5; var->green.length = 5; var->blue.offset = 0; var->blue.length = 5; var->transp.offset = 15; var->transp.length = 1; } else { 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; } } else if (var->bits_per_pixel <= 24) { 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; } else { 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; } dprintk("matroxfb: truecolor: " "size=%d:%d:%d:%d, shift=%d:%d:%d:%d\n", var->transp.length, var->red.length, var->green.length, var->blue.length, var->transp.offset, var->red.offset, var->green.offset, var->blue.offset); *visual = MX_VISUAL_DIRECTCOLOR; } *video_cmap_len = matroxfb_get_cmap_len(var); dprintk(KERN_INFO "requested %d*%d/%dbpp (%d*%d)\n", var->xres, var->yres, var->bits_per_pixel, var->xres_virtual, var->yres_virtual); return 0;}static int matrox_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue, unsigned transp, struct fb_info *fb_info){ struct display* p;#ifdef CONFIG_FB_MATROX_MULTIHEAD struct matrox_fb_info* minfo = (struct matrox_fb_info*)fb_info;#endif DBG("matrox_setcolreg") /* * Set a single color register. The values supplied are * already rounded down to the hardware's capabilities * (according to the entries in the `var' structure). Return * != 0 for invalid regno. */ if (regno >= ACCESS_FBINFO(curr.cmap_len)) return 1; ACCESS_FBINFO(palette[regno].red) = red; ACCESS_FBINFO(palette[regno].green) = green; ACCESS_FBINFO(palette[regno].blue) = blue; ACCESS_FBINFO(palette[regno].transp) = transp; p = ACCESS_FBINFO(currcon_display); if (p->var.grayscale) { /* gray = 0.30*R + 0.59*G + 0.11*B */ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; } red = CNVT_TOHW(red, p->var.red.length); green = CNVT_TOHW(green, p->var.green.length); blue = CNVT_TOHW(blue, p->var.blue.length); transp = CNVT_TOHW(transp, p->var.transp.length); switch (p->var.bits_per_pixel) {#if defined(FBCON_HAS_CFB8) || defined(FBCON_HAS_CFB4) || defined(FBCON_HAS_VGATEXT)#ifdef FBCON_HAS_VGATEXT case 0:#endif#ifdef FBCON_HAS_CFB4 case 4:#endif#ifdef FBCON_HAS_CFB8 case 8:#endif mga_outb(M_DAC_REG, regno); mga_outb(M_DAC_VAL, red); mga_outb(M_DAC_VAL, green); mga_outb(M_DAC_VAL, blue); break;#endif#ifdef FBCON_HAS_CFB16 case 16: ACCESS_FBINFO(cmap.cfb16[regno]) = (red << p->var.red.offset) | (green << p->var.green.offset) | (blue << p->var.blue.offset) | (transp << p->var.transp.offset); /* for 1:5:5:5 */ break;#endif#ifdef FBCON_HAS_CFB24 case 24: ACCESS_FBINFO(cmap.cfb24[regno]) = (red << p->var.red.offset) | (green << p->var.green.offset) | (blue << p->var.blue.offset); break;#endif#ifdef FBCON_HAS_CFB32 case 32: ACCESS_FBINFO(cmap.cfb32[regno]) = (red << p->var.red.offset) | (green << p->var.green.offset) | (blue << p->var.blue.offset) | (transp << p->var.transp.offset); /* 8:8:8:8 */ break;#endif } return 0;}static void do_install_cmap(WPMINFO struct display* dsp){ DBG("do_install_cmap") if (dsp->cmap.len) fb_set_cmap(&dsp->cmap, 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon)); else fb_set_cmap(fb_default_cmap(ACCESS_FBINFO(curr.cmap_len)), 1, matrox_setcolreg, &ACCESS_FBINFO(fbcon));}static int matroxfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ struct display* p; DBG("matroxfb_get_fix")#define minfo ((struct matrox_fb_info*)info) if (ACCESS_FBINFO(dead)) { return -ENXIO; } if (con >= 0) p = fb_display + con; else p = ACCESS_FBINFO(fbcon.disp); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id,"MATROX"); fix->smem_start = ACCESS_FBINFO(video.base) + ACCESS_FBINFO(curr.ydstorg.bytes); fix->smem_len = ACCESS_FBINFO(video.len_usable) - ACCESS_FBINFO(curr.ydstorg.bytes); fix->type = p->type; fix->type_aux = p->type_aux; fix->visual = p->visual; fix->xpanstep = 8; /* 8 for 8bpp, 4 for 16bpp, 2 for 32bpp */ fix->ypanstep = 1; fix->ywrapstep = 0; fix->line_length = p->line_length; fix->mmio_start = ACCESS_FBINFO(mmio.base); fix->mmio_len = ACCESS_FBINFO(mmio.len); fix->accel = ACCESS_FBINFO(devflags.accelerator); return 0;#undef minfo}static int matroxfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) DBG("matroxfb_get_var") if(con < 0) *var=ACCESS_FBINFO(fbcon.disp)->var; else *var=fb_display[con].var; return 0;#undef minfo}static int matroxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){#define minfo ((struct matrox_fb_info*)info) int err; int visual; int cmap_len; unsigned int ydstorg; struct display* display; int chgvar; DBG("matroxfb_set_var") if (ACCESS_FBINFO(dead)) { return -ENXIO; } if (con >= 0) display = fb_display + con; else display = ACCESS_FBINFO(fbcon.disp); if ((err = matroxfb_decode_var(PMINFO display, var, &visual, &cmap_len, &ydstorg)) != 0) return err; switch (var->activate & FB_ACTIVATE_MASK) { case FB_ACTIVATE_TEST: return 0; case FB_ACTIVATE_NXTOPEN: /* ?? */ case FB_ACTIVATE_NOW: break; /* continue */ default: return -EINVAL; /* unknown */ } if (con >= 0) { chgvar = ((display->var.xres != var->xres) || (display->var.yres != var->yres) || (display->var.xres_virtual != var->xres_virtual) || (display->var.yres_virtual != var->yres_virtual) || (display->var.bits_per_pixel != var->bits_per_pixel) || memcmp(&display->var.red, &var->red, sizeof(var->red)) || memcmp(&display->var.green, &var->green, sizeof(var->green)) || memcmp(&display->var.blue, &var->blue, sizeof(var->blue))); } else { chgvar = 0; } display->var = *var; /* cmap */ display->screen_base = vaddr_va(ACCESS_FBINFO(video.vbase)) + ydstorg; display->visual = visual; display->ypanstep = 1; display->ywrapstep = 0; if (var->bits_per_pixel) { display->type = FB_TYPE_PACKED_PIXELS; display->type_aux = 0; display->next_line = display->line_length = (var->xres_virtual * var->bits_per_pixel) >> 3; } else { display->type = FB_TYPE_TEXT; display->type_aux = ACCESS_FBINFO(devflags.text_type_aux); display->next_line = display->line_length = (var->xres_virtual / (fontwidth(display)?fontwidth(display):8)) * ACCESS_FBINFO(devflags.textstep); } display->can_soft_blank = 1; display->inverse = ACCESS_FBINFO(devflags.inverse); /* conp, fb_info, vrows, cursor_x, cursor_y, fgcol, bgcol */ /* next_plane, fontdata, _font*, userfont */ initMatrox(PMINFO display); /* dispsw */ /* dispsw, scrollmode, yscroll */ /* fgshift, bgshift, charmask */ if (chgvar && info && info->changevar) info->changevar(con); if (con == ACCESS_FBINFO(currcon)) { unsigned int pos; ACCESS_FBINFO(curr.cmap_len) = cmap_len; if (display->type == FB_TYPE_TEXT) { /* textmode must be in first megabyte, so no ydstorg allowed */ ACCESS_FBINFO(curr.ydstorg.bytes) = 0; ACCESS_FBINFO(curr.ydstorg.chunks) = 0; ACCESS_FBINFO(curr.ydstorg.pixels) = 0; } else { ydstorg += ACCESS_FBINFO(devflags.ydstorg); ACCESS_FBINFO(curr.ydstorg.bytes) = ydstorg; ACCESS_FBINFO(curr.ydstorg.chunks) = ydstorg >> (isInterleave(MINFO)?3:2); if (var->bits_per_pixel == 4) ACCESS_FBINFO(curr.ydstorg.pixels) = ydstorg; else ACCESS_FBINFO(curr.ydstorg.pixels) = (ydstorg * 8) / var->bits_per_pixel; } ACCESS_FBINFO(curr.final_bppShift) = matroxfb_get_final_bppShift(PMINFO var->bits_per_pixel); if (visual == MX_VISUAL_PSEUDOCOLOR) { int i; for (i = 0; i < 16; i++) { int j; j = color_table[i]; ACCESS_FBINFO(palette[i].red) = default_red[j]; ACCESS_FBINFO(palette[i].green) = default_grn[j]; ACCESS_FBINFO(palette[i].blue) = default_blu[j]; } } { struct my_timming mt; struct matrox_hw_state* hw; struct matrox_hw_state* ohw; matroxfb_var2my(var, &mt); /* CRTC1 delays */ switch (var->bits_per_pixel) { case 0: mt.delay = 31 + 0; break; case 16: mt.delay = 21 + 8; break; case 24: mt.delay = 17 + 8; break; case 32: mt.delay = 16 + 8; break; default: mt.delay = 31 + 8; break; } hw = ACCESS_FBINFO(newhw); ohw = ACCESS_FBINFO(currenthw); /* copy last setting... */ memcpy(hw, ohw, sizeof(*hw)); del_timer_sync(&ACCESS_FBINFO(cursor.timer)); ACCESS_FBINFO(cursor.state) = CM_ERASE; ACCESS_FBINFO(hw_switch->init(PMINFO hw, &mt, display)); if (display->type == FB_TYPE_TEXT) { if (fontheight(display)) pos = var->yoffset / fontheight(display) * display->next_line / ACCESS_FBINFO(devflags.textstep) + var->xoffset / (fontwidth(display)?fontwidth(display):8); else pos = 0; } else { pos = (var->yoffset * var->xres_virtual + var->xoffset) * ACCESS_FBINFO(curr.final_bppShift) / 32; pos += ACCESS_FBINFO(curr.ydstorg.chunks); } hw->CRTC[0x0D] = pos & 0xFF;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -