📄 stradis.c
字号:
}static int saa_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long argl){ struct saa7146 *saa = file->private_data; void __user *arg = (void __user *)argl; 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(arg, &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 < saa->endmarkhead) { if (saa->endmarkhead - saa->endmarktail < 2) return -ENOSPC; } else if (saa->endmarkhead <= saa->endmarktail) { if (saa->endmarktail - saa->endmarkhead > (MAX_MARKS - 2)) return -ENOSPC; } else return -ENOSPC; saa->endmark[saa->endmarktail] = saa->audtail; saa->endmarktail++; if (saa->endmarktail >= MAX_MARKS) saa->endmarktail = 0; } return -EINVAL; } case VIDIOCSWRITEMODE: { int mode; if (copy_from_user((void *) &mode, arg, sizeof(int))) return -EFAULT; if (mode == VID_WRITE_MPEG_AUD || mode == VID_WRITE_MPEG_VID || mode == VID_WRITE_CC || mode == VID_WRITE_TTX || mode == VID_WRITE_OSD) { saa->writemode = mode; return 0; } return -EINVAL; } case VIDIOCSMICROCODE: { struct video_code ucode; __u8 *udata;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -