* [GIT PATCHES FOR 2.6.37] Various gspca patches
@ 2010-10-27 12:35 Hans de Goede
2010-10-27 12:35 ` [PATCH 1/7] gspca: submit interrupt urbs *after* isoc urbs Hans de Goede
` (7 more replies)
0 siblings, 8 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine
Hi Mauro,
Please pull from:
http://linuxtv.org/hg/~hgoede/ibmcam3
Starting at the commit titled:
gspca: submit interrupt urbs *after* isoc urbs
This pull consists of the following commits:
gspca: submit interrupt urbs *after* isoc urbs
gspca: only set gspca->int_urb if submitting it succeeds
gspca-stv06xx: support bandwidth changing
gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes
gspca_xirlink_cit: Frames have a 4 byte footer
gspca_xirlink_cit: Add support camera button
gspca_ov519: generate release button event on stream stop if needed
Note that since the hg v4l-dvb tree is a bit out of data, pulling from
my hg tree won't apply cleanly though. So to make things easier for you
I'm in the process of switching over to git. This mail will be followed
by the 7 patches from this pull request in git format-patch format, rebased
on top of the master branch of your git tree:
git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-next.git
The reason I'm not sending a git pull request is because I don't
have a git tree, and I could not find documentation for creating
a git tree @ git.linuxtv.org. Can you help me with this?
Also this wiki page:
http://linuxtv.org/wiki/index.php/Maintaining_Git_trees
Points to the obsolete: git://linuxtv.org/v4l-dvb.git
Repository, please update it.
Thanks & Regards,
Hans
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/7] gspca: submit interrupt urbs *after* isoc urbs
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 2/7] gspca: only set gspca->int_urb if submitting it succeeds Hans de Goede
` (6 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
Currently gspca supported usb-1.1 webcams for which we support the input
button through an interrupt endpoint won't stream (not enough bandwidth
error) when used through an USB-2.0 hub.
After much debugging I've found out that the cause for this is that the
ehci-sched.c schedeling code does not like it when there are already urb's
scheduled when (large) isoc urbs are queued. By moving the submission
of the interrupt urbs to after submitting the isoc urbs the camera
starts working again through usb-2.0 hubs.
Note that this does not fix isoc. streaming through a usb-hub while another
1.1 usb device (like the microphone of the same cam) is also active
at the same time :(
I've spend a long time analyzing the linux kernel ehci scheduler code,
resulting in this (long) mail:
http://www.spinics.net/lists/linux-usb/msg37982.html
The conclusion of the following mail thread is that yes there are several
issues when using usb-1.1 devices through a usb-2.0 hub, but these are not
easily fixable in the current code. Fixing this in ehci-sched.c requires
an almost full rewrite, which is not bound to happen anytime soon.
So with this patch gspca driven usb-1.1 webcams will atleast work when
connected through an usb-2.0 hub when the microphone is not used.
As an added bonus this patch avoids extra destroy/create input urb cycles
when we end up falling back to a lower speed alt setting because of bandwidth
limitations.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/gspca.c | 10 ++++++----
1 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 8fe8fb4..dbd63c5 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -676,13 +676,11 @@ static struct usb_host_endpoint *get_ep(struct gspca_dev *gspca_dev)
i, ep->desc.bEndpointAddress);
gspca_dev->alt = i; /* memorize the current alt setting */
if (gspca_dev->nbalt > 1) {
- gspca_input_destroy_urb(gspca_dev);
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, i);
if (ret < 0) {
err("set alt %d err %d", i, ret);
ep = NULL;
}
- gspca_input_create_urb(gspca_dev);
}
return ep;
}
@@ -781,7 +779,7 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (!gspca_dev->present) {
ret = -ENODEV;
- goto out;
+ goto unlock;
}
/* reset the streaming variables */
@@ -802,8 +800,10 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (gspca_dev->sd_desc->isoc_init) {
ret = gspca_dev->sd_desc->isoc_init(gspca_dev);
if (ret < 0)
- goto out;
+ goto unlock;
}
+
+ gspca_input_destroy_urb(gspca_dev);
ep = get_ep(gspca_dev);
if (ep == NULL) {
ret = -EIO;
@@ -873,6 +873,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
}
}
out:
+ gspca_input_create_urb(gspca_dev);
+unlock:
mutex_unlock(&gspca_dev->usb_lock);
return ret;
}
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/7] gspca: only set gspca->int_urb if submitting it succeeds
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
2010-10-27 12:35 ` [PATCH 1/7] gspca: submit interrupt urbs *after* isoc urbs Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 3/7] gspca-stv06xx: support bandwidth changing Hans de Goede
` (5 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
Currently alloc_and_submit_int_urb() is setting gspca->int_urb
as soon as the allocation has succeeded, but if the subsequent
submit fails, the urb gets destroyed. And then later will
get destroyed again in gspca_input_destroy_urb() because
gspca->int_urb is set, leading to a double free.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/gspca.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index dbd63c5..a089fca 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -224,12 +224,12 @@ static int alloc_and_submit_int_urb(struct gspca_dev *gspca_dev,
buffer, buffer_len,
int_irq, (void *)gspca_dev, interval);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
- gspca_dev->int_urb = urb;
ret = usb_submit_urb(urb, GFP_KERNEL);
if (ret < 0) {
PDEBUG(D_ERR, "submit int URB failed with error %i", ret);
goto error_submit;
}
+ gspca_dev->int_urb = urb;
return ret;
error_submit:
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/7] gspca-stv06xx: support bandwidth changing
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
2010-10-27 12:35 ` [PATCH 1/7] gspca: submit interrupt urbs *after* isoc urbs Hans de Goede
2010-10-27 12:35 ` [PATCH 2/7] gspca: only set gspca->int_urb if submitting it succeeds Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:39 ` Erik Andrén
2010-10-27 12:35 ` [PATCH 4/7] gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes Hans de Goede
` (4 subsequent siblings)
7 siblings, 1 reply; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
stv06xx devices have only one altsetting, but the actual used
bandwidth can be programmed through a register. We were already
setting this register lower then the max packetsize of the altsetting
indicates. This patch makes the gspca-stv06xx update the usb descriptor
for the alt setting to reflect the actual packetsize in use, so that
the usb subsystem uses the correct information for scheduling usb transfers.
This patch also tries to fallback to lower speeds in case a ENOSPC error
is received when submitting urbs, but currently this is only supported
with stv06xx cams with the pb0100 sensor, as this is the only one for
which we know how to change the framerate.
This patch is based on an initial incomplete patch by
Lee Jones <lee.jones@canonical.com>
Signed-off-by: Lee Jones <lee.jones@canonical.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/stv06xx/stv06xx.c | 55 +++++++++++++++++++-
drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h | 11 ++++-
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 18 +++++--
drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h | 3 +
drivers/media/video/gspca/stv06xx/stv06xx_sensor.h | 4 ++
drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | 17 +------
drivers/media/video/gspca/stv06xx/stv06xx_st6422.h | 3 +
drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 9 ++--
8 files changed, 93 insertions(+), 27 deletions(-)
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
index 086de44..ca86762 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
@@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev *gspca_dev)
static int stv06xx_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int err;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
+ int err, packet_size;
+
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt) {
+ PDEBUG(D_ERR, "Couldn't get altsetting");
+ return -EIO;
+ }
+
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
+ if (err < 0)
+ return err;
/* Prepare the sensor for start */
err = sd->sensor->start(sd);
@@ -282,6 +296,43 @@ out:
return (err < 0) ? err : 0;
}
+static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
+{
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+ alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt->endpoint[0].desc.wMaxPacketSize =
+ cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
+
+ return 0;
+}
+
+static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
+{
+ int ret, packet_size, min_packet_size;
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
+ if (packet_size <= min_packet_size)
+ return -EIO;
+
+ packet_size -= 100;
+ if (packet_size < min_packet_size)
+ packet_size = min_packet_size;
+ alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
+
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+ if (ret < 0)
+ PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
+
+ return ret;
+}
+
static void stv06xx_stopN(struct gspca_dev *gspca_dev)
{
int err;
@@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = {
.start = stv06xx_start,
.stopN = stv06xx_stopN,
.pkt_scan = stv06xx_pkt_scan,
+ .isoc_init = stv06xx_isoc_init,
+ .isoc_nego = stv06xx_isoc_nego,
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
.int_pkt_scan = sd_int_pkt_scan,
#endif
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
index cf3d0cc..b538dce 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
@@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
+ /* FIXME (see if we can lower min_packet_size, needs testing, and also
+ adjusting framerate when the bandwidth gets lower) */
+ .min_packet_size = { 847 },
+ .max_packet_size = { 847 },
+
.init = hdcs_init,
.probe = hdcs_probe_1x00,
.start = hdcs_start,
@@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
+ /* FIXME (see if we can lower min_packet_size, needs testing, and also
+ adjusting framerate when the bandwidthm gets lower) */
+ .min_packet_size = { 847 },
+ .max_packet_size = { 847 },
+
.init = hdcs_init,
.probe = hdcs_probe_1020,
.start = hdcs_start,
@@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] = {
{STV_REG04, 0x07},
{STV_SCAN_RATE, 0x20},
- {STV_ISO_SIZE_L, 847},
{STV_Y_CTRL, 0x01},
{STV_X_CTRL, 0x0a}
};
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
index 285221e..ac47b4c 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
@@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd)
static int pb0100_start(struct sd *sd)
{
- int err;
+ int err, packet_size, max_packet_size;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
struct cam *cam = &sd->gspca_dev.cam;
s32 *sensor_settings = sd->sensor_priv;
u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+ /* If we don't have enough bandwidth use a lower framerate */
+ max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
+ if (packet_size < max_packet_size)
+ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
+ else
+ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
+
/* Setup sensor window */
if (mode & PB0100_CROP_TO_VGA) {
stv06xx_write_sensor(sd, PB_RSTART, 30);
@@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd)
stv06xx_write_bridge(sd, STV_REG03, 0x45);
stv06xx_write_bridge(sd, STV_REG04, 0x07);
- /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */
- stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847);
-
/* Scan/timing for the sensor */
stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
stv06xx_write_sensor(sd, PB_CFILLIN, 14);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
index 4de4fa5..757de24 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
@@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
.i2c_addr = 0xba,
.i2c_len = 2,
+ .min_packet_size = { 635, 847 },
+ .max_packet_size = { 847, 923 },
+
.init = pb0100_init,
.probe = pb0100_probe,
.start = pb0100_start,
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
index 934b9ce..fb229d8 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
@@ -53,6 +53,10 @@ struct stv06xx_sensor {
/* length of an i2c word */
u8 i2c_len;
+ /* Isoc packet size (per mode) */
+ int min_packet_size[4];
+ int max_packet_size[4];
+
/* Probes if the sensor is connected */
int (*probe)(struct sd *sd);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
index 3af5326..42390bd 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
@@ -213,7 +213,6 @@ static int st6422_init(struct sd *sd)
{ 0x150e, 0x8e },
{ 0x150f, 0x37 },
{ 0x15c0, 0x00 },
- { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
{ 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
@@ -237,23 +236,9 @@ static void st6422_disconnect(struct sd *sd)
static int st6422_start(struct sd *sd)
{
- int err, packet_size;
+ int err;
struct cam *cam = &sd->gspca_dev.cam;
s32 *sensor_settings = sd->sensor_priv;
- struct usb_host_interface *alt;
- struct usb_interface *intf;
-
- intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
- alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
- if (!alt) {
- err("Couldn't get altsetting");
- return -EIO;
- }
-
- packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
- err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
- if (err < 0)
- return err;
if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
index b2d45fe..12608ae 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
@@ -49,6 +49,9 @@ static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
const struct stv06xx_sensor stv06xx_sensor_st6422 = {
.name = "ST6422",
+ /* No known way to lower framerate in case of less bandwidth */
+ .min_packet_size = { 300, 847 },
+ .max_packet_size = { 300, 847 },
.init = st6422_init,
.probe = st6422_probe,
.start = st6422_start,
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
index b3b5508..7fe3587 100644
--- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
+++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
@@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
.i2c_flush = 5,
.i2c_addr = 0x20,
.i2c_len = 1,
+ /* FIXME (see if we can lower packet_size-s, needs testing, and also
+ adjusting framerate when the bandwidth gets lower) */
+ .min_packet_size = { 1023 },
+ .max_packet_size = { 1023 },
.init = vv6410_init,
.probe = vv6410_probe,
.start = vv6410_start,
@@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 - 0x153b */
0x02, 0x00, 0x60, 0x01, 0x20, 0x01
};
-static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */
- 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */
-};
-
static const struct stv_init stv_bridge_init[] = {
/* This reg is written twice. Some kind of reset? */
{NULL, 0x1620, 0x80},
@@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_init[] = {
{NULL, 0x1423, 0x04},
{x1500, 0x1500, ARRAY_SIZE(x1500)},
{x1536, 0x1536, ARRAY_SIZE(x1536)},
- {x15c1, 0x15c1, ARRAY_SIZE(x15c1)}
};
static const u8 vv6410_sensor_init[][2] = {
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/7] gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
` (2 preceding siblings ...)
2010-10-27 12:35 ` [PATCH 3/7] gspca-stv06xx: support bandwidth changing Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 5/7] gspca_xirlink_cit: Frames have a 4 byte footer Hans de Goede
` (3 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
The following usb bandwidth allocation changes were made to the ibm netcam
pro code:
- Don't restart negotiation at max packet size on stop0, as that gets called
by gspca_main during negotiation. Move this to sd_isoc_init.
- Don't ask for full bandwidth when running at 160x120, that does not need
full bandwidth
- Make minimum acceptable bandwidth depend upon resolution
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/xirlink_cit.c | 41 +++++++++++++++++++++++-------
1 files changed, 31 insertions(+), 10 deletions(-)
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index 8715577..f0f6279 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -2769,16 +2769,43 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+ struct usb_host_interface *alt;
+ int max_packet_size;
+
+ switch (gspca_dev->width) {
+ case 160: max_packet_size = 450; break;
+ case 176: max_packet_size = 600; break;
+ default: max_packet_size = 1022; break;
+ }
+
+ /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+ alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(max_packet_size);
+
+ return 0;
+}
+
static int sd_isoc_nego(struct gspca_dev *gspca_dev)
{
- int ret, packet_size;
+ int ret, packet_size, min_packet_size;
struct usb_host_interface *alt;
+ switch (gspca_dev->width) {
+ case 160: min_packet_size = 200; break;
+ case 176: min_packet_size = 266; break;
+ default: min_packet_size = 400; break;
+ }
+
alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
- packet_size -= 100;
- if (packet_size < 300)
+ if (packet_size <= min_packet_size)
return -EIO;
+
+ packet_size -= 100;
+ if (packet_size < min_packet_size)
+ packet_size = min_packet_size;
alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
@@ -2796,15 +2823,12 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct usb_host_interface *alt;
/* We cannot use gspca_dev->present here as that is not set when
sd_init gets called and we get called from sd_init */
if (!gspca_dev->dev)
return;
- alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
-
switch (sd->model) {
case CIT_MODEL0:
/* HDG windows does this, but it causes the cams autogain to
@@ -2859,10 +2883,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
restarting the stream after this */
/* cit_write_reg(gspca_dev, 0x0000, 0x0112); */
cit_write_reg(gspca_dev, 0x00c0, 0x0100);
-
- /* Start isoc bandwidth "negotiation" at max isoc bandwith
- next stream start */
- alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(1022);
break;
}
}
@@ -3179,6 +3199,7 @@ static const struct sd_desc sd_desc_isoc_nego = {
.config = sd_config,
.init = sd_init,
.start = sd_start,
+ .isoc_init = sd_isoc_init,
.isoc_nego = sd_isoc_nego,
.stopN = sd_stopN,
.stop0 = sd_stop0,
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/7] gspca_xirlink_cit: Frames have a 4 byte footer
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
` (3 preceding siblings ...)
2010-10-27 12:35 ` [PATCH 4/7] gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 6/7] gspca_xirlink_cit: Add support camera button Hans de Goede
` (2 subsequent siblings)
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
Atleast on the ibm netcam pro frames have a 4 byte footer, take this
into account when calculating sizeimage.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/xirlink_cit.c | 24 ++++++++++++------------
1 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index f0f6279..ea73377 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -185,60 +185,60 @@ static const struct ctrl sd_ctrls[] = {
static const struct v4l2_pix_format cif_yuv_mode[] = {
{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 176,
- .sizeimage = 176 * 144 * 3 / 2,
+ .sizeimage = 176 * 144 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{352, 288, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 352,
- .sizeimage = 352 * 288 * 3 / 2,
+ .sizeimage = 352 * 288 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
};
static const struct v4l2_pix_format vga_yuv_mode[] = {
{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 2,
+ .sizeimage = 160 * 120 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 320,
- .sizeimage = 320 * 240 * 3 / 2,
+ .sizeimage = 320 * 240 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{640, 480, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 640,
- .sizeimage = 640 * 480 * 3 / 2,
+ .sizeimage = 640 * 480 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
};
static const struct v4l2_pix_format model0_mode[] = {
{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 2,
+ .sizeimage = 160 * 120 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 176,
- .sizeimage = 176 * 144 * 3 / 2,
+ .sizeimage = 176 * 144 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{320, 240, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 320,
- .sizeimage = 320 * 240 * 3 / 2,
+ .sizeimage = 320 * 240 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
};
static const struct v4l2_pix_format model2_mode[] = {
{160, 120, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 2,
+ .sizeimage = 160 * 120 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{176, 144, V4L2_PIX_FMT_CIT_YYVYUY, V4L2_FIELD_NONE,
.bytesperline = 176,
- .sizeimage = 176 * 144 * 3 / 2,
+ .sizeimage = 176 * 144 * 3 / 2 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{320, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 320,
- .sizeimage = 320 * 240,
+ .sizeimage = 320 * 240 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
{352, 288, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 352,
- .sizeimage = 352 * 288,
+ .sizeimage = 352 * 288 + 4,
.colorspace = V4L2_COLORSPACE_SRGB},
};
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/7] gspca_xirlink_cit: Add support camera button
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
` (4 preceding siblings ...)
2010-10-27 12:35 ` [PATCH 5/7] gspca_xirlink_cit: Frames have a 4 byte footer Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 7/7] gspca_ov519: generate release button event on stream stop if needed Hans de Goede
2010-11-09 15:09 ` [GIT PATCHES FOR 2.6.37] Various gspca patches Mauro Carvalho Chehab
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/xirlink_cit.c | 117 ++++++++++++++++++++++---------
1 files changed, 84 insertions(+), 33 deletions(-)
diff --git a/drivers/media/video/gspca/xirlink_cit.c b/drivers/media/video/gspca/xirlink_cit.c
index ea73377..f884727 100644
--- a/drivers/media/video/gspca/xirlink_cit.c
+++ b/drivers/media/video/gspca/xirlink_cit.c
@@ -29,6 +29,7 @@
#define MODULE_NAME "xirlink-cit"
+#include <linux/input.h>
#include "gspca.h"
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
@@ -58,6 +59,7 @@ struct sd {
#define CIT_MODEL4 4
#define CIT_IBM_NETCAM_PRO 5
u8 input_index;
+ u8 button_state;
u8 stop_on_control_change;
u8 sof_read;
u8 sof_len;
@@ -804,7 +806,7 @@ static int cit_write_reg(struct gspca_dev *gspca_dev, u16 value, u16 index)
return 0;
}
-static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index)
+static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index, int verbose)
{
struct usb_device *udev = gspca_dev->dev;
__u8 *buf = gspca_dev->usb_buf;
@@ -819,10 +821,8 @@ static int cit_read_reg(struct gspca_dev *gspca_dev, u16 index)
return res;
}
- PDEBUG(D_PROBE,
- "Register %04x value: %02x %02x %02x %02x %02x %02x %02x %02x",
- index,
- buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+ if (verbose)
+ PDEBUG(D_PROBE, "Register %04x value: %02x", index, buf[0]);
return 0;
}
@@ -907,7 +907,7 @@ static void cit_Packet_Format1(struct gspca_dev *gspca_dev, u16 fkey, u16 val)
cit_send_x_00_05(gspca_dev, 0x0089);
cit_send_x_00(gspca_dev, fkey);
cit_send_00_04_06(gspca_dev);
- cit_read_reg(gspca_dev, 0x0126);
+ cit_read_reg(gspca_dev, 0x0126, 0);
cit_send_FF_04_02(gspca_dev);
}
@@ -1074,12 +1074,12 @@ static int cit_init_model0(struct gspca_dev *gspca_dev)
static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
{
- cit_read_reg(gspca_dev, 0x128);
+ cit_read_reg(gspca_dev, 0x128, 1);
cit_write_reg(gspca_dev, 0x0003, 0x0133);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0100);
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x0000, 0x0133);
@@ -1098,7 +1098,7 @@ static int cit_init_ibm_netcam_pro(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x00ff, 0x0130);
cit_write_reg(gspca_dev, 0xcd41, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
- cit_read_reg(gspca_dev, 0x0126);
+ cit_read_reg(gspca_dev, 0x0126, 1);
cit_model3_Packet1(gspca_dev, 0x0000, 0x0000);
cit_model3_Packet1(gspca_dev, 0x0000, 0x0001);
@@ -1557,18 +1557,20 @@ static int cit_restart_stream(struct gspca_dev *gspca_dev)
switch (sd->model) {
case CIT_MODEL0:
case CIT_MODEL1:
- case CIT_MODEL3:
- case CIT_IBM_NETCAM_PRO:
cit_write_reg(gspca_dev, 0x0001, 0x0114);
/* Fall through */
case CIT_MODEL2:
case CIT_MODEL4:
cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
- /* This happens repeatedly while streaming with the ibm netcam
- pro and the ibmcam driver did it for model3 after changing
- settings, but it does not seem to have any effect. */
- /* cit_write_reg(gspca_dev, 0x0001, 0x0113); */
+ break;
+ case CIT_MODEL3:
+ case CIT_IBM_NETCAM_PRO:
+ cit_write_reg(gspca_dev, 0x0001, 0x0114);
+ cit_write_reg(gspca_dev, 0x00c0, 0x010c); /* Go! */
+ usb_clear_halt(gspca_dev->dev, gspca_dev->urb[0]->pipe);
+ /* Clear button events from while we were not streaming */
+ cit_write_reg(gspca_dev, 0x0001, 0x0113);
break;
}
@@ -1680,23 +1682,23 @@ static int cit_start_model1(struct gspca_dev *gspca_dev)
if (clock_div < 0)
return clock_div;
- cit_read_reg(gspca_dev, 0x0128);
- cit_read_reg(gspca_dev, 0x0100);
+ cit_read_reg(gspca_dev, 0x0128, 1);
+ cit_read_reg(gspca_dev, 0x0100, 0);
cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
- cit_read_reg(gspca_dev, 0x0100);
+ cit_read_reg(gspca_dev, 0x0100, 0);
cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
- cit_read_reg(gspca_dev, 0x0100);
+ cit_read_reg(gspca_dev, 0x0100, 0);
cit_write_reg(gspca_dev, 0x01, 0x0100); /* LED On */
cit_write_reg(gspca_dev, 0x01, 0x0108);
cit_write_reg(gspca_dev, 0x03, 0x0112);
- cit_read_reg(gspca_dev, 0x0115);
+ cit_read_reg(gspca_dev, 0x0115, 0);
cit_write_reg(gspca_dev, 0x06, 0x0115);
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x44, 0x0116);
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x40, 0x0116);
- cit_read_reg(gspca_dev, 0x0115);
+ cit_read_reg(gspca_dev, 0x0115, 0);
cit_write_reg(gspca_dev, 0x0e, 0x0115);
cit_write_reg(gspca_dev, 0x19, 0x012c);
@@ -1878,7 +1880,7 @@ static int cit_start_model2(struct gspca_dev *gspca_dev)
int clock_div = 0;
cit_write_reg(gspca_dev, 0x0000, 0x0100); /* LED on */
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x00bc, 0x012c);
@@ -2070,10 +2072,10 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
/* HDG not in ibmcam driver, added to see if it helps with
auto-detecting between model3 and ibm netcamera pro */
- cit_read_reg(gspca_dev, 0x128);
+ cit_read_reg(gspca_dev, 0x128, 1);
cit_write_reg(gspca_dev, 0x0000, 0x0100);
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0112);
cit_write_reg(gspca_dev, 0x0000, 0x0123);
@@ -2083,7 +2085,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x0060, 0x0116);
cit_write_reg(gspca_dev, 0x0002, 0x0115);
cit_write_reg(gspca_dev, 0x0003, 0x0115);
- cit_read_reg(gspca_dev, 0x0115);
+ cit_read_reg(gspca_dev, 0x0115, 0);
cit_write_reg(gspca_dev, 0x000b, 0x0115);
/* TESTME HDG not in ibmcam driver, added to see if it helps with
@@ -2096,7 +2098,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x00ff, 0x0130);
cit_write_reg(gspca_dev, 0xcd41, 0x0124);
cit_write_reg(gspca_dev, 0xfffa, 0x0124);
- cit_read_reg(gspca_dev, 0x0126);
+ cit_read_reg(gspca_dev, 0x0126, 1);
}
cit_model3_Packet1(gspca_dev, 0x000a, 0x0040);
@@ -2293,7 +2295,7 @@ static int cit_start_model3(struct gspca_dev *gspca_dev)
if (rca_input) {
for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
if (rca_initdata[i][0])
- cit_read_reg(gspca_dev, rca_initdata[i][2]);
+ cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
else
cit_write_reg(gspca_dev, rca_initdata[i][1],
rca_initdata[i][2]);
@@ -2712,7 +2714,7 @@ static int cit_start_ibm_netcam_pro(struct gspca_dev *gspca_dev)
if (rca_input) {
for (i = 0; i < ARRAY_SIZE(rca_initdata); i++) {
if (rca_initdata[i][0])
- cit_read_reg(gspca_dev, rca_initdata[i][2]);
+ cit_read_reg(gspca_dev, rca_initdata[i][2], 0);
else
cit_write_reg(gspca_dev, rca_initdata[i][1],
rca_initdata[i][2]);
@@ -2839,7 +2841,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
break;
case CIT_MODEL1:
cit_send_FF_04_02(gspca_dev);
- cit_read_reg(gspca_dev, 0x0100);
+ cit_read_reg(gspca_dev, 0x0100, 0);
cit_write_reg(gspca_dev, 0x81, 0x0100); /* LED Off */
break;
case CIT_MODEL2:
@@ -2858,9 +2860,9 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
case CIT_MODEL3:
cit_write_reg(gspca_dev, 0x0006, 0x012c);
cit_model3_Packet1(gspca_dev, 0x0046, 0x0000);
- cit_read_reg(gspca_dev, 0x0116);
+ cit_read_reg(gspca_dev, 0x0116, 0);
cit_write_reg(gspca_dev, 0x0064, 0x0116);
- cit_read_reg(gspca_dev, 0x0115);
+ cit_read_reg(gspca_dev, 0x0115, 0);
cit_write_reg(gspca_dev, 0x0003, 0x0115);
cit_write_reg(gspca_dev, 0x0008, 0x0123);
cit_write_reg(gspca_dev, 0x0000, 0x0117);
@@ -2885,6 +2887,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
cit_write_reg(gspca_dev, 0x00c0, 0x0100);
break;
}
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ /* If the last button state is pressed, release it now! */
+ if (sd->button_state) {
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+ input_sync(gspca_dev->input_dev);
+ sd->button_state = 0;
+ }
+#endif
}
static u8 *cit_find_sof(struct gspca_dev *gspca_dev, u8 *data, int len)
@@ -3178,6 +3189,38 @@ static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+static void cit_check_button(struct gspca_dev *gspca_dev)
+{
+ int new_button_state;
+ struct sd *sd = (struct sd *)gspca_dev;
+
+ switch (sd->model) {
+ case CIT_MODEL3:
+ case CIT_IBM_NETCAM_PRO:
+ break;
+ default: /* TEST ME unknown if this works on other models too */
+ return;
+ }
+
+ /* Read the button state */
+ cit_read_reg(gspca_dev, 0x0113, 0);
+ new_button_state = !gspca_dev->usb_buf[0];
+
+ /* Tell the cam we've seen the button press, notice that this
+ is a nop (iow the cam keeps reporting pressed) until the
+ button is actually released. */
+ if (new_button_state)
+ cit_write_reg(gspca_dev, 0x01, 0x0113);
+
+ if (sd->button_state != new_button_state) {
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA,
+ new_button_state);
+ input_sync(gspca_dev->input_dev);
+ sd->button_state = new_button_state;
+ }
+}
+#endif
/* sub-driver description */
static const struct sd_desc sd_desc = {
@@ -3190,6 +3233,10 @@ static const struct sd_desc sd_desc = {
.stopN = sd_stopN,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ .dq_callback = cit_check_button,
+ .other_input = 1,
+#endif
};
static const struct sd_desc sd_desc_isoc_nego = {
@@ -3204,6 +3251,10 @@ static const struct sd_desc sd_desc_isoc_nego = {
.stopN = sd_stopN,
.stop0 = sd_stop0,
.pkt_scan = sd_pkt_scan,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ .dq_callback = cit_check_button,
+ .other_input = 1,
+#endif
};
/* -- module initialisation -- */
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/7] gspca_ov519: generate release button event on stream stop if needed
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
` (5 preceding siblings ...)
2010-10-27 12:35 ` [PATCH 6/7] gspca_xirlink_cit: Add support camera button Hans de Goede
@ 2010-10-27 12:35 ` Hans de Goede
2010-11-09 15:09 ` [GIT PATCHES FOR 2.6.37] Various gspca patches Mauro Carvalho Chehab
7 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 12:35 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine,
Hans de Goede
Generate a release button event when the button is still pressed when the
stream stops.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
drivers/media/video/gspca/ov519.c | 10 +++++++++-
1 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index 6cf6855..7e86faf 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -3912,7 +3912,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
pressed while we weren't streaming */
sd->snapshot_needs_reset = 1;
sd_reset_snapshot(gspca_dev);
- sd->snapshot_pressed = 0;
sd->first_frame = 3;
@@ -3940,6 +3939,15 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
if (sd->bridge == BRIDGE_W9968CF)
w9968cf_stop0(sd);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+ /* If the last button state is pressed, release it now! */
+ if (sd->snapshot_pressed) {
+ input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+ input_sync(gspca_dev->input_dev);
+ sd->snapshot_pressed = 0;
+ }
+#endif
}
static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)
--
1.7.3.1
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 3/7] gspca-stv06xx: support bandwidth changing
2010-10-27 12:35 ` [PATCH 3/7] gspca-stv06xx: support bandwidth changing Hans de Goede
@ 2010-10-27 12:39 ` Erik Andrén
2010-10-27 13:17 ` Hans de Goede
0 siblings, 1 reply; 11+ messages in thread
From: Erik Andrén @ 2010-10-27 12:39 UTC (permalink / raw)
To: Hans de Goede
Cc: Mauro Carvalho Chehab, Linux Media Mailing List, Lee Jones,
Jean-Francois Moine
2010/10/27 Hans de Goede <hdegoede@redhat.com>:
> stv06xx devices have only one altsetting, but the actual used
> bandwidth can be programmed through a register. We were already
> setting this register lower then the max packetsize of the altsetting
> indicates. This patch makes the gspca-stv06xx update the usb descriptor
> for the alt setting to reflect the actual packetsize in use, so that
> the usb subsystem uses the correct information for scheduling usb transfers.
>
> This patch also tries to fallback to lower speeds in case a ENOSPC error
> is received when submitting urbs, but currently this is only supported
> with stv06xx cams with the pb0100 sensor, as this is the only one for
> which we know how to change the framerate.
>
> This patch is based on an initial incomplete patch by
> Lee Jones <lee.jones@canonical.com>
>
> Signed-off-by: Lee Jones <lee.jones@canonical.com>
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Cool,
Has this been verified to work with all affected devices?
Best regards,
Erik
> ---
> drivers/media/video/gspca/stv06xx/stv06xx.c | 55 +++++++++++++++++++-
> drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h | 11 ++++-
> drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c | 18 +++++--
> drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h | 3 +
> drivers/media/video/gspca/stv06xx/stv06xx_sensor.h | 4 ++
> drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | 17 +------
> drivers/media/video/gspca/stv06xx/stv06xx_st6422.h | 3 +
> drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h | 9 ++--
> 8 files changed, 93 insertions(+), 27 deletions(-)
>
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c
> index 086de44..ca86762 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx.c
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c
> @@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev *gspca_dev)
> static int stv06xx_start(struct gspca_dev *gspca_dev)
> {
> struct sd *sd = (struct sd *) gspca_dev;
> - int err;
> + struct usb_host_interface *alt;
> + struct usb_interface *intf;
> + int err, packet_size;
> +
> + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
> + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
> + if (!alt) {
> + PDEBUG(D_ERR, "Couldn't get altsetting");
> + return -EIO;
> + }
> +
> + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
> + err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
> + if (err < 0)
> + return err;
>
> /* Prepare the sensor for start */
> err = sd->sensor->start(sd);
> @@ -282,6 +296,43 @@ out:
> return (err < 0) ? err : 0;
> }
>
> +static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
> +{
> + struct usb_host_interface *alt;
> + struct sd *sd = (struct sd *) gspca_dev;
> +
> + /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
> + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
> + alt->endpoint[0].desc.wMaxPacketSize =
> + cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
> +
> + return 0;
> +}
> +
> +static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
> +{
> + int ret, packet_size, min_packet_size;
> + struct usb_host_interface *alt;
> + struct sd *sd = (struct sd *) gspca_dev;
> +
> + alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
> + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
> + min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
> + if (packet_size <= min_packet_size)
> + return -EIO;
> +
> + packet_size -= 100;
> + if (packet_size < min_packet_size)
> + packet_size = min_packet_size;
> + alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
> +
> + ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
> + if (ret < 0)
> + PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
> +
> + return ret;
> +}
> +
> static void stv06xx_stopN(struct gspca_dev *gspca_dev)
> {
> int err;
> @@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = {
> .start = stv06xx_start,
> .stopN = stv06xx_stopN,
> .pkt_scan = stv06xx_pkt_scan,
> + .isoc_init = stv06xx_isoc_init,
> + .isoc_nego = stv06xx_isoc_nego,
> #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
> .int_pkt_scan = sd_int_pkt_scan,
> #endif
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
> index cf3d0cc..b538dce 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
> @@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1x00 = {
> .i2c_addr = (0x55 << 1),
> .i2c_len = 1,
>
> + /* FIXME (see if we can lower min_packet_size, needs testing, and also
> + adjusting framerate when the bandwidth gets lower) */
> + .min_packet_size = { 847 },
> + .max_packet_size = { 847 },
> +
> .init = hdcs_init,
> .probe = hdcs_probe_1x00,
> .start = hdcs_start,
> @@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sensor_hdcs1020 = {
> .i2c_addr = (0x55 << 1),
> .i2c_len = 1,
>
> + /* FIXME (see if we can lower min_packet_size, needs testing, and also
> + adjusting framerate when the bandwidthm gets lower) */
> + .min_packet_size = { 847 },
> + .max_packet_size = { 847 },
> +
> .init = hdcs_init,
> .probe = hdcs_probe_1020,
> .start = hdcs_start,
> @@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] = {
> {STV_REG04, 0x07},
>
> {STV_SCAN_RATE, 0x20},
> - {STV_ISO_SIZE_L, 847},
> {STV_Y_CTRL, 0x01},
> {STV_X_CTRL, 0x0a}
> };
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
> index 285221e..ac47b4c 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
> @@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd)
>
> static int pb0100_start(struct sd *sd)
> {
> - int err;
> + int err, packet_size, max_packet_size;
> + struct usb_host_interface *alt;
> + struct usb_interface *intf;
> struct cam *cam = &sd->gspca_dev.cam;
> s32 *sensor_settings = sd->sensor_priv;
> u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
>
> + intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
> + alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
> + packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
> +
> + /* If we don't have enough bandwidth use a lower framerate */
> + max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
> + if (packet_size < max_packet_size)
> + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
> + else
> + stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
> +
> /* Setup sensor window */
> if (mode & PB0100_CROP_TO_VGA) {
> stv06xx_write_sensor(sd, PB_RSTART, 30);
> @@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd)
> stv06xx_write_bridge(sd, STV_REG03, 0x45);
> stv06xx_write_bridge(sd, STV_REG04, 0x07);
>
> - /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */
> - stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847);
> -
> /* Scan/timing for the sensor */
> stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
> stv06xx_write_sensor(sd, PB_CFILLIN, 14);
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
> index 4de4fa5..757de24 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
> @@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sensor_pb0100 = {
> .i2c_addr = 0xba,
> .i2c_len = 2,
>
> + .min_packet_size = { 635, 847 },
> + .max_packet_size = { 847, 923 },
> +
> .init = pb0100_init,
> .probe = pb0100_probe,
> .start = pb0100_start,
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
> index 934b9ce..fb229d8 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
> @@ -53,6 +53,10 @@ struct stv06xx_sensor {
> /* length of an i2c word */
> u8 i2c_len;
>
> + /* Isoc packet size (per mode) */
> + int min_packet_size[4];
> + int max_packet_size[4];
> +
> /* Probes if the sensor is connected */
> int (*probe)(struct sd *sd);
>
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
> index 3af5326..42390bd 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
> @@ -213,7 +213,6 @@ static int st6422_init(struct sd *sd)
> { 0x150e, 0x8e },
> { 0x150f, 0x37 },
> { 0x15c0, 0x00 },
> - { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
> { 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
>
>
> @@ -237,23 +236,9 @@ static void st6422_disconnect(struct sd *sd)
>
> static int st6422_start(struct sd *sd)
> {
> - int err, packet_size;
> + int err;
> struct cam *cam = &sd->gspca_dev.cam;
> s32 *sensor_settings = sd->sensor_priv;
> - struct usb_host_interface *alt;
> - struct usb_interface *intf;
> -
> - intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
> - alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
> - if (!alt) {
> - err("Couldn't get altsetting");
> - return -EIO;
> - }
> -
> - packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
> - err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
> - if (err < 0)
> - return err;
>
> if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
> err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
> index b2d45fe..12608ae 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
> @@ -49,6 +49,9 @@ static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val);
>
> const struct stv06xx_sensor stv06xx_sensor_st6422 = {
> .name = "ST6422",
> + /* No known way to lower framerate in case of less bandwidth */
> + .min_packet_size = { 300, 847 },
> + .max_packet_size = { 300, 847 },
> .init = st6422_init,
> .probe = st6422_probe,
> .start = st6422_start,
> diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
> index b3b5508..7fe3587 100644
> --- a/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
> +++ b/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
> @@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sensor_vv6410 = {
> .i2c_flush = 5,
> .i2c_addr = 0x20,
> .i2c_len = 1,
> + /* FIXME (see if we can lower packet_size-s, needs testing, and also
> + adjusting framerate when the bandwidth gets lower) */
> + .min_packet_size = { 1023 },
> + .max_packet_size = { 1023 },
> .init = vv6410_init,
> .probe = vv6410_probe,
> .start = vv6410_start,
> @@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 - 0x153b */
> 0x02, 0x00, 0x60, 0x01, 0x20, 0x01
> };
>
> -static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */
> - 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */
> -};
> -
> static const struct stv_init stv_bridge_init[] = {
> /* This reg is written twice. Some kind of reset? */
> {NULL, 0x1620, 0x80},
> @@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_init[] = {
> {NULL, 0x1423, 0x04},
> {x1500, 0x1500, ARRAY_SIZE(x1500)},
> {x1536, 0x1536, ARRAY_SIZE(x1536)},
> - {x15c1, 0x15c1, ARRAY_SIZE(x15c1)}
> };
>
> static const u8 vv6410_sensor_init[][2] = {
> --
> 1.7.3.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/7] gspca-stv06xx: support bandwidth changing
2010-10-27 12:39 ` Erik Andrén
@ 2010-10-27 13:17 ` Hans de Goede
0 siblings, 0 replies; 11+ messages in thread
From: Hans de Goede @ 2010-10-27 13:17 UTC (permalink / raw)
To: Erik Andrén
Cc: Mauro Carvalho Chehab, Linux Media Mailing List, Lee Jones,
Jean-Francois Moine
Hi,
On 10/27/2010 02:39 PM, Erik Andrén wrote:
> 2010/10/27 Hans de Goede<hdegoede@redhat.com>:
>> stv06xx devices have only one altsetting, but the actual used
>> bandwidth can be programmed through a register. We were already
>> setting this register lower then the max packetsize of the altsetting
>> indicates. This patch makes the gspca-stv06xx update the usb descriptor
>> for the alt setting to reflect the actual packetsize in use, so that
>> the usb subsystem uses the correct information for scheduling usb transfers.
>>
>> This patch also tries to fallback to lower speeds in case a ENOSPC error
>> is received when submitting urbs, but currently this is only supported
>> with stv06xx cams with the pb0100 sensor, as this is the only one for
>> which we know how to change the framerate.
>>
>> This patch is based on an initial incomplete patch by
>> Lee Jones<lee.jones@canonical.com>
>>
>> Signed-off-by: Lee Jones<lee.jones@canonical.com>
>> Signed-off-by: Hans de Goede<hdegoede@redhat.com>
>
> Cool,
> Has this been verified to work with all affected devices?
Yes and no, it has been verified with a camera with a st6422 sensor
and one with a pb0100 sensor. It has not been verified with the others, but
it makes no changes to the others. See min and max bandwidth settings in
the sensor struct in the sensors .h file (and the FIXME comments there).
These result in the STV_ISO_SIZE_L register setting being left untouched
for the untested devices, effectively making this patch a nop for them.
Except that the usb core will be told that some of them do not use the full
bandwidth, which will allow peaceful coexistence with other devices.
AFAIK you have a vv6410 sensor camera, it would be cool if you could:
1) See if you can vary the framerate of it
2) See what the minimum required bandwidth is for each framerate
(change min and max packet_size to be the same to test).
3) Update max and min packetsize (to reflect the minimum needed
packetsize at the highest. resp lowest framerate).
4) Update the sensor_start function to program the framerate depending
on the available bandwidth (see the pb0100 code).
Thanks & Regards,
Hans
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [GIT PATCHES FOR 2.6.37] Various gspca patches
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
` (6 preceding siblings ...)
2010-10-27 12:35 ` [PATCH 7/7] gspca_ov519: generate release button event on stream stop if needed Hans de Goede
@ 2010-11-09 15:09 ` Mauro Carvalho Chehab
7 siblings, 0 replies; 11+ messages in thread
From: Mauro Carvalho Chehab @ 2010-11-09 15:09 UTC (permalink / raw)
To: Hans de Goede; +Cc: Linux Media Mailing List, Lee Jones, Jean-Francois Moine
Em 27-10-2010 10:35, Hans de Goede escreveu:
> Hi Mauro,
>
> Please pull from:
> http://linuxtv.org/hg/~hgoede/ibmcam3
>
> Starting at the commit titled:
> gspca: submit interrupt urbs *after* isoc urbs
>
> This pull consists of the following commits:
> gspca: submit interrupt urbs *after* isoc urbs
> gspca: only set gspca->int_urb if submitting it succeeds
> gspca-stv06xx: support bandwidth changing
> gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes
> gspca_xirlink_cit: Frames have a 4 byte footer
> gspca_xirlink_cit: Add support camera button
> gspca_ov519: generate release button event on stream stop if needed
>
> Note that since the hg v4l-dvb tree is a bit out of data, pulling from
> my hg tree won't apply cleanly though. So to make things easier for you
> I'm in the process of switching over to git. This mail will be followed
> by the 7 patches from this pull request in git format-patch format, rebased
> on top of the master branch of your git tree:
> git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-next.git
>
> The reason I'm not sending a git pull request is because I don't
> have a git tree, and I could not find documentation for creating
> a git tree @ git.linuxtv.org. Can you help me with this?
>
> Also this wiki page:
> http://linuxtv.org/wiki/index.php/Maintaining_Git_trees
> Points to the obsolete: git://linuxtv.org/v4l-dvb.git
> Repository, please update it.
>
> Thanks & Regards,
>
> Hans
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
All patches but one applied fine. I had to do one trivial merge conflict fix.
This one, however, has a more complex conflict, so I prefer if you could fix
and re-send. Feel free to resend via email, if you were not able to create your
git tree yet.
Thanks,
Mauro.
From: Hans de Goede <hdegoede@redhat.com>
Commiter: Hans de Goede <hdegoede@redhat.com>
Date: Tue Oct 26 14:43:35 2010 +0200
Subject: gspca-stv06xx: support bandwidth changing
stv06xx devices have only one altsetting, but the actual used
bandwidth can be programmed through a register. We were already
setting this register lower then the max packetsize of the altsetting
indicates. This patch makes the gspca-stv06xx update the usb descriptor
for the alt setting to reflect the actual packetsize in use, so that
the usb subsystem uses the correct information for scheduling usb transfers.
This patch also tries to fallback to lower speeds in case a ENOSPC error
is received when submitting urbs, but currently this is only supported
with stv06xx cams with the pb0100 sensor, as this is the only one for
which we know how to change the framerate.
This patch is based on an initial incomplete patch by
Lee Jones <lee.jones@canonical.com>
Priority: normal
Signed-off-by: Lee Jones <lee.jones@canonical.com>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx.c linux/drivers/media/video/gspca/stv06xx/stv06xx.c
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx.c 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx.c 2010-11-09 12:41:24.000000000 -0200
@@ -263,7 +263,21 @@ static int stv06xx_init(struct gspca_dev
static int stv06xx_start(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- int err;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
+ int err, packet_size;
+
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ if (!alt) {
+ PDEBUG(D_ERR, "Couldn't get altsetting");
+ return -EIO;
+ }
+
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ err = stv06xx_write_bridge(sd, STV_ISO_SIZE_L, packet_size);
+ if (err < 0)
+ return err;
/* Prepare the sensor for start */
err = sd->sensor->start(sd);
@@ -282,6 +296,43 @@ out:
return (err < 0) ? err : 0;
}
+static int stv06xx_isoc_init(struct gspca_dev *gspca_dev)
+{
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ /* Start isoc bandwidth "negotiation" at max isoc bandwidth */
+ alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ alt->endpoint[0].desc.wMaxPacketSize =
+ cpu_to_le16(sd->sensor->max_packet_size[gspca_dev->curr_mode]);
+
+ return 0;
+}
+
+static int stv06xx_isoc_nego(struct gspca_dev *gspca_dev)
+{
+ int ret, packet_size, min_packet_size;
+ struct usb_host_interface *alt;
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ alt = &gspca_dev->dev->config->intf_cache[0]->altsetting[1];
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+ min_packet_size = sd->sensor->min_packet_size[gspca_dev->curr_mode];
+ if (packet_size <= min_packet_size)
+ return -EIO;
+
+ packet_size -= 100;
+ if (packet_size < min_packet_size)
+ packet_size = min_packet_size;
+ alt->endpoint[0].desc.wMaxPacketSize = cpu_to_le16(packet_size);
+
+ ret = usb_set_interface(gspca_dev->dev, gspca_dev->iface, 1);
+ if (ret < 0)
+ PDEBUG(D_ERR|D_STREAM, "set alt 1 err %d", ret);
+
+ return ret;
+}
+
static void stv06xx_stopN(struct gspca_dev *gspca_dev)
{
int err;
@@ -462,6 +513,8 @@ static const struct sd_desc sd_desc = {
.start = stv06xx_start,
.stopN = stv06xx_stopN,
.pkt_scan = stv06xx_pkt_scan,
+ .isoc_init = stv06xx_isoc_init,
+ .isoc_nego = stv06xx_isoc_nego,
#ifdef CONFIG_INPUT
.int_pkt_scan = sd_int_pkt_scan,
#endif
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h 2010-11-09 12:41:24.000000000 -0200
@@ -146,6 +146,11 @@ const struct stv06xx_sensor stv06xx_sens
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
+ /* FIXME (see if we can lower min_packet_size, needs testing, and also
+ adjusting framerate when the bandwidth gets lower) */
+ .min_packet_size = { 847 },
+ .max_packet_size = { 847 },
+
.init = hdcs_init,
.probe = hdcs_probe_1x00,
.start = hdcs_start,
@@ -160,6 +165,11 @@ const struct stv06xx_sensor stv06xx_sens
.i2c_addr = (0x55 << 1),
.i2c_len = 1,
+ /* FIXME (see if we can lower min_packet_size, needs testing, and also
+ adjusting framerate when the bandwidthm gets lower) */
+ .min_packet_size = { 847 },
+ .max_packet_size = { 847 },
+
.init = hdcs_init,
.probe = hdcs_probe_1020,
.start = hdcs_start,
@@ -177,7 +187,6 @@ static const u16 stv_bridge_init[][2] =
{STV_REG04, 0x07},
{STV_SCAN_RATE, 0x20},
- {STV_ISO_SIZE_L, 847},
{STV_Y_CTRL, 0x01},
{STV_X_CTRL, 0x0a}
};
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c 2010-11-09 12:41:24.000000000 -0200
@@ -208,11 +208,24 @@ static int pb0100_probe(struct sd *sd)
static int pb0100_start(struct sd *sd)
{
- int err;
+ int err, packet_size, max_packet_size;
+ struct usb_host_interface *alt;
+ struct usb_interface *intf;
struct cam *cam = &sd->gspca_dev.cam;
s32 *sensor_settings = sd->sensor_priv;
u32 mode = cam->cam_mode[sd->gspca_dev.curr_mode].priv;
+ intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
+ alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
+ packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
+
+ /* If we don't have enough bandwidth use a lower framerate */
+ max_packet_size = sd->sensor->max_packet_size[sd->gspca_dev.curr_mode];
+ if (packet_size < max_packet_size)
+ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
+ else
+ stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(5)|BIT(3)|BIT(1));
+
/* Setup sensor window */
if (mode & PB0100_CROP_TO_VGA) {
stv06xx_write_sensor(sd, PB_RSTART, 30);
@@ -328,9 +341,6 @@ static int pb0100_init(struct sd *sd)
stv06xx_write_bridge(sd, STV_REG03, 0x45);
stv06xx_write_bridge(sd, STV_REG04, 0x07);
- /* ISO-Size (0x27b: 635... why? - HDCS uses 847) */
- stv06xx_write_bridge(sd, STV_ISO_SIZE_L, 847);
-
/* Scan/timing for the sensor */
stv06xx_write_sensor(sd, PB_ROWSPEED, BIT(4)|BIT(3)|BIT(1));
stv06xx_write_sensor(sd, PB_CFILLIN, 14);
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h 2010-11-09 12:41:24.000000000 -0200
@@ -138,6 +138,9 @@ const struct stv06xx_sensor stv06xx_sens
.i2c_addr = 0xba,
.i2c_len = 2,
+ .min_packet_size = { 635, 847 },
+ .max_packet_size = { 847, 923 },
+
.init = pb0100_init,
.probe = pb0100_probe,
.start = pb0100_start,
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_sensor.h 2010-11-09 12:41:24.000000000 -0200
@@ -53,6 +53,10 @@ struct stv06xx_sensor {
/* length of an i2c word */
u8 i2c_len;
+ /* Isoc packet size (per mode) */
+ int min_packet_size[4];
+ int max_packet_size[4];
+
/* Probes if the sensor is connected */
int (*probe)(struct sd *sd);
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c 2010-11-09 12:41:24.000000000 -0200
@@ -213,7 +213,6 @@ static int st6422_init(struct sd *sd)
{ 0x150e, 0x8e },
{ 0x150f, 0x37 },
{ 0x15c0, 0x00 },
- { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
{ 0x15c3, 0x08 }, /* 0x04/0x14 ... test pictures ??? */
@@ -237,23 +236,9 @@ static void st6422_disconnect(struct sd
static int st6422_start(struct sd *sd)
{
- int err, packet_size;
+ int err;
struct cam *cam = &sd->gspca_dev.cam;
s32 *sensor_settings = sd->sensor_priv;
- struct usb_host_interface *alt;
- struct usb_interface *intf;
-
- intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
- alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
- if (!alt) {
- PDEBUG(D_ERR, "Couldn't get altsetting");
- return -EIO;
- }
-
- packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
- err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
- if (err < 0)
- return err;
if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_st6422.h 2010-11-09 12:41:24.000000000 -0200
@@ -49,6 +49,9 @@ static int st6422_set_exposure(struct gs
const struct stv06xx_sensor stv06xx_sensor_st6422 = {
.name = "ST6422",
+ /* No known way to lower framerate in case of less bandwidth */
+ .min_packet_size = { 300, 847 },
+ .max_packet_size = { 300, 847 },
.init = st6422_init,
.probe = st6422_probe,
.start = st6422_start,
diff -upNr oldtree/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h
--- oldtree/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h 2010-11-09 12:41:28.000000000 -0200
+++ linux/drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h 2010-11-09 12:41:24.000000000 -0200
@@ -197,6 +197,10 @@ const struct stv06xx_sensor stv06xx_sens
.i2c_flush = 5,
.i2c_addr = 0x20,
.i2c_len = 1,
+ /* FIXME (see if we can lower packet_size-s, needs testing, and also
+ adjusting framerate when the bandwidth gets lower) */
+ .min_packet_size = { 1023 },
+ .max_packet_size = { 1023 },
.init = vv6410_init,
.probe = vv6410_probe,
.start = vv6410_start,
@@ -220,10 +224,6 @@ static const u8 x1536[] = { /* 0x1536 -
0x02, 0x00, 0x60, 0x01, 0x20, 0x01
};
-static const u8 x15c1[] = { /* 0x15c1 - 0x15c2 */
- 0xff, 0x03 /* Output word 0x03ff = 1023 (ISO size) */
-};
-
static const struct stv_init stv_bridge_init[] = {
/* This reg is written twice. Some kind of reset? */
{NULL, 0x1620, 0x80},
@@ -232,7 +232,6 @@ static const struct stv_init stv_bridge_
{NULL, 0x1423, 0x04},
{x1500, 0x1500, ARRAY_SIZE(x1500)},
{x1536, 0x1536, ARRAY_SIZE(x1536)},
- {x15c1, 0x15c1, ARRAY_SIZE(x15c1)}
};
static const u8 vv6410_sensor_init[][2] = {
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2010-11-09 15:10 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-10-27 12:35 [GIT PATCHES FOR 2.6.37] Various gspca patches Hans de Goede
2010-10-27 12:35 ` [PATCH 1/7] gspca: submit interrupt urbs *after* isoc urbs Hans de Goede
2010-10-27 12:35 ` [PATCH 2/7] gspca: only set gspca->int_urb if submitting it succeeds Hans de Goede
2010-10-27 12:35 ` [PATCH 3/7] gspca-stv06xx: support bandwidth changing Hans de Goede
2010-10-27 12:39 ` Erik Andrén
2010-10-27 13:17 ` Hans de Goede
2010-10-27 12:35 ` [PATCH 4/7] gspca_xirlink_cit: various usb bandwidth allocation improvements / fixes Hans de Goede
2010-10-27 12:35 ` [PATCH 5/7] gspca_xirlink_cit: Frames have a 4 byte footer Hans de Goede
2010-10-27 12:35 ` [PATCH 6/7] gspca_xirlink_cit: Add support camera button Hans de Goede
2010-10-27 12:35 ` [PATCH 7/7] gspca_ov519: generate release button event on stream stop if needed Hans de Goede
2010-11-09 15:09 ` [GIT PATCHES FOR 2.6.37] Various gspca patches Mauro Carvalho Chehab
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).