📄 w9968cf.c
字号:
value, index, res, symbolic(urb_errlist, res)) return (res >= 0) ? 0 : -1;}/*-------------------------------------------------------------------------- Read a W9968CF register. Return the register value on success, -1 otherwise. --------------------------------------------------------------------------*/static int w9968cf_read_reg(struct w9968cf_device* cam, u16 index){ struct usb_device* udev = cam->usbdev; u16* buff = cam->control_buffer; int res; res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 1, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, index, buff, 2, W9968CF_USB_CTRL_TIMEOUT); if (res < 0) DBG(4, "Failed to read a register " "(index 0x%02X, error #%d, %s)", index, res, symbolic(urb_errlist, res)) return (res >= 0) ? (int)(*buff) : -1;}/*-------------------------------------------------------------------------- Write 64-bit data to the fast serial bus registers. Return 0 on success, -1 otherwise. --------------------------------------------------------------------------*/static int w9968cf_write_fsb(struct w9968cf_device* cam, u16* data){ struct usb_device* udev = cam->usbdev; u16 value; int res; value = *data++; res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, value, 0x06, data, 6, W9968CF_USB_CTRL_TIMEOUT); if (res < 0) DBG(4, "Failed to write the FSB registers " "(error #%d, %s)", res, symbolic(urb_errlist, res)) return (res >= 0) ? 0 : -1;}/*-------------------------------------------------------------------------- Write data to the serial bus control register. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/static int w9968cf_write_sb(struct w9968cf_device* cam, u16 value){ int err = 0; err = w9968cf_write_reg(cam, value, 0x01); udelay(W9968CF_I2C_BUS_DELAY); return err;}/*-------------------------------------------------------------------------- Read data from the serial bus control register. Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/static int w9968cf_read_sb(struct w9968cf_device* cam){ int v = 0; v = w9968cf_read_reg(cam, 0x01); udelay(W9968CF_I2C_BUS_DELAY); return v;}/*-------------------------------------------------------------------------- Upload quantization tables for the JPEG compression. This function is called by w9968cf_start_transfer(). Return 0 on success, a negative number otherwise. --------------------------------------------------------------------------*/static int w9968cf_upload_quantizationtables(struct w9968cf_device* cam){ u16 a, b; int err = 0, i, j; err += w9968cf_write_reg(cam, 0x0010, 0x39); /* JPEG clock enable */ for (i = 0, j = 0; i < 32; i++, j += 2) { a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j+1]) << 8); b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j+1]) << 8); err += w9968cf_write_reg(cam, a, 0x40+i); err += w9968cf_write_reg(cam, b, 0x60+i); } err += w9968cf_write_reg(cam, 0x0012, 0x39); /* JPEG encoder enable */ return err;}/**************************************************************************** * Low-level I2C I/O functions. * * The adapter supports the following I2C transfer functions: * * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * * i2c_adap_read_byte_data() * * i2c_adap_read_byte() * ****************************************************************************/static int w9968cf_smbus_start(struct w9968cf_device* cam){ int err = 0; err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ return err;}static int w9968cf_smbus_stop(struct w9968cf_device* cam){ int err = 0; err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ return err;}static int w9968cf_smbus_write_byte(struct w9968cf_device* cam, u8 v){ u8 bit; int err = 0, sda; for (bit = 0 ; bit < 8 ; bit++) { sda = (v & 0x80) ? 2 : 0; v <<= 1; /* SDE=1, SDA=sda, SCL=0 */ err += w9968cf_write_sb(cam, 0x10 | sda); /* SDE=1, SDA=sda, SCL=1 */ err += w9968cf_write_sb(cam, 0x11 | sda); /* SDE=1, SDA=sda, SCL=0 */ err += w9968cf_write_sb(cam, 0x10 | sda); } return err;}static int w9968cf_smbus_read_byte(struct w9968cf_device* cam, u8* v){ u8 bit; int err = 0; *v = 0; for (bit = 0 ; bit < 8 ; bit++) { *v <<= 1; err += w9968cf_write_sb(cam, 0x0013); *v |= (w9968cf_read_sb(cam) & 0x0008) ? 1 : 0; err += w9968cf_write_sb(cam, 0x0012); } return err;}static int w9968cf_smbus_write_ack(struct w9968cf_device* cam){ int err = 0; err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ err += w9968cf_write_sb(cam, 0x0011); /* SDE=1, SDA=0, SCL=1 */ err += w9968cf_write_sb(cam, 0x0010); /* SDE=1, SDA=0, SCL=0 */ return err;}static int w9968cf_smbus_read_ack(struct w9968cf_device* cam){ int err = 0, sda; err += w9968cf_write_sb(cam, 0x0013); /* SDE=1, SDA=1, SCL=1 */ sda = (w9968cf_read_sb(cam) & 0x08) ? 1 : 0; /* sda = SDA */ err += w9968cf_write_sb(cam, 0x0012); /* SDE=1, SDA=1, SCL=0 */ if (sda < 0) err += sda; if (sda == 1) { DBG(6, "Couldn't receive the ACK") err += -1; } return err;}/* This seems to refresh the communication through the serial bus */static int w9968cf_smbus_refresh_bus(struct w9968cf_device* cam){ int err = 0, j; for (j = 1; j <= 10; j++) { err = w9968cf_write_reg(cam, 0x0020, 0x01); err += w9968cf_write_reg(cam, 0x0000, 0x01); if (err) break; } return err;}/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */static int w9968cf_i2c_adap_fastwrite_byte_data(struct w9968cf_device* cam, u16 address, u8 subaddress,u8 value){ u16* data = cam->data_buffer; int err = 0; err += w9968cf_smbus_refresh_bus(cam); /* Enable SBUS outputs */ err += w9968cf_write_sb(cam, 0x0020); data[0] = 0x082f | ((address & 0x80) ? 0x1500 : 0x0); data[0] |= (address & 0x40) ? 0x4000 : 0x0; data[1] = 0x2082 | ((address & 0x40) ? 0x0005 : 0x0); data[1] |= (address & 0x20) ? 0x0150 : 0x0; data[1] |= (address & 0x10) ? 0x5400 : 0x0; data[2] = 0x8208 | ((address & 0x08) ? 0x0015 : 0x0); data[2] |= (address & 0x04) ? 0x0540 : 0x0; data[2] |= (address & 0x02) ? 0x5000 : 0x0; data[3] = 0x1d20 | ((address & 0x02) ? 0x0001 : 0x0); data[3] |= (address & 0x01) ? 0x0054 : 0x0; err += w9968cf_write_fsb(cam, data); data[0] = 0x8208 | ((subaddress & 0x80) ? 0x0015 : 0x0); data[0] |= (subaddress & 0x40) ? 0x0540 : 0x0; data[0] |= (subaddress & 0x20) ? 0x5000 : 0x0; data[1] = 0x0820 | ((subaddress & 0x20) ? 0x0001 : 0x0); data[1] |= (subaddress & 0x10) ? 0x0054 : 0x0; data[1] |= (subaddress & 0x08) ? 0x1500 : 0x0; data[1] |= (subaddress & 0x04) ? 0x4000 : 0x0; data[2] = 0x2082 | ((subaddress & 0x04) ? 0x0005 : 0x0); data[2] |= (subaddress & 0x02) ? 0x0150 : 0x0; data[2] |= (subaddress & 0x01) ? 0x5400 : 0x0; data[3] = 0x001d; err += w9968cf_write_fsb(cam, data); data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); data[0] |= (value & 0x40) ? 0x0540 : 0x0; data[0] |= (value & 0x20) ? 0x5000 : 0x0; data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); data[1] |= (value & 0x10) ? 0x0054 : 0x0; data[1] |= (value & 0x08) ? 0x1500 : 0x0; data[1] |= (value & 0x04) ? 0x4000 : 0x0; data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); data[2] |= (value & 0x02) ? 0x0150 : 0x0; data[2] |= (value & 0x01) ? 0x5400 : 0x0; data[3] = 0xfe1d; err += w9968cf_write_fsb(cam, data); /* Disable SBUS outputs */ err += w9968cf_write_sb(cam, 0x0000); if (!err) DBG(5, "I2C write byte data done, addr.0x%04X, subaddr.0x%02X " "value 0x%02X", address, subaddress, value) else DBG(5, "I2C write byte data failed, addr.0x%04X, " "subaddr.0x%02X, value 0x%02X", address, subaddress, value) return err;}/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */static int w9968cf_i2c_adap_read_byte_data(struct w9968cf_device* cam, u16 address, u8 subaddress, u8* value){ int err = 0; /* Serial data enable */ err += w9968cf_write_sb(cam, 0x0013); /* don't change ! */ err += w9968cf_smbus_start(cam); err += w9968cf_smbus_write_byte(cam, address); err += w9968cf_smbus_read_ack(cam); err += w9968cf_smbus_write_byte(cam, subaddress); err += w9968cf_smbus_read_ack(cam); err += w9968cf_smbus_stop(cam); err += w9968cf_smbus_start(cam); err += w9968cf_smbus_write_byte(cam, address + 1); err += w9968cf_smbus_read_ack(cam); err += w9968cf_smbus_read_byte(cam, value); err += w9968cf_smbus_write_ack(cam); err += w9968cf_smbus_stop(cam); /* Serial data disable */ err += w9968cf_write_sb(cam, 0x0000); if (!err) DBG(5, "I2C read byte data done, addr.0x%04X, " "subaddr.0x%02X, value 0x%02X", address, subaddress, *value) else DBG(5, "I2C read byte data failed, addr.0x%04X, " "subaddr.0x%02X, wrong value 0x%02X", address, subaddress, *value) return err;}/* SMBus protocol: S Addr+1 Rd [A] [Value] NA P */static int w9968cf_i2c_adap_read_byte(struct w9968cf_device* cam, u16 address, u8* value){ int err = 0; /* Serial data enable */ err += w9968cf_write_sb(cam, 0x0013); err += w9968cf_smbus_start(cam); err += w9968cf_smbus_write_byte(cam, address + 1); err += w9968cf_smbus_read_ack(cam); err += w9968cf_smbus_read_byte(cam, value); err += w9968cf_smbus_write_ack(cam); err += w9968cf_smbus_stop(cam); /* Serial data disable */ err += w9968cf_write_sb(cam, 0x0000); if (!err) DBG(5, "I2C read byte done, addr.0x%04X, " "value 0x%02X", address, *value) else DBG(5, "I2C read byte failed, addr.0x%04X, " "wrong value 0x%02X", address, *value) return err;}/* SMBus protocol: S Addr Wr [A] Value [A] P */static int w9968cf_i2c_adap_write_byte(struct w9968cf_device* cam, u16 address, u8 value)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -