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

📄 buz.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
#define MAX_KMALLOC_MEM (512*1024)/*   buz - Iomega Buz driver version 1.0   Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>   based on   buz.0.0.3 Copyright (C) 1998 Dave Perks <dperks@ibm.net>   and   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/module.h>#include <linux/delay.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/malloc.h>#include <linux/mm.h>#include <linux/pci.h>#include <linux/signal.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/page.h>#include <linux/sched.h>#include <asm/segment.h>#include <linux/types.h>#include <linux/wrapper.h>#include <linux/spinlock.h>#include <linux/vmalloc.h>#include <linux/videodev.h>#include <linux/version.h>#include <asm/uaccess.h>#include <linux/i2c-old.h>#include "buz.h"#include <linux/video_decoder.h>#include <linux/video_encoder.h>#define IRQ_MASK ( ZR36057_ISR_GIRQ0 | /* ZR36057_ISR_GIRQ1 | ZR36057_ISR_CodRepIRQ | */ ZR36057_ISR_JPEGRepIRQ )#define GPIO_MASK 0xdf/*  BUZ    GPIO0 = 1, take board out of reset   GPIO1 = 1, take JPEG codec out of sleep mode   GPIO3 = 1, deassert FRAME# to 36060      GIRQ0 signals a vertical sync of the video signal   GIRQ1 signals that ZR36060's DATERR# line is asserted.   SAA7111A   In their infinite wisdom, the Iomega engineers decided to   use the same input line for composite and S-Video Color,   although there are two entries not connected at all!   Through this ingenious strike, it is not possible to   keep two running video sources connected at the same time   to Composite and S-VHS input!   mode 0 - N/C   mode 1 - S-Video Y   mode 2 - noise or something I don't know   mode 3 - Composite and S-Video C   mode 4 - N/C   mode 5 - S-Video (gain C independently selectable of gain Y)   mode 6 - N/C   mode 7 - S-Video (gain C adapted to gain Y) */#define MAJOR_VERSION 1		/* driver major version */#define MINOR_VERSION 0		/* driver minor version */#define BUZ_NAME      "Iomega BUZ V-1.0"	/* name of the driver */#define DEBUG(x)		/* Debug driver */#define IDEBUG(x)		/* Debug interrupt handler */#define IOCTL_DEBUG(x)/* The parameters for this driver *//*   The video mem address of the video card.   The driver has a little database for some videocards   to determine it from there. If your video card is not in there   you have either to give it to the driver as a parameter   or set in in a VIDIOCSFBUF ioctl */static unsigned long vidmem = 0;	/* Video memory base address *//* Special purposes only: */static int triton = 0;		/* 0=no, 1=yes */static int natoma = 0;		/* 0=no, 1=yes *//*   Number and size of grab buffers for Video 4 Linux   The vast majority of applications should not need more than 2,   the very popular BTTV driver actually does ONLY have 2.   Time sensitive applications might need more, the maximum   is VIDEO_MAX_FRAME (defined in <linux/videodev.h>).   The size is set so that the maximum possible request   can be satisfied. Decrease  it, if bigphys_area alloc'd   memory is low. If you don't have the bigphys_area patch,   set it to 128 KB. Will you allow only to grab small   images with V4L, but that's better than nothing.   v4l_bufsize has to be given in KB ! */static int v4l_nbufs = 2;static int v4l_bufsize = 128;	/* Everybody should be able to work with this setting *//*   Default input and video norm at startup of the driver. */static int default_input = 0;	/* 0=Composite, 1=S-VHS */static int default_norm = 0;	/* 0=PAL, 1=NTSC */MODULE_PARM(vidmem, "i");MODULE_PARM(triton, "i");MODULE_PARM(natoma, "i");MODULE_PARM(v4l_nbufs, "i");MODULE_PARM(v4l_bufsize, "i");MODULE_PARM(default_input, "i");MODULE_PARM(default_norm, "i");/* Anybody who uses more than four? */#define BUZ_MAX 4static int zoran_num;		/* number of Buzs in use */static struct zoran zoran[BUZ_MAX];/* forward references */static void v4l_fbuffer_free(struct zoran *zr);static void jpg_fbuffer_free(struct zoran *zr);static void zoran_feed_stat_com(struct zoran *zr);/* *   Allocate the V4L grab buffers * *   These have to be pysically contiguous. *   If v4l_bufsize <= MAX_KMALLOC_MEM we use kmalloc */static int v4l_fbuffer_alloc(struct zoran *zr){	int i, off;	unsigned char *mem;	for (i = 0; i < v4l_nbufs; i++) {		if (zr->v4l_gbuf[i].fbuffer)			printk(KERN_WARNING "%s: v4l_fbuffer_alloc: buffer %d allready allocated ?\n", zr->name, i);		if (v4l_bufsize <= MAX_KMALLOC_MEM) {			/* Use kmalloc */			mem = (unsigned char *) kmalloc(v4l_bufsize, GFP_KERNEL);			if (mem == 0) {				printk(KERN_ERR "%s: kmalloc for V4L bufs failed\n", zr->name);				v4l_fbuffer_free(zr);				return -ENOBUFS;			}			zr->v4l_gbuf[i].fbuffer = mem;			zr->v4l_gbuf[i].fbuffer_phys = virt_to_phys(mem);			zr->v4l_gbuf[i].fbuffer_bus = virt_to_bus(mem);			for (off = 0; off < v4l_bufsize; off += PAGE_SIZE)				mem_map_reserve(virt_to_page(mem + off));			DEBUG(printk(BUZ_INFO ": V4L frame %d mem 0x%x (bus: 0x%x=%d)\n", i, mem, virt_to_bus(mem), virt_to_bus(mem)));		} else {			v4l_fbuffer_free(zr);			return -ENOBUFS;		}	}	return 0;}/* free the V4L grab buffers */static void v4l_fbuffer_free(struct zoran *zr){	int i, off;	unsigned char *mem;	for (i = 0; i < v4l_nbufs; i++) {		if (!zr->v4l_gbuf[i].fbuffer)			continue;		mem = zr->v4l_gbuf[i].fbuffer;		for (off = 0; off < v4l_bufsize; off += PAGE_SIZE)			mem_map_unreserve(virt_to_page(mem + off));		kfree((void *) zr->v4l_gbuf[i].fbuffer);		zr->v4l_gbuf[i].fbuffer = NULL;	}}/* *   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_free_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. *       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_free_page, but delivers you *       virtual addresses) and then again have to make a lot of efforts *       to get the physical address. * */static int jpg_fbuffer_alloc(struct zoran *zr){	int i, j, off, alloc_contig;	unsigned long mem;	/* Decide if we should alloc contiguous or fragmented memory */	/* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */	alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM);	for (i = 0; i < zr->jpg_nbufs; i++) {		if (zr->jpg_gbuf[i].frag_tab)			printk(KERN_WARNING "%s: jpg_fbuffer_alloc: buffer %d allready allocated ???\n", zr->name, i);		/* Allocate fragment table for this buffer */		mem = get_free_page(GFP_KERNEL);		if (mem == 0) {			printk(KERN_ERR "%s: jpg_fbuffer_alloc: get_free_page (frag_tab) failed for buffer %d\n", zr->name, i);			jpg_fbuffer_free(zr);			return -ENOBUFS;		}		memset((void *) mem, 0, PAGE_SIZE);		zr->jpg_gbuf[i].frag_tab = (u32 *) mem;		zr->jpg_gbuf[i].frag_tab_bus = virt_to_bus((void *) mem);		if (alloc_contig) {			mem = (unsigned long) kmalloc(zr->jpg_bufsize, GFP_KERNEL);			if (mem == 0) {				jpg_fbuffer_free(zr);				return -ENOBUFS;			}			zr->jpg_gbuf[i].frag_tab[0] = virt_to_bus((void *) mem);			zr->jpg_gbuf[i].frag_tab[1] = ((zr->jpg_bufsize / 4) << 1) | 1;			for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE)				mem_map_reserve(virt_to_page(mem + off));		} else {			/* jpg_bufsize is alreay page aligned */			for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) {				mem = get_free_page(GFP_KERNEL);				if (mem == 0) {					jpg_fbuffer_free(zr);					return -ENOBUFS;				}				zr->jpg_gbuf[i].frag_tab[2 * j] = virt_to_bus((void *) mem);				zr->jpg_gbuf[i].frag_tab[2 * j + 1] = (PAGE_SIZE / 4) << 1;				mem_map_reserve(virt_to_page(mem));			}			zr->jpg_gbuf[i].frag_tab[2 * j - 1] |= 1;		}	}	DEBUG(printk("jpg_fbuffer_alloc: %d KB allocated\n",		     (zr->jpg_nbufs * zr->jpg_bufsize) >> 10));	zr->jpg_buffers_allocated = 1;	return 0;}/* free the MJPEG grab buffers */static void jpg_fbuffer_free(struct zoran *zr){	int i, j, off, alloc_contig;	unsigned char *mem;	/* Decide if we should alloc contiguous or fragmented memory */	/* This has to be identical in jpg_fbuffer_alloc and jpg_fbuffer_free */	alloc_contig = (zr->jpg_bufsize < MAX_KMALLOC_MEM);	for (i = 0; i < zr->jpg_nbufs; i++) {		if (!zr->jpg_gbuf[i].frag_tab)			continue;		if (alloc_contig) {			if (zr->jpg_gbuf[i].frag_tab[0]) {				mem = (unsigned char *) bus_to_virt(zr->jpg_gbuf[i].frag_tab[0]);				for (off = 0; off < zr->jpg_bufsize; off += PAGE_SIZE)					mem_map_unreserve(virt_to_page(mem + off));				kfree((void *) mem);				zr->jpg_gbuf[i].frag_tab[0] = 0;				zr->jpg_gbuf[i].frag_tab[1] = 0;			}		} else {			for (j = 0; j < zr->jpg_bufsize / PAGE_SIZE; j++) {				if (!zr->jpg_gbuf[i].frag_tab[2 * j])					break;				mem_map_unreserve(virt_to_page(bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j])));				free_page((unsigned long) bus_to_virt(zr->jpg_gbuf[i].frag_tab[2 * j]));				zr->jpg_gbuf[i].frag_tab[2 * j] = 0;				zr->jpg_gbuf[i].frag_tab[2 * j + 1] = 0;			}		}		free_page((unsigned long) zr->jpg_gbuf[i].frag_tab);		zr->jpg_gbuf[i].frag_tab = NULL;	}	zr->jpg_buffers_allocated = 0;}/* ----------------------------------------------------------------------- *//* I2C functions                                                           */#define I2C_DELAY   10/* software I2C functions */static void i2c_setlines(struct i2c_bus *bus, int ctrl, int data){	struct zoran *zr = (struct zoran *) bus->data;	btwrite((data << 1) | ctrl, ZR36057_I2CBR);	btread(ZR36057_I2CBR);	udelay(I2C_DELAY);}static int i2c_getdataline(struct i2c_bus *bus){	struct zoran *zr = (struct zoran *) bus->data;	return (btread(ZR36057_I2CBR) >> 1) & 1;}static void attach_inform(struct i2c_bus *bus, int id){	DEBUG(struct zoran *zr = (struct zoran *) bus->data);	DEBUG(printk(BUZ_DEBUG "-%u: i2c attach %02x\n", zr->id, id));}static void detach_inform(struct i2c_bus *bus, int id){	DEBUG(struct zoran *zr = (struct zoran *) bus->data);	DEBUG(printk(BUZ_DEBUG "-%u: i2c detach %02x\n", zr->id, id));}static struct i2c_bus zoran_i2c_bus_template ={	"zr36057",	I2C_BUSID_BT848,	NULL,	SPIN_LOCK_UNLOCKED,	attach_inform,	detach_inform,	i2c_setlines,	i2c_getdataline,	NULL,	NULL,};/* ----------------------------------------------------------------------- */static void GPIO(struct zoran *zr, unsigned bit, unsigned value){	u32 reg;	u32 mask;	mask = 1 << (24 + bit);	reg = btread(ZR36057_GPPGCR1) & ~mask;	if (value) {		reg |= mask;	}	btwrite(reg, ZR36057_GPPGCR1);	/* Stop any PCI posting on the GPIO bus */	btread(ZR36057_I2CBR);}/* *   Set the registers for the size we have specified. Don't bother *   trying to understand this without the ZR36057 manual in front of *   you [AC]. * *   PS: The manual is free for download in .pdf format from *   www.zoran.com - nicely done those folks. */struct tvnorm {	u16 Wt, Wa, Ht, Ha, HStart, VStart;};static struct tvnorm tvnorms[] ={   /* PAL-BDGHI */	{864, 720, 625, 576, 31, 16},   /* NTSC */	{858, 720, 525, 480, 21, 8},};#define TVNORMS (sizeof(tvnorms) / sizeof(tvnorm))static int format2bpp(int format){	int bpp;	/* Determine the number of bytes per pixel for the video format requested */	switch (format) {	case VIDEO_PALETTE_YUV422:		bpp = 2;		break;	case VIDEO_PALETTE_RGB555:		bpp = 2;		break;	case VIDEO_PALETTE_RGB565:		bpp = 2;		break;	case VIDEO_PALETTE_RGB24:		bpp = 3;		break;	case VIDEO_PALETTE_RGB32:		bpp = 4;		break;	default:		bpp = 0;	}	return bpp;}/* * set geometry */static void zr36057_set_vfe(struct zoran *zr, int video_width, int video_height,			    unsigned int video_format){	struct tvnorm *tvn;	unsigned HStart, HEnd, VStart, VEnd;	unsigned DispMode;	unsigned VidWinWid, VidWinHt;	unsigned hcrop1, hcrop2, vcrop1, vcrop2;	unsigned Wa, We, Ha, He;	unsigned X, Y, HorDcm, VerDcm;	u32 reg;	unsigned mask_line_size;	if (zr->params.norm < 0 || zr->params.norm > 1) {		printk(KERN_ERR "%s: set_vfe: video_norm = %d not valid\n", zr->name,  zr->params.norm);		return;	}	if (video_width < BUZ_MIN_WIDTH || video_height < BUZ_MIN_HEIGHT) {		printk(KERN_ERR "%s: set_vfe: w=%d h=%d not valid\n", zr->name, video_width, video_height);		return;	}	tvn = &tvnorms[zr->params.norm];	Wa = tvn->Wa;	Ha = tvn->Ha;

⌨️ 快捷键说明

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