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

📄 ivtv-i2c.c

📁 linux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		IVTV_DEBUG_I2C("resetting I2C\n");		for (i = 0; i < 16; ++i) {			ivtv_setscl(itv, 0);			ivtv_scldelay(itv);			ivtv_setscl(itv, 1);			ivtv_scldelay(itv);			ivtv_setsda(itv, 1);		}		ivtv_waitsda(itv, 1);		return -EREMOTEIO;	}	return 0;}/* Write a message to the given i2c slave.  do_stop may be 0 to prevent   issuing the i2c stop condition (when following with a read) */static int ivtv_write(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len, int do_stop){	int retry, ret = -EREMOTEIO;	u32 i;	for (retry = 0; ret != 0 && retry < 8; ++retry) {		ret = ivtv_start(itv);		if (ret == 0) {			ret = ivtv_sendbyte(itv, addr<<1);			for (i = 0; ret == 0 && i < len; ++i)				ret = ivtv_sendbyte(itv, data[i]);		}		if (ret != 0 || do_stop) {			ivtv_stop(itv);		}	}	if (ret)		IVTV_DEBUG_I2C("i2c write to %x failed\n", addr);	return ret;}/* Read data from the given i2c slave.  A stop condition is always issued. */static int ivtv_read(struct ivtv *itv, unsigned char addr, unsigned char *data, u32 len){	int retry, ret = -EREMOTEIO;	u32 i;	for (retry = 0; ret != 0 && retry < 8; ++retry) {		ret = ivtv_start(itv);		if (ret == 0)			ret = ivtv_sendbyte(itv, (addr << 1) | 1);		for (i = 0; ret == 0 && i < len; ++i) {			ret = ivtv_readbyte(itv, &data[i], i == len - 1);		}		ivtv_stop(itv);	}	if (ret)		IVTV_DEBUG_I2C("i2c read from %x failed\n", addr);	return ret;}/* Kernel i2c transfer implementation.  Takes a number of messages to be read   or written.  If a read follows a write, this will occur without an   intervening stop condition */static int ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num){	struct ivtv *itv = i2c_get_adapdata(i2c_adap);	int retval;	int i;	mutex_lock(&itv->i2c_bus_lock);	for (i = retval = 0; retval == 0 && i < num; i++) {		if (msgs[i].flags & I2C_M_RD)			retval = ivtv_read(itv, msgs[i].addr, msgs[i].buf, msgs[i].len);		else {			/* if followed by a read, don't stop */			int stop = !(i + 1 < num && msgs[i + 1].flags == I2C_M_RD);			retval = ivtv_write(itv, msgs[i].addr, msgs[i].buf, msgs[i].len, stop);		}	}	mutex_unlock(&itv->i2c_bus_lock);	return retval ? retval : num;}/* Kernel i2c capabilities */static u32 ivtv_functionality(struct i2c_adapter *adap){	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;}static struct i2c_algorithm ivtv_algo = {	.master_xfer   = ivtv_xfer,	.functionality = ivtv_functionality,};/* template for our-bit banger */static struct i2c_adapter ivtv_i2c_adap_hw_template = {	.name = "ivtv i2c driver",	.id = I2C_HW_B_CX2341X,	.algo = &ivtv_algo,	.algo_data = NULL,			/* filled from template */	.client_register = attach_inform,	.client_unregister = detach_inform,	.owner = THIS_MODULE,#ifdef I2C_ADAP_CLASS_TV_ANALOG	.class = I2C_ADAP_CLASS_TV_ANALOG,#endif};static void ivtv_setscl_old(void *data, int state){	struct ivtv *itv = (struct ivtv *)data;	if (state)		itv->i2c_state |= 0x01;	else		itv->i2c_state &= ~0x01;	/* write them out */	/* write bits are inverted */	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSCL_OFFSET);}static void ivtv_setsda_old(void *data, int state){	struct ivtv *itv = (struct ivtv *)data;	if (state)		itv->i2c_state |= 0x01;	else		itv->i2c_state &= ~0x01;	/* write them out */	/* write bits are inverted */	write_reg(~itv->i2c_state, IVTV_REG_I2C_SETSDA_OFFSET);}static int ivtv_getscl_old(void *data){	struct ivtv *itv = (struct ivtv *)data;	return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;}static int ivtv_getsda_old(void *data){	struct ivtv *itv = (struct ivtv *)data;	return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;}/* template for i2c-bit-algo */static struct i2c_adapter ivtv_i2c_adap_template = {	.name = "ivtv i2c driver",	.id = I2C_HW_B_CX2341X,  	/* algo-bit is OR'd with this */	.algo = NULL,                   /* set by i2c-algo-bit */	.algo_data = NULL,              /* filled from template */	.client_register = attach_inform,	.client_unregister = detach_inform,	.owner = THIS_MODULE,#ifdef I2C_ADAP_CLASS_TV_ANALOG	.class = I2C_ADAP_CLASS_TV_ANALOG,#endif};static const struct i2c_algo_bit_data ivtv_i2c_algo_template = {	.setsda		= ivtv_setsda_old,	.setscl		= ivtv_setscl_old,	.getsda		= ivtv_getsda_old,	.getscl		= ivtv_getscl_old,	.udelay		= 10,	.timeout	= 200,};static struct i2c_client ivtv_i2c_client_template = {	.name = "ivtv internal",};int ivtv_call_i2c_client(struct ivtv *itv, int addr, unsigned int cmd, void *arg){	struct i2c_client *client;	int retval;	int i;	IVTV_DEBUG_I2C("call_i2c_client addr=%02x\n", addr);	for (i = 0; i < I2C_CLIENTS_MAX; i++) {		client = itv->i2c_clients[i];		if (client == NULL) {			continue;		}		if (client->driver->command == NULL) {			continue;		}		if (addr == client->addr) {			retval = client->driver->command(client, cmd, arg);			return retval;		}	}	if (cmd != VIDIOC_G_CHIP_IDENT)		IVTV_ERR("i2c addr 0x%02x not found for command 0x%x\n", addr, cmd);	return -ENODEV;}/* Find the i2c device based on the driver ID and return   its i2c address or -ENODEV if no matching device was found. */static int ivtv_i2c_id_addr(struct ivtv *itv, u32 id){	struct i2c_client *client;	int retval = -ENODEV;	int i;	for (i = 0; i < I2C_CLIENTS_MAX; i++) {		client = itv->i2c_clients[i];		if (client == NULL)			continue;		if (id == client->driver->id) {			retval = client->addr;			break;		}	}	return retval;}/* Find the i2c device name matching the DRIVERID */static const char *ivtv_i2c_id_name(u32 id){	int i;	for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)		if (hw_driverids[i] == id)			return hw_drivernames[i];	return "unknown device";}/* Find the i2c device name matching the IVTV_HW_ flag */static const char *ivtv_i2c_hw_name(u32 hw){	int i;	for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)		if (1 << i == hw)			return hw_drivernames[i];	return "unknown device";}/* Find the i2c device matching the IVTV_HW_ flag and return   its i2c address or -ENODEV if no matching device was found. */int ivtv_i2c_hw_addr(struct ivtv *itv, u32 hw){	int i;	for (i = 0; i < ARRAY_SIZE(hw_driverids); i++)		if (1 << i == hw)			return ivtv_i2c_id_addr(itv, hw_driverids[i]);	return -ENODEV;}/* Calls i2c device based on IVTV_HW_ flag. If hw == 0, then do nothing.   If hw == IVTV_HW_GPIO then call the gpio handler. */int ivtv_i2c_hw(struct ivtv *itv, u32 hw, unsigned int cmd, void *arg){	int addr;	if (hw == IVTV_HW_GPIO)		return ivtv_gpio(itv, cmd, arg);	if (hw == 0)		return 0;	addr = ivtv_i2c_hw_addr(itv, hw);	if (addr < 0) {		IVTV_ERR("i2c hardware 0x%08x (%s) not found for command 0x%x\n",			       hw, ivtv_i2c_hw_name(hw), cmd);		return addr;	}	return ivtv_call_i2c_client(itv, addr, cmd, arg);}/* Calls i2c device based on I2C driver ID. */int ivtv_i2c_id(struct ivtv *itv, u32 id, unsigned int cmd, void *arg){	int addr;	addr = ivtv_i2c_id_addr(itv, id);	if (addr < 0) {		if (cmd != VIDIOC_G_CHIP_IDENT)			IVTV_ERR("i2c ID 0x%08x (%s) not found for command 0x%x\n",				id, ivtv_i2c_id_name(id), cmd);		return addr;	}	return ivtv_call_i2c_client(itv, addr, cmd, arg);}int ivtv_cx25840(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_CX25840_I2C_ADDR, cmd, arg);}int ivtv_saa7115(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_SAA7115_I2C_ADDR, cmd, arg);}int ivtv_saa7127(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_SAA7127_I2C_ADDR, cmd, arg);}int ivtv_saa717x(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_SAA717x_I2C_ADDR, cmd, arg);}int ivtv_upd64031a(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_UPD64031A_I2C_ADDR, cmd, arg);}int ivtv_upd64083(struct ivtv *itv, unsigned int cmd, void *arg){	return ivtv_call_i2c_client(itv, IVTV_UPD64083_I2C_ADDR, cmd, arg);}/* broadcast cmd for all I2C clients and for the gpio subsystem */void ivtv_call_i2c_clients(struct ivtv *itv, unsigned int cmd, void *arg){	if (itv->i2c_adap.algo == NULL) {		IVTV_ERR("Adapter is not set");		return;	}	i2c_clients_command(&itv->i2c_adap, cmd, arg);	if (itv->hw_flags & IVTV_HW_GPIO)		ivtv_gpio(itv, cmd, arg);}/* init + register i2c algo-bit adapter */int init_ivtv_i2c(struct ivtv *itv){	IVTV_DEBUG_I2C("i2c init\n");	if (itv->options.newi2c > 0) {		memcpy(&itv->i2c_adap, &ivtv_i2c_adap_hw_template,		       sizeof(struct i2c_adapter));	} else {		memcpy(&itv->i2c_adap, &ivtv_i2c_adap_template,		       sizeof(struct i2c_adapter));		memcpy(&itv->i2c_algo, &ivtv_i2c_algo_template,		       sizeof(struct i2c_algo_bit_data));		itv->i2c_algo.data = itv;		itv->i2c_adap.algo_data = &itv->i2c_algo;	}	sprintf(itv->i2c_adap.name + strlen(itv->i2c_adap.name), " #%d",		itv->num);	i2c_set_adapdata(&itv->i2c_adap, itv);	memcpy(&itv->i2c_client, &ivtv_i2c_client_template,	       sizeof(struct i2c_client));	itv->i2c_client.adapter = &itv->i2c_adap;	itv->i2c_adap.dev.parent = &itv->dev->dev;	IVTV_DEBUG_I2C("setting scl and sda to 1\n");	ivtv_setscl(itv, 1);	ivtv_setsda(itv, 1);	if (itv->options.newi2c > 0)		return i2c_add_adapter(&itv->i2c_adap);	else		return i2c_bit_add_bus(&itv->i2c_adap);}void exit_ivtv_i2c(struct ivtv *itv){	IVTV_DEBUG_I2C("i2c exit\n");	i2c_del_adapter(&itv->i2c_adap);}

⌨️ 快捷键说明

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