aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/gspca/zc3xx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca/zc3xx.c')
-rw-r--r--drivers/media/video/gspca/zc3xx.c92
1 files changed, 60 insertions, 32 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index d02aa5c8472..4473f0fb8b7 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -22,7 +22,6 @@
#define MODULE_NAME "zc3xx"
#include <linux/input.h>
-#include <linux/slab.h>
#include "gspca.h"
#include "jpeg.h"
@@ -40,15 +39,16 @@ static int force_sensor = -1;
struct sd {
struct gspca_dev gspca_dev; /* !! must be the first item */
+ u8 brightness;
u8 contrast;
u8 gamma;
u8 autogain;
u8 lightfreq;
u8 sharpness;
u8 quality; /* image quality */
-#define QUALITY_MIN 40
-#define QUALITY_MAX 60
-#define QUALITY_DEF 50
+#define QUALITY_MIN 50
+#define QUALITY_MAX 80
+#define QUALITY_DEF 70
u8 sensor; /* Type of image sensor chip */
/* !! values used in different tables */
@@ -75,10 +75,12 @@ struct sd {
#define SENSOR_MAX 19
unsigned short chip_revision;
- u8 *jpeg_hdr;
+ u8 jpeg_hdr[JPEG_HDR_SZ];
};
/* 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);
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
@@ -93,6 +95,20 @@ static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val);
static const struct ctrl sd_ctrls[] = {
{
{
+ .id = V4L2_CID_BRIGHTNESS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Brightness",
+ .minimum = 0,
+ .maximum = 255,
+ .step = 1,
+#define BRIGHTNESS_DEF 128
+ .default_value = BRIGHTNESS_DEF,
+ },
+ .set = sd_setbrightness,
+ .get = sd_getbrightness,
+ },
+ {
+ {
.id = V4L2_CID_CONTRAST,
.type = V4L2_CTRL_TYPE_INTEGER,
.name = "Contrast",
@@ -132,7 +148,7 @@ static const struct ctrl sd_ctrls[] = {
.set = sd_setautogain,
.get = sd_getautogain,
},
-#define LIGHTFREQ_IDX 3
+#define LIGHTFREQ_IDX 4
{
{
.id = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -6011,9 +6027,12 @@ static void setcontrast(struct gspca_dev *gspca_dev)
struct sd *sd = (struct sd *) gspca_dev;
struct usb_device *dev = gspca_dev->dev;
const u8 *Tgamma;
- int g, i, k, adj, gp;
+ int g, i, brightness, contrast, adj, gp1, gp2;
u8 gr[16];
- static const u8 delta_tb[16] = /* delta for contrast */
+ static const u8 delta_b[16] = /* delta for brightness */
+ {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
+ 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
+ static const u8 delta_c[16] = /* delta for contrast */
{0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
static const u8 gamma_tb[6][16] = {
@@ -6033,30 +6052,30 @@ static void setcontrast(struct gspca_dev *gspca_dev)
Tgamma = gamma_tb[sd->gamma - 1];
- k = ((int) sd->contrast - 128); /* -128 / 128 */
+ contrast = ((int) sd->contrast - 128); /* -128 / 127 */
+ brightness = ((int) sd->brightness - 128); /* -128 / 92 */
adj = 0;
- gp = 0;
+ gp1 = gp2 = 0;
for (i = 0; i < 16; i++) {
- g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2;
+ g = Tgamma[i] + delta_b[i] * brightness / 256
+ - delta_c[i] * contrast / 256 - adj / 2;
if (g > 0xff)
g = 0xff;
else if (g < 0)
g = 0;
reg_w(dev, g, 0x0120 + i); /* gamma */
- if (k > 0)
+ if (contrast > 0)
adj--;
- else
+ else if (contrast < 0)
adj++;
-
- if (i != 0) {
- if (gp == 0)
- gr[i - 1] = 0;
- else
- gr[i - 1] = g - gp;
- }
- gp = g;
+ if (i > 1)
+ gr[i - 1] = (g - gp2) / 2;
+ else if (i != 0)
+ gr[0] = gp1 == 0 ? 0 : (g - gp1);
+ gp2 = gp1;
+ gp1 = g;
}
- gr[15] = gr[14] / 2;
+ gr[15] = (0xff - gp2) / 2;
for (i = 0; i < 16; i++)
reg_w(dev, gr[i], 0x0130 + i); /* gradient */
}
@@ -6744,6 +6763,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->nmodes = ARRAY_SIZE(broken_vga_mode);
break;
}
+ sd->brightness = BRIGHTNESS_DEF;
sd->contrast = CONTRAST_DEF;
sd->gamma = gamma[sd->sensor];
sd->autogain = AUTOGAIN_DEF;
@@ -6798,9 +6818,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
};
/* create the JPEG header */
- sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
- if (!sd->jpeg_hdr)
- return -ENOMEM;
jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
0x21); /* JPEG 422 */
jpeg_set_qual(sd->jpeg_hdr, sd->quality);
@@ -6918,10 +6935,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
reg_w(dev, 0x00, 0x0007); /* (from win traces) */
reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
break;
- case SENSOR_PAS202B:
- reg_w(dev, 0x32, 0x0007); /* (from win traces) */
- reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
- break;
}
return 0;
}
@@ -6931,7 +6944,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
{
struct sd *sd = (struct sd *) gspca_dev;
- kfree(sd->jpeg_hdr);
if (!gspca_dev->present)
return;
send_unknown(gspca_dev->dev, sd->sensor);
@@ -6962,6 +6974,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
}
+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)
+ setcontrast(gspca_dev);
+ return 0;
+}
+
+static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+
+ *val = sd->brightness;
+ return 0;
+}
+
static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -7163,9 +7193,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
{USB_DEVICE(0x046d, 0x08aa)},
{USB_DEVICE(0x046d, 0x08ac)},
{USB_DEVICE(0x046d, 0x08ad)},
-#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
{USB_DEVICE(0x046d, 0x08ae)},
-#endif
{USB_DEVICE(0x046d, 0x08af)},
{USB_DEVICE(0x046d, 0x08b9)},
{USB_DEVICE(0x046d, 0x08d7)},