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

📄 zoran_driver.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
 *       Therefore there is no need to allocate them with vmalloc in order *       to get a contiguous virtual memory space. *       I don't understand why many other drivers first allocate them with *       vmalloc (which uses internally also get_zeroed_page, but delivers you *       virtual addresses) and then again have to make a lot of efforts *       to get the physical address. * *   Ben Capper: *       On big-endian architectures (such as ppc) some extra steps *       are needed. When reading and writing to the stat_com array *       and fragment buffers, the device expects to see little- *       endian values. The use of cpu_to_le32() and le32_to_cpu() *       in this function (and one or two others in zoran_device.c) *       ensure that these values are always stored in little-endian *       form, regardless of architecture. The zr36057 does Very Bad *       Things on big endian architectures if the stat_com array *       and fragment buffers are not little-endian. */static intjpg_fbuffer_alloc (struct file *file){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int i, j, off;	unsigned long mem;	/* we might have old buffers lying around */	if (fh->jpg_buffers.ready_to_be_freed) {		jpg_fbuffer_free(file);	}	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {		if (fh->jpg_buffers.buffer[i].frag_tab)			dprintk(2,				KERN_WARNING				"%s: jpg_fbuffer_alloc() - buffer %d allready allocated!?\n",				ZR_DEVNAME(zr), i);		/* Allocate fragment table for this buffer */		mem = get_zeroed_page(GFP_KERNEL);		if (mem == 0) {			dprintk(1,				KERN_ERR				"%s: jpg_fbuffer_alloc() - get_zeroed_page (frag_tab) failed for buffer %d\n",				ZR_DEVNAME(zr), i);			jpg_fbuffer_free(file);			return -ENOBUFS;		}		memset((void *) mem, 0, PAGE_SIZE);		fh->jpg_buffers.buffer[i].frag_tab = (u32 *) mem;		fh->jpg_buffers.buffer[i].frag_tab_bus =		    virt_to_bus((void *) mem);		//if (alloc_contig) {		if (fh->jpg_buffers.need_contiguous) {			mem =			    (unsigned long) kmalloc(fh->jpg_buffers.						    buffer_size,						    GFP_KERNEL);			if (mem == 0) {				dprintk(1,					KERN_ERR					"%s: jpg_fbuffer_alloc() - kmalloc failed for buffer %d\n",					ZR_DEVNAME(zr), i);				jpg_fbuffer_free(file);				return -ENOBUFS;			}			fh->jpg_buffers.buffer[i].frag_tab[0] =			    cpu_to_le32(virt_to_bus((void *) mem));			fh->jpg_buffers.buffer[i].frag_tab[1] =			    cpu_to_le32(((fh->jpg_buffers.buffer_size / 4) << 1) | 1);			for (off = 0; off < fh->jpg_buffers.buffer_size;			     off += PAGE_SIZE)				SetPageReserved(MAP_NR(mem + off));		} else {			/* jpg_bufsize is allreay page aligned */			for (j = 0;			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;			     j++) {				mem = get_zeroed_page(GFP_KERNEL);				if (mem == 0) {					dprintk(1,						KERN_ERR						"%s: jpg_fbuffer_alloc() - get_zeroed_page failed for buffer %d\n",						ZR_DEVNAME(zr), i);					jpg_fbuffer_free(file);					return -ENOBUFS;				}				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =				    cpu_to_le32(virt_to_bus((void *) mem));				fh->jpg_buffers.buffer[i].frag_tab[2 * j +								   1] =				    cpu_to_le32((PAGE_SIZE / 4) << 1);				SetPageReserved(MAP_NR(mem));			}			fh->jpg_buffers.buffer[i].frag_tab[2 * j - 1] |= cpu_to_le32(1);		}	}	dprintk(4,		KERN_DEBUG "%s: jpg_fbuffer_alloc() - %d KB allocated\n",		ZR_DEVNAME(zr),		(fh->jpg_buffers.num_buffers *		 fh->jpg_buffers.buffer_size) >> 10);	fh->jpg_buffers.allocated = 1;	return 0;}/* free the MJPEG grab buffers */static voidjpg_fbuffer_free (struct file *file){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int i, j, off;	unsigned char *mem;	dprintk(4, KERN_DEBUG "%s: jpg_fbuffer_free()\n", ZR_DEVNAME(zr));	for (i = 0; i < fh->jpg_buffers.num_buffers; i++) {		if (!fh->jpg_buffers.buffer[i].frag_tab)			continue;		//if (alloc_contig) {		if (fh->jpg_buffers.need_contiguous) {			if (fh->jpg_buffers.buffer[i].frag_tab[0]) {				mem = (unsigned char *) bus_to_virt(le32_to_cpu(					fh->jpg_buffers.buffer[i].frag_tab[0]));				for (off = 0;				     off < fh->jpg_buffers.buffer_size;				     off += PAGE_SIZE)					ClearPageReserved(MAP_NR							  (mem + off));				kfree(mem);				fh->jpg_buffers.buffer[i].frag_tab[0] = 0;				fh->jpg_buffers.buffer[i].frag_tab[1] = 0;			}		} else {			for (j = 0;			     j < fh->jpg_buffers.buffer_size / PAGE_SIZE;			     j++) {				if (!fh->jpg_buffers.buffer[i].				    frag_tab[2 * j])					break;				ClearPageReserved(MAP_NR						  (bus_to_virt						   (le32_to_cpu						    (fh->jpg_buffers.						     buffer[i].frag_tab[2 *								       j]))));				free_page((unsigned long)					  bus_to_virt					          (le32_to_cpu						   (fh->jpg_buffers.						      buffer[i].						      frag_tab[2 * j])));				fh->jpg_buffers.buffer[i].frag_tab[2 * j] =				    0;				fh->jpg_buffers.buffer[i].frag_tab[2 * j +								   1] = 0;			}		}		free_page((unsigned long) fh->jpg_buffers.buffer[i].			  frag_tab);		fh->jpg_buffers.buffer[i].frag_tab = NULL;	}	fh->jpg_buffers.allocated = 0;	fh->jpg_buffers.ready_to_be_freed = 0;}/* *   V4L Buffer grabbing */static intzoran_v4l_set_format (struct file               *file,		      int                        width,		      int                        height,		      const struct zoran_format *format){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int bpp;	/* Check size and format of the grab wanted */	if (height < BUZ_MIN_HEIGHT || width < BUZ_MIN_WIDTH ||	    height > BUZ_MAX_HEIGHT || width > BUZ_MAX_WIDTH) {		dprintk(1,			KERN_ERR			"%s: v4l_set_format() - wrong frame size (%dx%d)\n",			ZR_DEVNAME(zr), width, height);		return -EINVAL;	}	bpp = (format->depth + 7) / 8;	/* Check against available buffer size */	if (height * width * bpp > fh->v4l_buffers.buffer_size) {		dprintk(1,			KERN_ERR			"%s: v4l_set_format() - video buffer size (%d kB) is too small\n",			ZR_DEVNAME(zr), fh->v4l_buffers.buffer_size >> 10);		return -EINVAL;	}	/* The video front end needs 4-byte alinged line sizes */	if ((bpp == 2 && (width & 1)) || (bpp == 3 && (width & 3))) {		dprintk(1,			KERN_ERR			"%s: v4l_set_format() - wrong frame alingment\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	fh->v4l_settings.width = width;	fh->v4l_settings.height = height;	fh->v4l_settings.format = format;	fh->v4l_settings.bytesperline = bpp * fh->v4l_settings.width;	return 0;}static intzoran_v4l_queue_frame (struct file *file,		       int          num){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	unsigned long flags;	int res = 0;	if (!fh->v4l_buffers.allocated) {		dprintk(1,			KERN_ERR			"%s: v4l_queue_frame() - buffers not yet allocated\n",			ZR_DEVNAME(zr));		res = -ENOMEM;	}	/* No grabbing outside the buffer range! */	if (num >= fh->v4l_buffers.num_buffers || num < 0) {		dprintk(1,			KERN_ERR			"%s: v4l_queue_frame() - buffer %d is out of range\n",			ZR_DEVNAME(zr), num);		res = -EINVAL;	}	spin_lock_irqsave(&zr->spinlock, flags);	if (fh->v4l_buffers.active == ZORAN_FREE) {		if (zr->v4l_buffers.active == ZORAN_FREE) {			zr->v4l_buffers = fh->v4l_buffers;			fh->v4l_buffers.active = ZORAN_ACTIVE;		} else {			dprintk(1,				KERN_ERR				"%s: v4l_queue_frame() - another session is already capturing\n",				ZR_DEVNAME(zr));			res = -EBUSY;		}	}	/* make sure a grab isn't going on currently with this buffer */	if (!res) {		switch (zr->v4l_buffers.buffer[num].state) {		default:		case BUZ_STATE_PEND:			if (zr->v4l_buffers.active == ZORAN_FREE) {				fh->v4l_buffers.active = ZORAN_FREE;				zr->v4l_buffers.allocated = 0;			}			res = -EBUSY;	/* what are you doing? */			break;		case BUZ_STATE_DONE:			dprintk(2,				KERN_WARNING				"%s: v4l_queue_frame() - queueing buffer %d in state DONE!?\n",				ZR_DEVNAME(zr), num);		case BUZ_STATE_USER:			/* since there is at least one unused buffer there's room for at least			 * one more pend[] entry */			zr->v4l_pend[zr->v4l_pend_head++ &					V4L_MASK_FRAME] = num;			zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;			zr->v4l_buffers.buffer[num].bs.length =			    fh->v4l_settings.bytesperline *			    zr->v4l_settings.height;			fh->v4l_buffers.buffer[num] =			    zr->v4l_buffers.buffer[num];			break;		}	}	spin_unlock_irqrestore(&zr->spinlock, flags);	if (!res && zr->v4l_buffers.active == ZORAN_FREE)		zr->v4l_buffers.active = fh->v4l_buffers.active;	return res;}static intv4l_grab (struct file       *file,	  struct video_mmap *mp){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int res = 0, i;	for (i = 0; i < zoran_num_formats; i++) {		if (zoran_formats[i].palette == mp->format &&		    zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE &&		    !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED))			break;	}	if (i == zoran_num_formats || zoran_formats[i].depth == 0) {		dprintk(1,			KERN_ERR			"%s: v4l_grab() - wrong bytes-per-pixel format\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	/*	 * To minimize the time spent in the IRQ routine, we avoid setting up	 * the video front end there.	 * If this grab has different parameters from a running streaming capture	 * we stop the streaming capture and start it over again.	 */	if (zr->v4l_memgrab_active &&	    (zr->v4l_settings.width != mp->width ||	     zr->v4l_settings.height != mp->height ||	     zr->v4l_settings.format->palette != mp->format)) {		res = wait_grab_pending(zr);		if (res)			return res;	}	if ((res = zoran_v4l_set_format(file,					mp->width,					mp->height,					&zoran_formats[i])))		return res;	zr->v4l_settings = fh->v4l_settings;	/* queue the frame in the pending queue */	if ((res = zoran_v4l_queue_frame(file, mp->frame))) {		fh->v4l_buffers.active = ZORAN_FREE;		return res;	}	/* put the 36057 into frame grabbing mode */	if (!res && !zr->v4l_memgrab_active)		zr36057_set_memgrab(zr, 1);	//dprintk(4, KERN_INFO "%s: Frame grab 3...\n", ZR_DEVNAME(zr));	return res;}/* * Sync on a V4L buffer */static intv4l_sync (struct file *file,	  int          frame){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	unsigned long flags;	if (fh->v4l_buffers.active == ZORAN_FREE) {		dprintk(1,			KERN_ERR			"%s: v4l_sync() - no grab active for this session\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	/* check passed-in frame number */	if (frame >= fh->v4l_buffers.num_buffers || frame < 0) {		dprintk(1,			KERN_ERR "%s: v4l_sync() - frame %d is invalid\n",			ZR_DEVNAME(zr), frame);		return -EINVAL;	}	/* Check if is buffer was queued at all */	if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {		dprintk(1,			KERN_ERR			"%s: v4l_sync() - attempt to sync on a buffer which was not queued?\n",			ZR_DEVNAME(zr));		return -EPROTO;	}	/* wait on this buffer to get ready */	if (!wait_event_interruptible_timeout(zr->v4l_capq,				(zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND),				10*HZ))		return -ETIME;	if (signal_pending(current))		return -ERESTARTSYS;	/* buffer should now be in BUZ_STATE_DONE */	if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)		dprintk(2,			KERN_ERR "%s: v4l_sync() - internal state error\n",			ZR_DEVNAME(zr));	zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;	fh->v4l_buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];	spin_lock_irqsave(&zr->spinlock, flags);	/* Check if streaming capture has finished */	if (zr->v4l_pend_tail == zr->v4l_pend_head) {		zr36057_set_memgrab(zr, 0);		if (zr->v4l_buffers.active == ZORAN_ACTIVE) {			fh->v4l_buffers.active = zr->v4l_buffers.active =			    ZORAN_FREE;			zr->v4l_buffers.allocated = 0;		}	}	spin_unlock_irqrestore(&zr->spinlock, flags);	return 0;}/* *   Queue a MJPEG buffer for capture/playback */static intzoran_jpg_queue_frame (struct file          *file,		       int                   num,		       enum zoran_codec_mode mode){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	unsigned long flags;	int res = 0;	/* Check if buffers are allocated */	if (!fh->jpg_buffers.allocated) {		dprintk(1,			KERN_ERR			"%s: jpg_queue_frame() - buffers not yet allocated\n",			ZR_DEVNAME(zr));		return -ENOMEM;	}	/* No grabbing outside the buffer range! */	if (num >= fh->jpg_buffers.num_buffers || num < 0) {		dprintk(1,			KERN_ERR			"%s: jpg_queue_frame() - buffer %d out of range\n",			ZR_DEVNAME(zr), num);		return -EINVAL;	}	/* what is the codec mode right now? */	if (zr->codec_mode == BUZ_MODE_IDLE) {		zr->jpg_settings = fh->jpg_settings;	} else if (zr->codec_mode != mode) {		/* wrong codec mode active - invalid */		dprintk(1,			KERN_ERR			"%s: jpg_queue_frame() - codec in wrong mode\n",			ZR_DEVNAME(zr));		return -EINVAL;	}	if (fh->jpg_buffers.active == ZORAN_FREE) {		if (zr->jpg_buffers.active == ZORAN_FREE) {			zr->jpg_buffers = fh->jpg_buffers;			fh->jpg_buffers.active = ZORAN_ACTIVE;		} else {			dprintk(1,				KERN_ERR				"%s: jpg_queue_frame() - another session is already capturing\n",				ZR_DEVNAME(zr));			res = -EBUSY;		}	}	if (!res && zr->codec_mode == BUZ_MODE_IDLE) {		/* Ok load up the jpeg codec */		zr36057_enable_jpg(zr, mode);	}	spin_lock_irqsave(&zr->spinlock, flags);	if (!res) {		switch (zr->jpg_buffers.buffer[num].state) {		case BUZ_STATE_DONE:			dprintk(2,				KERN_WARNING				"%s: jpg_queue_frame() - queing frame in BUZ_STATE_DONE state!?\n",				ZR_DEVNAME(zr));		case BUZ_STATE_USER:

⌨️ 快捷键说明

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