162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * This module is adapted from the in kernel v4l1 w9968cf driver: 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci/* Note this is not a stand alone driver, it gets included in ov519.c, this 1362306a36Sopenharmony_ci is a bit of a hack, but it needs the driver code for a lot of different 1462306a36Sopenharmony_ci ov sensors which is already present in ov519.c (the old v4l1 driver used 1562306a36Sopenharmony_ci the ovchipcam framework). When we have the time we really should move 1662306a36Sopenharmony_ci the sensor drivers to v4l2 sub drivers, and properly split of this 1762306a36Sopenharmony_ci driver from ov519.c */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define Y_QUANTABLE (&sd->jpeg_hdr[JPEG_QT0_OFFSET]) 2462306a36Sopenharmony_ci#define UV_QUANTABLE (&sd->jpeg_hdr[JPEG_QT1_OFFSET]) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_cistatic const struct v4l2_pix_format w9968cf_vga_mode[] = { 2762306a36Sopenharmony_ci {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 2862306a36Sopenharmony_ci .bytesperline = 160 * 2, 2962306a36Sopenharmony_ci .sizeimage = 160 * 120 * 2, 3062306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG}, 3162306a36Sopenharmony_ci {176, 144, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 3262306a36Sopenharmony_ci .bytesperline = 176 * 2, 3362306a36Sopenharmony_ci .sizeimage = 176 * 144 * 2, 3462306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG}, 3562306a36Sopenharmony_ci {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 3662306a36Sopenharmony_ci .bytesperline = 320 * 2, 3762306a36Sopenharmony_ci .sizeimage = 320 * 240 * 2, 3862306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG}, 3962306a36Sopenharmony_ci {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 4062306a36Sopenharmony_ci .bytesperline = 352 * 2, 4162306a36Sopenharmony_ci .sizeimage = 352 * 288 * 2, 4262306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG}, 4362306a36Sopenharmony_ci {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, 4462306a36Sopenharmony_ci .bytesperline = 640 * 2, 4562306a36Sopenharmony_ci .sizeimage = 640 * 480 * 2, 4662306a36Sopenharmony_ci .colorspace = V4L2_COLORSPACE_JPEG}, 4762306a36Sopenharmony_ci}; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void reg_w(struct sd *sd, u16 index, u16 value); 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/*-------------------------------------------------------------------------- 5262306a36Sopenharmony_ci Write 64-bit data to the fast serial bus registers. 5362306a36Sopenharmony_ci Return 0 on success, -1 otherwise. 5462306a36Sopenharmony_ci --------------------------------------------------------------------------*/ 5562306a36Sopenharmony_cistatic void w9968cf_write_fsb(struct sd *sd, u16* data) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct usb_device *udev = sd->gspca_dev.dev; 5862306a36Sopenharmony_ci u16 value; 5962306a36Sopenharmony_ci int ret; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 6262306a36Sopenharmony_ci return; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci value = *data++; 6562306a36Sopenharmony_ci memcpy(sd->gspca_dev.usb_buf, data, 6); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 6862306a36Sopenharmony_ci udelay(150); 6962306a36Sopenharmony_ci ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0, 7062306a36Sopenharmony_ci USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, 7162306a36Sopenharmony_ci value, 0x06, sd->gspca_dev.usb_buf, 6, 500); 7262306a36Sopenharmony_ci if (ret < 0) { 7362306a36Sopenharmony_ci pr_err("Write FSB registers failed (%d)\n", ret); 7462306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 7562306a36Sopenharmony_ci } 7662306a36Sopenharmony_ci} 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci/*-------------------------------------------------------------------------- 7962306a36Sopenharmony_ci Write data to the serial bus control register. 8062306a36Sopenharmony_ci Return 0 on success, a negative number otherwise. 8162306a36Sopenharmony_ci --------------------------------------------------------------------------*/ 8262306a36Sopenharmony_cistatic void w9968cf_write_sb(struct sd *sd, u16 value) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci int ret; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 8762306a36Sopenharmony_ci return; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 9062306a36Sopenharmony_ci udelay(150); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci /* We don't use reg_w here, as that would cause all writes when 9362306a36Sopenharmony_ci bitbanging i2c to be logged, making the logs impossible to read */ 9462306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 9562306a36Sopenharmony_ci usb_sndctrlpipe(sd->gspca_dev.dev, 0), 9662306a36Sopenharmony_ci 0, 9762306a36Sopenharmony_ci USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 9862306a36Sopenharmony_ci value, 0x01, NULL, 0, 500); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci udelay(W9968CF_I2C_BUS_DELAY); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci if (ret < 0) { 10362306a36Sopenharmony_ci pr_err("Write SB reg [01] %04x failed\n", value); 10462306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 10562306a36Sopenharmony_ci } 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci/*-------------------------------------------------------------------------- 10962306a36Sopenharmony_ci Read data from the serial bus control register. 11062306a36Sopenharmony_ci Return 0 on success, a negative number otherwise. 11162306a36Sopenharmony_ci --------------------------------------------------------------------------*/ 11262306a36Sopenharmony_cistatic int w9968cf_read_sb(struct sd *sd) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci int ret; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci if (sd->gspca_dev.usb_err < 0) 11762306a36Sopenharmony_ci return -1; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci /* Avoid things going to fast for the bridge with a xhci host */ 12062306a36Sopenharmony_ci udelay(150); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci /* We don't use reg_r here, as the w9968cf is special and has 16 12362306a36Sopenharmony_ci bit registers instead of 8 bit */ 12462306a36Sopenharmony_ci ret = usb_control_msg(sd->gspca_dev.dev, 12562306a36Sopenharmony_ci usb_rcvctrlpipe(sd->gspca_dev.dev, 0), 12662306a36Sopenharmony_ci 1, 12762306a36Sopenharmony_ci USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 12862306a36Sopenharmony_ci 0, 0x01, sd->gspca_dev.usb_buf, 2, 500); 12962306a36Sopenharmony_ci if (ret >= 0) { 13062306a36Sopenharmony_ci ret = sd->gspca_dev.usb_buf[0] | 13162306a36Sopenharmony_ci (sd->gspca_dev.usb_buf[1] << 8); 13262306a36Sopenharmony_ci } else { 13362306a36Sopenharmony_ci pr_err("Read SB reg [01] failed\n"); 13462306a36Sopenharmony_ci sd->gspca_dev.usb_err = ret; 13562306a36Sopenharmony_ci /* 13662306a36Sopenharmony_ci * Make sure the buffer is zeroed to avoid uninitialized 13762306a36Sopenharmony_ci * values. 13862306a36Sopenharmony_ci */ 13962306a36Sopenharmony_ci memset(sd->gspca_dev.usb_buf, 0, 2); 14062306a36Sopenharmony_ci } 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci udelay(W9968CF_I2C_BUS_DELAY); 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci return ret; 14562306a36Sopenharmony_ci} 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci/*-------------------------------------------------------------------------- 14862306a36Sopenharmony_ci Upload quantization tables for the JPEG compression. 14962306a36Sopenharmony_ci This function is called by w9968cf_start_transfer(). 15062306a36Sopenharmony_ci Return 0 on success, a negative number otherwise. 15162306a36Sopenharmony_ci --------------------------------------------------------------------------*/ 15262306a36Sopenharmony_cistatic void w9968cf_upload_quantizationtables(struct sd *sd) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci u16 a, b; 15562306a36Sopenharmony_ci int i, j; 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci reg_w(sd, 0x39, 0x0010); /* JPEG clock enable */ 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci for (i = 0, j = 0; i < 32; i++, j += 2) { 16062306a36Sopenharmony_ci a = Y_QUANTABLE[j] | ((unsigned)(Y_QUANTABLE[j + 1]) << 8); 16162306a36Sopenharmony_ci b = UV_QUANTABLE[j] | ((unsigned)(UV_QUANTABLE[j + 1]) << 8); 16262306a36Sopenharmony_ci reg_w(sd, 0x40 + i, a); 16362306a36Sopenharmony_ci reg_w(sd, 0x60 + i, b); 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci reg_w(sd, 0x39, 0x0012); /* JPEG encoder enable */ 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci/**************************************************************************** 16962306a36Sopenharmony_ci * Low-level I2C I/O functions. * 17062306a36Sopenharmony_ci * The adapter supports the following I2C transfer functions: * 17162306a36Sopenharmony_ci * i2c_adap_fastwrite_byte_data() (at 400 kHz bit frequency only) * 17262306a36Sopenharmony_ci * i2c_adap_read_byte_data() * 17362306a36Sopenharmony_ci * i2c_adap_read_byte() * 17462306a36Sopenharmony_ci ****************************************************************************/ 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic void w9968cf_smbus_start(struct sd *sd) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ 17962306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_cistatic void w9968cf_smbus_stop(struct sd *sd) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0010); /* SDE=1, SDA=0, SCL=0 */ 18562306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0011); /* SDE=1, SDA=0, SCL=1 */ 18662306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic void w9968cf_smbus_write_byte(struct sd *sd, u8 v) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci u8 bit; 19262306a36Sopenharmony_ci int sda; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci for (bit = 0 ; bit < 8 ; bit++) { 19562306a36Sopenharmony_ci sda = (v & 0x80) ? 2 : 0; 19662306a36Sopenharmony_ci v <<= 1; 19762306a36Sopenharmony_ci /* SDE=1, SDA=sda, SCL=0 */ 19862306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x10 | sda); 19962306a36Sopenharmony_ci /* SDE=1, SDA=sda, SCL=1 */ 20062306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x11 | sda); 20162306a36Sopenharmony_ci /* SDE=1, SDA=sda, SCL=0 */ 20262306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x10 | sda); 20362306a36Sopenharmony_ci } 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_cistatic void w9968cf_smbus_read_byte(struct sd *sd, u8 *v) 20762306a36Sopenharmony_ci{ 20862306a36Sopenharmony_ci u8 bit; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* No need to ensure SDA is high as we are always called after 21162306a36Sopenharmony_ci read_ack which ends with SDA high */ 21262306a36Sopenharmony_ci *v = 0; 21362306a36Sopenharmony_ci for (bit = 0 ; bit < 8 ; bit++) { 21462306a36Sopenharmony_ci *v <<= 1; 21562306a36Sopenharmony_ci /* SDE=1, SDA=1, SCL=1 */ 21662306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0013); 21762306a36Sopenharmony_ci *v |= (w9968cf_read_sb(sd) & 0x0008) ? 1 : 0; 21862306a36Sopenharmony_ci /* SDE=1, SDA=1, SCL=0 */ 21962306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0012); 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci} 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic void w9968cf_smbus_write_nack(struct sd *sd) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci /* No need to ensure SDA is high as we are always called after 22662306a36Sopenharmony_ci read_byte which ends with SDA high */ 22762306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ 22862306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic void w9968cf_smbus_read_ack(struct sd *sd) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 23462306a36Sopenharmony_ci int sda; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* Ensure SDA is high before raising clock to avoid a spurious stop */ 23762306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ 23862306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0013); /* SDE=1, SDA=1, SCL=1 */ 23962306a36Sopenharmony_ci sda = w9968cf_read_sb(sd); 24062306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */ 24162306a36Sopenharmony_ci if (sda >= 0 && (sda & 0x08)) { 24262306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "Did not receive i2c ACK\n"); 24362306a36Sopenharmony_ci sd->gspca_dev.usb_err = -EIO; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci/* SMBus protocol: S Addr Wr [A] Subaddr [A] Value [A] P */ 24862306a36Sopenharmony_cistatic void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value) 24962306a36Sopenharmony_ci{ 25062306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 25162306a36Sopenharmony_ci u16* data = (u16 *)sd->gspca_dev.usb_buf; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci data[0] = 0x082f | ((sd->sensor_addr & 0x80) ? 0x1500 : 0x0); 25462306a36Sopenharmony_ci data[0] |= (sd->sensor_addr & 0x40) ? 0x4000 : 0x0; 25562306a36Sopenharmony_ci data[1] = 0x2082 | ((sd->sensor_addr & 0x40) ? 0x0005 : 0x0); 25662306a36Sopenharmony_ci data[1] |= (sd->sensor_addr & 0x20) ? 0x0150 : 0x0; 25762306a36Sopenharmony_ci data[1] |= (sd->sensor_addr & 0x10) ? 0x5400 : 0x0; 25862306a36Sopenharmony_ci data[2] = 0x8208 | ((sd->sensor_addr & 0x08) ? 0x0015 : 0x0); 25962306a36Sopenharmony_ci data[2] |= (sd->sensor_addr & 0x04) ? 0x0540 : 0x0; 26062306a36Sopenharmony_ci data[2] |= (sd->sensor_addr & 0x02) ? 0x5000 : 0x0; 26162306a36Sopenharmony_ci data[3] = 0x1d20 | ((sd->sensor_addr & 0x02) ? 0x0001 : 0x0); 26262306a36Sopenharmony_ci data[3] |= (sd->sensor_addr & 0x01) ? 0x0054 : 0x0; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci w9968cf_write_fsb(sd, data); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci data[0] = 0x8208 | ((reg & 0x80) ? 0x0015 : 0x0); 26762306a36Sopenharmony_ci data[0] |= (reg & 0x40) ? 0x0540 : 0x0; 26862306a36Sopenharmony_ci data[0] |= (reg & 0x20) ? 0x5000 : 0x0; 26962306a36Sopenharmony_ci data[1] = 0x0820 | ((reg & 0x20) ? 0x0001 : 0x0); 27062306a36Sopenharmony_ci data[1] |= (reg & 0x10) ? 0x0054 : 0x0; 27162306a36Sopenharmony_ci data[1] |= (reg & 0x08) ? 0x1500 : 0x0; 27262306a36Sopenharmony_ci data[1] |= (reg & 0x04) ? 0x4000 : 0x0; 27362306a36Sopenharmony_ci data[2] = 0x2082 | ((reg & 0x04) ? 0x0005 : 0x0); 27462306a36Sopenharmony_ci data[2] |= (reg & 0x02) ? 0x0150 : 0x0; 27562306a36Sopenharmony_ci data[2] |= (reg & 0x01) ? 0x5400 : 0x0; 27662306a36Sopenharmony_ci data[3] = 0x001d; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci w9968cf_write_fsb(sd, data); 27962306a36Sopenharmony_ci 28062306a36Sopenharmony_ci data[0] = 0x8208 | ((value & 0x80) ? 0x0015 : 0x0); 28162306a36Sopenharmony_ci data[0] |= (value & 0x40) ? 0x0540 : 0x0; 28262306a36Sopenharmony_ci data[0] |= (value & 0x20) ? 0x5000 : 0x0; 28362306a36Sopenharmony_ci data[1] = 0x0820 | ((value & 0x20) ? 0x0001 : 0x0); 28462306a36Sopenharmony_ci data[1] |= (value & 0x10) ? 0x0054 : 0x0; 28562306a36Sopenharmony_ci data[1] |= (value & 0x08) ? 0x1500 : 0x0; 28662306a36Sopenharmony_ci data[1] |= (value & 0x04) ? 0x4000 : 0x0; 28762306a36Sopenharmony_ci data[2] = 0x2082 | ((value & 0x04) ? 0x0005 : 0x0); 28862306a36Sopenharmony_ci data[2] |= (value & 0x02) ? 0x0150 : 0x0; 28962306a36Sopenharmony_ci data[2] |= (value & 0x01) ? 0x5400 : 0x0; 29062306a36Sopenharmony_ci data[3] = 0xfe1d; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci w9968cf_write_fsb(sd, data); 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBO, "i2c 0x%02x -> [0x%02x]\n", value, reg); 29562306a36Sopenharmony_ci} 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */ 29862306a36Sopenharmony_cistatic int w9968cf_i2c_r(struct sd *sd, u8 reg) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci struct gspca_dev *gspca_dev = (struct gspca_dev *)sd; 30162306a36Sopenharmony_ci int ret = 0; 30262306a36Sopenharmony_ci u8 value; 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci /* Fast serial bus data control disable */ 30562306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0013); /* don't change ! */ 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci w9968cf_smbus_start(sd); 30862306a36Sopenharmony_ci w9968cf_smbus_write_byte(sd, sd->sensor_addr); 30962306a36Sopenharmony_ci w9968cf_smbus_read_ack(sd); 31062306a36Sopenharmony_ci w9968cf_smbus_write_byte(sd, reg); 31162306a36Sopenharmony_ci w9968cf_smbus_read_ack(sd); 31262306a36Sopenharmony_ci w9968cf_smbus_stop(sd); 31362306a36Sopenharmony_ci w9968cf_smbus_start(sd); 31462306a36Sopenharmony_ci w9968cf_smbus_write_byte(sd, sd->sensor_addr + 1); 31562306a36Sopenharmony_ci w9968cf_smbus_read_ack(sd); 31662306a36Sopenharmony_ci w9968cf_smbus_read_byte(sd, &value); 31762306a36Sopenharmony_ci /* signal we don't want to read anymore, the v4l1 driver used to 31862306a36Sopenharmony_ci send an ack here which is very wrong! (and then fixed 31962306a36Sopenharmony_ci the issues this gave by retrying reads) */ 32062306a36Sopenharmony_ci w9968cf_smbus_write_nack(sd); 32162306a36Sopenharmony_ci w9968cf_smbus_stop(sd); 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Fast serial bus data control re-enable */ 32462306a36Sopenharmony_ci w9968cf_write_sb(sd, 0x0030); 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (sd->gspca_dev.usb_err >= 0) { 32762306a36Sopenharmony_ci ret = value; 32862306a36Sopenharmony_ci gspca_dbg(gspca_dev, D_USBI, "i2c [0x%02X] -> 0x%02X\n", 32962306a36Sopenharmony_ci reg, value); 33062306a36Sopenharmony_ci } else 33162306a36Sopenharmony_ci gspca_err(gspca_dev, "i2c read [0x%02x] failed\n", reg); 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci return ret; 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/*-------------------------------------------------------------------------- 33762306a36Sopenharmony_ci Turn on the LED on some webcams. A beep should be heard too. 33862306a36Sopenharmony_ci Return 0 on success, a negative number otherwise. 33962306a36Sopenharmony_ci --------------------------------------------------------------------------*/ 34062306a36Sopenharmony_cistatic void w9968cf_configure(struct sd *sd) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci reg_w(sd, 0x00, 0xff00); /* power-down */ 34362306a36Sopenharmony_ci reg_w(sd, 0x00, 0xbf17); /* reset everything */ 34462306a36Sopenharmony_ci reg_w(sd, 0x00, 0xbf10); /* normal operation */ 34562306a36Sopenharmony_ci reg_w(sd, 0x01, 0x0010); /* serial bus, SDS high */ 34662306a36Sopenharmony_ci reg_w(sd, 0x01, 0x0000); /* serial bus, SDS low */ 34762306a36Sopenharmony_ci reg_w(sd, 0x01, 0x0010); /* ..high 'beep-beep' */ 34862306a36Sopenharmony_ci reg_w(sd, 0x01, 0x0030); /* Set sda scl to FSB mode */ 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci sd->stopped = 1; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_cistatic void w9968cf_init(struct sd *sd) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci unsigned long hw_bufsize = sd->sif ? (352 * 288 * 2) : (640 * 480 * 2), 35662306a36Sopenharmony_ci y0 = 0x0000, 35762306a36Sopenharmony_ci u0 = y0 + hw_bufsize / 2, 35862306a36Sopenharmony_ci v0 = u0 + hw_bufsize / 4, 35962306a36Sopenharmony_ci y1 = v0 + hw_bufsize / 4, 36062306a36Sopenharmony_ci u1 = y1 + hw_bufsize / 2, 36162306a36Sopenharmony_ci v1 = u1 + hw_bufsize / 4; 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci reg_w(sd, 0x00, 0xff00); /* power off */ 36462306a36Sopenharmony_ci reg_w(sd, 0x00, 0xbf10); /* power on */ 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci reg_w(sd, 0x03, 0x405d); /* DRAM timings */ 36762306a36Sopenharmony_ci reg_w(sd, 0x04, 0x0030); /* SDRAM timings */ 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci reg_w(sd, 0x20, y0 & 0xffff); /* Y buf.0, low */ 37062306a36Sopenharmony_ci reg_w(sd, 0x21, y0 >> 16); /* Y buf.0, high */ 37162306a36Sopenharmony_ci reg_w(sd, 0x24, u0 & 0xffff); /* U buf.0, low */ 37262306a36Sopenharmony_ci reg_w(sd, 0x25, u0 >> 16); /* U buf.0, high */ 37362306a36Sopenharmony_ci reg_w(sd, 0x28, v0 & 0xffff); /* V buf.0, low */ 37462306a36Sopenharmony_ci reg_w(sd, 0x29, v0 >> 16); /* V buf.0, high */ 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci reg_w(sd, 0x22, y1 & 0xffff); /* Y buf.1, low */ 37762306a36Sopenharmony_ci reg_w(sd, 0x23, y1 >> 16); /* Y buf.1, high */ 37862306a36Sopenharmony_ci reg_w(sd, 0x26, u1 & 0xffff); /* U buf.1, low */ 37962306a36Sopenharmony_ci reg_w(sd, 0x27, u1 >> 16); /* U buf.1, high */ 38062306a36Sopenharmony_ci reg_w(sd, 0x2a, v1 & 0xffff); /* V buf.1, low */ 38162306a36Sopenharmony_ci reg_w(sd, 0x2b, v1 >> 16); /* V buf.1, high */ 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci reg_w(sd, 0x32, y1 & 0xffff); /* JPEG buf 0 low */ 38462306a36Sopenharmony_ci reg_w(sd, 0x33, y1 >> 16); /* JPEG buf 0 high */ 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci reg_w(sd, 0x34, y1 & 0xffff); /* JPEG buf 1 low */ 38762306a36Sopenharmony_ci reg_w(sd, 0x35, y1 >> 16); /* JPEG bug 1 high */ 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci reg_w(sd, 0x36, 0x0000);/* JPEG restart interval */ 39062306a36Sopenharmony_ci reg_w(sd, 0x37, 0x0804);/*JPEG VLE FIFO threshold*/ 39162306a36Sopenharmony_ci reg_w(sd, 0x38, 0x0000);/* disable hw up-scaling */ 39262306a36Sopenharmony_ci reg_w(sd, 0x3f, 0x0000); /* JPEG/MCTL test data */ 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic void w9968cf_set_crop_window(struct sd *sd) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci int start_cropx, start_cropy, x, y, fw, fh, cw, ch, 39862306a36Sopenharmony_ci max_width, max_height; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (sd->sif) { 40162306a36Sopenharmony_ci max_width = 352; 40262306a36Sopenharmony_ci max_height = 288; 40362306a36Sopenharmony_ci } else { 40462306a36Sopenharmony_ci max_width = 640; 40562306a36Sopenharmony_ci max_height = 480; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci if (sd->sensor == SEN_OV7620) { 40962306a36Sopenharmony_ci /* 41062306a36Sopenharmony_ci * Sigh, this is dependend on the clock / framerate changes 41162306a36Sopenharmony_ci * made by the frequency control, sick. 41262306a36Sopenharmony_ci * 41362306a36Sopenharmony_ci * Note we cannot use v4l2_ctrl_g_ctrl here, as we get called 41462306a36Sopenharmony_ci * from ov519.c:setfreq() with the ctrl lock held! 41562306a36Sopenharmony_ci */ 41662306a36Sopenharmony_ci if (sd->freq->val == 1) { 41762306a36Sopenharmony_ci start_cropx = 277; 41862306a36Sopenharmony_ci start_cropy = 37; 41962306a36Sopenharmony_ci } else { 42062306a36Sopenharmony_ci start_cropx = 105; 42162306a36Sopenharmony_ci start_cropy = 37; 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci } else { 42462306a36Sopenharmony_ci start_cropx = 320; 42562306a36Sopenharmony_ci start_cropy = 35; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci /* Work around to avoid FP arithmetic */ 42962306a36Sopenharmony_ci #define SC(x) ((x) << 10) 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci /* Scaling factors */ 43262306a36Sopenharmony_ci fw = SC(sd->gspca_dev.pixfmt.width) / max_width; 43362306a36Sopenharmony_ci fh = SC(sd->gspca_dev.pixfmt.height) / max_height; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.pixfmt.width) / fh; 43662306a36Sopenharmony_ci ch = (fw >= fh) ? SC(sd->gspca_dev.pixfmt.height) / fw : max_height; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci sd->sensor_width = max_width; 43962306a36Sopenharmony_ci sd->sensor_height = max_height; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci x = (max_width - cw) / 2; 44262306a36Sopenharmony_ci y = (max_height - ch) / 2; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci reg_w(sd, 0x10, start_cropx + x); 44562306a36Sopenharmony_ci reg_w(sd, 0x11, start_cropy + y); 44662306a36Sopenharmony_ci reg_w(sd, 0x12, start_cropx + x + cw); 44762306a36Sopenharmony_ci reg_w(sd, 0x13, start_cropy + y + ch); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic void w9968cf_mode_init_regs(struct sd *sd) 45162306a36Sopenharmony_ci{ 45262306a36Sopenharmony_ci int val, vs_polarity, hs_polarity; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_ci w9968cf_set_crop_window(sd); 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci reg_w(sd, 0x14, sd->gspca_dev.pixfmt.width); 45762306a36Sopenharmony_ci reg_w(sd, 0x15, sd->gspca_dev.pixfmt.height); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* JPEG width & height */ 46062306a36Sopenharmony_ci reg_w(sd, 0x30, sd->gspca_dev.pixfmt.width); 46162306a36Sopenharmony_ci reg_w(sd, 0x31, sd->gspca_dev.pixfmt.height); 46262306a36Sopenharmony_ci 46362306a36Sopenharmony_ci /* Y & UV frame buffer strides (in WORD) */ 46462306a36Sopenharmony_ci if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == 46562306a36Sopenharmony_ci V4L2_PIX_FMT_JPEG) { 46662306a36Sopenharmony_ci reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width / 2); 46762306a36Sopenharmony_ci reg_w(sd, 0x2d, sd->gspca_dev.pixfmt.width / 4); 46862306a36Sopenharmony_ci } else 46962306a36Sopenharmony_ci reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width); 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci reg_w(sd, 0x00, 0xbf17); /* reset everything */ 47262306a36Sopenharmony_ci reg_w(sd, 0x00, 0xbf10); /* normal operation */ 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci /* Transfer size in WORDS (for UYVY format only) */ 47562306a36Sopenharmony_ci val = sd->gspca_dev.pixfmt.width * sd->gspca_dev.pixfmt.height; 47662306a36Sopenharmony_ci reg_w(sd, 0x3d, val & 0xffff); /* low bits */ 47762306a36Sopenharmony_ci reg_w(sd, 0x3e, val >> 16); /* high bits */ 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == 48062306a36Sopenharmony_ci V4L2_PIX_FMT_JPEG) { 48162306a36Sopenharmony_ci /* We may get called multiple times (usb isoc bw negotiat.) */ 48262306a36Sopenharmony_ci jpeg_define(sd->jpeg_hdr, sd->gspca_dev.pixfmt.height, 48362306a36Sopenharmony_ci sd->gspca_dev.pixfmt.width, 0x22); /* JPEG 420 */ 48462306a36Sopenharmony_ci jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual)); 48562306a36Sopenharmony_ci w9968cf_upload_quantizationtables(sd); 48662306a36Sopenharmony_ci v4l2_ctrl_grab(sd->jpegqual, true); 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci /* Video Capture Control Register */ 49062306a36Sopenharmony_ci if (sd->sensor == SEN_OV7620) { 49162306a36Sopenharmony_ci /* Seems to work around a bug in the image sensor */ 49262306a36Sopenharmony_ci vs_polarity = 1; 49362306a36Sopenharmony_ci hs_polarity = 1; 49462306a36Sopenharmony_ci } else { 49562306a36Sopenharmony_ci vs_polarity = 1; 49662306a36Sopenharmony_ci hs_polarity = 0; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci val = (vs_polarity << 12) | (hs_polarity << 11); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci /* NOTE: We may not have enough memory to do double buffering while 50262306a36Sopenharmony_ci doing compression (amount of memory differs per model cam). 50362306a36Sopenharmony_ci So we use the second image buffer also as jpeg stream buffer 50462306a36Sopenharmony_ci (see w9968cf_init), and disable double buffering. */ 50562306a36Sopenharmony_ci if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat == 50662306a36Sopenharmony_ci V4L2_PIX_FMT_JPEG) { 50762306a36Sopenharmony_ci /* val |= 0x0002; YUV422P */ 50862306a36Sopenharmony_ci val |= 0x0003; /* YUV420P */ 50962306a36Sopenharmony_ci } else 51062306a36Sopenharmony_ci val |= 0x0080; /* Enable HW double buffering */ 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci /* val |= 0x0020; enable clamping */ 51362306a36Sopenharmony_ci /* val |= 0x0008; enable (1-2-1) filter */ 51462306a36Sopenharmony_ci /* val |= 0x000c; enable (2-3-6-3-2) filter */ 51562306a36Sopenharmony_ci 51662306a36Sopenharmony_ci val |= 0x8000; /* capt. enable */ 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci reg_w(sd, 0x16, val); 51962306a36Sopenharmony_ci 52062306a36Sopenharmony_ci sd->gspca_dev.empty_packet = 0; 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic void w9968cf_stop0(struct sd *sd) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci v4l2_ctrl_grab(sd->jpegqual, false); 52662306a36Sopenharmony_ci reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */ 52762306a36Sopenharmony_ci reg_w(sd, 0x16, 0x0000); /* stop video capture */ 52862306a36Sopenharmony_ci} 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF 53162306a36Sopenharmony_ci for the next frame). This seems to simply not be true when operating 53262306a36Sopenharmony_ci in JPEG mode, in this case there may be empty packets within the 53362306a36Sopenharmony_ci frame. So in JPEG mode use the JPEG SOI marker to detect SOF. 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci Note to make things even more interesting the w9968cf sends *PLANAR* jpeg, 53662306a36Sopenharmony_ci to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS, 53762306a36Sopenharmony_ci V-data, EOI. */ 53862306a36Sopenharmony_cistatic void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, 53962306a36Sopenharmony_ci u8 *data, /* isoc packet */ 54062306a36Sopenharmony_ci int len) /* iso packet length */ 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci struct sd *sd = (struct sd *) gspca_dev; 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat == 54562306a36Sopenharmony_ci V4L2_PIX_FMT_JPEG) { 54662306a36Sopenharmony_ci if (len >= 2 && 54762306a36Sopenharmony_ci data[0] == 0xff && 54862306a36Sopenharmony_ci data[1] == 0xd8) { 54962306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, 55062306a36Sopenharmony_ci NULL, 0); 55162306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 55262306a36Sopenharmony_ci sd->jpeg_hdr, JPEG_HDR_SZ); 55362306a36Sopenharmony_ci /* Strip the ff d8, our own header (which adds 55462306a36Sopenharmony_ci huffman and quantization tables) already has this */ 55562306a36Sopenharmony_ci len -= 2; 55662306a36Sopenharmony_ci data += 2; 55762306a36Sopenharmony_ci } 55862306a36Sopenharmony_ci } else { 55962306a36Sopenharmony_ci /* In UYVY mode an empty packet signals EOF */ 56062306a36Sopenharmony_ci if (gspca_dev->empty_packet) { 56162306a36Sopenharmony_ci gspca_frame_add(gspca_dev, LAST_PACKET, 56262306a36Sopenharmony_ci NULL, 0); 56362306a36Sopenharmony_ci gspca_frame_add(gspca_dev, FIRST_PACKET, 56462306a36Sopenharmony_ci NULL, 0); 56562306a36Sopenharmony_ci gspca_dev->empty_packet = 0; 56662306a36Sopenharmony_ci } 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 56962306a36Sopenharmony_ci} 570