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

📄 w9968cf.c

📁 优龙2410linux2.6.8内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	DBG(4, "i2c_write_byte() is an unsupported transfer mode")	return -EINVAL;}/**************************************************************************** * I2C interface to kernel                                                  * ****************************************************************************/static intw9968cf_i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,                        unsigned short flags, char read_write, u8 command,                       int size, union i2c_smbus_data *data){	struct w9968cf_device* cam = i2c_get_adapdata(adapter);	u8 i;	int err = 0; 	switch (addr) {		case OV6xx0_SID:		case OV7xx0_SID:			break;		default:			DBG(4, "Rejected slave ID 0x%04X", addr)			return -EINVAL;	}	if (size == I2C_SMBUS_BYTE) {		/* Why addr <<= 1? See OVXXX0_SID defines in ovcamchip.h */		addr <<= 1;		if (read_write == I2C_SMBUS_WRITE) 			err = w9968cf_i2c_adap_write_byte(cam, addr, command);		else if (read_write == I2C_SMBUS_READ) 			err = w9968cf_i2c_adap_read_byte(cam,addr,&data->byte);	} else if (size == I2C_SMBUS_BYTE_DATA) {		addr <<= 1;		if (read_write == I2C_SMBUS_WRITE) 			err = w9968cf_i2c_adap_fastwrite_byte_data(cam, addr,			                                  command, data->byte);		else if (read_write == I2C_SMBUS_READ) {			for (i = 1; i <= W9968CF_I2C_RW_RETRIES; i++) {				err = w9968cf_i2c_adap_read_byte_data(cam,addr,				                         command, &data->byte);				if (err) {					if (w9968cf_smbus_refresh_bus(cam)) {						err = -EIO;						break;					}				} else					break;			}		} else			return -EINVAL;	} else {		DBG(4, "Unsupported I2C transfer mode (%d)", size)		return -EINVAL;	}	return err;}static u32 w9968cf_i2c_func(struct i2c_adapter* adap){	return I2C_FUNC_SMBUS_READ_BYTE |	       I2C_FUNC_SMBUS_READ_BYTE_DATA  |	       I2C_FUNC_SMBUS_WRITE_BYTE_DATA;}static int w9968cf_i2c_attach_inform(struct i2c_client* client){	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);	const char* clientname = i2c_clientname(client);	int id = client->driver->id, err = 0;	if (id == I2C_DRIVERID_OVCAMCHIP) {		cam->sensor_client = client;		err = w9968cf_sensor_init(cam);		if (err) {			cam->sensor_client = NULL;			return err;		}	} else {		DBG(4, "Rejected client [%s] with driver [%s]", 		    clientname, client->driver->name)		return -EINVAL;	}	DBG(5, "I2C attach client [%s] with driver [%s]",	    clientname, client->driver->name)	return 0;}static int w9968cf_i2c_detach_inform(struct i2c_client* client){	struct w9968cf_device* cam = i2c_get_adapdata(client->adapter);	const char* clientname = i2c_clientname(client);	if (cam->sensor_client == client)		cam->sensor_client = NULL;	DBG(5, "I2C detach client [%s]", clientname)	return 0;}static int w9968cf_i2c_control(struct i2c_adapter* adapter, unsigned int cmd,                    unsigned long arg){	return 0;}static int w9968cf_i2c_init(struct w9968cf_device* cam){	int err = 0;	static struct i2c_algorithm algo = {		.name =          "W996[87]CF algorithm",		.id =            I2C_ALGO_SMBUS,		.smbus_xfer =    w9968cf_i2c_smbus_xfer,		.algo_control =  w9968cf_i2c_control,		.functionality = w9968cf_i2c_func,	};	static struct i2c_adapter adap = {		.id =                I2C_ALGO_SMBUS | I2C_HW_SMBUS_W9968CF,		.class =             I2C_CLASS_CAM_DIGITAL,		.owner =             THIS_MODULE,		.client_register =   w9968cf_i2c_attach_inform,		.client_unregister = w9968cf_i2c_detach_inform,		.algo =              &algo,	};	memcpy(&cam->i2c_adapter, &adap, sizeof(struct i2c_adapter));	strcpy(cam->i2c_adapter.name, "w9968cf");	i2c_set_adapdata(&cam->i2c_adapter, cam);	DBG(6, "Registering I2C adapter with kernel...")	err = i2c_add_adapter(&cam->i2c_adapter);	if (err)		DBG(1, "Failed to register the I2C adapter")	else		DBG(5, "I2C adapter registered")	return err;}/**************************************************************************** * Helper functions                                                         * ****************************************************************************//*--------------------------------------------------------------------------  Turn on the LED on some webcams. A beep should be heard too.  Return 0 on success, a negative number otherwise.  --------------------------------------------------------------------------*/static int w9968cf_turn_on_led(struct w9968cf_device* cam){	int err = 0;	err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power-down */	err += w9968cf_write_reg(cam, 0xbf17, 0x00); /* reset everything */	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* normal operation */	err += w9968cf_write_reg(cam, 0x0010, 0x01); /* serial bus, SDS high */	err += w9968cf_write_reg(cam, 0x0000, 0x01); /* serial bus, SDS low */	err += w9968cf_write_reg(cam, 0x0010, 0x01); /* ..high 'beep-beep' */	if (err)		DBG(2, "Couldn't turn on the LED")	DBG(5, "LED turned on")	return err;}/*--------------------------------------------------------------------------  Write some registers for the device initialization.  This function is called once on open().  Return 0 on success, a negative number otherwise.  --------------------------------------------------------------------------*/static int w9968cf_init_chip(struct w9968cf_device* cam){	unsigned long hw_bufsize = cam->maxwidth*cam->maxheight*2,	              y0 = 0x0000,	              u0 = y0 + hw_bufsize/2,	              v0 = u0 + hw_bufsize/4,	              y1 = v0 + hw_bufsize/4,	              u1 = y1 + hw_bufsize/2,	              v1 = u1 + hw_bufsize/4;	int err = 0;	err += w9968cf_write_reg(cam, 0xff00, 0x00); /* power off */	err += w9968cf_write_reg(cam, 0xbf10, 0x00); /* power on */	err += w9968cf_write_reg(cam, 0x405d, 0x03); /* DRAM timings */	err += w9968cf_write_reg(cam, 0x0030, 0x04); /* SDRAM timings */	err += w9968cf_write_reg(cam, y0 & 0xffff, 0x20); /* Y buf.0, low */	err += w9968cf_write_reg(cam, y0 >> 16, 0x21);    /* Y buf.0, high */	err += w9968cf_write_reg(cam, u0 & 0xffff, 0x24); /* U buf.0, low */	err += w9968cf_write_reg(cam, u0 >> 16, 0x25);    /* U buf.0, high */	err += w9968cf_write_reg(cam, v0 & 0xffff, 0x28); /* V buf.0, low */	err += w9968cf_write_reg(cam, v0 >> 16, 0x29);    /* V buf.0, high */	err += w9968cf_write_reg(cam, y1 & 0xffff, 0x22); /* Y buf.1, low */	err += w9968cf_write_reg(cam, y1 >> 16, 0x23);    /* Y buf.1, high */	err += w9968cf_write_reg(cam, u1 & 0xffff, 0x26); /* U buf.1, low */	err += w9968cf_write_reg(cam, u1 >> 16, 0x27);    /* U buf.1, high */	err += w9968cf_write_reg(cam, v1 & 0xffff, 0x2a); /* V buf.1, low */	err += w9968cf_write_reg(cam, v1 >> 16, 0x2b);    /* V buf.1, high */	err += w9968cf_write_reg(cam, y1 & 0xffff, 0x32); /* JPEG buf 0 low */	err += w9968cf_write_reg(cam, y1 >> 16, 0x33);    /* JPEG buf 0 high */	err += w9968cf_write_reg(cam, y1 & 0xffff, 0x34); /* JPEG buf 1 low */	err += w9968cf_write_reg(cam, y1 >> 16, 0x35);    /* JPEG bug 1 high */	err += w9968cf_write_reg(cam, 0x0000, 0x36);/* JPEG restart interval */	err += w9968cf_write_reg(cam, 0x0804, 0x37);/*JPEG VLE FIFO threshold*/	err += w9968cf_write_reg(cam, 0x0000, 0x38);/* disable hw up-scaling */	err += w9968cf_write_reg(cam, 0x0000, 0x3f); /* JPEG/MCTL test data */	err += w9968cf_set_picture(cam, cam->picture); /* this before */	err += w9968cf_set_window(cam, cam->window);	if (err)		DBG(1, "Chip initialization failed")	else		DBG(5, "Chip successfully initialized")	return err;}/*--------------------------------------------------------------------------  Return non-zero if the palette is supported, 0 otherwise.  --------------------------------------------------------------------------*/static inline u16 w9968cf_valid_palette(u16 palette){	u8 i = 0;	while (w9968cf_formatlist[i].palette != 0) {		if (palette == w9968cf_formatlist[i].palette)			return palette;		i++;	}	return 0;}/*--------------------------------------------------------------------------  Return the depth corresponding to the given palette.  Palette _must_ be supported !  --------------------------------------------------------------------------*/static inline u16 w9968cf_valid_depth(u16 palette){	u8 i=0;	while (w9968cf_formatlist[i].palette != palette)		i++;	return w9968cf_formatlist[i].depth;}/*--------------------------------------------------------------------------  Return non-zero if the format requires decompression, 0 otherwise.  --------------------------------------------------------------------------*/static inline u8 w9968cf_need_decompression(u16 palette){	u8 i = 0;	while (w9968cf_formatlist[i].palette != 0) {		if (palette == w9968cf_formatlist[i].palette)			return w9968cf_formatlist[i].compression;		i++;	}	return 0;}/*--------------------------------------------------------------------------  Change the picture settings of the camera.  Return 0 on success, a negative number otherwise.  --------------------------------------------------------------------------*/static intw9968cf_set_picture(struct w9968cf_device* cam, struct video_picture pict){	u16 fmt, hw_depth, hw_palette, reg_v = 0x0000;	int err = 0;	/* Make sure we are using a valid depth */	pict.depth = w9968cf_valid_depth(pict.palette);	fmt = pict.palette;	hw_depth = pict.depth; /* depth used by the winbond chip */	hw_palette = pict.palette; /* palette used by the winbond chip */	/* VS & HS polarities */	reg_v = (cam->vs_polarity << 12) | (cam->hs_polarity << 11);	switch (fmt)	{		case VIDEO_PALETTE_UYVY:			reg_v |= 0x0000;			cam->vpp_flag = VPP_NONE;			break;		case VIDEO_PALETTE_YUV422P:			reg_v |= 0x0002;			cam->vpp_flag = VPP_DECOMPRESSION;			break;		case VIDEO_PALETTE_YUV420:		case VIDEO_PALETTE_YUV420P:			reg_v |= 0x0003;			cam->vpp_flag = VPP_DECOMPRESSION;			break;		case VIDEO_PALETTE_YUYV:		case VIDEO_PALETTE_YUV422:			reg_v |= 0x0000;			cam->vpp_flag = VPP_SWAP_YUV_BYTES;			hw_palette = VIDEO_PALETTE_UYVY;			break;		/* Original video is used instead of RGBX palettes. 		   Software conversion later. */		case VIDEO_PALETTE_GREY:		case VIDEO_PALETTE_RGB555:		case VIDEO_PALETTE_RGB565:		case VIDEO_PALETTE_RGB24:		case VIDEO_PALETTE_RGB32:			reg_v |= 0x0000; /* UYVY 16 bit is used */			hw_depth = 16;			hw_palette = VIDEO_PALETTE_UYVY;			cam->vpp_flag = VPP_UYVY_TO_RGBX;			break;	}	/* NOTE: due to memory issues, it is better to disable the hardware	         double buffering during compression */	if (cam->double_buffer && !(cam->vpp_flag & VPP_DECOMPRESSION))		reg_v |= 0x0080;	if (cam->clamping)		reg_v |= 0x0020;	if (cam->filter_type == 1)		reg_v |= 0x0008;	else if (cam->filter_type == 2)		reg_v |= 0x000c;	if ((err = w9968cf_write_reg(cam, reg_v, 0x16)))		goto

⌨️ 快捷键说明

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