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

📄 ov511.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	PDEBUG(5, "reg read: 0x%02X:0x%02X", reg, buffer[0]);		if (rc < 0) {		err("reg read: error %d", rc);		return rc;	} else {		return buffer[0];		}}static int ov511_i2c_write(struct usb_device *dev,			   unsigned char reg,			   unsigned char value){	int rc, retries;	PDEBUG(5, "i2c write: 0x%02X:0x%02X", reg, value);	/* Three byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_3_BYTE, reg);		if (rc < 0) goto error;		/* Write "value" to I2C data port of OV511 */		rc = ov511_reg_write(dev, OV511_REG_I2C_DATA_PORT, value);			if (rc < 0) goto error;		/* Initiate 3-byte write cycle */		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x01);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;#if 0		/* I2C abort */			ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);#endif		if (--retries < 0) {			err("i2c write retries exhausted");			rc = -1;			goto error;		}	}	return 0;error:	err("i2c write: error %d", rc);	return rc;}/* returns: negative is error, pos or zero is data */static int ov511_i2c_read(struct usb_device *dev, unsigned char reg){	int rc, value, retries;	/* Two byte write cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Select camera register */		rc = ov511_reg_write(dev, OV511_REG_I2C_SUB_ADDRESS_2_BYTE, reg);		if (rc < 0) goto error;		/* Initiate 2-byte write cycle */		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x03);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);		if (--retries < 0) {			err("i2c write retries exhausted");			rc = -1;			goto error;		}	}	/* Two byte read cycle */	for (retries = OV511_I2C_RETRIES; ; ) {		/* Initiate 2-byte read cycle */		rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);		if (rc < 0) goto error;		do rc = ov511_reg_read(dev, OV511_REG_I2C_CONTROL);		while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */		if (rc < 0) goto error;		if ((rc&2) == 0) /* Ack? */			break;		/* I2C abort */			rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x10);		if (rc < 0) goto error;		if (--retries < 0) {			err("i2c read retries exhausted");			rc = -1;			goto error;		}	}	value = ov511_reg_read(dev, OV511_REG_I2C_DATA_PORT);	PDEBUG(5, "i2c read: 0x%02X:0x%02X", reg, value);			/* This is needed to make ov511_i2c_write() work */	rc = ov511_reg_write(dev, OV511_REG_I2C_CONTROL, 0x05);	if (rc < 0)		goto error;		return value;error:	err("i2c read: error %d", rc);	return rc;}static int ov511_write_regvals(struct usb_device *dev,			       struct ov511_regvals * pRegvals){	int rc;	while (pRegvals->bus != OV511_DONE_BUS) {		if (pRegvals->bus == OV511_REG_BUS) {			if ((rc = ov511_reg_write(dev, pRegvals->reg,			                           pRegvals->val)) < 0)				goto error;		} else if (pRegvals->bus == OV511_I2C_BUS) {			if ((rc = ov511_i2c_write(dev, pRegvals->reg, 			                           pRegvals->val)) < 0)				goto error;		} else {			err("Bad regval array");			rc = -1;			goto error;		}		pRegvals++;	}	return 0;error:	err("write regvals: error %d", rc);	return rc;}#ifdef OV511_DEBUG static void ov511_dump_i2c_range(struct usb_device *dev, int reg1, int regn){	int i;	int rc;	for(i = reg1; i <= regn; i++) {		rc = ov511_i2c_read(dev, i);		PDEBUG(1, "OV7610[0x%X] = 0x%X", i, rc);	}}static void ov511_dump_i2c_regs(struct usb_device *dev){	PDEBUG(3, "I2C REGS");	ov511_dump_i2c_range(dev, 0x00, 0x7C);}#if 0static void ov511_dump_reg_range(struct usb_device *dev, int reg1, int regn){	int i;	int rc;	for(i = reg1; i <= regn; i++) {	  rc = ov511_reg_read(dev, i);	  PDEBUG(1, "OV511[0x%X] = 0x%X", i, rc);	}}static void ov511_dump_regs(struct usb_device *dev){	PDEBUG(1, "CAMERA INTERFACE REGS");	ov511_dump_reg_range(dev, 0x10, 0x1f);	PDEBUG(1, "DRAM INTERFACE REGS");	ov511_dump_reg_range(dev, 0x20, 0x23);	PDEBUG(1, "ISO FIFO REGS");	ov511_dump_reg_range(dev, 0x30, 0x31);	PDEBUG(1, "PIO REGS");	ov511_dump_reg_range(dev, 0x38, 0x39);	ov511_dump_reg_range(dev, 0x3e, 0x3e);	PDEBUG(1, "I2C REGS");	ov511_dump_reg_range(dev, 0x40, 0x49);	PDEBUG(1, "SYSTEM CONTROL REGS");	ov511_dump_reg_range(dev, 0x50, 0x55);	ov511_dump_reg_range(dev, 0x5e, 0x5f);	PDEBUG(1, "OmniCE REGS");	ov511_dump_reg_range(dev, 0x70, 0x79);	ov511_dump_reg_range(dev, 0x80, 0x9f);	ov511_dump_reg_range(dev, 0xa0, 0xbf);}#endif#endifstatic int ov511_reset(struct usb_device *dev, unsigned char reset_type){	int rc;		PDEBUG(4, "Reset: type=0x%X", reset_type);	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, reset_type);	rc = ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0);	if (rc < 0)		err("reset: command failed");	return rc;}/* Temporarily stops OV511 from functioning. Must do this before changing * registers while the camera is streaming */static inline int ov511_stop(struct usb_device *dev){	PDEBUG(4, "stopping");	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x3d));}/* Restarts OV511 after ov511_stop() is called */static inline int ov511_restart(struct usb_device *dev){	PDEBUG(4, "restarting");	return (ov511_reg_write(dev, OV511_REG_SYSTEM_RESET, 0x00));}static int ov511_set_packet_size(struct usb_ov511 *ov511, int size){	int alt, mult;	if (ov511_stop(ov511->dev) < 0)		return -EIO;	mult = size >> 5;	if (ov511->bridge == BRG_OV511) {		if (size == 0) alt = OV511_ALT_SIZE_0;		else if (size == 257) alt = OV511_ALT_SIZE_257;		else if (size == 513) alt = OV511_ALT_SIZE_513;		else if (size == 769) alt = OV511_ALT_SIZE_769;		else if (size == 993) alt = OV511_ALT_SIZE_993;		else {			err("Set packet size: invalid size (%d)", size);			return -EINVAL;		}	} else if (ov511->bridge == BRG_OV511PLUS) {		if (size == 0) alt = OV511PLUS_ALT_SIZE_0;		else if (size == 33) alt = OV511PLUS_ALT_SIZE_33;		else if (size == 129) alt = OV511PLUS_ALT_SIZE_129;		else if (size == 257) alt = OV511PLUS_ALT_SIZE_257;		else if (size == 385) alt = OV511PLUS_ALT_SIZE_385;		else if (size == 513) alt = OV511PLUS_ALT_SIZE_513;		else if (size == 769) alt = OV511PLUS_ALT_SIZE_769;		else if (size == 961) alt = OV511PLUS_ALT_SIZE_961;		else {			err("Set packet size: invalid size (%d)", size);			return -EINVAL;		}	} else {		err("Set packet size: Invalid bridge type");		return -EINVAL;	}	PDEBUG(3, "set packet size: %d, mult=%d, alt=%d", size, mult, alt);	if (ov511_reg_write(ov511->dev, OV511_REG_FIFO_PACKET_SIZE, mult) < 0)		return -ENOMEM;		if (usb_set_interface(ov511->dev, ov511->iface, alt) < 0) {		err("Set packet size: set interface error");		return -EBUSY;	}	// FIXME - Should we only reset the FIFO?	if (ov511_reset(ov511->dev, OV511_RESET_NOREGS) < 0)		return -ENOMEM;	ov511->packet_size = size;	if (ov511_restart(ov511->dev) < 0)		return -EIO;	return 0;}static inline intov7610_set_picture(struct usb_ov511 *ov511, struct video_picture *p){	int ret;	struct usb_device *dev = ov511->dev;	PDEBUG(4, "ov511_set_picture");	if (ov511_stop(dev) < 0)		return -EIO;	ov511->contrast = p->contrast;	ov511->brightness = p->brightness;	ov511->colour = p->colour;	ov511->hue = p->hue;	ov511->whiteness = p->whiteness;	if ((ret = ov511_i2c_read(dev, OV7610_REG_COM_B)) < 0)		return -EIO;#if 0	/* disable auto adjust mode */	if (ov511_i2c_write(dev, OV7610_REG_COM_B, ret & 0xfe) < 0)		return -EIO;#endif	if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV7620AE		|| ov511->sensor == SEN_OV6620)		if (ov511_i2c_write(dev, OV7610_REG_SAT, p->colour >> 8) < 0)			return -EIO;	if (ov511->sensor == SEN_OV7610 || ov511->sensor == SEN_OV6620) {		if (ov511_i2c_write(dev, OV7610_REG_CNT, p->contrast >> 8) < 0)			return -EIO;		if (ov511_i2c_write(dev, OV7610_REG_RED, 0xFF - (p->hue >> 8)) < 0)			return -EIO;		if (ov511_i2c_write(dev, OV7610_REG_BLUE, p->hue >> 8) < 0)			return -EIO;		if (ov511_i2c_write(dev, OV7610_REG_BRT, p->brightness >> 8) < 0)			return -EIO;	} else if ((ov511->sensor == SEN_OV7620) 	         || (ov511->sensor == SEN_OV7620AE)) {#if 0		int cur_sat, new_sat, tmp;		cur_sat = ov511_i2c_read(dev, OV7610_REG_BLUE);		tmp = (p->hue >> 8) - cur_sat;		new_sat = (tmp < 0) ? (-tmp) | 0x80 : tmp;	        PDEBUG(1, "cur=%d target=%d diff=%d", cur_sat, p->hue >> 8, tmp); 		if (ov511_i2c_write(dev, OV7610_REG_BLUE, new_sat) < 0)			return -EIO;	        // DEBUG_CODE	        PDEBUG(1, "hue=%d", ov511_i2c_read(dev, OV7610_REG_BLUE)); #endif	}	if (ov511_restart(dev) < 0)		return -EIO;	return 0;}static inline intov7610_get_picture(struct usb_ov511 *ov511, struct video_picture *p){	int ret;	struct usb_device *dev = ov511->dev;	PDEBUG(4, "ov511_get_picture");	if (ov511_stop(dev) < 0)		return -EIO;	if ((ret = ov511_i2c_read(dev, OV7610_REG_SAT)) < 0) return -EIO;	p->colour = ret << 8;	if ((ret = ov511_i2c_read(dev, OV7610_REG_CNT)) < 0) return -EIO;	p->contrast = ret << 8;	if ((ret = ov511_i2c_read(dev, OV7610_REG_BRT)) < 0) return -EIO;	p->brightness = ret << 8;	/* This may not be the best way to do it */	if ((ret = ov511_i2c_read(dev, OV7610_REG_BLUE)) < 0) return -EIO;	p->hue = ret << 8;	p->whiteness = 105 << 8;	/* Can we get these from frame[0]? -claudio? */	p->depth = ov511->frame[0].depth;	p->palette = ov511->frame[0].format;	if (ov511_restart(dev) < 0)		return -EIO;	return 0;}/* Returns number of bits per pixel (regardless of where they are located; planar or * not), or zero for unsupported format. */static int ov511_get_depth(int palette){	switch (palette) {	case VIDEO_PALETTE_GREY:    return 8;	case VIDEO_PALETTE_RGB565:  return 16;	case VIDEO_PALETTE_RGB24:   return 24;  	case VIDEO_PALETTE_YUV422:  return 16;	case VIDEO_PALETTE_YUYV:    return 16;	case VIDEO_PALETTE_YUV420:  return 24;	case VIDEO_PALETTE_YUV422P: return 24; /* Planar */	default:		    return 0;  /* Invalid format */	}}/* LNCNT values fixed by Lawrence Glaister <lg@jfm.bc.ca> */static struct mode_list mlist[] = {	/* W    H   C  PXCNT LNCNT PXDIV LNDIV M420  COMA  COML */	{ 640, 480, 0, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },	{ 640, 480, 1, 0x4f, 0x3b, 0x00, 0x00, 0x03, 0x24, 0x9e },	{ 320, 240, 0, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 320, 240, 1, 0x27, 0x1d, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 352, 288, 0, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 352, 288, 1, 0x2b, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 384, 288, 0, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 384, 288, 1, 0x2f, 0x25, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 448, 336, 0, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 448, 336, 1, 0x37, 0x29, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 176, 144, 0, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 176, 144, 1, 0x15, 0x12, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 160, 120, 0, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 160, 120, 1, 0x13, 0x0e, 0x00, 0x00, 0x03, 0x04, 0x1e },	{ 0, 0 }};static intov511_mode_init_regs(struct usb_ov511 *ov511,		     int width, int height, int mode, int sub_flag){	int i;	struct usb_device *dev = ov511->dev;	int hwsbase, hwebase, vwsbase, vwebase, hwsize, vwsize; 	int hwscale = 0, vwscale = 0;	PDEBUG(3, "width:%d, height:%d, mode:%d, sub:%d",	       width, height, mode, sub_flag);	if (ov511_stop(ov511->dev) < 0)		return -EIO;	/* Dumppix only works with RGB24 */	if (dumppix && (mode != VIDEO_PALETTE_RGB24)) {		err("dumppix only supported with RGB 24");		return -EINVAL;	}	if (mode == VIDEO_PALETTE_GREY) {		ov511_reg_write(dev, 0x16, 0x00);		if (ov511->sensor == SEN_OV7610		    || ov511->sensor == SEN_OV7620AE) {			/* these aren't valid on the OV6620/OV7620 */			ov511_i2c_write(dev, 0x0e, 0x44);		}		ov511_i2c_write(dev, 0x13, autoadjust ? 0x21 : 0x20);		/* For snapshot */		ov511_reg_write(dev, 0x1e, 0x00);		ov511_reg_write(dev, 0x1f, 0x01);	} else {		ov511_reg_write(dev, 0x16, 0x01);		if (ov511->sensor == SEN_OV7610		    || ov511->sensor == SEN_OV7620AE) {			/* not valid on the OV6620/OV7620 */			ov511_i2c_write(dev, 0x0e, 0x04);		}		ov511_i2c_write(dev, 0x13, autoadjust ? 0x01 : 0x00);		/* For snapshot */		ov511_reg_write(dev, 0x1e, 0x01);		ov511_reg_write(dev, 0x1f, 0x03);	}	/* The different sensor ICs handle setting up of window differently */	switch (ov511->sensor) {	case SEN_OV7610:	case SEN_OV7620AE:		hwsbase = 0x38;		hwebase = 0x3a;		vwsbase = vwebase = 0x05;		break;	case SEN_OV6620:		hwsbase = 0x38;		hwebase = 0x3a;		vwsbase = 0x05;		vwebase = 0x06;		break;	case SEN_OV7620:		hwsbase = 0x2c;		hwebase = 0x2d;		vwsbase = vwebase = 0x05;		break;

⌨️ 快捷键说明

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