Enscript Output

extractedLnx/linux/drivers/char/stradis.c_saa_ioctl.c

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 > 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 <  
						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((void *) &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((void *) 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.