summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--linux/Documentation/video4linux/gspca.txt26
-rw-r--r--linux/drivers/media/video/gspca/conex.c4
-rw-r--r--linux/drivers/media/video/gspca/etoms.c4
-rw-r--r--linux/drivers/media/video/gspca/gspca.c37
-rw-r--r--linux/drivers/media/video/gspca/gspca.h11
-rw-r--r--linux/drivers/media/video/gspca/mars.c4
-rw-r--r--linux/drivers/media/video/gspca/ov519.c4
-rw-r--r--linux/drivers/media/video/gspca/pac207.c4
-rw-r--r--linux/drivers/media/video/gspca/pac7311.c185
-rw-r--r--linux/drivers/media/video/gspca/sonixb.c4
-rw-r--r--linux/drivers/media/video/gspca/sonixj.c226
-rw-r--r--linux/drivers/media/video/gspca/spca500.c4
-rw-r--r--linux/drivers/media/video/gspca/spca501.c4
-rw-r--r--linux/drivers/media/video/gspca/spca505.c4
-rw-r--r--linux/drivers/media/video/gspca/spca506.c4
-rw-r--r--linux/drivers/media/video/gspca/spca508.c4
-rw-r--r--linux/drivers/media/video/gspca/spca561.c104
-rw-r--r--linux/drivers/media/video/gspca/stk014.c4
-rw-r--r--linux/drivers/media/video/gspca/sunplus.c4
-rw-r--r--linux/drivers/media/video/gspca/t613.c8
-rw-r--r--linux/drivers/media/video/gspca/tv8532.c4
-rw-r--r--linux/drivers/media/video/gspca/vc032x.c4
-rw-r--r--linux/drivers/media/video/gspca/zc3xx.c35
-rw-r--r--linux/include/linux/videodev2.h5
24 files changed, 486 insertions, 211 deletions
diff --git a/linux/Documentation/video4linux/gspca.txt b/linux/Documentation/video4linux/gspca.txt
index c7fc9fa8b..2dd2f774d 100644
--- a/linux/Documentation/video4linux/gspca.txt
+++ b/linux/Documentation/video4linux/gspca.txt
@@ -88,14 +88,14 @@ zc3xx 0471:0325 Philips SPC 200 NC
zc3xx 0471:0326 Philips SPC 300 NC
sonixj 0471:0327 Philips SPC 600 NC
sonixj 0471:0328 Philips SPC 700 NC
-zc3xx 0471:032d Philips spc210nc
-zc3xx 0471:032e Philips spc315nc
-sonixj 0471:0330 Philips SPC 710NC
+zc3xx 0471:032d Philips SPC 210 NC
+zc3xx 0471:032e Philips SPC 315 NC
+sonixj 0471:0330 Philips SPC 710 NC
spca501 0497:c001 Smile International
sunplus 04a5:3003 Benq DC 1300
sunplus 04a5:3008 Benq DC 1500
-sunplus 04a5:300a Benq DC3410
-spca500 04a5:300c Benq DC1016
+sunplus 04a5:300a Benq DC 3410
+spca500 04a5:300c Benq DC 1016
sunplus 04f1:1001 JVC GC A50
spca561 04fc:0561 Flexcam 100
sunplus 04fc:500c Sunplus CA500C
@@ -175,18 +175,18 @@ sunplus 08ca:2060 Aiptek PocketDV5300
tv8532 0923:010f ICM532 cams
mars 093a:050f Mars-Semi Pc-Camera
pac207 093a:2460 PAC207 Qtec Webcam 100
-pac207 093a:2463 Philips spc200nc pac207
+pac207 093a:2463 Philips SPC 220 NC
pac207 093a:2464 Labtec Webcam 1200
pac207 093a:2468 PAC207
pac207 093a:2470 Genius GF112
-pac207 093a:2471 PAC207 Genius VideoCam ge111
-pac207 093a:2472 PAC207 Genius VideoCam ge110
+pac207 093a:2471 Genius VideoCam ge111
+pac207 093a:2472 Genius VideoCam ge110
pac7311 093a:2600 PAC7311 Typhoon
-pac7311 093a:2601 PAC7311 Phillips SPC610NC
+pac7311 093a:2601 Philips SPC 610 NC
pac7311 093a:2603 PAC7312
-pac7311 093a:2608 PAC7311 Trust WB-3300p
-pac7311 093a:260e PAC7311 Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
-pac7311 093a:260f PAC7311 SnakeCam
+pac7311 093a:2608 Trust WB-3300p
+pac7311 093a:260e Gigaware VGA PC Camera, Trust WB-3350p, SIGMA cam 2350
+pac7311 093a:260f SnakeCam
pac7311 093a:2621 PAC731x
zc3xx 0ac8:0302 Z-star Vimicro zc0302
vc032x 0ac8:0321 Vimicro generic vc0321
@@ -235,7 +235,7 @@ zc3xx 10fd:0128 Typhoon Webshot II USB 300k 0x0128
spca561 10fd:7e50 FlyCam Usb 100
zc3xx 10fd:8050 Typhoon Webshot II USB 300k
spca501 1776:501c Arowana 300K CMOS Camera
-t613 17a1:0128 T613/TAS5130A
+t613 17a1:0128 TASCORP JPEG Webcam, NGS Cyclops
vc032x 17ef:4802 Lenovo Vc0323+MI1310_SOC
pac207 2001:f115 D-Link DSB-C120
spca500 2899:012c Toptro Industrial
diff --git a/linux/drivers/media/video/gspca/conex.c b/linux/drivers/media/video/gspca/conex.c
index cd3a3f582..739ef557c 100644
--- a/linux/drivers/media/video/gspca/conex.c
+++ b/linux/drivers/media/video/gspca/conex.c
@@ -1026,6 +1026,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/etoms.c b/linux/drivers/media/video/gspca/etoms.c
index a9d043606..626d03e17 100644
--- a/linux/drivers/media/video/gspca/etoms.c
+++ b/linux/drivers/media/video/gspca/etoms.c
@@ -932,6 +932,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/gspca.c b/linux/drivers/media/video/gspca/gspca.c
index 61071a4f4..df7c5cb0a 100644
--- a/linux/drivers/media/video/gspca/gspca.c
+++ b/linux/drivers/media/video/gspca/gspca.c
@@ -118,7 +118,8 @@ static void fill_frame(struct gspca_dev *gspca_dev,
cam_pkt_op pkt_scan;
if (urb->status != 0) {
- PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
+ if (!gspca_dev->frozen)
+ PDEBUG(D_ERR|D_PACK, "urb status: %d", urb->status);
return; /* disconnection ? */
}
pkt_scan = gspca_dev->sd_desc->pkt_scan;
@@ -857,6 +858,8 @@ static int vidioc_querycap(struct file *file, void *priv,
cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
| V4L2_CAP_STREAMING
| V4L2_CAP_READWRITE;
+ if (gspca_dev->flags & GSPCA_SENSOR_UPSIDE_DOWN_FLAG)
+ cap->capabilities |= V4L2_CAP_SENSOR_UPSIDE_DOWN;
return 0;
}
@@ -890,11 +893,6 @@ static int vidioc_queryctrl(struct file *file, void *priv,
return 0;
}
}
- if (id >= V4L2_CID_BASE
- && id <= V4L2_CID_LASTP1) {
- q_ctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
- return 0;
- }
return -EINVAL;
}
@@ -1815,6 +1813,33 @@ void gspca_disconnect(struct usb_interface *intf)
}
EXPORT_SYMBOL(gspca_disconnect);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+ if (!gspca_dev->streaming)
+ return 0;
+ gspca_dev->frozen = 1; /* avoid urb error messages */
+ gspca_dev->sd_desc->stopN(gspca_dev);
+ destroy_urbs(gspca_dev);
+ gspca_set_alt0(gspca_dev);
+ gspca_dev->sd_desc->stop0(gspca_dev);
+ return 0;
+}
+EXPORT_SYMBOL(gspca_suspend);
+
+int gspca_resume(struct usb_interface *intf)
+{
+ struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
+
+ gspca_dev->frozen = 0;
+ if (!gspca_dev->streaming)
+ return 0;
+ return gspca_init_transfer(gspca_dev);
+}
+EXPORT_SYMBOL(gspca_resume);
+#endif
/* -- cam driver utility functions -- */
/* auto gain and exposure algorithm based on the knee algorithm described here:
diff --git a/linux/drivers/media/video/gspca/gspca.h b/linux/drivers/media/video/gspca/gspca.h
index 5cb584546..1920c99d6 100644
--- a/linux/drivers/media/video/gspca/gspca.h
+++ b/linux/drivers/media/video/gspca/gspca.h
@@ -118,6 +118,9 @@ struct gspca_frame {
struct v4l2_buffer v4l2_buf;
};
+/* defines for the flags member */
+#define GSPCA_SENSOR_UPSIDE_DOWN_FLAG 0x01
+
struct gspca_dev {
struct video_device vdev; /* !! must be the first item */
struct file_operations fops;
@@ -154,12 +157,16 @@ struct gspca_dev {
struct mutex queue_lock; /* ISOC queue protection */
__u32 sequence; /* frame sequence number */
char streaming;
+#ifdef CONFIG_PM
+ char frozen; /* suspend - resume */
+#endif
char users; /* number of opens */
char present; /* device connected */
char nbufread; /* number of buffers for read() */
char nurbs; /* number of allocated URBs */
char memory; /* memory type (V4L2_MEMORY_xxx) */
__u8 nbalt; /* number of USB alternate settings */
+ __u8 flags; /* see GSPCA_XXX_FLAG defines */
};
int gspca_dev_probe(struct usb_interface *intf,
@@ -173,6 +180,10 @@ struct gspca_frame *gspca_frame_add(struct gspca_dev *gspca_dev,
struct gspca_frame *frame,
const __u8 *data,
int len);
+#ifdef CONFIG_PM
+int gspca_suspend(struct usb_interface *intf, pm_message_t message);
+int gspca_resume(struct usb_interface *intf);
+#endif
int gspca_auto_gain_n_exposure(struct gspca_dev *gspca_dev, int avg_lum,
int desired_avg_lum, int deadzone, int gain_knee, int exposure_knee);
#endif /* GSPCAV2_H */
diff --git a/linux/drivers/media/video/gspca/mars.c b/linux/drivers/media/video/gspca/mars.c
index 21c4ee56a..d7e209578 100644
--- a/linux/drivers/media/video/gspca/mars.c
+++ b/linux/drivers/media/video/gspca/mars.c
@@ -439,6 +439,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/ov519.c b/linux/drivers/media/video/gspca/ov519.c
index 2379433f0..e1c665b4d 100644
--- a/linux/drivers/media/video/gspca/ov519.c
+++ b/linux/drivers/media/video/gspca/ov519.c
@@ -2157,6 +2157,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/pac207.c b/linux/drivers/media/video/gspca/pac207.c
index cee45b048..d9668f4cb 100644
--- a/linux/drivers/media/video/gspca/pac207.c
+++ b/linux/drivers/media/video/gspca/pac207.c
@@ -596,6 +596,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/pac7311.c b/linux/drivers/media/video/gspca/pac7311.c
index c148d1003..94f0cd1b8 100644
--- a/linux/drivers/media/video/gspca/pac7311.c
+++ b/linux/drivers/media/video/gspca/pac7311.c
@@ -40,6 +40,9 @@ struct sd {
unsigned char contrast;
unsigned char colors;
unsigned char autogain;
+ __u8 hflip;
+ __u8 vflip;
+ __u8 qindex;
char tosof; /* number of bytes before next start of frame */
signed char ag_cnt;
@@ -59,6 +62,10 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val);
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val);
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
static struct ctrl sd_ctrls[] = {
{
@@ -82,9 +89,10 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 255,
+#define CONTRAST_MAX 255
+ .maximum = CONTRAST_MAX,
.step = 1,
-#define CONTRAST_DEF 127
+#define CONTRAST_DEF 60
.default_value = CONTRAST_DEF,
},
.set = sd_setcontrast,
@@ -94,9 +102,10 @@ static struct ctrl sd_ctrls[] = {
{
.id = V4L2_CID_SATURATION,
.type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Color",
+ .name = "Saturation",
.minimum = 0,
- .maximum = 255,
+#define COLOR_MAX 255
+ .maximum = COLOR_MAX,
.step = 1,
#define COLOR_DEF 127
.default_value = COLOR_DEF,
@@ -118,6 +127,35 @@ static struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
+/* next controls work with pac7302 only */
+ {
+ {
+ .id = V4L2_CID_HFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Mirror",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define HFLIP_DEF 0
+ .default_value = HFLIP_DEF,
+ },
+ .set = sd_sethflip,
+ .get = sd_gethflip,
+ },
+ {
+ {
+ .id = V4L2_CID_VFLIP,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Vflip",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+#define VFLIP_DEF 0
+ .default_value = VFLIP_DEF,
+ },
+ .set = sd_setvflip,
+ .get = sd_getvflip,
+ },
};
static struct v4l2_pix_format vga_mode[] = {
@@ -425,20 +463,53 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->contrast = CONTRAST_DEF;
sd->colors = COLOR_DEF;
sd->autogain = AUTOGAIN_DEF;
+ sd->hflip = HFLIP_DEF;
+ sd->vflip = VFLIP_DEF;
+ sd->qindex = 3;
sd->ag_cnt = -1;
return 0;
}
+/* rev 12a only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ int i, v;
+ static const __u8 max[10] =
+ {0x29, 0x33, 0x42, 0x5a, 0x6e, 0x80, 0x9f, 0xbb,
+ 0xd4, 0xec};
+ static const __u8 delta[10] =
+ {0x35, 0x33, 0x33, 0x2f, 0x2a, 0x25, 0x1e, 0x17,
+ 0x11, 0x0b};
+
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ for (i = 0; i < 10; i++) {
+ v = max[i];
+ v += (sd->brightness - BRIGHTNESS_MAX)
+ * 150 / BRIGHTNESS_MAX; /* 200 ? */
+ v -= delta[i] * sd->contrast / CONTRAST_MAX;
+ if (v < 0)
+ v = 0;
+ else if (v > 0xff)
+ v = 0xff;
+ reg_w(gspca_dev, 0xa2 + i, v);
+ }
+ reg_w(gspca_dev, 0xdc, 0x01);
+}
+
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
int brightness;
- if (sd->sensor == SENSOR_PAC7302)
+ if (sd->sensor == SENSOR_PAC7302) {
+ setbrightcont(gspca_dev);
return;
+ }
/*jfm: inverted?*/
brightness = BRIGHTNESS_MAX - sd->brightness;
reg_w(gspca_dev, 0xff, 0x04);
+ reg_w(gspca_dev, 0x0e, 0x00);
reg_w(gspca_dev, 0x0f, brightness);
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
@@ -449,23 +520,41 @@ static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- if (sd->sensor == SENSOR_PAC7302)
+ if (sd->sensor == SENSOR_PAC7302) {
+ setbrightcont(gspca_dev);
return;
+ }
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x80, sd->contrast);
+ reg_w(gspca_dev, 0x10, sd->contrast);
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
- PDEBUG(D_CONF|D_STREAM, "contrast: %i", sd->contrast);
}
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- if (sd->sensor == SENSOR_PAC7302)
+ if (sd->sensor == SENSOR_PAC7302) {
+ int i, v;
+ static const int a[9] =
+ {217, -212, 0, -101, 170, -67, -38, -315, 355};
+ static const int b[9] =
+ {19, 106, 0, 19, 106, 1, 19, 106, 1};
+
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
+ reg_w(gspca_dev, 0x11, 0x01);
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
+ for (i = 0; i < 9; i++) {
+ v = a[i] * sd->colors / COLOR_MAX + b[i];
+ reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
+ reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
+ }
+ reg_w(gspca_dev, 0xdc, 0x01);
return;
+ }
reg_w(gspca_dev, 0xff, 0x01);
- reg_w(gspca_dev, 0x10, sd->colors);
+ reg_w(gspca_dev, 0x80, sd->colors);
/* load registers to sensor (Bit 0, auto clear) */
reg_w(gspca_dev, 0x11, 0x01);
PDEBUG(D_CONF|D_STREAM, "color: %i", sd->colors);
@@ -483,10 +572,23 @@ static void setautogain(struct gspca_dev *gspca_dev)
}
}
+/* this function is used by pac7302 only */
+static void sethvflip(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ __u8 data;
+
+ reg_w(gspca_dev, 0xff, 0x03); /* page 3 */
+ data = (sd->hflip ? 0x00 : 0x08)
+ | (sd->vflip ? 0x04 : 0x00);
+ reg_w(gspca_dev, 0x21, data);
+ reg_w(gspca_dev, 0x11, 0x01);
+}
+
/* this function is called at open time */
static int sd_open(struct gspca_dev *gspca_dev)
{
- reg_w(gspca_dev, 0x78, 0x00); /* Turn on LED */
+ reg_w(gspca_dev, 0x78, 0x44); /* Turn on LED */
return 0;
}
@@ -515,27 +617,24 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x08, 0x09);
reg_w(gspca_dev, 0x17, 0x20);
reg_w(gspca_dev, 0x1b, 0x00);
-/* reg_w(gspca_dev, 0x80, 0x69); */
reg_w(gspca_dev, 0x87, 0x10);
break;
case 1: /* 320x240 pac7311 */
reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x03);
+ reg_w(gspca_dev, 0x02, 0x07);
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x08, 0x09);
reg_w(gspca_dev, 0x17, 0x30);
-/* reg_w(gspca_dev, 0x80, 0x3f); */
reg_w(gspca_dev, 0x87, 0x11);
break;
case 0: /* 640x480 */
if (sd->sensor == SENSOR_PAC7302)
break;
reg_w(gspca_dev, 0xff, 0x04);
- reg_w(gspca_dev, 0x02, 0x03);
+ reg_w(gspca_dev, 0x02, 0x07);
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x08, 0x08);
reg_w(gspca_dev, 0x17, 0x00);
-/* reg_w(gspca_dev, 0x80, 0x1c); */
reg_w(gspca_dev, 0x87, 0x12);
break;
}
@@ -543,12 +642,13 @@ static void sd_start(struct gspca_dev *gspca_dev)
/* start stream */
reg_w(gspca_dev, 0xff, 0x01);
if (sd->sensor == SENSOR_PAC7302) {
+ sethvflip(gspca_dev);
reg_w(gspca_dev, 0x78, 0x01);
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x78, 0x01);
} else {
- reg_w(gspca_dev, 0x78, 0x04);
- reg_w(gspca_dev, 0x78, 0x05);
+ reg_w(gspca_dev, 0x78, 0x44);
+ reg_w(gspca_dev, 0x78, 0x45);
}
}
@@ -568,7 +668,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x2a, 0x0e);
reg_w(gspca_dev, 0xff, 0x01);
reg_w(gspca_dev, 0x3e, 0x20);
- reg_w(gspca_dev, 0x78, 0x04); /* Bit_0=start stream, Bit_7=LED */
+ reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
reg_w(gspca_dev, 0x78, 0x44); /* Bit_0=start stream, Bit_7=LED */
}
@@ -677,7 +777,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
if (sd->tosof > LUM_OFFSET)
sd->lum_sum += data[-LUM_OFFSET];
sd->tosof = 0;
- jpeg_put_header(gspca_dev, frame, 1, 0x21);
+ jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
}
for (i = 0; i < len; i++) {
@@ -697,7 +797,7 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
sd->tosof = -len;
break;
}
- jpeg_put_header(gspca_dev, frame, 1, 0x21);
+ jpeg_put_header(gspca_dev, frame, sd->qindex, 0x21);
break;
#if 0 /*fixme:test+*/
/* is there a start of frame ? */
@@ -715,7 +815,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
data += i + 7;
len -= i + 7;
i = 0;
- jpeg_put_header(gspca_dev, frame, 1, 0x21);
+ jpeg_put_header(gspca_dev, frame,
+ sd->qindex, 0x21);
break;
}
break;
@@ -798,6 +899,42 @@ static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
return 0;
}
+static int sd_sethflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->hflip = val;
+ if (gspca_dev->streaming)
+ sethvflip(gspca_dev);
+ return 0;
+}
+
+static int sd_gethflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->hflip;
+ return 0;
+}
+
+static int sd_setvflip(struct gspca_dev *gspca_dev, __s32 val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ sd->vflip = val;
+ if (gspca_dev->streaming)
+ sethvflip(gspca_dev);
+ return 0;
+}
+
+static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->vflip;
+ return 0;
+}
+
/* sub-driver description */
static struct sd_desc sd_desc = {
.name = MODULE_NAME,
@@ -839,6 +976,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/sonixb.c b/linux/drivers/media/video/gspca/sonixb.c
index 4d979fa39..afbb969ba 100644
--- a/linux/drivers/media/video/gspca/sonixb.c
+++ b/linux/drivers/media/video/gspca/sonixb.c
@@ -1264,6 +1264,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/sonixj.c b/linux/drivers/media/video/gspca/sonixj.c
index 2c76f02ce..217a31a0e 100644
--- a/linux/drivers/media/video/gspca/sonixj.c
+++ b/linux/drivers/media/video/gspca/sonixj.c
@@ -78,7 +78,8 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Brightness",
.minimum = 0,
- .maximum = 0xffff,
+#define BRIGHTNESS_MAX 0xffff
+ .maximum = BRIGHTNESS_MAX,
.step = 1,
#define BRIGHTNESS_DEF 0x7fff
.default_value = BRIGHTNESS_DEF,
@@ -92,7 +93,8 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
.minimum = 0,
- .maximum = 127,
+#define CONTRAST_MAX 127
+ .maximum = CONTRAST_MAX,
.step = 1,
#define CONTRAST_DEF 63
.default_value = CONTRAST_DEF,
@@ -106,9 +108,9 @@ static struct ctrl sd_ctrls[] = {
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Color",
.minimum = 0,
- .maximum = 255,
+ .maximum = 64,
.step = 1,
-#define COLOR_DEF 127
+#define COLOR_DEF 32
.default_value = COLOR_DEF,
},
.set = sd_setcolors,
@@ -133,7 +135,7 @@ static struct ctrl sd_ctrls[] = {
static struct v4l2_pix_format vga_mode[] = {
{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 8 + 590,
+ .sizeimage = 160 * 120 * 4 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 2},
{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -252,27 +254,20 @@ static const __u8 *sn_tb[] = {
sn_ov7660
};
-static const __u8 regsn20[] = {
+static const __u8 gamma_def[] = {
0x00, 0x2d, 0x46, 0x5a, 0x6c, 0x7c, 0x8b, 0x99,
0xa6, 0xb2, 0xbf, 0xca, 0xd5, 0xe0, 0xeb, 0xf5, 0xff
};
-static const __u8 regsn20_sn9c325[] = {
- 0x0a, 0x3a, 0x56, 0x6c, 0x7e, 0x8d, 0x9a, 0xa4,
- 0xaf, 0xbb, 0xc5, 0xcd, 0xd5, 0xde, 0xe8, 0xed, 0xf5
-};
static const __u8 reg84[] = {
0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe5, 0x0f,
0xe4, 0x0f, 0x38, 0x00, 0x3e, 0x00, 0xc3, 0x0f,
-/* 0x00, 0x00, 0x00, 0x00, 0x00 */
+#if 1
+ 0xf7, 0x0f, 0x00, 0x00, 0x00
+#else
0xf7, 0x0f, 0x0a, 0x00, 0x00
+#endif
};
-static const __u8 reg84_sn9c325[] = {
- 0x14, 0x00, 0x27, 0x00, 0x07, 0x00, 0xe4, 0x0f,
- 0xd3, 0x0f, 0x4b, 0x00, 0x48, 0x00, 0xc0, 0x0f,
- 0xf8, 0x0f, 0x00, 0x00, 0x00
-};
-
static const __u8 hv7131r_sensor_init[][8] = {
{0xC1, 0x11, 0x01, 0x08, 0x01, 0x00, 0x00, 0x10},
{0xB1, 0x11, 0x34, 0x17, 0x7F, 0x00, 0x00, 0x10},
@@ -423,7 +418,7 @@ static const __u8 ov7630_sensor_init[][8] = {
{0xa1, 0x21, 0x12, 0xc8, 0x00, 0x00, 0x00, 0x10},
/* win: delay 20ms */
{0xa1, 0x21, 0x12, 0x48, 0x00, 0x00, 0x00, 0x10},
-/* win: loop on 2 wwrite, 1 read */
+/* win: i2c_r from 00 to 80 */
{0xd1, 0x21, 0x03, 0x80, 0x10, 0x20, 0x80, 0x10},
{0xb1, 0x21, 0x0c, 0x20, 0x20, 0x00, 0x00, 0x10},
{0xd1, 0x21, 0x11, 0x00, 0x48, 0xc0, 0x00, 0x10},
@@ -458,9 +453,11 @@ static const __u8 ov7630_sensor_init[][8] = {
{0xa1, 0x21, 0x10, 0x32, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xb1, 0x21, 0x01, 0x80, 0x80, 0x00, 0x00, 0x10},
+/* */
{0xa1, 0x21, 0x11, 0x00, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x2a, 0x88, 0x00, 0x00, 0x00, 0x10},
{0xa1, 0x21, 0x2b, 0x34, 0x00, 0x00, 0x00, 0x10},
+/* */
{0xa1, 0x21, 0x10, 0x83, 0x00, 0x00, 0x00, 0x10},
{0xb1, 0x21, 0x01, 0x88, 0x70, 0x00, 0x00, 0x10},
{}
@@ -790,7 +787,11 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
static const __u8 regd4[] = {0x60, 0x00, 0x00};
reg_w1(gspca_dev, 0xf1, 0x00);
- reg_w1(gspca_dev, 0x01, 0x00); /*jfm was sn9c1xx[1] in v1*/
+#if 1
+ reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
+#else
+ reg_w1(gspca_dev, 0x01, 0x00); /*jfm: in some win traces*/
+#endif
/* configure gpio */
reg_w(gspca_dev, 0x01, &sn9c1xx[1], 2);
@@ -817,12 +818,13 @@ static int configure_gpio(struct gspca_dev *gspca_dev,
reg_w1(gspca_dev, 0x17, 0x64);
reg_w1(gspca_dev, 0x01, 0x42);
break;
-#if 0
+#if 1
/*jfm: from win trace */
case SENSOR_OV7630:
reg_w1(gspca_dev, 0x01, 0x61);
reg_w1(gspca_dev, 0x17, 0xe2);
reg_w1(gspca_dev, 0x01, 0x60);
+ reg_w1(gspca_dev, 0x01, 0x40);
break;
#endif
case SENSOR_OV7648:
@@ -898,9 +900,20 @@ static void ov7630_InitSensor(struct gspca_dev *gspca_dev)
{
int i = 0;
- i2c_w8(gspca_dev, ov7630_sensor_init[i]);
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 76 01 */
+ i++;
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 (RGB+SRST) */
+ i++;
+ msleep(20);
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
+ i++;
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 c8 */
i++;
msleep(20);
+ i2c_w8(gspca_dev, ov7630_sensor_init[i]); /* 12 48 */
+ i++;
+/*jfm:win i2c_r from 00 to 80*/
+
while (ov7630_sensor_init[i][0]) {
i2c_w8(gspca_dev, ov7630_sensor_init[i]);
i++;
@@ -1076,7 +1089,7 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
expo = 0x0001;
gainOm[3] = expo >> 2;
i2c_w8(gspca_dev, gainOm);
- reg_w1(gspca_dev, 0x96, expo >> 5);
+ reg_w1(gspca_dev, 0x96, (expo >> 5) & 0x1f);
PDEBUG(D_CONF, "set exposure %d", gainOm[3]);
break;
}
@@ -1084,6 +1097,28 @@ static unsigned int setexposure(struct gspca_dev *gspca_dev,
return expo;
}
+/* this function is used for sensors o76xx only */
+static void setbrightcont(struct gspca_dev *gspca_dev)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ unsigned val;
+ __u8 reg84_full[13];
+
+ memset(reg84_full, 0, sizeof reg84_full);
+ val = sd->contrast * 0x20 / CONTRAST_MAX + 0x10; /* 10..30 */
+ reg84_full[2] = val;
+ reg84_full[0] = (val + 1) / 2;
+ reg84_full[4] = (val + 1) / 5;
+ if (val > BRIGHTNESS_DEF)
+ val = (sd->brightness - BRIGHTNESS_DEF) * 0x20
+ / BRIGHTNESS_MAX;
+ else
+ val = 0;
+ reg84_full[10] = val; /* 00..1f */
+ reg_w(gspca_dev, 0x84, reg84_full, sizeof reg84_full);
+}
+
+/* sensor != ov76xx */
static void setbrightness(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1115,6 +1150,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x96, k2);
}
+/* sensor != ov76xx */
static void setcontrast(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -1131,15 +1167,18 @@ static void setcontrast(struct gspca_dev *gspca_dev)
static void setcolors(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- __u8 data;
- int colour;
+ __u8 blue, red;
- colour = sd->colors - 128;
- if (colour > 0)
- data = (colour + 32) & 0x7f; /* blue */
- else
- data = (-colour + 32) & 0x7f; /* red */
- reg_w1(gspca_dev, 0x05, data);
+ if (sd->colors >= 32) {
+ red = 32 + (sd->colors - 32) / 2;
+ blue = 64 - sd->colors;
+ } else {
+ red = sd->colors;
+ blue = 32 + (32 - sd->colors) / 2;
+ }
+ reg_w1(gspca_dev, 0x05, red);
+/* reg_w1(gspca_dev, 0x07, 32); */
+ reg_w1(gspca_dev, 0x06, blue);
}
static void setautogain(struct gspca_dev *gspca_dev)
@@ -1210,24 +1249,23 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x07, sn9c1xx[7]);
reg_w1(gspca_dev, 0x06, sn9c1xx[6]);
reg_w1(gspca_dev, 0x14, sn9c1xx[0x14]);
+ reg_w(gspca_dev, 0x20, gamma_def, sizeof gamma_def);
+ for (i = 0; i < 8; i++)
+ reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+#if 0
switch (sd->bridge) {
case BRIDGE_SN9C325:
- reg_w(gspca_dev, 0x20, regsn20_sn9c325,
- sizeof regsn20_sn9c325);
- for (i = 0; i < 8; i++)
- reg_w(gspca_dev, 0x84, reg84_sn9c325,
- sizeof reg84_sn9c325);
reg_w1(gspca_dev, 0x9a, 0x0a);
reg_w1(gspca_dev, 0x99, 0x60);
break;
default:
- reg_w(gspca_dev, 0x20, regsn20, sizeof regsn20);
- for (i = 0; i < 8; i++)
- reg_w(gspca_dev, 0x84, reg84, sizeof reg84);
+#endif
reg_w1(gspca_dev, 0x9a, 0x08);
reg_w1(gspca_dev, 0x99, 0x59);
+#if 0
break;
}
+#endif
mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
if (mode)
@@ -1259,7 +1297,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
case SENSOR_OV7630:
ov7630_InitSensor(gspca_dev);
reg17 = 0xe2;
- reg1 = 0x40;
+ reg1 = 0x44;
break;
case SENSOR_OV7648:
ov7648_InitSensor(gspca_dev);
@@ -1313,8 +1351,18 @@ static void sd_start(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x17, reg17);
reg_w1(gspca_dev, 0x01, reg1);
- setbrightness(gspca_dev);
- setcontrast(gspca_dev);
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setbrightness(gspca_dev);
+ setcontrast(gspca_dev);
+ break;
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
setautogain(gspca_dev);
}
@@ -1352,7 +1400,7 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
reg_w1(gspca_dev, 0x17, sn9c1xx[0x17]);
reg_w1(gspca_dev, 0x01, sn9c1xx[1]);
reg_w1(gspca_dev, 0x01, data);
- reg_w1(gspca_dev, 0xf1, 0x01);
+ reg_w1(gspca_dev, 0xf1, 0x00);
}
static void sd_stop0(struct gspca_dev *gspca_dev)
@@ -1450,72 +1498,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
}
-static unsigned int getexposure(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
- __u8 hexpo, mexpo, lexpo;
-
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x25);
- return (gspca_dev->usb_buf[0] << 16)
- | (gspca_dev->usb_buf[1] << 8)
- | gspca_dev->usb_buf[2];
- case SENSOR_MI0360:
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x09);
- return (gspca_dev->usb_buf[0] << 8)
- | gspca_dev->usb_buf[1];
- default:
-/* case SENSOR_MO4000: */
- i2c_r5(gspca_dev, 0x0e);
- hexpo = 0; /* gspca_dev->usb_buf[1] & 0x07; */
- mexpo = 0x40; /* gspca_dev->usb_buf[2] & 0xff; */
- lexpo = (gspca_dev->usb_buf[1] & 0x30) >> 4;
- PDEBUG(D_CONF, "exposure %d",
- (hexpo << 10) | (mexpo << 2) | lexpo);
- return (hexpo << 10) | (mexpo << 2) | lexpo;
-#if 0 /* keep */
-/*jfm: not called*/
-/* case SENSOR_OV7648: * jfm: is it ok for 7648? */
-/* case SENSOR_OV7660: */
- /* read sensor exposure */
- i2c_r5(gspca_dev, 0x04);
- hexpo = gspca_dev->usb_buf[3] & 0x2f;
- lexpo = gspca_dev->usb_buf[0] & 0x02;
- i2c_r5(gspca_dev, 0x08);
- mexpo = gspca_dev->usb_buf[2];
- return (hexpo << 10) | (mexpo << 2) | lexpo;
-#endif
- }
- /* not reached */
-}
-
-static void getbrightness(struct gspca_dev *gspca_dev)
-{
- struct sd *sd = (struct sd *) gspca_dev;
-
- /* hardcoded registers seem not readable */
- switch (sd->sensor) {
- case SENSOR_HV7131R:
- sd->brightness = getexposure(gspca_dev) >> 4;
- break;
- case SENSOR_MI0360:
- case SENSOR_MO4000:
- case SENSOR_OM6802:
- sd->brightness = getexposure(gspca_dev) << 4;
- break;
- }
-}
-
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
sd->brightness = val;
- if (gspca_dev->streaming)
- setbrightness(gspca_dev);
+ if (gspca_dev->streaming) {
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setbrightness(gspca_dev);
+ break;
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
+ }
return 0;
}
@@ -1523,7 +1523,6 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
{
struct sd *sd = (struct sd *) gspca_dev;
- getbrightness(gspca_dev);
*val = sd->brightness;
return 0;
}
@@ -1533,8 +1532,19 @@ static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
struct sd *sd = (struct sd *) gspca_dev;
sd->contrast = val;
- if (gspca_dev->streaming)
- setcontrast(gspca_dev);
+ if (gspca_dev->streaming) {
+ switch (sd->sensor) {
+ case SENSOR_HV7131R:
+ case SENSOR_MI0360:
+ case SENSOR_MO4000:
+ case SENSOR_OM6802:
+ setcontrast(gspca_dev);
+ break;
+ default: /* OV76xx */
+ setbrightcont(gspca_dev);
+ break;
+ }
+ }
return 0;
}
@@ -1662,6 +1672,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca500.c b/linux/drivers/media/video/gspca/spca500.c
index be88d30a3..2aff5af9a 100644
--- a/linux/drivers/media/video/gspca/spca500.c
+++ b/linux/drivers/media/video/gspca/spca500.c
@@ -1110,6 +1110,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca501.c b/linux/drivers/media/video/gspca/spca501.c
index f8df18e85..df657cb9d 100644
--- a/linux/drivers/media/video/gspca/spca501.c
+++ b/linux/drivers/media/video/gspca/spca501.c
@@ -2165,6 +2165,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca505.c b/linux/drivers/media/video/gspca/spca505.c
index 1cde4b34f..440e6853c 100644
--- a/linux/drivers/media/video/gspca/spca505.c
+++ b/linux/drivers/media/video/gspca/spca505.c
@@ -924,6 +924,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca506.c b/linux/drivers/media/video/gspca/spca506.c
index f622fa757..ae772488c 100644
--- a/linux/drivers/media/video/gspca/spca506.c
+++ b/linux/drivers/media/video/gspca/spca506.c
@@ -772,6 +772,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca508.c b/linux/drivers/media/video/gspca/spca508.c
index 52e2f7462..585468863 100644
--- a/linux/drivers/media/video/gspca/spca508.c
+++ b/linux/drivers/media/video/gspca/spca508.c
@@ -1705,6 +1705,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/spca561.c b/linux/drivers/media/video/gspca/spca561.c
index 075699433..d686b6bd7 100644
--- a/linux/drivers/media/video/gspca/spca561.c
+++ b/linux/drivers/media/video/gspca/spca561.c
@@ -38,9 +38,9 @@ struct sd {
#define CONTRAST_MAX 0x3fff
__u16 exposure; /* rev12a only */
-#define EXPOSURE_MIN 0x0120
-#define EXPOSURE_DEF 0x20ae
-#define EXPOSURE_MAX 0x5720
+#define EXPOSURE_MIN 0
+#define EXPOSURE_DEF 200
+#define EXPOSURE_MAX 762
__u8 brightness; /* rev72a only */
#define BRIGHTNESS_MIN 0
@@ -48,7 +48,7 @@ struct sd {
#define BRIGHTNESS_MAX 63
__u8 white; /* rev12a only */
-#define WHITE_MIN 0
+#define WHITE_MIN 1
#define WHITE_DEF 0x40
#define WHITE_MAX 0x7f
@@ -62,6 +62,9 @@ struct sd {
#define GAIN_DEF 0x24
#define GAIN_MAX 0x24
+#define EXPO12A_DEF 3
+ __u8 expo12a; /* expo/gain? for rev 12a */
+
__u8 chip_revision;
#define Rev012A 0
#define Rev072A 1
@@ -567,6 +570,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->exposure = EXPOSURE_DEF;
sd->autogain = AUTOGAIN_DEF;
sd->gain = GAIN_DEF;
+ sd->expo12a = EXPO12A_DEF;
return 0;
}
@@ -600,28 +604,11 @@ static void setcontrast(struct gspca_dev *gspca_dev)
break;
default: {
/* case Rev012A: { */
-#if 1
static const __u8 Reg8391[] =
{ 0x92, 0x30, 0x20, 0x00, 0x0c, 0x00, 0x00, 0x00 };
reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
-#else
- int expotimes;
- __u8 Reg8391[] =
- { 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00 };
-
-/*fixme: does not work..*/
- /* Write camera sensor settings */
- expotimes = sd->contrast >> 5;
- /* exposure is in 8309 2b, range 0120 - 5720 */
- Reg8391[0] = expotimes; /* exposure */
- Reg8391[1] = 0x18 | (expotimes >> 8);
- Reg8391[2] = sd->brightness; /* gain */
- /* gain in 8335, 2b range 0000 - 2400 */
- reg_w_buf(gspca_dev, 0x8391, Reg8391, 8);
- reg_w_buf(gspca_dev, 0x8390, Reg8391, 8);
-#endif
break;
}
}
@@ -635,17 +622,10 @@ static void setwhite(struct gspca_dev *gspca_dev)
__u8 reg8614, reg8616;
white = sd->white;
- if (sd->white == 0) {
- PDEBUG(D_CONF, "Discarding null whiteness");
- return;
- }
/* try to emulate MS-win as possible */
- if (white < 0x45)
- reg8616 = white;
- else
- reg8616 = 0x93 + (white >> 2);
- reg8614 = 0x28 + (white >> 4);
+ reg8616 = 0x90 - white * 5 / 8;
reg_w_val(gspca_dev->dev, 0x8616, reg8616);
+ reg8614 = 0x20 + white * 3 / 8;
reg_w_val(gspca_dev->dev, 0x8614, reg8614);
}
@@ -653,30 +633,34 @@ static void setwhite(struct gspca_dev *gspca_dev)
static void setexposure(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
+ int expo;
+ __u8 data[2];
- reg_w_val(dev, 0x8309, sd->gain);
+ expo = sd->exposure + 0x20a8; /* from test */
+ data[0] = expo;
+ data[1] = expo >> 8;
+ reg_w_buf(gspca_dev, 0x8309, data, 2);
}
/* rev 12a only */
static void setgain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- struct usb_device *dev = gspca_dev->dev;
+ __u8 data[2];
- reg_w_val(dev, 0x8335, sd->gain);
+ data[0] = sd->gain;
+ data[1] = 0;
+ reg_w_buf(gspca_dev, 0x8335, data, 2);
}
static void setautogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- if (sd->chip_revision == Rev072A) {
- if (sd->autogain)
- sd->ag_cnt = AG_CNT_START;
- else
- sd->ag_cnt = -1;
- }
+ if (sd->autogain)
+ sd->ag_cnt = AG_CNT_START;
+ else
+ sd->ag_cnt = -1;
}
static void sd_start_12a(struct gspca_dev *gspca_dev)
@@ -715,6 +699,7 @@ static void sd_start_12a(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev->dev, 0x850b, 0x03);
setcontrast(gspca_dev);
setwhite(gspca_dev);
+ setautogain(gspca_dev);
}
static void sd_start_72a(struct gspca_dev *gspca_dev)
{
@@ -744,12 +729,24 @@ static void sd_start_72a(struct gspca_dev *gspca_dev)
static void sd_stopN(struct gspca_dev *gspca_dev)
{
- reg_w_val(gspca_dev->dev, 0x8112, 0x20);
- reg_w_val(gspca_dev->dev, 0x8102, 0x00); /* white balance - new */
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->chip_revision == Rev012A) {
+ reg_w_val(gspca_dev->dev, 0x8112, 0x0e);
+ } else {
+ reg_w_val(gspca_dev->dev, 0x8112, 0x20);
+/* reg_w_val(gspca_dev->dev, 0x8102, 0x00); ?? */
+ }
}
static void sd_stop0(struct gspca_dev *gspca_dev)
{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ if (sd->chip_revision == Rev012A) {
+ reg_w_val(gspca_dev->dev, 0x8118, 0x29);
+ reg_w_val(gspca_dev->dev, 0x8114, 0x08);
+ }
}
/* this function is called at close time */
@@ -758,7 +755,6 @@ static void sd_close(struct gspca_dev *gspca_dev)
reg_w_val(gspca_dev->dev, 0x8114, 0);
}
-/* rev72a only */
static void do_autogain(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -770,6 +766,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
__u8 luma_mean = 110;
__u8 luma_delta = 20;
__u8 spring = 4;
+ __u8 reg8339[2];
if (sd->ag_cnt < 0)
return;
@@ -824,13 +821,16 @@ static void do_autogain(struct gspca_dev *gspca_dev)
}
break;
case Rev012A:
- /* sensor registers is access and memory mapped to 0x8300 */
- /* readind all 0x83xx block the sensor */
- /*
- * The data from the header seem wrong where is the luma
- * and chroma mean value
- * at the moment set exposure in contrast set
- */
+ reg_r(gspca_dev, 0x8330, 2);
+ if (gspca_dev->usb_buf[1] > 0x08) {
+ reg8339[0] = ++sd->expo12a;
+ reg8339[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ } else if (gspca_dev->usb_buf[1] < 0x02) {
+ reg8339[0] = --sd->expo12a;
+ reg8339[1] = 0;
+ reg_w_buf(gspca_dev, 0x8339, reg8339, 2);
+ }
break;
}
}
@@ -1198,6 +1198,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/stk014.c b/linux/drivers/media/video/gspca/stk014.c
index 16219cf6a..387a8cf2b 100644
--- a/linux/drivers/media/video/gspca/stk014.c
+++ b/linux/drivers/media/video/gspca/stk014.c
@@ -564,6 +564,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/sunplus.c b/linux/drivers/media/video/gspca/sunplus.c
index 8701b07c8..e1a7e53ba 100644
--- a/linux/drivers/media/video/gspca/sunplus.c
+++ b/linux/drivers/media/video/gspca/sunplus.c
@@ -1487,6 +1487,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/t613.c b/linux/drivers/media/video/gspca/t613.c
index 56b1dfa72..27bff51a0 100644
--- a/linux/drivers/media/video/gspca/t613.c
+++ b/linux/drivers/media/video/gspca/t613.c
@@ -30,7 +30,7 @@
#define MAX_GAMMA 0x10 /* 0 to 15 */
-#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_EFFECTS (V4L2_CID_PRIVATE_BASE + 0)
MODULE_AUTHOR("Leandro Costantino <le_costantino@pixartargentina.com.ar>");
MODULE_DESCRIPTION("GSPCA/T613 (JPEG Compliance) USB Camera Driver");
@@ -233,7 +233,7 @@ static char *effects_control[] = {
static struct v4l2_pix_format vga_mode_t16[] = {
{160, 120, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
.bytesperline = 160,
- .sizeimage = 160 * 120 * 3 / 8 + 590,
+ .sizeimage = 160 * 120 * 4 / 8 + 590,
.colorspace = V4L2_COLORSPACE_JPEG,
.priv = 4},
{176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
@@ -1037,6 +1037,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/tv8532.c b/linux/drivers/media/video/gspca/tv8532.c
index fcac077bb..c55dbe8ac 100644
--- a/linux/drivers/media/video/gspca/tv8532.c
+++ b/linux/drivers/media/video/gspca/tv8532.c
@@ -653,6 +653,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/vc032x.c b/linux/drivers/media/video/gspca/vc032x.c
index 0e23edb16..f37c63d6d 100644
--- a/linux/drivers/media/video/gspca/vc032x.c
+++ b/linux/drivers/media/video/gspca/vc032x.c
@@ -1971,6 +1971,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
/* -- module insert / remove -- */
diff --git a/linux/drivers/media/video/gspca/zc3xx.c b/linux/drivers/media/video/gspca/zc3xx.c
index 468b01b8f..a3f109ac4 100644
--- a/linux/drivers/media/video/gspca/zc3xx.c
+++ b/linux/drivers/media/video/gspca/zc3xx.c
@@ -70,6 +70,10 @@ struct sd {
unsigned short chip_revision;
};
+#define DRIVER_INFO(sensor, flags) .driver_info = ((sensor) << 8) | (flags)
+#define DRIVER_INFO_GET_SENSOR(driver_info) ((driver_info) >> 8)
+#define DRIVER_INFO_GET_FLAGS(driver_info) ((driver_info) & 0xff)
+
/* V4L2 controls supported by the driver */
static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
@@ -7020,7 +7024,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
/* define some sensors from the vendor/product */
sd->sharpness = 2;
- sd->sensor = id->driver_info;
+ sd->sensor = DRIVER_INFO_GET_SENSOR(id->driver_info);
+ gspca_dev->flags = DRIVER_INFO_GET_FLAGS(id->driver_info);
sensor = zcxx_probeSensor(gspca_dev);
if (sensor >= 0)
PDEBUG(D_PROBE, "probe sensor -> %02x", sensor);
@@ -7517,19 +7522,19 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x041e, 0x041e)},
#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x041e, 0x4017)},
- {USB_DEVICE(0x041e, 0x401c), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x041e, 0x401c), DRIVER_INFO(SENSOR_PAS106, 0)},
{USB_DEVICE(0x041e, 0x401e)},
{USB_DEVICE(0x041e, 0x401f)},
#endif
{USB_DEVICE(0x041e, 0x4029)},
#ifndef CONFIG_USB_ZC0301
- {USB_DEVICE(0x041e, 0x4034), .driver_info = SENSOR_PAS106},
- {USB_DEVICE(0x041e, 0x4035), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x041e, 0x4034), DRIVER_INFO(SENSOR_PAS106, 0)},
+ {USB_DEVICE(0x041e, 0x4035), DRIVER_INFO(SENSOR_PAS106, 0)},
{USB_DEVICE(0x041e, 0x4036)},
{USB_DEVICE(0x041e, 0x403a)},
#endif
- {USB_DEVICE(0x041e, 0x4051), .driver_info = SENSOR_TAS5130C_VF0250},
- {USB_DEVICE(0x041e, 0x4053), .driver_info = SENSOR_TAS5130C_VF0250},
+ {USB_DEVICE(0x041e, 0x4051), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)},
+ {USB_DEVICE(0x041e, 0x4053), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)},
#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x0458, 0x7007)},
{USB_DEVICE(0x0458, 0x700c)},
@@ -7555,11 +7560,13 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x046d, 0x08d9)},
{USB_DEVICE(0x046d, 0x08d8)},
{USB_DEVICE(0x046d, 0x08da)},
- {USB_DEVICE(0x046d, 0x08dd), .driver_info = SENSOR_MC501CB},
- {USB_DEVICE(0x0471, 0x0325), .driver_info = SENSOR_PAS106},
- {USB_DEVICE(0x0471, 0x0326), .driver_info = SENSOR_PAS106},
- {USB_DEVICE(0x0471, 0x032d), .driver_info = SENSOR_PAS106},
- {USB_DEVICE(0x0471, 0x032e), .driver_info = SENSOR_PAS106},
+ {USB_DEVICE(0x046d, 0x08dd), DRIVER_INFO(SENSOR_MC501CB, 0)},
+ {USB_DEVICE(0x0471, 0x0325), DRIVER_INFO(SENSOR_PAS106,
+ GSPCA_SENSOR_UPSIDE_DOWN_FLAG)},
+ {USB_DEVICE(0x0471, 0x0326), DRIVER_INFO(SENSOR_PAS106,
+ GSPCA_SENSOR_UPSIDE_DOWN_FLAG)},
+ {USB_DEVICE(0x0471, 0x032d), DRIVER_INFO(SENSOR_PAS106, 0)},
+ {USB_DEVICE(0x0471, 0x032e), DRIVER_INFO(SENSOR_PAS106, 0)},
{USB_DEVICE(0x055f, 0xc005)},
#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x055f, 0xd003)},
@@ -7571,7 +7578,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x0ac8, 0x301b)},
{USB_DEVICE(0x0ac8, 0x303b)},
#endif
- {USB_DEVICE(0x0ac8, 0x305b), .driver_info = SENSOR_TAS5130C_VF0250},
+ {USB_DEVICE(0x0ac8, 0x305b), DRIVER_INFO(SENSOR_TAS5130C_VF0250, 0)},
#ifndef CONFIG_USB_ZC0301
{USB_DEVICE(0x0ac8, 0x307b)},
{USB_DEVICE(0x10fd, 0x0128)},
@@ -7596,6 +7603,10 @@ static struct usb_driver sd_driver = {
.id_table = device_table,
.probe = sd_probe,
.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+ .suspend = gspca_suspend,
+ .resume = gspca_resume,
+#endif
};
static int __init sd_mod_init(void)
diff --git a/linux/include/linux/videodev2.h b/linux/include/linux/videodev2.h
index a79fc1584..4fd194ce3 100644
--- a/linux/include/linux/videodev2.h
+++ b/linux/include/linux/videodev2.h
@@ -261,6 +261,11 @@ struct v4l2_capability {
#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */
+/* This flags gets set if the "sensor" is known to be upside down and this can
+ *not* be fixed using v4l2 flipx/y controls. Note that absence of this flag
+ is not a guarantee for the image not being upside down. */
+#define V4L2_CAP_SENSOR_UPSIDE_DOWN 0x10000000
+
/*
* V I D E O I M A G E F O R M A T
*/