aboutsummaryrefslogtreecommitdiffstats
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 d02aa5c8472a..4473f0fb8b73 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -22,7 +22,6 @@
22#define MODULE_NAME "zc3xx" 22#define MODULE_NAME "zc3xx"
23 23
24#include <linux/input.h> 24#include <linux/input.h>
25#include <linux/slab.h>
26#include "gspca.h" 25#include "gspca.h"
27#include "jpeg.h" 26#include "jpeg.h"
28 27
@@ -40,15 +39,16 @@ static int force_sensor = -1;
40struct sd { 39struct sd {
41 struct gspca_dev gspca_dev; /* !! must be the first item */ 40 struct gspca_dev gspca_dev; /* !! must be the first item */
42 41
42 u8 brightness;
43 u8 contrast; 43 u8 contrast;
44 u8 gamma; 44 u8 gamma;
45 u8 autogain; 45 u8 autogain;
46 u8 lightfreq; 46 u8 lightfreq;
47 u8 sharpness; 47 u8 sharpness;
48 u8 quality; /* image quality */ 48 u8 quality; /* image quality */
49#define QUALITY_MIN 40 49#define QUALITY_MIN 50
50#define QUALITY_MAX 60 50#define QUALITY_MAX 80
51#define QUALITY_DEF 50 51#define QUALITY_DEF 70
52 52
53 u8 sensor; /* Type of image sensor chip */ 53 u8 sensor; /* Type of image sensor chip */
54/* !! values used in different tables */ 54/* !! values used in different tables */
@@ -75,10 +75,12 @@ struct sd {
75#define SENSOR_MAX 19 75#define SENSOR_MAX 19
76 unsigned short chip_revision; 76 unsigned short chip_revision;
77 77
78 u8 *jpeg_hdr; 78 u8 jpeg_hdr[JPEG_HDR_SZ];
79}; 79};
80 80
81/* V4L2 controls supported by the driver */ 81/* V4L2 controls supported by the driver */
82static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
82static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); 84static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val);
83static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); 85static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val);
84static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); 86static 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);
93static const struct ctrl sd_ctrls[] = { 95static const struct ctrl sd_ctrls[] = {
94 { 96 {
95 { 97 {
98 .id = V4L2_CID_BRIGHTNESS,
99 .type = V4L2_CTRL_TYPE_INTEGER,
100 .name = "Brightness",
101 .minimum = 0,
102 .maximum = 255,
103 .step = 1,
104#define BRIGHTNESS_DEF 128
105 .default_value = BRIGHTNESS_DEF,
106 },
107 .set = sd_setbrightness,
108 .get = sd_getbrightness,
109 },
110 {
111 {
96 .id = V4L2_CID_CONTRAST, 112 .id = V4L2_CID_CONTRAST,
97 .type = V4L2_CTRL_TYPE_INTEGER, 113 .type = V4L2_CTRL_TYPE_INTEGER,
98 .name = "Contrast", 114 .name = "Contrast",
@@ -132,7 +148,7 @@ static const struct ctrl sd_ctrls[] = {
132 .set = sd_setautogain, 148 .set = sd_setautogain,
133 .get = sd_getautogain, 149 .get = sd_getautogain,
134 }, 150 },
135#define LIGHTFREQ_IDX 3 151#define LIGHTFREQ_IDX 4
136 { 152 {
137 { 153 {
138 .id = V4L2_CID_POWER_LINE_FREQUENCY, 154 .id = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -6011,9 +6027,12 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6011 struct sd *sd = (struct sd *) gspca_dev; 6027 struct sd *sd = (struct sd *) gspca_dev;
6012 struct usb_device *dev = gspca_dev->dev; 6028 struct usb_device *dev = gspca_dev->dev;
6013 const u8 *Tgamma; 6029 const u8 *Tgamma;
6014 int g, i, k, adj, gp; 6030 int g, i, brightness, contrast, adj, gp1, gp2;
6015 u8 gr[16]; 6031 u8 gr[16];
6016 static const u8 delta_tb[16] = /* delta for contrast */ 6032 static const u8 delta_b[16] = /* delta for brightness */
6033 {0x50, 0x38, 0x2d, 0x28, 0x24, 0x21, 0x1e, 0x1d,
6034 0x1d, 0x1b, 0x1b, 0x1b, 0x19, 0x18, 0x18, 0x18};
6035 static const u8 delta_c[16] = /* delta for contrast */
6017 {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06, 6036 {0x2c, 0x1a, 0x12, 0x0c, 0x0a, 0x06, 0x06, 0x06,
6018 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02}; 6037 0x04, 0x06, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02};
6019 static const u8 gamma_tb[6][16] = { 6038 static const u8 gamma_tb[6][16] = {
@@ -6033,30 +6052,30 @@ static void setcontrast(struct gspca_dev *gspca_dev)
6033 6052
6034 Tgamma = gamma_tb[sd->gamma - 1]; 6053 Tgamma = gamma_tb[sd->gamma - 1];
6035 6054
6036 k = ((int) sd->contrast - 128); /* -128 / 128 */ 6055 contrast = ((int) sd->contrast - 128); /* -128 / 127 */
6056 brightness = ((int) sd->brightness - 128); /* -128 / 92 */
6037 adj = 0; 6057 adj = 0;
6038 gp = 0; 6058 gp1 = gp2 = 0;
6039 for (i = 0; i < 16; i++) { 6059 for (i = 0; i < 16; i++) {
6040 g = Tgamma[i] - delta_tb[i] * k / 256 - adj / 2; 6060 g = Tgamma[i] + delta_b[i] * brightness / 256
6061 - delta_c[i] * contrast / 256 - adj / 2;
6041 if (g > 0xff) 6062 if (g > 0xff)
6042 g = 0xff; 6063 g = 0xff;
6043 else if (g < 0) 6064 else if (g < 0)
6044 g = 0; 6065 g = 0;
6045 reg_w(dev, g, 0x0120 + i); /* gamma */ 6066 reg_w(dev, g, 0x0120 + i); /* gamma */
6046 if (k > 0) 6067 if (contrast > 0)
6047 adj--; 6068 adj--;
6048 else 6069 else if (contrast < 0)
6049 adj++; 6070 adj++;
6050 6071 if (i > 1)
6051 if (i != 0) { 6072 gr[i - 1] = (g - gp2) / 2;
6052 if (gp == 0) 6073 else if (i != 0)
6053 gr[i - 1] = 0; 6074 gr[0] = gp1 == 0 ? 0 : (g - gp1);
6054 else 6075 gp2 = gp1;
6055 gr[i - 1] = g - gp; 6076 gp1 = g;
6056 }
6057 gp = g;
6058 } 6077 }
6059 gr[15] = gr[14] / 2; 6078 gr[15] = (0xff - gp2) / 2;
6060 for (i = 0; i < 16; i++) 6079 for (i = 0; i < 16; i++)
6061 reg_w(dev, gr[i], 0x0130 + i); /* gradient */ 6080 reg_w(dev, gr[i], 0x0130 + i); /* gradient */
6062} 6081}
@@ -6744,6 +6763,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
6744 cam->nmodes = ARRAY_SIZE(broken_vga_mode); 6763 cam->nmodes = ARRAY_SIZE(broken_vga_mode);
6745 break; 6764 break;
6746 } 6765 }
6766 sd->brightness = BRIGHTNESS_DEF;
6747 sd->contrast = CONTRAST_DEF; 6767 sd->contrast = CONTRAST_DEF;
6748 sd->gamma = gamma[sd->sensor]; 6768 sd->gamma = gamma[sd->sensor];
6749 sd->autogain = AUTOGAIN_DEF; 6769 sd->autogain = AUTOGAIN_DEF;
@@ -6798,9 +6818,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
6798 }; 6818 };
6799 6819
6800 /* create the JPEG header */ 6820 /* create the JPEG header */
6801 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
6802 if (!sd->jpeg_hdr)
6803 return -ENOMEM;
6804 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, 6821 jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
6805 0x21); /* JPEG 422 */ 6822 0x21); /* JPEG 422 */
6806 jpeg_set_qual(sd->jpeg_hdr, sd->quality); 6823 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
@@ -6918,10 +6935,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
6918 reg_w(dev, 0x00, 0x0007); /* (from win traces) */ 6935 reg_w(dev, 0x00, 0x0007); /* (from win traces) */
6919 reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING); 6936 reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
6920 break; 6937 break;
6921 case SENSOR_PAS202B:
6922 reg_w(dev, 0x32, 0x0007); /* (from win traces) */
6923 reg_w(dev, 0x02, ZC3XX_R008_CLOCKSETTING);
6924 break;
6925 } 6938 }
6926 return 0; 6939 return 0;
6927} 6940}
@@ -6931,7 +6944,6 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
6931{ 6944{
6932 struct sd *sd = (struct sd *) gspca_dev; 6945 struct sd *sd = (struct sd *) gspca_dev;
6933 6946
6934 kfree(sd->jpeg_hdr);
6935 if (!gspca_dev->present) 6947 if (!gspca_dev->present)
6936 return; 6948 return;
6937 send_unknown(gspca_dev->dev, sd->sensor); 6949 send_unknown(gspca_dev->dev, sd->sensor);
@@ -6962,6 +6974,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
6962 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 6974 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6963} 6975}
6964 6976
6977static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
6978{
6979 struct sd *sd = (struct sd *) gspca_dev;
6980
6981 sd->brightness = val;
6982 if (gspca_dev->streaming)
6983 setcontrast(gspca_dev);
6984 return 0;
6985}
6986
6987static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
6988{
6989 struct sd *sd = (struct sd *) gspca_dev;
6990
6991 *val = sd->brightness;
6992 return 0;
6993}
6994
6965static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) 6995static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val)
6966{ 6996{
6967 struct sd *sd = (struct sd *) gspca_dev; 6997 struct sd *sd = (struct sd *) gspca_dev;
@@ -7163,9 +7193,7 @@ static const __devinitdata struct usb_device_id device_table[] = {
7163 {USB_DEVICE(0x046d, 0x08aa)}, 7193 {USB_DEVICE(0x046d, 0x08aa)},
7164 {USB_DEVICE(0x046d, 0x08ac)}, 7194 {USB_DEVICE(0x046d, 0x08ac)},
7165 {USB_DEVICE(0x046d, 0x08ad)}, 7195 {USB_DEVICE(0x046d, 0x08ad)},
7166#if !defined CONFIG_USB_ZC0301 && !defined CONFIG_USB_ZC0301_MODULE
7167 {USB_DEVICE(0x046d, 0x08ae)}, 7196 {USB_DEVICE(0x046d, 0x08ae)},
7168#endif
7169 {USB_DEVICE(0x046d, 0x08af)}, 7197 {USB_DEVICE(0x046d, 0x08af)},
7170 {USB_DEVICE(0x046d, 0x08b9)}, 7198 {USB_DEVICE(0x046d, 0x08b9)},
7171 {USB_DEVICE(0x046d, 0x08d7)}, 7199 {USB_DEVICE(0x046d, 0x08d7)},