summaryrefslogtreecommitdiff
path: root/drivers/media/usb/gspca/w996Xcf.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/gspca/w996Xcf.c')
-rw-r--r--drivers/media/usb/gspca/w996Xcf.c71
1 files changed, 35 insertions, 36 deletions
diff --git a/drivers/media/usb/gspca/w996Xcf.c b/drivers/media/usb/gspca/w996Xcf.c
index 2165da0c7ce1..79baa0c1a031 100644
--- a/drivers/media/usb/gspca/w996Xcf.c
+++ b/drivers/media/usb/gspca/w996Xcf.c
@@ -1,5 +1,5 @@
-/**
- *
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
* GSPCA sub driver for W996[78]CF JPEG USB Dual Mode Camera Chip.
*
* Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
@@ -7,21 +7,6 @@
* This module is adapted from the in kernel v4l1 w9968cf driver:
*
* Copyright (C) 2002-2004 by Luca Risolia <luca.risolia@studio.unibo.it>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
*/
/* Note this is not a stand alone driver, it gets included in ov519.c, this
@@ -79,6 +64,8 @@ static void w9968cf_write_fsb(struct sd *sd, u16* data)
value = *data++;
memcpy(sd->gspca_dev.usb_buf, data, 6);
+ /* Avoid things going to fast for the bridge with a xhci host */
+ udelay(150);
ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0,
USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE,
value, 0x06, sd->gspca_dev.usb_buf, 6, 500);
@@ -99,6 +86,9 @@ static void w9968cf_write_sb(struct sd *sd, u16 value)
if (sd->gspca_dev.usb_err < 0)
return;
+ /* Avoid things going to fast for the bridge with a xhci host */
+ udelay(150);
+
/* We don't use reg_w here, as that would cause all writes when
bitbanging i2c to be logged, making the logs impossible to read */
ret = usb_control_msg(sd->gspca_dev.dev,
@@ -126,6 +116,9 @@ static int w9968cf_read_sb(struct sd *sd)
if (sd->gspca_dev.usb_err < 0)
return -1;
+ /* Avoid things going to fast for the bridge with a xhci host */
+ udelay(150);
+
/* We don't use reg_r here, as the w9968cf is special and has 16
bit registers instead of 8 bit */
ret = usb_control_msg(sd->gspca_dev.dev,
@@ -139,6 +132,11 @@ static int w9968cf_read_sb(struct sd *sd)
} else {
pr_err("Read SB reg [01] failed\n");
sd->gspca_dev.usb_err = ret;
+ /*
+ * Make sure the buffer is zeroed to avoid uninitialized
+ * values.
+ */
+ memset(sd->gspca_dev.usb_buf, 0, 2);
}
udelay(W9968CF_I2C_BUS_DELAY);
@@ -241,7 +239,7 @@ static void w9968cf_smbus_read_ack(struct sd *sd)
sda = w9968cf_read_sb(sd);
w9968cf_write_sb(sd, 0x0012); /* SDE=1, SDA=1, SCL=0 */
if (sda >= 0 && (sda & 0x08)) {
- PDEBUG(D_USBI, "Did not receive i2c ACK");
+ gspca_dbg(gspca_dev, D_USBI, "Did not receive i2c ACK\n");
sd->gspca_dev.usb_err = -EIO;
}
}
@@ -293,7 +291,7 @@ static void w9968cf_i2c_w(struct sd *sd, u8 reg, u8 value)
w9968cf_write_fsb(sd, data);
- PDEBUG(D_USBO, "i2c 0x%02x -> [0x%02x]", value, reg);
+ gspca_dbg(gspca_dev, D_USBO, "i2c 0x%02x -> [0x%02x]\n", value, reg);
}
/* SMBus protocol: S Addr Wr [A] Subaddr [A] P S Addr+1 Rd [A] [Value] NA P */
@@ -327,9 +325,10 @@ static int w9968cf_i2c_r(struct sd *sd, u8 reg)
if (sd->gspca_dev.usb_err >= 0) {
ret = value;
- PDEBUG(D_USBI, "i2c [0x%02X] -> 0x%02X", reg, value);
+ gspca_dbg(gspca_dev, D_USBI, "i2c [0x%02X] -> 0x%02X\n",
+ reg, value);
} else
- PERR("i2c read [0x%02x] failed", reg);
+ gspca_err(gspca_dev, "i2c read [0x%02x] failed\n", reg);
return ret;
}
@@ -426,15 +425,15 @@ static void w9968cf_set_crop_window(struct sd *sd)
start_cropy = 35;
}
- /* Work around to avoid FP arithmetics */
+ /* Work around to avoid FP arithmetic */
#define SC(x) ((x) << 10)
/* Scaling factors */
- fw = SC(sd->gspca_dev.width) / max_width;
- fh = SC(sd->gspca_dev.height) / max_height;
+ fw = SC(sd->gspca_dev.pixfmt.width) / max_width;
+ fh = SC(sd->gspca_dev.pixfmt.height) / max_height;
- cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.width) / fh;
- ch = (fw >= fh) ? SC(sd->gspca_dev.height) / fw : max_height;
+ cw = (fw >= fh) ? max_width : SC(sd->gspca_dev.pixfmt.width) / fh;
+ ch = (fw >= fh) ? SC(sd->gspca_dev.pixfmt.height) / fw : max_height;
sd->sensor_width = max_width;
sd->sensor_height = max_height;
@@ -454,34 +453,34 @@ static void w9968cf_mode_init_regs(struct sd *sd)
w9968cf_set_crop_window(sd);
- reg_w(sd, 0x14, sd->gspca_dev.width);
- reg_w(sd, 0x15, sd->gspca_dev.height);
+ reg_w(sd, 0x14, sd->gspca_dev.pixfmt.width);
+ reg_w(sd, 0x15, sd->gspca_dev.pixfmt.height);
/* JPEG width & height */
- reg_w(sd, 0x30, sd->gspca_dev.width);
- reg_w(sd, 0x31, sd->gspca_dev.height);
+ reg_w(sd, 0x30, sd->gspca_dev.pixfmt.width);
+ reg_w(sd, 0x31, sd->gspca_dev.pixfmt.height);
/* Y & UV frame buffer strides (in WORD) */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) {
- reg_w(sd, 0x2c, sd->gspca_dev.width / 2);
- reg_w(sd, 0x2d, sd->gspca_dev.width / 4);
+ reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width / 2);
+ reg_w(sd, 0x2d, sd->gspca_dev.pixfmt.width / 4);
} else
- reg_w(sd, 0x2c, sd->gspca_dev.width);
+ reg_w(sd, 0x2c, sd->gspca_dev.pixfmt.width);
reg_w(sd, 0x00, 0xbf17); /* reset everything */
reg_w(sd, 0x00, 0xbf10); /* normal operation */
/* Transfer size in WORDS (for UYVY format only) */
- val = sd->gspca_dev.width * sd->gspca_dev.height;
+ val = sd->gspca_dev.pixfmt.width * sd->gspca_dev.pixfmt.height;
reg_w(sd, 0x3d, val & 0xffff); /* low bits */
reg_w(sd, 0x3e, val >> 16); /* high bits */
if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
V4L2_PIX_FMT_JPEG) {
/* We may get called multiple times (usb isoc bw negotiat.) */
- jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
- sd->gspca_dev.width, 0x22); /* JPEG 420 */
+ jpeg_define(sd->jpeg_hdr, sd->gspca_dev.pixfmt.height,
+ sd->gspca_dev.pixfmt.width, 0x22); /* JPEG 420 */
jpeg_set_qual(sd->jpeg_hdr, v4l2_ctrl_g_ctrl(sd->jpegqual));
w9968cf_upload_quantizationtables(sd);
v4l2_ctrl_grab(sd->jpegqual, true);