📄 ov511_core.c
字号:
rc = reg_r(ov, R51x_I2C_DATA); if (rc < 0) goto out; else *val = rc; PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, *val); /* This is needed to make writes work again */ rc = reg_w(ov, R511_I2C_CTL, 0x05);out: if (rc < 0) PDEBUG(5, "I2C read error (%d)", rc); return rc;}static intov511_i2c_adap_write_byte(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr){ int rc, retries; PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, subaddr); /* Set slave addresses */ rc = ov51x_i2c_adap_set_slave(ov, addr); if (rc < 0) return rc; /* Two byte write cycle */ for (retries = OV511_I2C_RETRIES; ; ) { /* Select camera register */ rc = reg_w(ov, R51x_I2C_SADDR_2, subaddr); if (rc < 0) goto out; /* Initiate 2-byte write cycle */ rc = reg_w(ov, R511_I2C_CTL, 0x03); if (rc < 0) goto out; do rc = reg_r(ov, R511_I2C_CTL); while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */ if (rc < 0) goto out; if ((rc&2) == 0) /* Ack? */ break; /* I2C abort */ rc = reg_w(ov, R511_I2C_CTL, 0x10); if (rc < 0) goto out; if (--retries < 0) { PDEBUG(5, "i2c write retries exhausted"); rc = -1; goto out; } }out: if (rc < 0) PDEBUG(5, "I2C write error (%d)", rc); return rc;}static intov511_i2c_adap_read_byte_data(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr, unsigned char *val){ int rc; rc = ov511_i2c_adap_write_byte(ov, addr, subaddr); if (rc < 0) return rc; rc = ov511_i2c_adap_read_byte(ov, addr, val); return rc;}static intov511_i2c_adap_write_byte_data(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr, unsigned char val){ int rc, retries; PDEBUG(5, "(0x%02X) 0x%02X:0x%02X", addr<<1, subaddr, val); /* Set slave addresses */ rc = ov51x_i2c_adap_set_slave(ov, addr); if (rc < 0) return rc; /* Three byte write cycle */ for (retries = OV511_I2C_RETRIES; ; ) { /* Select camera register */ rc = reg_w(ov, R51x_I2C_SADDR_3, subaddr); if (rc < 0) goto out; /* Write "value" to I2C data port of OV511 */ rc = reg_w(ov, R51x_I2C_DATA, val); if (rc < 0) goto out; /* Initiate 3-byte write cycle */ rc = reg_w(ov, R511_I2C_CTL, 0x01); if (rc < 0) goto out; do rc = reg_r(ov, R511_I2C_CTL); while (rc > 0 && ((rc&1) == 0)); /* Retry until idle */ if (rc < 0) goto out; if ((rc&2) == 0) /* Ack? */ break;#if 0 /* I2C abort */ reg_w(ov, R511_I2C_CTL, 0x10);#endif if (--retries < 0) { PDEBUG(5, "i2c write retries exhausted"); rc = -1; goto out; } }out: if (rc < 0) PDEBUG(5, "I2C write error (%d)", rc); return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_read_byte(struct usb_ov511 *ov, unsigned char addr, unsigned char *val){ int rc; /* Set slave addresses */ rc = ov51x_i2c_adap_set_slave(ov, addr); if (rc < 0) return rc; /* Initiate 2-byte read cycle */ rc = reg_w(ov, R518_I2C_CTL, 0x05); if (rc < 0) goto out; rc = reg_r(ov, R51x_I2C_DATA); if (rc < 0) goto out; else *val = rc; PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, *val);out: if (rc < 0) PDEBUG(5, "I2C read error (%d)", rc); return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_write_byte(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr){ int rc; PDEBUG(5, "(0x%02X) 0x%02X", addr<<1, subaddr); /* Set slave addresses */ rc = ov51x_i2c_adap_set_slave(ov, addr); if (rc < 0) return rc; /* Select camera register */ rc = reg_w(ov, R51x_I2C_SADDR_2, subaddr); if (rc < 0) goto out; /* Initiate 2-byte write cycle */ rc = reg_w(ov, R518_I2C_CTL, 0x03); if (rc < 0) goto out;out: if (rc < 0) PDEBUG(5, "I2C write error (%d)", rc); return rc;}static intov518_i2c_adap_read_byte_data(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr, unsigned char *val){ int rc; rc = ov518_i2c_adap_write_byte(ov, addr, subaddr); if (rc < 0) return rc; rc = ov518_i2c_adap_read_byte(ov, addr, val); return rc;}/* NOTE: this function always succeeds regardless of whether the sensor is * present and working. */static intov518_i2c_adap_write_byte_data(struct usb_ov511 *ov, unsigned char addr, unsigned char subaddr, unsigned char val){ int rc; PDEBUG(5, "(0x%02X) 0x%02X:0x%02X", addr<<1, subaddr, val); /* Set slave addresses */ rc = ov51x_i2c_adap_set_slave(ov, addr); if (rc < 0) return rc; /* Select camera register */ rc = reg_w(ov, R51x_I2C_SADDR_3, subaddr); if (rc < 0) goto out; /* Write "value" to I2C data port of OV511 */ rc = reg_w(ov, R51x_I2C_DATA, val); if (rc < 0) goto out; /* Initiate 3-byte write cycle */ rc = reg_w(ov, R518_I2C_CTL, 0x01); if (rc < 0) goto out;out: if (rc < 0) PDEBUG(5, "I2C write error (%d)", rc); return rc;}static intwrite_regvals(struct usb_ov511 *ov, struct regval *regvals){ int rc; while (regvals->mask != 0) { rc = reg_w_mask(ov, regvals->reg, regvals->val, regvals->mask); if (rc < 0) return rc; regvals++; } return 0;}#ifdef OV511_DEBUGstatic voiddump_reg_range(struct usb_ov511 *ov, int reg1, int regn){ int i, rc; for (i = reg1; i <= regn; i++) { rc = reg_r(ov, i); info("OV511[0x%02X] = 0x%02X", i, rc); }}static voidov511_dump_regs(struct usb_ov511 *ov){ info("CAMERA INTERFACE REGS"); dump_reg_range(ov, 0x10, 0x1f); info("DRAM INTERFACE REGS"); dump_reg_range(ov, 0x20, 0x23); info("ISO FIFO REGS"); dump_reg_range(ov, 0x30, 0x31); info("PIO REGS"); dump_reg_range(ov, 0x38, 0x39); dump_reg_range(ov, 0x3e, 0x3e); info("I2C REGS"); dump_reg_range(ov, 0x40, 0x49); info("SYSTEM CONTROL REGS"); dump_reg_range(ov, 0x50, 0x55); dump_reg_range(ov, 0x5e, 0x5f); info("OmniCE REGS"); dump_reg_range(ov, 0x70, 0x79); /* NOTE: Quantization tables are not readable. You will get the value * in reg. 0x79 for every table register */ dump_reg_range(ov, 0x80, 0x9f); dump_reg_range(ov, 0xa0, 0xbf);}static voidov518_dump_regs(struct usb_ov511 *ov){ info("VIDEO MODE REGS"); dump_reg_range(ov, 0x20, 0x2f); info("DATA PUMP AND SNAPSHOT REGS"); dump_reg_range(ov, 0x30, 0x3f); info("I2C REGS"); dump_reg_range(ov, 0x40, 0x4f); info("SYSTEM CONTROL AND VENDOR REGS"); dump_reg_range(ov, 0x50, 0x5f); info("60 - 6F"); dump_reg_range(ov, 0x60, 0x6f); info("70 - 7F"); dump_reg_range(ov, 0x70, 0x7f); info("Y QUANTIZATION TABLE"); dump_reg_range(ov, 0x80, 0x8f); info("UV QUANTIZATION TABLE"); dump_reg_range(ov, 0x90, 0x9f); info("A0 - BF"); dump_reg_range(ov, 0xa0, 0xbf); info("CBR"); dump_reg_range(ov, 0xc0, 0xcf);}#endif/********************************************************************** * * Kernel I2C Interface * **********************************************************************/static intov511_i2c_validate_addr(struct usb_ov511 *ov, u16 addr){ switch (addr) { case 0x00c2>>1: /* Tuner */ case 0x0088>>1: /* Audiochip */ if (ov->tuner_type >= 0) return 0; else goto reject; case SAA7111A_SID: return 0; case OV6xx0_SID: case OV7xx0_SID: /* Got to be careful here... tuner gives a false ACK at * address 0x00c0>>1 */ if (ov->tuner_type >= 0) goto reject; else return 0; }reject: PDEBUG(3, "Rejected slave ID 0x%04X", addr); return -ENODEV;}static intov518_i2c_validate_addr(struct usb_ov511 *ov, u16 addr){ switch (addr) { case OV6xx0_SID: case OV7xx0_SID: return 0; default: PDEBUG(3, "Rejected slave ID 0x%04X", addr); return -ENODEV; }}static inline intsensor_cmd(struct usb_ov511 *ov, unsigned int cmd, void *arg){ struct i2c_client *c = ov->sensor_client; if (ov->sensor == SEN_SAA7111A) return -EPERM; /* Non-fatal error */ if (c && c->driver->command) return c->driver->command(ov->sensor_client, cmd, arg); else return -ENODEV;}static voidcall_i2c_clients(struct usb_ov511 *ov, unsigned int cmd, void *arg){#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) struct i2c_client *client; int i; for (i = 0; i < I2C_CLIENT_MAX; i++) { client = ov->i2c_adap.clients[i]; /* Sensor_client is not called from here for now, since it has different enumeration for cmd */ if (client == ov->sensor_client) continue; if (client && client->driver->command) client->driver->command(client, cmd, arg); }#else i2c_clients_command(&ov->i2c_adap, cmd, arg);#endif}static intov511_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data){ struct usb_ov511 *ov = i2c_get_adapdata(adapter); int rc; rc = ov511_i2c_validate_addr(ov, addr); if (rc < 0) return rc; if (size == I2C_SMBUS_QUICK) { PDEBUG(4, "Got probed at addr 0x%04X", addr); } else if (size == I2C_SMBUS_BYTE) { if (read_write == I2C_SMBUS_WRITE) { rc = ov511_i2c_adap_write_byte(ov, addr, command); } else if (read_write == I2C_SMBUS_READ) { rc = ov511_i2c_adap_read_byte(ov, addr, &data->byte); } } else if (size == I2C_SMBUS_BYTE_DATA) { if (read_write == I2C_SMBUS_WRITE) { rc = ov511_i2c_adap_write_byte_data(ov, addr, command, data->byte); } else if (read_write == I2C_SMBUS_READ) { rc = ov511_i2c_adap_read_byte_data(ov, addr, command, &data->byte); } } else { warn("Unsupported I2C transfer mode (%d)", size); return -EINVAL; } /* This works around a bug in the I2C core */ if (rc > 0) rc = 0; return rc;}static u32ov511_i2c_func(struct i2c_adapter *adap){ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;}static intov518_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, char read_write, u8 command, int size, union i2c_smbus_data *data){ struct usb_ov511 *ov = i2c_get_adapdata(adapter); int rc; /* With OV518 we must be more aggressive about rejecting * unknown addresses, since it can't report NAKs. */ rc = ov518_i2c_validate_addr(ov, addr); if (rc < 0) return rc; if (size == I2C_SMBUS_QUICK) { PDEBUG(4, "Got probed at addr 0x%04X", addr); } else if (size == I2C_SMBUS_BYTE) { if (read_write == I2C_SMBUS_WRITE) { rc = ov518_i2c_adap_write_byte(ov, addr, command); } else if (read_write == I2C_SMBUS_READ) { rc = ov518_i2c_adap_read_byte(ov, addr, &data->byte); } } else if (size == I2C_SMBUS_BYTE_DATA) { if (read_write == I2C_SMBUS_WRITE) { rc = ov518_i2c_adap_write_byte_data(ov, addr, command, data->byte); } else if (read_write == I2C_SMBUS_READ) { rc = ov518_i2c_adap_read_byte_data(ov, addr, command, &data->byte); } } else { warn("Unsupported I2C transfer mode (%d)", size); return -EINVAL; } /* This works around a bug in the I2C core */ if (rc > 0) rc = 0; return rc;}static u32ov518_i2c_func(struct i2c_adapter *adap){ return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -