spin_lock(&itv->v4l2_dev.lock);
v4l2_device_for_each_subdev(sd, &itv->v4l2_dev) { if (sd->grp_id == hw) {
result = sd; break;
}
}
spin_unlock(&itv->v4l2_dev.lock); return result;
}
/* Set the serial clock line to the desired state */ staticvoid ivtv_setscl(struct ivtv *itv, int state)
{ /* write them out */ /* write bits are inverted */
write_reg(~state, IVTV_REG_I2C_SETSCL_OFFSET);
}
/* Set the serial data line to the desired state */ staticvoid ivtv_setsda(struct ivtv *itv, int state)
{ /* write them out */ /* write bits are inverted */
write_reg(~state & 1, IVTV_REG_I2C_SETSDA_OFFSET);
}
/* Read the serial clock line */ staticint ivtv_getscl(struct ivtv *itv)
{ return read_reg(IVTV_REG_I2C_GETSCL_OFFSET) & 1;
}
/* Read the serial data line */ staticint ivtv_getsda(struct ivtv *itv)
{ return read_reg(IVTV_REG_I2C_GETSDA_OFFSET) & 1;
}
/* Implement a short delay by polling the serial clock line */ staticvoid ivtv_scldelay(struct ivtv *itv)
{ int i;
for (i = 0; i < 5; ++i)
ivtv_getscl(itv);
}
/* Wait for the serial clock line to become set to a specific value */ staticint ivtv_waitscl(struct ivtv *itv, int val)
{ int i;
ivtv_scldelay(itv); for (i = 0; i < 1000; ++i) { if (ivtv_getscl(itv) == val) return1;
} return0;
}
/* Wait for the serial data line to become set to a specific value */ staticint ivtv_waitsda(struct ivtv *itv, int val)
{ int i;
ivtv_scldelay(itv); for (i = 0; i < 1000; ++i) { if (ivtv_getsda(itv) == val) return1;
} return0;
}
/* Wait for the slave to issue an ACK */ staticint ivtv_ack(struct ivtv *itv)
{ int ret = 0;
if (ivtv_getscl(itv) == 1) {
IVTV_DEBUG_HI_I2C("SCL was high starting an ack\n");
ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) {
IVTV_DEBUG_I2C("Could not set SCL low starting an ack\n"); return -EREMOTEIO;
}
}
ivtv_setsda(itv, 1);
ivtv_scldelay(itv);
ivtv_setscl(itv, 1); if (!ivtv_waitsda(itv, 0)) {
IVTV_DEBUG_I2C("Slave did not ack\n");
ret = -EREMOTEIO;
}
ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) {
IVTV_DEBUG_I2C("Failed to set SCL low after ACK\n");
ret = -EREMOTEIO;
} return ret;
}
/* Write a single byte to the i2c bus and wait for the slave to ACK */ staticint ivtv_sendbyte(struct ivtv *itv, unsignedchar byte)
{ int i, bit;
IVTV_DEBUG_HI_I2C("write %x\n",byte); for (i = 0; i < 8; ++i, byte<<=1) {
ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) {
IVTV_DEBUG_I2C("Error setting SCL low\n"); return -EREMOTEIO;
}
bit = (byte>>7)&1;
ivtv_setsda(itv, bit); if (!ivtv_waitsda(itv, bit)) {
IVTV_DEBUG_I2C("Error setting SDA\n"); return -EREMOTEIO;
}
ivtv_setscl(itv, 1); if (!ivtv_waitscl(itv, 1)) {
IVTV_DEBUG_I2C("Slave not ready for bit\n"); return -EREMOTEIO;
}
}
ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) {
IVTV_DEBUG_I2C("Error setting SCL low\n"); return -EREMOTEIO;
} return ivtv_ack(itv);
}
/* Read a byte from the i2c bus and send a NACK if applicable (i.e. for the
final byte) */ staticint ivtv_readbyte(struct ivtv *itv, unsignedchar *byte, int nack)
{ int i;
/* Issue a start condition on the i2c bus to alert slaves to prepare for
an address write */ staticint ivtv_start(struct ivtv *itv)
{ int sda;
sda = ivtv_getsda(itv); if (sda != 1) {
IVTV_DEBUG_HI_I2C("SDA was low at start\n");
ivtv_setsda(itv, 1); if (!ivtv_waitsda(itv, 1)) {
IVTV_DEBUG_I2C("SDA stuck low\n"); return -EREMOTEIO;
}
} if (ivtv_getscl(itv) != 1) {
ivtv_setscl(itv, 1); if (!ivtv_waitscl(itv, 1)) {
IVTV_DEBUG_I2C("SCL stuck low at start\n"); return -EREMOTEIO;
}
}
ivtv_setsda(itv, 0);
ivtv_scldelay(itv); return0;
}
/* Issue a stop condition on the i2c bus to release it */ staticint ivtv_stop(struct ivtv *itv)
{ int i;
if (ivtv_getscl(itv) != 0) {
IVTV_DEBUG_HI_I2C("SCL not low when stopping\n");
ivtv_setscl(itv, 0); if (!ivtv_waitscl(itv, 0)) {
IVTV_DEBUG_I2C("SCL could not be set low\n");
}
}
ivtv_setsda(itv, 0);
ivtv_scldelay(itv);
ivtv_setscl(itv, 1); if (!ivtv_waitscl(itv, 1)) {
IVTV_DEBUG_I2C("SCL could not be set high\n"); return -EREMOTEIO;
}
ivtv_scldelay(itv);
ivtv_setsda(itv, 1); if (!ivtv_waitsda(itv, 1)) {
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;
} return0;
}
/* 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) */ staticint ivtv_write(struct ivtv *itv, unsignedchar addr, unsignedchar *data, u32 len, intdo_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. */ staticint ivtv_read(struct ivtv *itv, unsignedchar addr, unsignedchar *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 orwritten.Ifareadfollowsawrite,thiswilloccurwithoutan
intervening stop condition */ staticint ivtv_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
{ struct v4l2_device *v4l2_dev = i2c_get_adapdata(i2c_adap); struct ivtv *itv = to_ivtv(v4l2_dev); 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);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.