⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zoran_driver.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
		return -EINVAL;	}	if (height <= 0 || width <= 0 || bytesperline <= 0) {		dprintk(1,			KERN_ERR			"%s: setup_fbuffer() - invalid height/width/bpl value (%d|%d|%d)\n",			ZR_DEVNAME(zr), width, height, bytesperline);		return -EINVAL;	}	if (bytesperline & 3) {		dprintk(1,			KERN_ERR			"%s: setup_fbuffer() - bytesperline (%d) must be 4-byte aligned\n",			ZR_DEVNAME(zr), bytesperline);		return -EINVAL;	}	zr->buffer.base = (void *) ((unsigned long) base & ~3);	zr->buffer.height = height;	zr->buffer.width = width;	zr->buffer.depth = fmt->depth;	zr->overlay_settings.format = fmt;	zr->buffer.bytesperline = bytesperline;	/* The user should set new window parameters */	zr->overlay_settings.is_set = 0;	return 0;}static intsetup_window (struct file       *file,	      int                x,	      int                y,	      int                width,	      int                height,	      struct video_clip __user *clips,	      int                clipcount,	      void              __user *bitmap){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	struct video_clip *vcp = NULL;	int on, end;	if (!zr->buffer.base) {		dprintk(1,			KERN_ERR			"%s: setup_window() - frame buffer has to be set first\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	if (!fh->overlay_settings.format) {		dprintk(1,			KERN_ERR			"%s: setup_window() - no overlay format set\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	/*	 * The video front end needs 4-byte alinged line sizes, we correct that	 * silently here if necessary	 */	if (zr->buffer.depth == 15 || zr->buffer.depth == 16) {		end = (x + width) & ~1;	/* round down */		x = (x + 1) & ~1;	/* round up */		width = end - x;	}	if (zr->buffer.depth == 24) {		end = (x + width) & ~3;	/* round down */		x = (x + 3) & ~3;	/* round up */		width = end - x;	}	if (width > BUZ_MAX_WIDTH)		width = BUZ_MAX_WIDTH;	if (height > BUZ_MAX_HEIGHT)		height = BUZ_MAX_HEIGHT;	/* Check for vaild parameters */	if (width < BUZ_MIN_WIDTH || height < BUZ_MIN_HEIGHT ||	    width > BUZ_MAX_WIDTH || height > BUZ_MAX_HEIGHT) {		dprintk(1,			KERN_ERR			"%s: setup_window() - width = %d or height = %d invalid\n",			ZR_DEVNAME(zr), width, height);		return -EINVAL;	}	fh->overlay_settings.x = x;	fh->overlay_settings.y = y;	fh->overlay_settings.width = width;	fh->overlay_settings.height = height;	fh->overlay_settings.clipcount = clipcount;	/*	 * If an overlay is running, we have to switch it off	 * and switch it on again in order to get the new settings in effect.	 *	 * We also want to avoid that the overlay mask is written	 * when an overlay is running.	 */	on = zr->v4l_overlay_active && !zr->v4l_memgrab_active &&	    zr->overlay_active != ZORAN_FREE &&	    fh->overlay_active != ZORAN_FREE;	if (on)		zr36057_overlay(zr, 0);	/*	 *   Write the overlay mask if clips are wanted.	 *   We prefer a bitmap.	 */	if (bitmap) {		/* fake value - it just means we want clips */		fh->overlay_settings.clipcount = 1;		if (copy_from_user(fh->overlay_mask, bitmap,				   (width * height + 7) / 8)) {			return -EFAULT;		}	} else if (clipcount > 0) {		/* write our own bitmap from the clips */		vcp = vmalloc(sizeof(struct video_clip) * (clipcount + 4));		if (vcp == NULL) {			dprintk(1,				KERN_ERR				"%s: setup_window() - Alloc of clip mask failed\n",				ZR_DEVNAME(zr));			return -ENOMEM;		}		if (copy_from_user		    (vcp, clips, sizeof(struct video_clip) * clipcount)) {			vfree(vcp);			return -EFAULT;		}		write_overlay_mask(file, vcp, clipcount);		vfree(vcp);	}	fh->overlay_settings.is_set = 1;	if (fh->overlay_active != ZORAN_FREE &&	    zr->overlay_active != ZORAN_FREE)		zr->overlay_settings = fh->overlay_settings;	if (on)		zr36057_overlay(zr, 1);	/* Make sure the changes come into effect */	return wait_grab_pending(zr);}static intsetup_overlay (struct file *file,	       int          on){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	/* If there is nothing to do, return immediatly */	if ((on && fh->overlay_active != ZORAN_FREE) ||	    (!on && fh->overlay_active == ZORAN_FREE))		return 0;	/* check whether we're touching someone else's overlay */	if (on && zr->overlay_active != ZORAN_FREE &&	    fh->overlay_active == ZORAN_FREE) {		dprintk(1,			KERN_ERR			"%s: setup_overlay() - overlay is already active for another session\n",			ZR_DEVNAME(zr));		return -EBUSY;	}	if (!on && zr->overlay_active != ZORAN_FREE &&	    fh->overlay_active == ZORAN_FREE) {		dprintk(1,			KERN_ERR			"%s: setup_overlay() - you cannot cancel someone else's session\n",			ZR_DEVNAME(zr));		return -EPERM;	}	if (on == 0) {		zr->overlay_active = fh->overlay_active = ZORAN_FREE;		zr->v4l_overlay_active = 0;		/* When a grab is running, the video simply		 * won't be switched on any more */		if (!zr->v4l_memgrab_active)			zr36057_overlay(zr, 0);		zr->overlay_mask = NULL;	} else {		if (!zr->buffer.base || !fh->overlay_settings.is_set) {			dprintk(1,				KERN_ERR				"%s: setup_overlay() - buffer or window not set\n",				ZR_DEVNAME(zr));			return -EINVAL;		}		if (!fh->overlay_settings.format) {			dprintk(1,				KERN_ERR				"%s: setup_overlay() - no overlay format set\n",				ZR_DEVNAME(zr));			return -EINVAL;		}		zr->overlay_active = fh->overlay_active = ZORAN_LOCKED;		zr->v4l_overlay_active = 1;		zr->overlay_mask = fh->overlay_mask;		zr->overlay_settings = fh->overlay_settings;		if (!zr->v4l_memgrab_active)			zr36057_overlay(zr, 1);		/* When a grab is running, the video will be		 * switched on when grab is finished */	}	/* Make sure the changes come into effect */	return wait_grab_pending(zr);}#ifdef HAVE_V4L2	/* get the status of a buffer in the clients buffer queue */static intzoran_v4l2_buffer_status (struct file        *file,			  struct v4l2_buffer *buf,			  int                 num){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	buf->flags = V4L2_BUF_FLAG_MAPPED;	switch (fh->map_mode) {	case ZORAN_MAP_MODE_RAW:		/* check range */		if (num < 0 || num >= fh->v4l_buffers.num_buffers ||		    !fh->v4l_buffers.allocated) {			dprintk(1,				KERN_ERR				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",				ZR_DEVNAME(zr));			return -EINVAL;		}		buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;		buf->length = fh->v4l_buffers.buffer_size;		/* get buffer */		buf->bytesused = fh->v4l_buffers.buffer[num].bs.length;		if (fh->v4l_buffers.buffer[num].state == BUZ_STATE_DONE ||		    fh->v4l_buffers.buffer[num].state == BUZ_STATE_USER) {			buf->sequence = fh->v4l_buffers.buffer[num].bs.seq;			buf->flags |= V4L2_BUF_FLAG_DONE;			buf->timestamp =			    fh->v4l_buffers.buffer[num].bs.timestamp;		} else {			buf->flags |= V4L2_BUF_FLAG_QUEUED;		}		if (fh->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)			buf->field = V4L2_FIELD_TOP;		else			buf->field = V4L2_FIELD_INTERLACED;		break;	case ZORAN_MAP_MODE_JPG_REC:	case ZORAN_MAP_MODE_JPG_PLAY:		/* check range */		if (num < 0 || num >= fh->jpg_buffers.num_buffers ||		    !fh->jpg_buffers.allocated) {			dprintk(1,				KERN_ERR				"%s: v4l2_buffer_status() - wrong number or buffers not allocated\n",				ZR_DEVNAME(zr));			return -EINVAL;		}		buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?			      V4L2_BUF_TYPE_VIDEO_CAPTURE :			      V4L2_BUF_TYPE_VIDEO_OUTPUT;		buf->length = fh->jpg_buffers.buffer_size;		/* these variables are only written after frame has been captured */		if (fh->jpg_buffers.buffer[num].state == BUZ_STATE_DONE ||		    fh->jpg_buffers.buffer[num].state == BUZ_STATE_USER) {			buf->sequence = fh->jpg_buffers.buffer[num].bs.seq;			buf->timestamp =			    fh->jpg_buffers.buffer[num].bs.timestamp;			buf->bytesused =			    fh->jpg_buffers.buffer[num].bs.length;			buf->flags |= V4L2_BUF_FLAG_DONE;		} else {			buf->flags |= V4L2_BUF_FLAG_QUEUED;		}		/* which fields are these? */		if (fh->jpg_settings.TmpDcm != 1)			buf->field =			    fh->jpg_settings.			    odd_even ? V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;		else			buf->field =			    fh->jpg_settings.			    odd_even ? V4L2_FIELD_SEQ_TB :			    V4L2_FIELD_SEQ_BT;		break;	default:		dprintk(5,			KERN_ERR			"%s: v4l2_buffer_status() - invalid buffer type|map_mode (%d|%d)\n",			ZR_DEVNAME(zr), buf->type, fh->map_mode);		return -EINVAL;	}	buf->memory = V4L2_MEMORY_MMAP;	buf->index = num;	buf->m.offset = buf->length * num;	return 0;}#endifstatic intzoran_set_norm (struct zoran *zr,	        int           norm) /* VIDEO_MODE_* */{	int norm_encoder, on;	if (zr->v4l_buffers.active != ZORAN_FREE ||	    zr->jpg_buffers.active != ZORAN_FREE) {		dprintk(1,			KERN_WARNING			"%s: set_norm() called while in playback/capture mode\n",			ZR_DEVNAME(zr));		return -EBUSY;	}	if (lock_norm && norm != zr->norm) {		if (lock_norm > 1) {			dprintk(1,				KERN_WARNING				"%s: set_norm() - TV standard is locked, can not switch norm\n",				ZR_DEVNAME(zr));			return -EPERM;		} else {			dprintk(1,				KERN_WARNING				"%s: set_norm() - TV standard is locked, norm was not changed\n",				ZR_DEVNAME(zr));			norm = zr->norm;		}	}	if (norm != VIDEO_MODE_AUTO &&	    (norm < 0 || norm >= zr->card.norms ||	     !zr->card.tvn[norm])) {		dprintk(1,			KERN_ERR "%s: set_norm() - unsupported norm %d\n",			ZR_DEVNAME(zr), norm);		return -EINVAL;	}	if (norm == VIDEO_MODE_AUTO) {		int status;		/* if we have autodetect, ... */		struct video_decoder_capability caps;		decoder_command(zr, DECODER_GET_CAPABILITIES, &caps);		if (!(caps.flags & VIDEO_DECODER_AUTO)) {			dprintk(1, KERN_ERR "%s: norm=auto unsupported\n",				ZR_DEVNAME(zr));			return -EINVAL;		}		decoder_command(zr, DECODER_SET_NORM, &norm);		/* let changes come into effect */		ssleep(2);		decoder_command(zr, DECODER_GET_STATUS, &status);		if (!(status & DECODER_STATUS_GOOD)) {			dprintk(1,				KERN_ERR				"%s: set_norm() - no norm detected\n",				ZR_DEVNAME(zr));			/* reset norm */			decoder_command(zr, DECODER_SET_NORM, &zr->norm);			return -EIO;		}		if (status & DECODER_STATUS_NTSC)			norm = VIDEO_MODE_NTSC;		else if (status & DECODER_STATUS_SECAM)			norm = VIDEO_MODE_SECAM;		else			norm = VIDEO_MODE_PAL;	}	zr->timing = zr->card.tvn[norm];	norm_encoder = norm;	/* We switch overlay off and on since a change in the	 * norm needs different VFE settings */	on = zr->overlay_active && !zr->v4l_memgrab_active;	if (on)		zr36057_overlay(zr, 0);	decoder_command(zr, DECODER_SET_NORM, &norm);	encoder_command(zr, ENCODER_SET_NORM, &norm_encoder);	if (on)		zr36057_overlay(zr, 1);	/* Make sure the changes come into effect */	zr->norm = norm;	return 0;}static intzoran_set_input (struct zoran *zr,		 int           input){	int realinput;	if (input == zr->input) {		return 0;	}	if (zr->v4l_buffers.active != ZORAN_FREE ||	    zr->jpg_buffers.active != ZORAN_FREE) {		dprintk(1,			KERN_WARNING			"%s: set_input() called while in playback/capture mode\n",			ZR_DEVNAME(zr));		return -EBUSY;	}	if (input < 0 || input >= zr->card.inputs) {		dprintk(1,			KERN_ERR			"%s: set_input() - unnsupported input %d\n",			ZR_DEVNAME(zr), input);		return -EINVAL;	}	realinput = zr->card.input[input].muxsel;	zr->input = input;	decoder_command(zr, DECODER_SET_INPUT, &realinput);	return 0;}/* *   ioctl routine */static intzoran_do_ioctl (struct inode *inode,	        struct file  *file,	        unsigned int  cmd,	        void         *arg){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	/* CAREFUL: used in multiple places here */	struct zoran_jpg_settings settings;	/* we might have older buffers lying around... We don't want	 * to wait, but we do want to try cleaning them up ASAP. So	 * we try to obtain the lock and free them. If that fails, we	 * don't do anything and wait for the next turn. In the end,	 * zoran_close() or a new allocation will still free them...	 * This is just a 'the sooner the better' extra 'feature'	 *	 * We don't free the buffers right on munmap() because that	 * causes oopses (kfree() inside munmap() oopses for no	 * apparent reason - it's also not reproduceable in any way,	 * but moving the free code outside the munmap() handler fixes	 * all this... If someone knows why, please explain me (Ronald)	 */	if (!down_trylock(&zr->resource_lock)) {		/* we obtained it! Let's try to free some things */		if (fh->jpg_buffers.ready_to_be_freed)			jpg_fbuffer_free(file);		if (fh->v4l_buffers.ready_to_be_freed)			v4l_fbuffer_free(file);		up(&zr->resource_lock);	}	switch (cmd) {	case VIDIOCGCAP:	{		struct video_capability *vcap = arg;		dprintk(3, KERN_DEBUG "%s: VIDIOCGCAP\n", ZR_DEVNAME(zr));		memset(vcap, 0, sizeof(struct video_capability));		strncpy(vcap->name, ZR_DEVNAME(zr), sizeof(vcap->name));		vcap->type = ZORAN_VID_TYPE;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -