aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/gspca
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/gspca')
-rw-r--r--drivers/media/video/gspca/zc3xx.c76
1 files changed, 69 insertions, 7 deletions
diff --git a/drivers/media/video/gspca/zc3xx.c b/drivers/media/video/gspca/zc3xx.c
index 6dcb1cf11b5..fa164e861cd 100644
--- a/drivers/media/video/gspca/zc3xx.c
+++ b/drivers/media/video/gspca/zc3xx.c
@@ -39,6 +39,7 @@ static int force_sensor = -1;
39enum e_ctrl { 39enum e_ctrl {
40 BRIGHTNESS, 40 BRIGHTNESS,
41 CONTRAST, 41 CONTRAST,
42 EXPOSURE,
42 GAMMA, 43 GAMMA,
43 AUTOGAIN, 44 AUTOGAIN,
44 LIGHTFREQ, 45 LIGHTFREQ,
@@ -46,6 +47,8 @@ enum e_ctrl {
46 NCTRLS /* number of controls */ 47 NCTRLS /* number of controls */
47}; 48};
48 49
50#define AUTOGAIN_DEF 1
51
49/* specific webcam descriptor */ 52/* specific webcam descriptor */
50struct sd { 53struct sd {
51 struct gspca_dev gspca_dev; /* !! must be the first item */ 54 struct gspca_dev gspca_dev; /* !! must be the first item */
@@ -92,7 +95,8 @@ enum sensors {
92 95
93/* V4L2 controls supported by the driver */ 96/* V4L2 controls supported by the driver */
94static void setcontrast(struct gspca_dev *gspca_dev); 97static void setcontrast(struct gspca_dev *gspca_dev);
95static void setautogain(struct gspca_dev *gspca_dev); 98static void setexposure(struct gspca_dev *gspca_dev);
99static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
96static void setlightfreq(struct gspca_dev *gspca_dev); 100static void setlightfreq(struct gspca_dev *gspca_dev);
97static void setsharpness(struct gspca_dev *gspca_dev); 101static void setsharpness(struct gspca_dev *gspca_dev);
98 102
@@ -121,6 +125,18 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
121 }, 125 },
122 .set_control = setcontrast 126 .set_control = setcontrast
123 }, 127 },
128[EXPOSURE] = {
129 {
130 .id = V4L2_CID_EXPOSURE,
131 .type = V4L2_CTRL_TYPE_INTEGER,
132 .name = "Exposure",
133 .minimum = 0x30d,
134 .maximum = 0x493e,
135 .step = 1,
136 .default_value = 0x927
137 },
138 .set_control = setexposure
139 },
124[GAMMA] = { 140[GAMMA] = {
125 { 141 {
126 .id = V4L2_CID_GAMMA, 142 .id = V4L2_CID_GAMMA,
@@ -141,9 +157,10 @@ static const struct ctrl sd_ctrls[NCTRLS] = {
141 .minimum = 0, 157 .minimum = 0,
142 .maximum = 1, 158 .maximum = 1,
143 .step = 1, 159 .step = 1,
144 .default_value = 1, 160 .default_value = AUTOGAIN_DEF,
161 .flags = V4L2_CTRL_FLAG_UPDATE
145 }, 162 },
146 .set_control = setautogain 163 .set = sd_setautogain
147 }, 164 },
148[LIGHTFREQ] = { 165[LIGHTFREQ] = {
149 { 166 {
@@ -5926,6 +5943,26 @@ static void setcontrast(struct gspca_dev *gspca_dev)
5926 reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */ 5943 reg_w(gspca_dev, gr[i], 0x0130 + i); /* gradient */
5927} 5944}
5928 5945
5946static void getexposure(struct gspca_dev *gspca_dev)
5947{
5948 struct sd *sd = (struct sd *) gspca_dev;
5949
5950 sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9)
5951 | (i2c_read(gspca_dev, 0x26) << 1)
5952 | (i2c_read(gspca_dev, 0x27) >> 7);
5953}
5954
5955static void setexposure(struct gspca_dev *gspca_dev)
5956{
5957 struct sd *sd = (struct sd *) gspca_dev;
5958 int val;
5959
5960 val = sd->ctrls[EXPOSURE].val;
5961 i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
5962 i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
5963 i2c_write(gspca_dev, 0x27, val << 7, 0x00);
5964}
5965
5929static void setquality(struct gspca_dev *gspca_dev) 5966static void setquality(struct gspca_dev *gspca_dev)
5930{ 5967{
5931 struct sd *sd = (struct sd *) gspca_dev; 5968 struct sd *sd = (struct sd *) gspca_dev;
@@ -6623,10 +6660,19 @@ static int sd_init(struct gspca_dev *gspca_dev)
6623 sd->ctrls[GAMMA].def = gamma[sd->sensor]; 6660 sd->ctrls[GAMMA].def = gamma[sd->sensor];
6624 6661
6625 switch (sd->sensor) { 6662 switch (sd->sensor) {
6663 case SENSOR_HV7131R:
6664 break;
6626 case SENSOR_OV7630C: 6665 case SENSOR_OV7630C:
6627 gspca_dev->ctrl_dis = (1 << LIGHTFREQ); 6666 gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE);
6667 break;
6668 default:
6669 gspca_dev->ctrl_dis = (1 << EXPOSURE);
6628 break; 6670 break;
6629 } 6671 }
6672#if AUTOGAIN_DEF
6673 if (sd->ctrls[AUTOGAIN].val)
6674 gspca_dev->ctrl_inac = (1 << EXPOSURE);
6675#endif
6630 6676
6631 /* switch off the led */ 6677 /* switch off the led */
6632 reg_w(gspca_dev, 0x01, 0x0000); 6678 reg_w(gspca_dev, 0x01, 0x0000);
@@ -6772,9 +6818,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
6772 reg_w(gspca_dev, 0x40, 0x0117); 6818 reg_w(gspca_dev, 0x40, 0x0117);
6773 break; 6819 break;
6774 case SENSOR_HV7131R: 6820 case SENSOR_HV7131R:
6775 i2c_write(gspca_dev, 0x25, 0x04, 0x00); /* exposure */ 6821 if (!sd->ctrls[AUTOGAIN].val)
6776 i2c_write(gspca_dev, 0x26, 0x93, 0x00); 6822 setexposure(gspca_dev);
6777 i2c_write(gspca_dev, 0x27, 0xe0, 0x00);
6778 reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN); 6823 reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
6779 break; 6824 break;
6780 case SENSOR_GC0305: 6825 case SENSOR_GC0305:
@@ -6852,6 +6897,23 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
6852 gspca_frame_add(gspca_dev, INTER_PACKET, data, len); 6897 gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
6853} 6898}
6854 6899
6900static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
6901{
6902 struct sd *sd = (struct sd *) gspca_dev;
6903
6904 sd->ctrls[AUTOGAIN].val = val;
6905 if (val) {
6906 gspca_dev->ctrl_inac |= (1 << EXPOSURE);
6907 } else {
6908 gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
6909 if (gspca_dev->streaming)
6910 getexposure(gspca_dev);
6911 }
6912 if (gspca_dev->streaming)
6913 setautogain(gspca_dev);
6914 return gspca_dev->usb_err;
6915}
6916
6855static int sd_querymenu(struct gspca_dev *gspca_dev, 6917static int sd_querymenu(struct gspca_dev *gspca_dev,
6856 struct v4l2_querymenu *menu) 6918 struct v4l2_querymenu *menu)
6857{ 6919{