📄 matroxfb_base.c
字号:
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(CPMINFO struct fb_vblank *vblank){ unsigned int sts1; 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; vblank->hcount = 0; vblank->count = 0; 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 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; } } if (!changes) return 0; matroxfb_switch(ACCESS_FBINFO(currcon), info); return 0; } case MATROXFB_GET_OUTPUT_CONNECTION: { u_int32_t conn = 0; int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (ACCESS_FBINFO(outputs[i]).src == MATROXFB_SRC_CRTC1) { conn |= 1 << i; } } if (put_user(conn, (u_int32_t*)arg)) return -EFAULT; return 0; } case MATROXFB_GET_AVAILABLE_OUTPUTS: { u_int32_t conn = 0; int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (ACCESS_FBINFO(outputs[i]).output) { switch (ACCESS_FBINFO(outputs[i]).src) { case MATROXFB_SRC_NONE: case MATROXFB_SRC_CRTC1: conn |= 1 << i; break; } } } if (ACCESS_FBINFO(devflags.panellink)) { if (conn & MATROXFB_OUTPUT_CONN_DFP) conn &= ~MATROXFB_OUTPUT_CONN_SECONDARY; if (conn & MATROXFB_OUTPUT_CONN_SECONDARY) conn &= ~MATROXFB_OUTPUT_CONN_DFP; } if (put_user(conn, (u_int32_t*)arg)) return -EFAULT; return 0; } case MATROXFB_GET_ALL_OUTPUTS: { u_int32_t conn = 0; int i; for (i = 0; i < MATROXFB_MAX_OUTPUTS; i++) { if (ACCESS_FBINFO(outputs[i]).output) { conn |= 1 << i; } } if (put_user(conn, (u_int32_t*)arg)) return -EFAULT; return 0; } case 0x80585600: { struct { char name[32]; int type; int inputs; int outputs; int audios; int maxwidth; int maxheight; int minwidth; int minheight; int maxframerate; __u32 flags; __u32 reserved[4]; } r; memset(&r, 0, sizeof(r)); strcat(r.name, "Matrox TVO"); r.type = 2; // output r.inputs = 0; r.outputs = 1; r.audios = 0; r.maxwidth = 1023; // max visible width r.maxheight = 625; // max picture height: full PAL r.minwidth = 512; // min visible width... ~480 r.minheight = 480; // min picture height: visible portion of NTSC r.maxframerate = 60; // max: NTSC, 60Hz interlaced r.flags = 0; // nothing is supported... if (copy_to_user((void*)arg, &r, sizeof(r))) return -EFAULT; return 0; } case MATROXFB_TVOQUERYCTRL: { struct matroxfb_queryctrl qctrl; int err; if (copy_from_user(&qctrl, (struct matroxfb_queryctrl*)arg, sizeof(qctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); if (!ACCESS_FBINFO(outputs[1]).output) { err = -ENXIO; } else if (ACCESS_FBINFO(outputs[1]).output->getqueryctrl) { err = ACCESS_FBINFO(outputs[1]).output->getqueryctrl(ACCESS_FBINFO(outputs[1]).data, &qctrl); } else { err = -EINVAL; } up_read(&ACCESS_FBINFO(altout).lock); if (err >= 0 && copy_to_user((struct matroxfb_queryctrl*)arg, &qctrl, sizeof(qctrl))) return -EFAULT; return err; } case MATROXFB_G_TVOCTRL: { struct matroxfb_control ctrl; int err; if (copy_from_user(&ctrl, (struct matroxfb_control*)arg, sizeof(ctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); if (!ACCESS_FBINFO(outputs[1]).output) { err = -ENXIO; } else if (ACCESS_FBINFO(outputs[1]).output->getctrl) { err = ACCESS_FBINFO(outputs[1]).output->getctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); } else { err = -EINVAL; } up_read(&ACCESS_FBINFO(altout).lock); if (err >= 0 && copy_to_user((struct matroxfb_control*)arg, &ctrl, sizeof(ctrl))) return -EFAULT; return err; } case MATROXFB_S_TVOCTRL: { struct matroxfb_control ctrl; int err; if (copy_from_user(&ctrl, (struct matroxfb_control*)arg, sizeof(ctrl))) return -EFAULT; down_read(&ACCESS_FBINFO(altout).lock); if (!ACCESS_FBINFO(outputs[1]).output) { err = -ENXIO; } else if (ACCESS_FBINFO(outputs[1]).output->setctrl) { err = ACCESS_FBINFO(outputs[1]).output->setctrl(ACCESS_FBINFO(outputs[1]).data, &ctrl); } else { err = -EINVAL; } up_read(&ACCESS_FBINFO(altout).lock); return err; } } return -ENOTTY;#undef minfo}/* 0 unblank, 1 blank, 2 no vsync, 3 no hsync, 4 off */static int matroxfb_blank(int blank, struct fb_info *info){#define minfo (list_entry(info, struct matrox_fb_info, fbcon)) int seq; int crtc; CRITFLAGS DBG("matroxfb_blank")
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -