From: Chia-I Wu <olvaffe@gmail.com>
To: "Erik Andrén" <erik.andren@gmail.com>
Cc: video4linux-list@redhat.com, noodles@earth.li,
qce-ga-devel@lists.sourceforge.net
Subject: Re: Please test the gspca-stv06xx branch
Date: Tue, 25 Nov 2008 16:20:02 +0800 [thread overview]
Message-ID: <20081125082002.GC18787@m500.domain> (raw)
In-Reply-To: <492B15E1.2080207@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1116 bytes --]
Hi Erik,
On Mon, Nov 24, 2008 at 10:00:17PM +0100, Erik Andrén wrote:
> I've reworked the driver somewhat and added initial support for th
> pb0100.
> Please test with the latest version of the gspca-stv06xx tree and
> see if you can get an image. Ekiga works best for me at the moment.
I am trying to make gspca-stv06xx work with my QuickCam Express
(046d:0840). It comes with the HDCS 1000 sensor. So far, I am able to
receive frames using gstreamer (with libv4l). The colors are wrong
though.
While working on it, I encounter two minor issues:
* stv06xx_write_sensor sends an extra packet unconditionally. It causes
the function call return error.
* Turning LED on/off kills the device. I have to re-plug the device to
make it work again.
I could put those functions inside an if clause:
if (udev->descriptor.idProduct != 0x840)
do_something;
and things work. But as I do not have other cameras to test, I am not
sure if this is the right way. Do you have any suggestion?
I will keep working on it. But you can find a primitive patch and a
sample image in the attachments.
--
Regards,
olv
[-- Attachment #2: qc-ex-primitive.patch --]
[-- Type: text/x-diff, Size: 7510 bytes --]
diff -r 4e778359e610 -r 378675539541 linux/drivers/media/video/gspca/stv06xx/stv06xx.c
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx.c Mon Nov 24 18:06:49 2008 +0100
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx.c Tue Nov 25 15:55:12 2008 +0800
@@ -127,10 +127,12 @@
STV06XX_URB_MSG_TIMEOUT);
/* Quickam Web needs an extra packet */
- buf[0] = 0;
- err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
- 0x04, 0x40, 0x1704, 0, buf, 1,
- STV06XX_URB_MSG_TIMEOUT);
+ if (udev->descriptor.idProduct != 0x840) {
+ buf[0] = 0;
+ err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+ 0x04, 0x40, 0x1704, 0, buf, 1,
+ STV06XX_URB_MSG_TIMEOUT);
+ }
return (err < 0) ? err : 0;
}
@@ -261,9 +263,11 @@
goto out;
/* Turn on LED */
- err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
- if (err < 0)
- goto out;
+ if (sd->gspca_dev.dev->descriptor.idProduct != 0x840) {
+ err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_ON);
+ if (err < 0)
+ goto out;
+ }
/* Start isochronous streaming */
err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 1);
@@ -283,9 +287,11 @@
struct sd *sd = (struct sd *) gspca_dev;
/* Turn off LED */
- err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
- if (err < 0)
- goto out;
+ if (sd->gspca_dev.dev->descriptor.idProduct != 0x840) {
+ err = stv06xx_write_bridge(sd, STV_LED_CTRL, LED_OFF);
+ if (err < 0)
+ goto out;
+ }
/* stop ISO-streaming */
err = stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
diff -r 4e778359e610 -r 378675539541 linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c Mon Nov 24 18:06:49 2008 +0100
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c Tue Nov 25 15:55:12 2008 +0800
@@ -57,16 +57,132 @@
return -ENODEV;
}
+static int hdcs_set_exposure(struct sd *sd, int val)
+{
+ unsigned int rowexp; /* rowexp,srowexp = 15 bits (0..32767) */
+ unsigned int srowexp; /* sub-row exposure (smaller is brighter) */
+ unsigned int max_srowexp; /* Maximum srowexp value + 1 */
+ int width = 360;
+
+ /* Absolute black at srowexp=2672,width=360; 2616, width=352; 1896, width=256 for hdcs1000 */
+
+ val *= 16; /* 16 seems to be the smallest change that actually affects brightness */
+ max_srowexp = width * 15 / 2 - 104 + 1;
+ srowexp = max_srowexp - (val % max_srowexp) - 1;
+ rowexp = val / max_srowexp;
+
+ /* Number of rows to expose */
+ stv06xx_write_sensor_b(sd, HDCS_ROWEXPL, rowexp & 0xff);
+ stv06xx_write_sensor_b(sd, HDCS_ROWEXPH, rowexp >> 8);
+
+ if (IS_1020(sd)) {
+ srowexp = 0; //FIXME:need formula to compute srowexp for HDCS1020!
+ srowexp >>= 2; /* Bits 0..1 are hardwired to 0 */
+
+ /* Number of pixels to expose */
+ stv06xx_write_sensor_b(sd, HDCS20_SROWEXP, srowexp & 0xff);
+ } else {
+ /* Number of pixels to expose */
+ stv06xx_write_sensor_b(sd, HDCS00_SROWEXPL, srowexp & 0xff);
+ stv06xx_write_sensor_b(sd, HDCS00_SROWEXPH, srowexp >> 8);
+ }
+
+ if (IS_1020(sd)) {
+ /* Reset exposure error flag */
+ stv06xx_write_sensor_b(sd, HDCS20_ERROR, BIT(0));
+ } else {
+ /* Reset exposure error flag */
+ stv06xx_write_sensor_b(sd, HDCS_STATUS, BIT(4));
+ }
+
+ return 0;
+}
+
+static int hdcs_set_gains(struct sd *sd, unsigned int hue, unsigned int sat, unsigned int val)
+{
+ static const unsigned int min_gain = 8;
+ unsigned int rgain, bgain, ggain;
+
+ //qc_hsv2rgb(hue, sat, val, &rgain, &bgain, &ggain);
+ rgain = hue;
+ ggain = sat;
+ bgain = val;
+
+ rgain >>= 8; /* After this the values are 0..255 */
+ ggain >>= 8;
+ bgain >>= 8;
+
+ rgain = max(rgain, min_gain); /* Do not allow very small values, they cause bad (low-contrast) image */
+ ggain = max(ggain, min_gain);
+ bgain = max(bgain, min_gain);
+
+ if (rgain > 127) rgain = rgain/2 | BIT(7); /* Bit 7 doubles the programmed values */
+ if (ggain > 127) ggain = ggain/2 | BIT(7); /* Double programmed value if necessary */
+ if (bgain > 127) bgain = bgain/2 | BIT(7);
+
+ stv06xx_write_sensor_b(sd, HDCS_ERECPGA, ggain);
+ stv06xx_write_sensor_b(sd, HDCS_EROCPGA, rgain);
+ stv06xx_write_sensor_b(sd, HDCS_ORECPGA, bgain);
+ stv06xx_write_sensor_b(sd, HDCS_OROCPGA, ggain);
+
+ return 0;
+}
+
+static int hdcs_set_size(struct sd *sd, unsigned int width, unsigned int height)
+{
+ /* The datasheet doesn't seem to say this, but HDCS-1000
+ * has visible windows size of 360x296 pixels, the first upper-left
+ * visible pixel is at 8,8.
+ * From Andrey's test image: looks like HDCS-1020 upper-left
+ * visible pixel is at 24,8 (y maybe even smaller?) and lower-right
+ * visible pixel at 375,299 (x maybe even larger?)
+ */
+ unsigned int originx = IS_1020(sd) ? 24 : 8; /* First visible pixel */
+ unsigned int maxwidth = IS_1020(sd) ? 352 : 360; /* Visible sensor size */
+ unsigned int originy = 8;
+ unsigned int maxheight = IS_1020(sd) ? 292 : 296;
+ unsigned int x, y;
+ int ret;
+
+ printk("set size\n");
+
+ width = (width + 3) / 4 * 4; /* Width must be multiple of 4 */
+ height = (height + 3)/ 4 * 4; /* Height must be multiple of 4 */
+
+ x = (maxwidth - width) / 2; /* Center image by computing upper-left corner */
+ y = (maxheight - height) / 2;
+ width /= 4;
+ height /= 4;
+ x = (x + originx) / 4; /* Must be multiple of 4 (low bits wired to 0) */
+ y = (y + originy) / 4;
+
+ ret = stv06xx_write_sensor_b(sd, GET_CONTROL, 0);
+
+ stv06xx_write_sensor_b(sd, HDCS_FWROW, y);
+ stv06xx_write_sensor_b(sd, HDCS_FWCOL, x);
+ stv06xx_write_sensor_b(sd, HDCS_LWROW, y + height - 1);
+ stv06xx_write_sensor_b(sd, HDCS_LWCOL, x + width - 1);
+
+ if (1)
+ hdcs_set_exposure(sd, 32768);
+
+ ret = stv06xx_write_sensor_b(sd, GET_CONTROL, HDCS_RUN_ENABLE);
+ printk("set gains: %d\n", ret);
+ hdcs_set_gains(sd, 32768, 32768, 32768);
+
+ return 0;
+}
+
int hdcs_start(struct sd *sd)
{
- int err = stv06xx_write_sensor_b(sd, HDCS_RUN_ENABLE, GET_CONTROL);
+ int err = stv06xx_write_sensor_b(sd, GET_CONTROL, HDCS_RUN_ENABLE);
PDEBUG(D_STREAM, "Starting stream");
return (err < 0) ? err : 0;
}
int hdcs_stop(struct sd *sd)
{
- int err = stv06xx_write_sensor_b(sd, HDCS_SLEEP_MODE, GET_CONTROL);
+ int err = stv06xx_write_sensor_b(sd, GET_CONTROL, HDCS_SLEEP_MODE);
PDEBUG(D_STREAM, "Halting stream");
return (err < 0) ? err : 0;
}
@@ -182,9 +298,17 @@
/* CONFIG: Bit 3: continous frame capture,
bit 2: stop when frame complete */
- stv06xx_write_sensor_b(sd, GET_CONTROL, BIT(3));
+ stv06xx_write_sensor_b(sd, GET_CONFIG, BIT(3));
/* ADC output resolution to 10 bits */
stv06xx_write_sensor_b(sd, HDCS_ADCCTRL, 10);
+
+ stv06xx_write_bridge(sd, STV_ISO_ENABLE, 0);
+ hdcs_stop(sd);
+
+ hdcs_set_size(sd, 360, 296);
+
+ info("hdcs_inited");
+
return 0;
}
diff -r 4e778359e610 -r 378675539541 linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
--- a/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h Mon Nov 24 18:06:49 2008 +0100
+++ b/linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h Tue Nov 25 15:55:12 2008 +0800
@@ -114,6 +114,7 @@
#define IS_870(sd) ((sd)->gspca_dev.dev->descriptor.idProduct == 0x870)
#define IS_1020(sd) ((sd)->sensor == &stv06xx_sensor_hdcs1020)
+#define GET_CONFIG (IS_1020(sd) ? HDCS20_CONFIG : HDCS00_CONFIG)
#define GET_CONTROL (IS_1020(sd) ? HDCS20_CONTROL : HDCS00_CONTROL)
int hdcs_probe(struct sd *sd);
@@ -126,6 +127,7 @@
.name = "HP HDCS-1000/1100",
.i2c_flush = 0,
.i2c_addr = HDCS_ADDR,
+ .i2c_len = 1,
.init = hdcs_init,
.probe = hdcs_probe,
[-- Attachment #3: qc.png --]
[-- Type: image/png, Size: 84574 bytes --]
[-- Attachment #4: Type: text/plain, Size: 164 bytes --]
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
next prev parent reply other threads:[~2008-11-25 8:20 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-24 21:00 Please test the gspca-stv06xx branch Erik Andrén
2008-11-25 8:20 ` Chia-I Wu [this message]
2008-11-25 11:22 ` Erik Andrén
2008-11-25 11:39 ` Chia-I Wu
2008-11-25 12:02 ` Erik Andrén
[not found] ` <492E7906.905@redhat.com>
2008-11-27 10:59 ` Chia-I Wu
2008-11-27 11:55 ` Erik Andrén
2008-11-27 16:00 ` Chia-I Wu
[not found] ` <492EE597.7010100@redhat.com>
2008-11-28 4:26 ` Chia-I Wu
2008-11-27 11:51 ` Erik Andrén
2008-11-27 18:08 ` Hans de Goede
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20081125082002.GC18787@m500.domain \
--to=olvaffe@gmail.com \
--cc=erik.andren@gmail.com \
--cc=noodles@earth.li \
--cc=qce-ga-devel@lists.sourceforge.net \
--cc=video4linux-list@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox