extractedLnx/linux-2.6.9/drivers/media/video/stradis.c_saa_ioctl.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;
int i;
if (copy_from_user(&ucode, arg, sizeof(ucode)))
return -EFAULT;
if (ucode.datasize > 65536 || ucode.datasize < 1024 ||
strncmp(ucode.loadwhat, "dec", 3))
return -EINVAL;
if ((udata = vmalloc(ucode.datasize)) == NULL)
return -ENOMEM;
if (copy_from_user(udata, ucode.data, ucode.datasize)) {
vfree(udata);
return -EFAULT;
}
ucode.data = udata;
if (!strncmp(ucode.loadwhat, "decoder.aud", 11)
|| !strncmp(ucode.loadwhat, "decoder.vid", 11))
i = initialize_ibmmpeg2(&ucode);
else
i = initialize_fpga(&ucode);
vfree(udata);
if (i)
return -EINVAL;
return 0;
}
case VIDIOCGCHAN: /* this makes xawtv happy */
{
struct video_channel v;
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
v.flags = VIDEO_VC_AUDIO;
v.tuners = 0;
v.type = VID_TYPE_MPEG_DECODER;
v.norm = CurrentMode;
strcpy(v.name, "MPEG2");
if (copy_to_user(arg, &v, sizeof(v)))
return -EFAULT;
return 0;
}
case VIDIOCSCHAN: /* this makes xawtv happy */
{
struct video_channel v;
if (copy_from_user(&v, arg, sizeof(v)))
return -EFAULT;
/* do nothing */
return 0;
}
default:
return -ENOIOCTLCMD;
}
return 0;
}
Generated by GNU enscript 1.6.4.