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

📄 w9966.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	regs[0x06] = (y1 & 0x0ff);		// Y-start (8 low bits)	regs[0x07] = (y1 & 0x300)>>8;		// Y-start (2 high bits)	regs[0x08] = (x2 & 0x0ff);		// X-end (8 low bits)	regs[0x09] = (x2 & 0x300)>>8;		// X-end (2 high bits)	regs[0x0a] = (y2 & 0x0ff);		// Y-end (8 low bits)	regs[0x0c] = W9966_SRAMID;		// SRAM-banks (1x 128kb)		// Enhancement layer	regs[0x0d] = (enh_s& 0x000ff);		// Enh. start (0-7)	regs[0x0e] = (enh_s& 0x0ff00)>>8;	// Enh. start (8-15)	regs[0x0f] = (enh_s& 0x70000)>>16;	// Enh. start (16-17/18??)	regs[0x10] = (enh_e& 0x000ff);		// Enh. end (0-7)	regs[0x11] = (enh_e& 0x0ff00)>>8;	// Enh. end (8-15)	regs[0x12] = (enh_e& 0x70000)>>16;	// Enh. end (16-17/18??)	// Misc	regs[0x13] = 0x40;			// VEE control (raw 4:2:2)	regs[0x17] = 0x00;			// ???	regs[0x18] = cam->i2c_state = 0x00;	// Serial bus	regs[0x19] = 0xff;			// I/O port direction control	regs[0x1a] = 0xff;			// I/O port data register	regs[0x1b] = 0x10;			// ???		// SAA7111 chip settings	saa7111_regs[0x0a] = cam->brightness;	saa7111_regs[0x0b] = cam->contrast;	saa7111_regs[0x0c] = cam->color;	saa7111_regs[0x0d] = cam->hue;// Reset (ECP-fifo & serial-bus)	if (w9966_wReg(cam, 0x00, 0x03) == -1)		return -1;// Write regs to w9966cf chip	for (i = 0; i < 0x1c; i++)		if (w9966_wReg(cam, i, regs[i]) == -1)			return -1;// Write regs to saa7111 chip	for (i = 0; i < 0x20; i++)		if (w9966_wReg_i2c(cam, i, saa7111_regs[i]) == -1)			return -1;	return 0;}/* *	Ugly and primitive i2c protocol functions */// Sets the data line on the i2c bus.// Expects a claimed pdev.static inline void w9966_i2c_setsda(struct w9966_dev* cam, int state){	if (state)		cam->i2c_state |= W9966_I2C_W_DATA;	else		cam->i2c_state &= ~W9966_I2C_W_DATA;		w9966_wReg(cam, 0x18, cam->i2c_state);	udelay(5);}// Get peripheral clock line// Expects a claimed pdev.static inline int w9966_i2c_getscl(struct w9966_dev* cam){	const unsigned char state = w9966_rReg(cam, 0x18);	return ((state & W9966_I2C_R_CLOCK) > 0);}// Sets the clock line on the i2c bus.// Expects a claimed pdev. -1 on errorstatic inline int w9966_i2c_setscl(struct w9966_dev* cam, int state){	unsigned long timeout;	if (state)		cam->i2c_state |= W9966_I2C_W_CLOCK;	else		cam->i2c_state &= ~W9966_I2C_W_CLOCK;	w9966_wReg(cam, 0x18, cam->i2c_state);	udelay(5);		// we go to high, we also expect the peripheral to ack.	if (state) {		timeout = jiffies + 100;		while (!w9966_i2c_getscl(cam)) {			if (time_after(jiffies, timeout))				return -1;		}	}	return 0;}// Get peripheral data line// Expects a claimed pdev.static inline int w9966_i2c_getsda(struct w9966_dev* cam){	const unsigned char state = w9966_rReg(cam, 0x18);	return ((state & W9966_I2C_R_DATA) > 0);}// Write a byte with ack to the i2c bus.// Expects a claimed pdev. -1 on errorstatic int w9966_i2c_wbyte(struct w9966_dev* cam, int data){	int i;	for (i = 7; i >= 0; i--)	{		w9966_i2c_setsda(cam, (data >> i) & 0x01);		if (w9966_i2c_setscl(cam, 1) == -1)			return -1;					w9966_i2c_setscl(cam, 0);	}	w9966_i2c_setsda(cam, 1);		if (w9966_i2c_setscl(cam, 1) == -1)		return -1;	w9966_i2c_setscl(cam, 0);		return 0;}// Read a data byte with ack from the i2c-bus// Expects a claimed pdev. -1 on error#if 0static int w9966_i2c_rbyte(struct w9966_dev* cam){	unsigned char data = 0x00;	int i;			w9966_i2c_setsda(cam, 1);	for (i = 0; i < 8; i++)	{		if (w9966_i2c_setscl(cam, 1) == -1)			return -1;		data = data << 1;		if (w9966_i2c_getsda(cam))			data |= 0x01;				w9966_i2c_setscl(cam, 0);	}	return data;}#endif// Read a register from the i2c device.// Expects claimed pdev. -1 on error#if 0static int w9966_rReg_i2c(struct w9966_dev* cam, int reg){	int data;	w9966_i2c_setsda(cam, 0);	w9966_i2c_setscl(cam, 0);	if (		w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||		w9966_i2c_wbyte(cam, reg) == -1	)		return -1;	w9966_i2c_setsda(cam, 1);	if (w9966_i2c_setscl(cam, 1) == -1)		return -1;	w9966_i2c_setsda(cam, 0);	w9966_i2c_setscl(cam, 0);	if (		w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1 ||		(data = w9966_i2c_rbyte(cam)) == -1	)		return -1;	w9966_i2c_setsda(cam, 0);		if (w9966_i2c_setscl(cam, 1) == -1)		return -1;	w9966_i2c_setsda(cam, 1);		return data;}#endif// Write a register to the i2c device.// Expects claimed pdev. -1 on errorstatic int w9966_wReg_i2c(struct w9966_dev* cam, int reg, int data){	w9966_i2c_setsda(cam, 0);	w9966_i2c_setscl(cam, 0);	if (		w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||		w9966_i2c_wbyte(cam, reg) == -1 ||		w9966_i2c_wbyte(cam, data) == -1	)		return -1;	w9966_i2c_setsda(cam, 0);	if (w9966_i2c_setscl(cam, 1) == -1)		return -1;			w9966_i2c_setsda(cam, 1);	return 0;}/* *	Video4linux interfacing */static int w9966_v4l_do_ioctl(struct inode *inode, struct file *file,			      unsigned int cmd, void *arg){	struct video_device *vdev = video_devdata(file);	struct w9966_dev *cam = vdev->priv;		switch(cmd)	{	case VIDIOCGCAP:	{		static struct video_capability vcap = {			.name      = W9966_DRIVERNAME,			.type      = VID_TYPE_CAPTURE | VID_TYPE_SCALES,			.channels  = 1,			.maxwidth  = W9966_WND_MAX_W,			.maxheight = W9966_WND_MAX_H,			.minwidth  = 2,			.minheight = 1,		};		struct video_capability *cap = arg;		*cap = vcap;		return 0;	}	case VIDIOCGCHAN:	{		struct video_channel *vch = arg;		if(vch->channel != 0)	// We only support one channel (#0)			return -EINVAL;		memset(vch,0,sizeof(*vch));		strcpy(vch->name, "CCD-input");		vch->type = VIDEO_TYPE_CAMERA;		return 0;	}	case VIDIOCSCHAN:	{		struct video_channel *vch = arg;		if(vch->channel != 0)			return -EINVAL;		return 0;	}	case VIDIOCGTUNER:	{		struct video_tuner *vtune = arg;		if(vtune->tuner != 0)			return -EINVAL;		strcpy(vtune->name, "no tuner");		vtune->rangelow = 0;		vtune->rangehigh = 0;		vtune->flags = VIDEO_TUNER_NORM;		vtune->mode = VIDEO_MODE_AUTO;		vtune->signal = 0xffff;		return 0;	}	case VIDIOCSTUNER:	{		struct video_tuner *vtune = arg;		if (vtune->tuner != 0)			return -EINVAL;		if (vtune->mode != VIDEO_MODE_AUTO)			return -EINVAL;		return 0;	}	case VIDIOCGPICT:	{		struct video_picture vpic = {			cam->brightness << 8,	// brightness			(cam->hue + 128) << 8,	// hue			cam->color << 9,	// color			cam->contrast << 9,	// contrast			0x8000,			// whiteness			16, VIDEO_PALETTE_YUV422// bpp, palette format		};		struct video_picture *pic = arg;		*pic = vpic;		return 0;	}	case VIDIOCSPICT:	{		struct video_picture *vpic = arg;		if (vpic->depth != 16 || vpic->palette != VIDEO_PALETTE_YUV422)			return -EINVAL;					cam->brightness = vpic->brightness >> 8;		cam->hue = (vpic->hue >> 8) - 128;		cam->color = vpic->colour >> 9;		cam->contrast = vpic->contrast >> 9;		w9966_pdev_claim(cam);				if (			w9966_wReg_i2c(cam, 0x0a, cam->brightness) == -1 ||			w9966_wReg_i2c(cam, 0x0b, cam->contrast) == -1 ||			w9966_wReg_i2c(cam, 0x0c, cam->color) == -1 ||			w9966_wReg_i2c(cam, 0x0d, cam->hue) == -1		) {			w9966_pdev_release(cam);			return -EIO;		}				w9966_pdev_release(cam);		return 0;	}	case VIDIOCSWIN:	{		int ret;		struct video_window *vwin = arg;				if (vwin->flags != 0)			return -EINVAL;		if (vwin->clipcount != 0)			return -EINVAL;		if (vwin->width < 2 || vwin->width > W9966_WND_MAX_W)			return -EINVAL;				if (vwin->height < 1 || vwin->height > W9966_WND_MAX_H)			return -EINVAL;		// Update camera regs		w9966_pdev_claim(cam);		ret = w9966_setup(cam, 0, 0, 1023, 1023, vwin->width, vwin->height);		w9966_pdev_release(cam);				if (ret != 0) {			DPRINTF("VIDIOCSWIN: w9966_setup() failed.\n");			return -EIO;		}				return 0;	}	case VIDIOCGWIN:	{		struct video_window *vwin = arg;		memset(vwin, 0, sizeof(*vwin));		vwin->width = cam->width;		vwin->height = cam->height;		return 0;	}	// Unimplemented	case VIDIOCCAPTURE:		case VIDIOCGFBUF:	case VIDIOCSFBUF:	case VIDIOCKEY:	case VIDIOCGFREQ:	case VIDIOCSFREQ:	case VIDIOCGAUDIO:	case VIDIOCSAUDIO:		return -EINVAL;	default:		return -ENOIOCTLCMD;	}	return 0;}static int w9966_v4l_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg){	return video_usercopy(inode, file, cmd, arg, w9966_v4l_do_ioctl);}// Capture datastatic ssize_t w9966_v4l_read(struct file *file, char  __user *buf,			      size_t count, loff_t *ppos){	struct video_device *vdev = video_devdata(file);	struct w9966_dev *cam = vdev->priv;	unsigned char addr = 0xa0;	// ECP, read, CCD-transfer, 00000	unsigned char __user *dest = (unsigned char __user *)buf;	unsigned long dleft = count;	unsigned char *tbuf;		// Why would anyone want more than this??	if (count > cam->width * cam->height * 2)		return -EINVAL;		w9966_pdev_claim(cam);	w9966_wReg(cam, 0x00, 0x02);	// Reset ECP-FIFO buffer	w9966_wReg(cam, 0x00, 0x00);	// Return to normal operation	w9966_wReg(cam, 0x01, 0x98);	// Enable capture	// write special capture-addr and negotiate into data transfer		if (		(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0	)||		(parport_write(cam->pport, &addr, 1) != 1						)||		(parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0	)	) {		w9966_pdev_release(cam);		return -EFAULT;	}	tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);	if (tbuf == NULL) {		count = -ENOMEM;		goto out;	}	while(dleft > 0)	{		unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;			if (parport_read(cam->pport, tbuf, tsize) < tsize) {			count = -EFAULT;			goto out;		}		if (copy_to_user(dest, tbuf, tsize) != 0) {			count = -EFAULT;			goto out;		}		dest += tsize;		dleft -= tsize;	}	w9966_wReg(cam, 0x01, 0x18);	// Disable captureout:	kfree(tbuf);	w9966_pdev_release(cam);	return count;}// Called once for every parport on initstatic void w9966_attach(struct parport *port){	int i;		for (i = 0; i < W9966_MAXCAMS; i++)	{		if (w9966_cams[i].dev_state != 0)	// Cam is already assigned			continue;		if (			strcmp(pardev[i], "aggressive") == 0 ||			strcmp(pardev[i], port->name) == 0		) {			if (w9966_init(&w9966_cams[i], port) != 0)			w9966_term(&w9966_cams[i]);			break;	// return		}	}}// Called once for every parport on terminationstatic void w9966_detach(struct parport *port){	int i;	for (i = 0; i < W9966_MAXCAMS; i++)	if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)		w9966_term(&w9966_cams[i]);}static struct parport_driver w9966_ppd = {	.name = W9966_DRIVERNAME,	.attach = w9966_attach,	.detach = w9966_detach,};// Module entry pointstatic int __init w9966_mod_init(void){	int i;	for (i = 0; i < W9966_MAXCAMS; i++)		w9966_cams[i].dev_state = 0;	return parport_register_driver(&w9966_ppd);}// Module cleanupstatic void __exit w9966_mod_term(void){	parport_unregister_driver(&w9966_ppd);}module_init(w9966_mod_init);module_exit(w9966_mod_term);

⌨️ 快捷键说明

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