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/se401.c184
1 files changed, 73 insertions, 111 deletions
diff --git a/drivers/media/video/gspca/se401.c b/drivers/media/video/gspca/se401.c
index bb70092c2229..17e7f89a1122 100644
--- a/drivers/media/video/gspca/se401.c
+++ b/drivers/media/video/gspca/se401.c
@@ -45,15 +45,6 @@ MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
45MODULE_DESCRIPTION("Endpoints se401"); 45MODULE_DESCRIPTION("Endpoints se401");
46MODULE_LICENSE("GPL"); 46MODULE_LICENSE("GPL");
47 47
48/* controls */
49enum e_ctrl {
50 BRIGHTNESS,
51 GAIN,
52 EXPOSURE,
53 FREQ,
54 NCTRL /* number of controls */
55};
56
57/* exposure change state machine states */ 48/* exposure change state machine states */
58enum { 49enum {
59 EXPO_CHANGED, 50 EXPO_CHANGED,
@@ -64,7 +55,11 @@ enum {
64/* specific webcam descriptor */ 55/* specific webcam descriptor */
65struct sd { 56struct sd {
66 struct gspca_dev gspca_dev; /* !! must be the first item */ 57 struct gspca_dev gspca_dev; /* !! must be the first item */
67 struct gspca_ctrl ctrls[NCTRL]; 58 struct { /* exposure/freq control cluster */
59 struct v4l2_ctrl *exposure;
60 struct v4l2_ctrl *freq;
61 };
62 bool has_brightness;
68 struct v4l2_pix_format fmts[MAX_MODES]; 63 struct v4l2_pix_format fmts[MAX_MODES];
69 int pixels_read; 64 int pixels_read;
70 int packet_read; 65 int packet_read;
@@ -77,60 +72,6 @@ struct sd {
77 int expo_change_state; 72 int expo_change_state;
78}; 73};
79 74
80static void setbrightness(struct gspca_dev *gspca_dev);
81static void setgain(struct gspca_dev *gspca_dev);
82static void setexposure(struct gspca_dev *gspca_dev);
83
84static const struct ctrl sd_ctrls[NCTRL] = {
85[BRIGHTNESS] = {
86 {
87 .id = V4L2_CID_BRIGHTNESS,
88 .type = V4L2_CTRL_TYPE_INTEGER,
89 .name = "Brightness",
90 .minimum = 0,
91 .maximum = 255,
92 .step = 1,
93 .default_value = 15,
94 },
95 .set_control = setbrightness
96 },
97[GAIN] = {
98 {
99 .id = V4L2_CID_GAIN,
100 .type = V4L2_CTRL_TYPE_INTEGER,
101 .name = "Gain",
102 .minimum = 0,
103 .maximum = 50, /* Really 63 but > 50 is not pretty */
104 .step = 1,
105 .default_value = 25,
106 },
107 .set_control = setgain
108 },
109[EXPOSURE] = {
110 {
111 .id = V4L2_CID_EXPOSURE,
112 .type = V4L2_CTRL_TYPE_INTEGER,
113 .name = "Exposure",
114 .minimum = 0,
115 .maximum = 32767,
116 .step = 1,
117 .default_value = 15000,
118 },
119 .set_control = setexposure
120 },
121[FREQ] = {
122 {
123 .id = V4L2_CID_POWER_LINE_FREQUENCY,
124 .type = V4L2_CTRL_TYPE_MENU,
125 .name = "Light frequency filter",
126 .minimum = 0,
127 .maximum = 2,
128 .step = 1,
129 .default_value = 0,
130 },
131 .set_control = setexposure
132 },
133};
134 75
135static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value, 76static void se401_write_req(struct gspca_dev *gspca_dev, u16 req, u16 value,
136 int silent) 77 int silent)
@@ -224,22 +165,15 @@ static int se401_get_feature(struct gspca_dev *gspca_dev, u16 selector)
224 return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8); 165 return gspca_dev->usb_buf[0] | (gspca_dev->usb_buf[1] << 8);
225} 166}
226 167
227static void setbrightness(struct gspca_dev *gspca_dev) 168static void setbrightness(struct gspca_dev *gspca_dev, s32 val)
228{ 169{
229 struct sd *sd = (struct sd *) gspca_dev;
230
231 if (gspca_dev->ctrl_dis & (1 << BRIGHTNESS))
232 return;
233
234 /* HDG: this does not seem to do anything on my cam */ 170 /* HDG: this does not seem to do anything on my cam */
235 se401_write_req(gspca_dev, SE401_REQ_SET_BRT, 171 se401_write_req(gspca_dev, SE401_REQ_SET_BRT, val, 0);
236 sd->ctrls[BRIGHTNESS].val, 0);
237} 172}
238 173
239static void setgain(struct gspca_dev *gspca_dev) 174static void setgain(struct gspca_dev *gspca_dev, s32 val)
240{ 175{
241 struct sd *sd = (struct sd *) gspca_dev; 176 u16 gain = 63 - val;
242 u16 gain = 63 - sd->ctrls[GAIN].val;
243 177
244 /* red color gain */ 178 /* red color gain */
245 se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain); 179 se401_set_feature(gspca_dev, HV7131_REG_ARCG, gain);
@@ -249,10 +183,10 @@ static void setgain(struct gspca_dev *gspca_dev)
249 se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain); 183 se401_set_feature(gspca_dev, HV7131_REG_ABCG, gain);
250} 184}
251 185
252static void setexposure(struct gspca_dev *gspca_dev) 186static void setexposure(struct gspca_dev *gspca_dev, s32 val, s32 freq)
253{ 187{
254 struct sd *sd = (struct sd *) gspca_dev; 188 struct sd *sd = (struct sd *) gspca_dev;
255 int integration = sd->ctrls[EXPOSURE].val << 6; 189 int integration = val << 6;
256 u8 expose_h, expose_m, expose_l; 190 u8 expose_h, expose_m, expose_l;
257 191
258 /* Do this before the set_feature calls, for proper timing wrt 192 /* Do this before the set_feature calls, for proper timing wrt
@@ -262,9 +196,9 @@ static void setexposure(struct gspca_dev *gspca_dev)
262 through so be it */ 196 through so be it */
263 sd->expo_change_state = EXPO_CHANGED; 197 sd->expo_change_state = EXPO_CHANGED;
264 198
265 if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_50HZ) 199 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_50HZ)
266 integration = integration - integration % 106667; 200 integration = integration - integration % 106667;
267 if (sd->ctrls[FREQ].val == V4L2_CID_POWER_LINE_FREQUENCY_60HZ) 201 if (freq == V4L2_CID_POWER_LINE_FREQUENCY_60HZ)
268 integration = integration - integration % 88889; 202 integration = integration - integration % 88889;
269 203
270 expose_h = (integration >> 16); 204 expose_h = (integration >> 16);
@@ -375,15 +309,12 @@ static int sd_config(struct gspca_dev *gspca_dev,
375 cam->bulk = 1; 309 cam->bulk = 1;
376 cam->bulk_size = BULK_SIZE; 310 cam->bulk_size = BULK_SIZE;
377 cam->bulk_nurbs = 4; 311 cam->bulk_nurbs = 4;
378 cam->ctrls = sd->ctrls;
379 sd->resetlevel = 0x2d; /* Set initial resetlevel */ 312 sd->resetlevel = 0x2d; /* Set initial resetlevel */
380 313
381 /* See if the camera supports brightness */ 314 /* See if the camera supports brightness */
382 se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1); 315 se401_read_req(gspca_dev, SE401_REQ_GET_BRT, 1);
383 if (gspca_dev->usb_err) { 316 sd->has_brightness = !!gspca_dev->usb_err;
384 gspca_dev->ctrl_dis = (1 << BRIGHTNESS); 317 gspca_dev->usb_err = 0;
385 gspca_dev->usb_err = 0;
386 }
387 318
388 return 0; 319 return 0;
389} 320}
@@ -442,9 +373,7 @@ static int sd_start(struct gspca_dev *gspca_dev)
442 } 373 }
443 se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode); 374 se401_set_feature(gspca_dev, SE401_OPERATINGMODE, mode);
444 375
445 setbrightness(gspca_dev); 376 v4l2_ctrl_handler_setup(&gspca_dev->ctrl_handler);
446 setgain(gspca_dev);
447 setexposure(gspca_dev);
448 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel); 377 se401_set_feature(gspca_dev, HV7131_REG_ARLV, sd->resetlevel);
449 378
450 sd->packet_read = 0; 379 sd->packet_read = 0;
@@ -666,27 +595,6 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
666 sd_pkt_scan_janggu(gspca_dev, data, len); 595 sd_pkt_scan_janggu(gspca_dev, data, len);
667} 596}
668 597
669static int sd_querymenu(struct gspca_dev *gspca_dev,
670 struct v4l2_querymenu *menu)
671{
672 switch (menu->id) {
673 case V4L2_CID_POWER_LINE_FREQUENCY:
674 switch (menu->index) {
675 case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED:
676 strcpy((char *) menu->name, "NoFliker");
677 return 0;
678 case V4L2_CID_POWER_LINE_FREQUENCY_50HZ:
679 strcpy((char *) menu->name, "50 Hz");
680 return 0;
681 case V4L2_CID_POWER_LINE_FREQUENCY_60HZ:
682 strcpy((char *) menu->name, "60 Hz");
683 return 0;
684 }
685 break;
686 }
687 return -EINVAL;
688}
689
690#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 598#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
691static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len) 599static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
692{ 600{
@@ -714,19 +622,73 @@ static int sd_int_pkt_scan(struct gspca_dev *gspca_dev, u8 *data, int len)
714} 622}
715#endif 623#endif
716 624
625static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
626{
627 struct gspca_dev *gspca_dev =
628 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
629 struct sd *sd = (struct sd *)gspca_dev;
630
631 gspca_dev->usb_err = 0;
632
633 if (!gspca_dev->streaming)
634 return 0;
635
636 switch (ctrl->id) {
637 case V4L2_CID_BRIGHTNESS:
638 setbrightness(gspca_dev, ctrl->val);
639 break;
640 case V4L2_CID_GAIN:
641 setgain(gspca_dev, ctrl->val);
642 break;
643 case V4L2_CID_EXPOSURE:
644 setexposure(gspca_dev, ctrl->val, sd->freq->val);
645 break;
646 }
647 return gspca_dev->usb_err;
648}
649
650static const struct v4l2_ctrl_ops sd_ctrl_ops = {
651 .s_ctrl = sd_s_ctrl,
652};
653
654static int sd_init_controls(struct gspca_dev *gspca_dev)
655{
656 struct sd *sd = (struct sd *)gspca_dev;
657 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
658
659 gspca_dev->vdev.ctrl_handler = hdl;
660 v4l2_ctrl_handler_init(hdl, 4);
661 if (sd->has_brightness)
662 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
663 V4L2_CID_BRIGHTNESS, 0, 255, 1, 15);
664 /* max is really 63 but > 50 is not pretty */
665 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
666 V4L2_CID_GAIN, 0, 50, 1, 25);
667 sd->exposure = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
668 V4L2_CID_EXPOSURE, 0, 32767, 1, 15000);
669 sd->freq = v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
670 V4L2_CID_POWER_LINE_FREQUENCY,
671 V4L2_CID_POWER_LINE_FREQUENCY_60HZ, 0, 0);
672
673 if (hdl->error) {
674 pr_err("Could not initialize controls\n");
675 return hdl->error;
676 }
677 v4l2_ctrl_cluster(2, &sd->exposure);
678 return 0;
679}
680
717/* sub-driver description */ 681/* sub-driver description */
718static const struct sd_desc sd_desc = { 682static const struct sd_desc sd_desc = {
719 .name = MODULE_NAME, 683 .name = MODULE_NAME,
720 .ctrls = sd_ctrls,
721 .nctrls = ARRAY_SIZE(sd_ctrls),
722 .config = sd_config, 684 .config = sd_config,
723 .init = sd_init, 685 .init = sd_init,
686 .init_controls = sd_init_controls,
724 .isoc_init = sd_isoc_init, 687 .isoc_init = sd_isoc_init,
725 .start = sd_start, 688 .start = sd_start,
726 .stopN = sd_stopN, 689 .stopN = sd_stopN,
727 .dq_callback = sd_dq_callback, 690 .dq_callback = sd_dq_callback,
728 .pkt_scan = sd_pkt_scan, 691 .pkt_scan = sd_pkt_scan,
729 .querymenu = sd_querymenu,
730#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) 692#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
731 .int_pkt_scan = sd_int_pkt_scan, 693 .int_pkt_scan = sd_int_pkt_scan,
732#endif 694#endif