📄 stradis.c
字号:
temp += 32; } } else { for (y = 0; y < h; y++) { *temp++ |= bitsleft; for (x = 1; x < w; x++) *temp++ = 0xffffffff; *temp |= bitsright; temp += (32 - w); } }}static void make_clip_tab(struct saa7146 *saa, struct video_clip *cr, int ncr){ int i, width, height; u32 *clipmap; clipmap = saa->dmavid2; if((width=saa->win.width)>1023) width = 1023; /* sanity check */ if((height=saa->win.height)>640) height = 639; /* sanity check */ if (ncr > 0) { /* rectangles pased */ /* convert rectangular clips to a bitmap */ memset(clipmap, 0, VIDEO_CLIPMAP_SIZE); /* clear map */ for (i = 0; i < ncr; i++) clip_draw_rectangle(clipmap, cr[i].x, cr[i].y, cr[i].width, cr[i].height); } /* clip against viewing window AND screen so we do not have to rely on the user program */ clip_draw_rectangle(clipmap,(saa->win.x+width>saa->win.swidth) ? (saa->win.swidth-saa->win.x) : width, 0, 1024, 768); clip_draw_rectangle(clipmap,0,(saa->win.y+height>saa->win.sheight) ? (saa->win.sheight-saa->win.y) : height,1024,768); if (saa->win.x<0) clip_draw_rectangle(clipmap, 0, 0, -(saa->win.x), 768); if (saa->win.y<0) clip_draw_rectangle(clipmap, 0, 0, 1024, -(saa->win.y));}static int saa_ioctl(struct video_device *dev, unsigned int cmd, void *arg){ struct saa7146 *saa = (struct saa7146 *) dev; switch (cmd) { case VIDIOCGCAP: { struct video_capability b; strcpy(b.name, saa->video_dev.name); b.type = VID_TYPE_CAPTURE | VID_TYPE_OVERLAY | VID_TYPE_CLIPPING | VID_TYPE_FRAMERAM | VID_TYPE_SCALES; b.channels = 1; b.audios = 1; b.maxwidth = 768; b.maxheight = 576; b.minwidth = 32; b.minheight = 32; if (copy_to_user(arg, &b, sizeof(b))) return -EFAULT; return 0; } case VIDIOCGPICT: { struct video_picture p = saa->picture; if (saa->win.depth == 8) p.palette = VIDEO_PALETTE_HI240; if (saa->win.depth == 15) p.palette = VIDEO_PALETTE_RGB555; if (saa->win.depth == 16) p.palette = VIDEO_PALETTE_RGB565; if (saa->win.depth == 24) p.palette = VIDEO_PALETTE_RGB24; if (saa->win.depth == 32) p.palette = VIDEO_PALETTE_RGB32; if (copy_to_user(arg, &p, sizeof(p))) return -EFAULT; return 0; } case VIDIOCSPICT: { struct video_picture p; u32 format; if (copy_from_user(&p, arg, sizeof(p))) return -EFAULT; if (p.palette < sizeof(palette2fmt) / sizeof(u32)) { format = palette2fmt[p.palette]; saa->win.color_fmt = format; saawrite(format|0x60, SAA7146_CLIP_FORMAT_CTRL); } saawrite(((p.brightness & 0xff00) << 16) | ((p.contrast & 0xfe00) << 7) | ((p.colour & 0xfe00) >> 9), SAA7146_BCS_CTRL); saa->picture = p; /* upload changed registers */ saawrite(((SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V) << 16) | SAA7146_MC2_UPLD_HPS_H | SAA7146_MC2_UPLD_HPS_V, SAA7146_MC2); return 0; } case VIDIOCSWIN: { struct video_window vw; struct video_clip *vcp = NULL; if (copy_from_user(&vw, arg, sizeof(vw))) return -EFAULT; if (vw.flags || vw.width < 16 || vw.height < 16) { /* stop capture */ saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); return -EINVAL; } if (saa->win.bpp < 4) { /* 32-bit align start and adjust width */ int i = vw.x; vw.x = (vw.x + 3) & ~3; i = vw.x - i; vw.width -= i; } saa->win.x = vw.x; saa->win.y = vw.y; saa->win.width = vw.width; if (saa->win.width > 768) saa->win.width = 768; saa->win.height = vw.height; if (CurrentMode == VIDEO_MODE_NTSC) { if (saa->win.height > 480) saa->win.height = 480; } else { if (saa->win.height > 576) saa->win.height = 576; } /* stop capture */ saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); saa7146_set_winsize(saa); /* * Do any clips. */ if (vw.clipcount < 0) { if (copy_from_user(saa->dmavid2, vw.clips, VIDEO_CLIPMAP_SIZE)) return -EFAULT; } else if (vw.clipcount > 16384) { return -EINVAL; } else if (vw.clipcount > 0) { if ((vcp = vmalloc(sizeof(struct video_clip) * (vw.clipcount))) == NULL) return -ENOMEM; if (copy_from_user(vcp, vw.clips, sizeof(struct video_clip) * vw.clipcount)) { vfree(vcp); return -EFAULT; } } else /* nothing clipped */ memset(saa->dmavid2, 0, VIDEO_CLIPMAP_SIZE); make_clip_tab(saa, vcp, vw.clipcount); if (vw.clipcount > 0) vfree(vcp); /* start capture & clip dma if we have an address */ if ((saa->cap & 3) && saa->win.vidadr != 0) saawrite(((SAA7146_MC1_TR_E_1 | SAA7146_MC1_TR_E_2) << 16) | 0xffff, SAA7146_MC1); return 0; } case VIDIOCGWIN: { struct video_window vw; vw.x = saa->win.x; vw.y = saa->win.y; vw.width = saa->win.width; vw.height = saa->win.height; vw.chromakey = 0; vw.flags = 0; if (copy_to_user(arg, &vw, sizeof(vw))) return -EFAULT; return 0; } case VIDIOCCAPTURE: { int v; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; if (v == 0) { saa->cap &= ~1; saawrite((SAA7146_MC1_TR_E_1 << 16), SAA7146_MC1); } else { if (saa->win.vidadr == 0 || saa->win.width == 0 || saa->win.height == 0) return -EINVAL; saa->cap |= 1; saawrite((SAA7146_MC1_TR_E_1 << 16) | 0xffff, SAA7146_MC1); } return 0; } case VIDIOCGFBUF: { struct video_buffer v; v.base = (void *) saa->win.vidadr; v.height = saa->win.sheight; v.width = saa->win.swidth; v.depth = saa->win.depth; v.bytesperline = saa->win.bpl; if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDIOCSFBUF: { struct video_buffer v; if (!capable(CAP_SYS_ADMIN)) return -EPERM; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; if (v.depth != 8 && v.depth != 15 && v.depth != 16 && v.depth != 24 && v.depth != 32 && v.width > 16 && v.height > 16 && v.bytesperline > 16) return -EINVAL; if (v.base) saa->win.vidadr = (unsigned long) v.base; saa->win.sheight = v.height; saa->win.swidth = v.width; saa->win.bpp = ((v.depth + 7) & 0x38) / 8; saa->win.depth = v.depth; saa->win.bpl = v.bytesperline; DEBUG(printk("Display at %p is %d by %d, bytedepth %d, bpl %d\n", v.base, v.width, v.height, saa->win.bpp, saa->win.bpl)); saa7146_set_winsize(saa); return 0; } case VIDIOCKEY: { /* Will be handled higher up .. */ return 0; } case VIDIOCGAUDIO: { struct video_audio v; v = saa->audio_dev; v.flags &= ~(VIDEO_AUDIO_MUTE | VIDEO_AUDIO_MUTABLE); v.flags |= VIDEO_AUDIO_MUTABLE | VIDEO_AUDIO_VOLUME; strcpy(v.name, "MPEG"); v.mode = VIDEO_SOUND_STEREO; if (copy_to_user(arg, &v, sizeof(v))) return -EFAULT; return 0; } case VIDIOCSAUDIO: { struct video_audio v; int i; if (copy_from_user(&v, arg, sizeof(v))) return -EFAULT; i = (~(v.volume>>8))&0xff; if (!HaveCS4341) { if (v.flags & VIDEO_AUDIO_MUTE) { debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0xffff, 2); } if (!(v.flags & VIDEO_AUDIO_MUTE)) debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, 0x0000, 2); if (v.flags & VIDEO_AUDIO_VOLUME) debiwrite(saa, debNormal, IBM_MP2_FRNT_ATTEN, (i<<8)|i, 2); } else { if (v.flags & VIDEO_AUDIO_MUTE) cs4341_setlevel(saa, 0xff, 0xff); if (!(v.flags & VIDEO_AUDIO_MUTE)) cs4341_setlevel(saa, 0, 0); if (v.flags & VIDEO_AUDIO_VOLUME) cs4341_setlevel(saa, i, i); } saa->audio_dev = v; return 0; } case VIDIOCGUNIT: { struct video_unit vu; vu.video = saa->video_dev.minor; vu.vbi = VIDEO_NO_UNIT; vu.radio = VIDEO_NO_UNIT; vu.audio = VIDEO_NO_UNIT; vu.teletext = VIDEO_NO_UNIT; if (copy_to_user((void *) arg, (void *) &vu, sizeof(vu))) return -EFAULT; return 0; } case VIDIOCSPLAYMODE: { struct video_play_mode pmode; if (copy_from_user((void *) &pmode, arg, sizeof(struct video_play_mode))) return -EFAULT; switch (pmode.mode) { case VID_PLAY_VID_OUT_MODE: if (pmode.p1 != VIDEO_MODE_NTSC && pmode.p1 != VIDEO_MODE_PAL) return -EINVAL; set_out_format(saa, pmode.p1); return 0; case VID_PLAY_GENLOCK: debiwrite(saa, debNormal, XILINX_CTL0, (pmode.p1 ? 0x8000 : 0x8080), 2); if (NewCard) set_genlock_offset(saa, pmode.p2); return 0; case VID_PLAY_NORMAL: debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); saa->playmode = pmode.mode; return 0; case VID_PLAY_PAUSE: /* IBM removed the PAUSE command */ /* they say use SINGLE_FRAME now */ case VID_PLAY_SINGLE_FRAME: ibm_send_command(saa, IBM_MP2_SINGLE_FRAME, 0, 0); if (saa->playmode == pmode.mode) { debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); } saa->playmode = pmode.mode; return 0; case VID_PLAY_FAST_FORWARD: ibm_send_command(saa, IBM_MP2_FAST_FORWARD, 0, 0); saa->playmode = pmode.mode; return 0; case VID_PLAY_SLOW_MOTION: ibm_send_command(saa, IBM_MP2_SLOW_MOTION, pmode.p1, 0); saa->playmode = pmode.mode; return 0; case VID_PLAY_IMMEDIATE_NORMAL: /* ensure transfers resume */ debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); ibm_send_command(saa, IBM_MP2_IMED_NORM_PLAY, 0, 0); saa->playmode = VID_PLAY_NORMAL; return 0; case VID_PLAY_SWITCH_CHANNELS: saa->audhead = saa->audtail = 0; saa->vidhead = saa->vidtail = 0; ibm_send_command(saa, IBM_MP2_FREEZE_FRAME, 0, 1); ibm_send_command(saa, IBM_MP2_RESET_AUD_RATE, 0, 1); debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, 0, 2); ibm_send_command(saa, IBM_MP2_CHANNEL_SWITCH, 0, 1); debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); ibm_send_command(saa, IBM_MP2_PLAY, 0, 0); saa->playmode = VID_PLAY_NORMAL; return 0; case VID_PLAY_FREEZE_FRAME: ibm_send_command(saa, IBM_MP2_FREEZE_FRAME, 0, 0); saa->playmode = pmode.mode; return 0; case VID_PLAY_STILL_MODE: ibm_send_command(saa, IBM_MP2_SET_STILL_MODE, 0, 0); saa->playmode = pmode.mode; return 0; case VID_PLAY_MASTER_MODE: if (pmode.p1 == VID_PLAY_MASTER_NONE) saa->boardcfg[1] = 0x13; else if (pmode.p1 == VID_PLAY_MASTER_VIDEO) saa->boardcfg[1] = 0x23; else if (pmode.p1 == VID_PLAY_MASTER_AUDIO) saa->boardcfg[1] = 0x43; else return -EINVAL; debiwrite(saa, debNormal, IBM_MP2_CHIP_CONTROL, ChipControl, 2); return 0; case VID_PLAY_ACTIVE_SCANLINES: if (CurrentMode == VIDEO_MODE_PAL) { if (pmode.p1 < 1 || pmode.p2 > 625) return -EINVAL; saa->boardcfg[5] = pmode.p1; saa->boardcfg[55] = (pmode.p1 + (pmode.p2/2) - 1) & 0xff; } else { if (pmode.p1 < 4 || pmode.p2 > 525) return -EINVAL; saa->boardcfg[4] = pmode.p1; saa->boardcfg[54] = (pmode.p1 + (pmode.p2/2) - 4) & 0xff; } set_out_format(saa, CurrentMode); case VID_PLAY_RESET: return do_ibm_reset(saa); case VID_PLAY_END_MARK: if (saa->endmarktail <
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -