📄 matroxfb_base.c
字号:
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 = ACCESS_FBINFO(fbcon.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; int out; matroxfb_var2my(var, &mt); mt.crtc = MATROXFB_SRC_CRTC1; /* 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(hw); del_timer_sync(&ACCESS_FBINFO(cursor.timer)); ACCESS_FBINFO(cursor.state) = CM_ERASE; down_read(&ACCESS_FBINFO(altout).lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && ACCESS_FBINFO(outputs[out]).output->compute) { ACCESS_FBINFO(outputs[out]).output->compute(ACCESS_FBINFO(outputs[out]).data, &mt); } } up_read(&ACCESS_FBINFO(altout).lock); ACCESS_FBINFO(crtc1).pixclock = mt.pixclock; ACCESS_FBINFO(crtc1).mnp = mt.mnp; ACCESS_FBINFO(hw_switch->init(PMINFO &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; hw->CRTC[0x0C] = (pos & 0xFF00) >> 8; hw->CRTCEXT[0] = (hw->CRTCEXT[0] & 0xF0) | ((pos >> 16) & 0x0F) | ((pos >> 14) & 0x40); hw->CRTCEXT[8] = pos >> 21; ACCESS_FBINFO(hw_switch->restore(PMINFO display)); down_read(&ACCESS_FBINFO(altout).lock); for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && ACCESS_FBINFO(outputs[out]).output->program) { ACCESS_FBINFO(outputs[out]).output->program(ACCESS_FBINFO(outputs[out]).data); } } ACCESS_FBINFO(cursor.redraw) = 1; for (out = 0; out < MATROXFB_MAX_OUTPUTS; out++) { if (ACCESS_FBINFO(outputs[out]).src == MATROXFB_SRC_CRTC1 && ACCESS_FBINFO(outputs[out]).output->start) { ACCESS_FBINFO(outputs[out]).output->start(ACCESS_FBINFO(outputs[out]).data); } } up_read(&ACCESS_FBINFO(altout).lock); matrox_cfbX_init(PMINFO display); my_install_cmap(PMINFO2);#if defined(CONFIG_FB_COMPAT_XPMAC) if (console_fb_info == &ACCESS_FBINFO(fbcon)) { int vmode, cmode; display_info.width = var->xres; display_info.height = var->yres; display_info.depth = var->bits_per_pixel; display_info.pitch = (var->xres_virtual)*(var->bits_per_pixel)/8; if (mac_var_to_vmode(var, &vmode, &cmode)) display_info.mode = 0; else display_info.mode = vmode; strcpy(display_info.name, ACCESS_FBINFO(matrox_name)); display_info.fb_address = ACCESS_FBINFO(video.base); display_info.cmap_adr_address = 0; display_info.cmap_data_address = 0; display_info.disp_reg_address = ACCESS_FBINFO(mmio.base); }#endif /* CONFIG_FB_COMPAT_XPMAC */ } } return 0;#undef minfo}static int matrox_getcolreg(unsigned regno, unsigned *red, unsigned *green, unsigned *blue, unsigned *transp, struct fb_info *info){ DBG("matrox_getcolreg")#define minfo (list_entry(info, struct matrox_fb_info, fbcon)) /* * Read a single color register and split it into colors/transparent. * Return != 0 for invalid regno. */ if (regno >= ACCESS_FBINFO(curr.cmap_len)) return 1; *red = ACCESS_FBINFO(palette[regno].red); *green = ACCESS_FBINFO(palette[regno].green); *blue = ACCESS_FBINFO(palette[regno].blue); *transp = ACCESS_FBINFO(palette[regno].transp); return 0;#undef minfo}static int matroxfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){#define minfo (list_entry(info, struct matrox_fb_info, fbcon)) struct display* dsp = (con < 0) ? ACCESS_FBINFO(fbcon.disp) : fb_display + con; DBG("matroxfb_get_cmap") if (ACCESS_FBINFO(dead)) { return -ENXIO; } if (con == ACCESS_FBINFO(currcon)) /* current console? */ return fb_get_cmap(cmap, kspc, matrox_getcolreg, info); else if (dsp->cmap.len) /* non default colormap? */ fb_copy_cmap(&dsp->cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(matroxfb_get_cmap_len(&dsp->var)), cmap, kspc ? 0 : 2); return 0;#undef minfo}static int matroxfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ unsigned int cmap_len; struct display* dsp = (con < 0) ? info->disp : (fb_display + con);#define minfo (list_entry(info, struct matrox_fb_info, fbcon)) DBG("matroxfb_set_cmap") if (ACCESS_FBINFO(dead)) { return -ENXIO; } cmap_len = matroxfb_get_cmap_len(&dsp->var); if (dsp->cmap.len != cmap_len) { int err; err = fb_alloc_cmap(&dsp->cmap, cmap_len, 0); if (err) return err; } if (con == ACCESS_FBINFO(currcon)) { /* current console? */ return fb_set_cmap(cmap, kspc, matroxfb_setcolreg, info); } else fb_copy_cmap(cmap, &dsp->cmap, kspc ? 0 : 1); return 0;#undef minfo}static int matroxfb_get_vblank(WPMINFO struct fb_vblank *vblank){ unsigned int sts1; matroxfb_enable_irq(PMINFO 0); memset(vblank, 0, sizeof(*vblank)); vblank->flags = FB_VBLANK_HAVE_VCOUNT | FB_VBLANK_HAVE_VSYNC | FB_VBLANK_HAVE_VBLANK | FB_VBLANK_HAVE_HBLANK; sts1 = mga_inb(M_INSTS1); vblank->vcount = mga_inl(M_VCOUNT); /* BTW, on my PIII/450 with G400, reading M_INSTS1 byte makes this call about 12% slower (1.70 vs. 2.05 us per ioctl()) */ if (sts1 & 1) vblank->flags |= FB_VBLANK_HBLANKING; if (sts1 & 8) vblank->flags |= FB_VBLANK_VSYNCING; if (vblank->vcount >= ACCESS_FBINFO(currcon_display)->var.yres) vblank->flags |= FB_VBLANK_VBLANKING; if (test_bit(0, &ACCESS_FBINFO(irq_flags))) { vblank->flags |= FB_VBLANK_HAVE_COUNT; /* Only one writer, aligned int value... it should work without lock and without atomic_t */ vblank->count = ACCESS_FBINFO(crtc1).vsync.cnt; } return 0;}static struct matrox_altout panellink_output = { .owner = THIS_MODULE, .name = "Panellink output",};static int matroxfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){#define minfo (list_entry(info, struct matrox_fb_info, fbcon)) DBG("matroxfb_ioctl") if (ACCESS_FBINFO(dead)) { return -ENXIO; } switch (cmd) { case FBIOGET_VBLANK: { struct fb_vblank vblank; int err; err = matroxfb_get_vblank(PMINFO &vblank); if (err) return err; if (copy_to_user((struct fb_vblank*)arg, &vblank, sizeof(vblank))) return -EFAULT; return 0; } case FBIO_WAITFORVSYNC: { u_int32_t crt; if (get_user(crt, (u_int32_t *)arg)) return -EFAULT; return matroxfb_wait_for_sync(PMINFO crt); } case MATROXFB_SET_OUTPUT_MODE: { struct matroxioc_output_mode mom; struct matrox_altout *oproc; int val; if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; down_read(&ACCESS_FBINFO(altout.lock)); oproc = ACCESS_FBINFO(outputs[mom.output]).output; if (!oproc) { val = -ENXIO; } else if (!oproc->verifymode) { if (mom.mode == MATROXFB_OUTPUT_MODE_MONITOR) { val = 0; } else { val = -EINVAL; } } else { val = oproc->verifymode(ACCESS_FBINFO(outputs[mom.output]).data, mom.mode); } if (!val) { if (ACCESS_FBINFO(outputs[mom.output]).mode != mom.mode) { ACCESS_FBINFO(outputs[mom.output]).mode = mom.mode; val = 1; } } up_read(&ACCESS_FBINFO(altout.lock)); if (val != 1) return val; switch (ACCESS_FBINFO(outputs[mom.output]).src) { case MATROXFB_SRC_CRTC1: matroxfb_switch(ACCESS_FBINFO(currcon), info); break; case MATROXFB_SRC_CRTC2: { struct matroxfb_dh_fb_info* crtc2; down_read(&ACCESS_FBINFO(crtc2.lock)); crtc2 = ACCESS_FBINFO(crtc2.info); if (crtc2) crtc2->fbcon.switch_con(crtc2->currcon, &crtc2->fbcon); up_read(&ACCESS_FBINFO(crtc2.lock)); } break; } return 0; } case MATROXFB_GET_OUTPUT_MODE: { struct matroxioc_output_mode mom; struct matrox_altout *oproc; int val; if (copy_from_user(&mom, (struct matroxioc_output_mode*)arg, sizeof(mom))) return -EFAULT; if (mom.output >= MATROXFB_MAX_OUTPUTS) return -ENXIO; down_read(&ACCESS_FBINFO(altout.lock)); oproc = ACCESS_FBINFO(outputs[mom.output]).output; if (!oproc) { val = -ENXIO; } else { mom.mode = ACCESS_FBINFO(outputs[mom.output]).mode; val = 0; } up_read(&ACCESS_FBINFO(altout.lock)); if (val) return val; if (copy_to_user((struct matroxioc_output_mode*)arg, &mom, sizeof(mom))) return -EFAULT; return 0; } case MATROXFB_SET_OUTPUT_CONNECTION: { u_int32_t tmp; int i; int changes; if (copy_from_user(&tmp, (u_int32_t*)arg, sizeof(tmp))) return -EFAULT; for (i = 0; i < 32; i++) { if (tmp & (1 << i)) { if (i >= MATROXFB_MAX_OUTPUTS) return -ENXIO; if (!ACCESS_FBINFO(outputs[i]).output) return -ENXIO; switch (ACCESS_FBINFO(outputs[i]).src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC1: break; default: return -EBUSY; } } } if (ACCESS_FBINFO(devflags.panellink)) { if (tmp & MATROXFB_OUTPUT_CONN_DFP) { if (tmp & MATROXFB_OUTPUT_CONN_SECONDARY) return -EINVAL; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC2) { return -EBUSY; } } } } changes = 0; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (tmp & (1 << i)) { if (ACCESS_FBINFO(outputs[i]).src != MATROXFB_SRC_CRTC1) { changes = 1; ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_CRTC1; } } else if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { changes = 1; ACCESS_FBINFO(outputs[i]).src = MATROXFB_SRC_NONE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -