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

📄 zoran_driver.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Zoran zr36057/zr36067 PCI controller driver, for the * Pinnacle/Miro DC10/DC10+/DC30/DC30+, Iomega Buz, Linux * Media Labs LML33/LML33R10. * * Copyright (C) 2000 Serguei Miridonov <mirsev@cicese.mx> * * Changes for BUZ by Wolfgang Scherr <scherr@net4you.net> * * Changes for DC10/DC30 by Laurent Pinchart <laurent.pinchart@skynet.be> * * Changes for LML33R10 by Maxim Yevtyushkin <max@linuxmedialabs.com> * * Changes for videodev2/v4l2 by Ronald Bultje <rbultje@ronald.bitfreak.net> * * Based on * * Miro DC10 driver * Copyright (C) 1999 Wolfgang Scherr <scherr@net4you.net> * * Iomega Buz driver version 1.0 * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de> * * buz.0.0.3 * Copyright (C) 1998 Dave Perks <dperks@ibm.net> * * bttv - Bt848 frame grabber driver * Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de) *                        & Marcus Metzler (mocm@thp.uni-koeln.de) * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/config.h>#include <linux/version.h>#include <linux/init.h>#include <linux/module.h>#include <linux/delay.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/vmalloc.h>#include <linux/wait.h>#include <linux/byteorder/generic.h>#include <linux/interrupt.h>#include <linux/i2c.h>#include <linux/i2c-algo-bit.h>#include <linux/spinlock.h>#define     MAP_NR(x)       virt_to_page(x)#define     ZORAN_HARDWARE  VID_HARDWARE_ZR36067#define     ZORAN_VID_TYPE  ( \				VID_TYPE_CAPTURE | \				VID_TYPE_OVERLAY | \				VID_TYPE_CLIPPING | \				VID_TYPE_FRAMERAM | \				VID_TYPE_SCALES | \				VID_TYPE_MJPEG_DECODER | \				VID_TYPE_MJPEG_ENCODER \			     )#include <linux/videodev.h>#include "videocodec.h"#include <asm/io.h>#include <asm/uaccess.h>#include <linux/proc_fs.h>#include <linux/video_decoder.h>#include <linux/video_encoder.h>#include "zoran.h"#include "zoran_device.h"#include "zoran_card.h"#ifdef HAVE_V4L2	/* we declare some card type definitions here, they mean	 * the same as the v4l1 ZORAN_VID_TYPE above, except it's v4l2 */#define ZORAN_V4L2_VID_FLAGS ( \				V4L2_CAP_STREAMING |\				V4L2_CAP_VIDEO_CAPTURE |\				V4L2_CAP_VIDEO_OUTPUT |\				V4L2_CAP_VIDEO_OVERLAY \                              )#endif#include <asm/byteorder.h>const struct zoran_format zoran_formats[] = {	{		.name = "15-bit RGB",		.palette = VIDEO_PALETTE_RGB555,#ifdef HAVE_V4L2#ifdef __LITTLE_ENDIAN		.fourcc = V4L2_PIX_FMT_RGB555,#else		.fourcc = V4L2_PIX_FMT_RGB555X,#endif		.colorspace = V4L2_COLORSPACE_SRGB,#endif		.depth = 15,		.flags = ZORAN_FORMAT_CAPTURE |			 ZORAN_FORMAT_OVERLAY,	}, {		.name = "16-bit RGB",		.palette = VIDEO_PALETTE_RGB565,#ifdef HAVE_V4L2#ifdef __LITTLE_ENDIAN		.fourcc = V4L2_PIX_FMT_RGB565,#else		.fourcc = V4L2_PIX_FMT_RGB565X,#endif		.colorspace = V4L2_COLORSPACE_SRGB,#endif		.depth = 16,		.flags = ZORAN_FORMAT_CAPTURE |			 ZORAN_FORMAT_OVERLAY,	}, {		.name = "24-bit RGB",		.palette = VIDEO_PALETTE_RGB24,#ifdef HAVE_V4L2#ifdef __LITTLE_ENDIAN		.fourcc = V4L2_PIX_FMT_BGR24,#else		.fourcc = V4L2_PIX_FMT_RGB24,#endif		.colorspace = V4L2_COLORSPACE_SRGB,#endif		.depth = 24,		.flags = ZORAN_FORMAT_CAPTURE |			 ZORAN_FORMAT_OVERLAY,	}, {		.name = "32-bit RGB",		.palette = VIDEO_PALETTE_RGB32,#ifdef HAVE_V4L2#ifdef __LITTLE_ENDIAN		.fourcc = V4L2_PIX_FMT_BGR32,#else		.fourcc = V4L2_PIX_FMT_RGB32,#endif		.colorspace = V4L2_COLORSPACE_SRGB,#endif		.depth = 32,		.flags = ZORAN_FORMAT_CAPTURE |			 ZORAN_FORMAT_OVERLAY,	}, {		.name = "4:2:2, packed, YUYV",		.palette = VIDEO_PALETTE_YUV422,#ifdef HAVE_V4L2		.fourcc = V4L2_PIX_FMT_YUYV,		.colorspace = V4L2_COLORSPACE_SMPTE170M,#endif		.depth = 16,		.flags = ZORAN_FORMAT_CAPTURE |		         ZORAN_FORMAT_OVERLAY,	}, {		.name = "Hardware-encoded Motion-JPEG",		.palette = -1,#ifdef HAVE_V4L2		.fourcc = V4L2_PIX_FMT_MJPEG,		.colorspace = V4L2_COLORSPACE_SMPTE170M,#endif		.depth = 0,		.flags = ZORAN_FORMAT_CAPTURE |			 ZORAN_FORMAT_PLAYBACK |			 ZORAN_FORMAT_COMPRESSED,	}};static const int zoran_num_formats =    (sizeof(zoran_formats) / sizeof(struct zoran_format));// RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined#if !defined(CONFIG_BIGPHYS_AREA)//#undef CONFIG_BIGPHYS_AREA#define BUZ_USE_HIMEM#endif#if defined(CONFIG_BIGPHYS_AREA)#   include <linux/bigphysarea.h>#endifextern int *zr_debug;#define dprintk(num, format, args...) \	do { \		if (*zr_debug >= num) \			printk(format, ##args);	\	} while (0)extern int v4l_nbufs;extern int v4l_bufsize;extern int jpg_nbufs;extern int jpg_bufsize;extern int pass_through;static int lock_norm = 0;	/* 1=Don't change TV standard (norm) */module_param(lock_norm, int, 0);MODULE_PARM_DESC(lock_norm, "Users can't change norm");#ifdef HAVE_V4L2	/* small helper function for calculating buffersizes for v4l2	 * we calculate the nearest higher power-of-two, which	 * will be the recommended buffersize */static __u32zoran_v4l2_calc_bufsize (struct zoran_jpg_settings *settings){	__u8 div = settings->VerDcm * settings->HorDcm * settings->TmpDcm;	__u32 num = (1024 * 512) / (div);	__u32 result = 2;	num--;	while (num) {		num >>= 1;		result <<= 1;	}	if (result > jpg_bufsize)		return jpg_bufsize;	if (result < 8192)		return 8192;	return result;}#endif/* forward references */static void v4l_fbuffer_free(struct file *file);static void jpg_fbuffer_free(struct file *file);/* *   Allocate the V4L grab buffers * *   These have to be pysically contiguous. *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc *   else we try to allocate them with bigphysarea_alloc_pages *   if the bigphysarea patch is present in the kernel, *   else we try to use high memory (if the user has bootet *   Linux with the necessary memory left over). */#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)static unsigned longget_high_mem (unsigned long size){/* * Check if there is usable memory at the end of Linux memory * of at least size. Return the physical address of this memory, * return 0 on failure. * * The idea is from Alexandro Rubini's book "Linux device drivers". * The driver from him which is downloadable from O'Reilly's * web site misses the "virt_to_phys(high_memory)" part * (and therefore doesn't work at all - at least with 2.2.x kernels). * * It should be unnecessary to mention that THIS IS DANGEROUS, * if more than one driver at a time has the idea to use this memory!!!! */	volatile unsigned char __iomem *mem;	unsigned char c;	unsigned long hi_mem_ph;	unsigned long i;	/* Map the high memory to user space */	hi_mem_ph = virt_to_phys(high_memory);	mem = ioremap(hi_mem_ph, size);	if (!mem) {		dprintk(1,			KERN_ERR "%s: get_high_mem() - ioremap failed\n",			ZORAN_NAME);		return 0;	}	for (i = 0; i < size; i++) {		/* Check if it is memory */		c = i & 0xff;		writeb(c, mem + i);		if (readb(mem + i) != c)			break;		c = 255 - c;		writeb(c, mem + i);		if (readb(mem + i) != c)			break;		writeb(0, mem + i);	/* zero out memory */		/* give the kernel air to breath */		if ((i & 0x3ffff) == 0x3ffff)			schedule();	}	iounmap(mem);	if (i != size) {		dprintk(1,			KERN_ERR			"%s: get_high_mem() - requested %lu, avail %lu\n",			ZORAN_NAME, size, i);		return 0;	}	return hi_mem_ph;}#endifstatic intv4l_fbuffer_alloc (struct file *file){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int i, off;	unsigned char *mem;#if defined(BUZ_USE_HIMEM) && !defined(CONFIG_BIGPHYS_AREA)	unsigned long pmem = 0;#endif	/* we might have old buffers lying around... */	if (fh->v4l_buffers.ready_to_be_freed) {		v4l_fbuffer_free(file);	}	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {		if (fh->v4l_buffers.buffer[i].fbuffer)			dprintk(2,				KERN_WARNING				"%s: v4l_fbuffer_alloc() - buffer %d allready allocated!?\n",				ZR_DEVNAME(zr), i);		//udelay(20);		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {			/* Use kmalloc */			mem =			    (unsigned char *) kmalloc(fh->v4l_buffers.						      buffer_size,						      GFP_KERNEL);			if (mem == 0) {				dprintk(1,					KERN_ERR					"%s: v4l_fbuffer_alloc() - kmalloc for V4L buf %d failed\n",					ZR_DEVNAME(zr), i);				v4l_fbuffer_free(file);				return -ENOBUFS;			}			fh->v4l_buffers.buffer[i].fbuffer = mem;			fh->v4l_buffers.buffer[i].fbuffer_phys =			    virt_to_phys(mem);			fh->v4l_buffers.buffer[i].fbuffer_bus =			    virt_to_bus(mem);			for (off = 0; off < fh->v4l_buffers.buffer_size;			     off += PAGE_SIZE)				SetPageReserved(MAP_NR(mem + off));			dprintk(4,				KERN_INFO				"%s: v4l_fbuffer_alloc() - V4L frame %d mem 0x%lx (bus: 0x%lx)\n",				ZR_DEVNAME(zr), i, (unsigned long) mem,				virt_to_bus(mem));		} else {#if defined(CONFIG_BIGPHYS_AREA)			/* Use bigphysarea_alloc_pages */			int n =			    (fh->v4l_buffers.buffer_size + PAGE_SIZE -			     1) / PAGE_SIZE;			mem =			    (unsigned char *) bigphysarea_alloc_pages(n, 0,								      GFP_KERNEL);			if (mem == 0) {				dprintk(1,					KERN_ERR					"%s: v4l_fbuffer_alloc() - bigphysarea_alloc_pages for V4L buf %d failed\n",					ZR_DEVNAME(zr), i);				v4l_fbuffer_free(file);				return -ENOBUFS;			}			fh->v4l_buffers.buffer[i].fbuffer = mem;			fh->v4l_buffers.buffer[i].fbuffer_phys =			    virt_to_phys(mem);			fh->v4l_buffers.buffer[i].fbuffer_bus =			    virt_to_bus(mem);			dprintk(4,				KERN_INFO				"%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)\n",				ZR_DEVNAME(zr), i, (unsigned) mem,				(unsigned) virt_to_bus(mem));			/* Zero out the allocated memory */			memset(fh->v4l_buffers.buffer[i].fbuffer, 0,			       fh->v4l_buffers.buffer_size);#elif defined(BUZ_USE_HIMEM)			/* Use high memory which has been left at boot time */			/* Ok., Ok. this is an evil hack - we make			 * the assumption that physical addresses are			 * the same as bus addresses (true at least			 * for Intel processors). The whole method of			 * obtaining and using this memory is not very			 * nice - but I hope it saves some poor users			 * from kernel hacking, which might have even			 * more evil results */			if (i == 0) {				int size =				    fh->v4l_buffers.num_buffers *				    fh->v4l_buffers.buffer_size;				pmem = get_high_mem(size);				if (pmem == 0) {					dprintk(1,						KERN_ERR						"%s: v4l_fbuffer_alloc() - get_high_mem (size = %d KB) for V4L bufs failed\n",						ZR_DEVNAME(zr), size >> 10);					return -ENOBUFS;				}				fh->v4l_buffers.buffer[0].fbuffer = NULL;				fh->v4l_buffers.buffer[0].fbuffer_phys = pmem;				fh->v4l_buffers.buffer[0].fbuffer_bus = pmem;				dprintk(4,					KERN_INFO					"%s: v4l_fbuffer_alloc() - using %d KB high memory\n",					ZR_DEVNAME(zr), size >> 10);			} else {				fh->v4l_buffers.buffer[i].fbuffer = NULL;				fh->v4l_buffers.buffer[i].fbuffer_phys =				    pmem + i * fh->v4l_buffers.buffer_size;				fh->v4l_buffers.buffer[i].fbuffer_bus =				    pmem + i * fh->v4l_buffers.buffer_size;			}#else			/* No bigphysarea present, usage of high memory disabled,			 * but user wants buffers of more than MAX_KMALLOC_MEM */			dprintk(1,				KERN_ERR				"%s: v4l_fbuffer_alloc() - no bigphysarea_patch present, usage of high memory disabled,\n",				ZR_DEVNAME(zr));			dprintk(1,				KERN_ERR				"%s: v4l_fbuffer_alloc() - sorry, could not allocate %d V4L buffers of size %d KB.\n",				ZR_DEVNAME(zr), fh->v4l_buffers.num_buffers,				fh->v4l_buffers.buffer_size >> 10);			return -ENOBUFS;#endif		}	}	fh->v4l_buffers.allocated = 1;	return 0;}/* free the V4L grab buffers */static voidv4l_fbuffer_free (struct file *file){	struct zoran_fh *fh = file->private_data;	struct zoran *zr = fh->zr;	int i, off;	unsigned char *mem;	dprintk(4, KERN_INFO "%s: v4l_fbuffer_free()\n", ZR_DEVNAME(zr));	for (i = 0; i < fh->v4l_buffers.num_buffers; i++) {		if (!fh->v4l_buffers.buffer[i].fbuffer)			continue;		if (fh->v4l_buffers.buffer_size <= MAX_KMALLOC_MEM) {			mem = fh->v4l_buffers.buffer[i].fbuffer;			for (off = 0; off < fh->v4l_buffers.buffer_size;			     off += PAGE_SIZE)				ClearPageReserved(MAP_NR(mem + off));			kfree((void *) fh->v4l_buffers.buffer[i].fbuffer);		}#if defined(CONFIG_BIGPHYS_AREA)		else			bigphysarea_free_pages((void *) fh->v4l_buffers.					       buffer[i].fbuffer);#endif		fh->v4l_buffers.buffer[i].fbuffer = NULL;	}	fh->v4l_buffers.allocated = 0;	fh->v4l_buffers.ready_to_be_freed = 0;}/* *   Allocate the MJPEG grab buffers. * *   If the requested buffer size is smaller than MAX_KMALLOC_MEM, *   kmalloc is used to request a physically contiguous area, *   else we allocate the memory in framgents with get_zeroed_page. * *   If a Natoma chipset is present and this is a revision 1 zr36057, *   each MJPEG buffer needs to be physically contiguous. *   (RJ: This statement is from Dave Perks' original driver, *   I could never check it because I have a zr36067) *   The driver cares about this because it reduces the buffer *   size to MAX_KMALLOC_MEM in that case (which forces contiguous allocation). * *   RJ: The contents grab buffers needs never be accessed in the driver.

⌨️ 快捷键说明

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