aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/gspca/gl860/gl860.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/usb/gspca/gl860/gl860.c')
-rw-r--r--drivers/media/usb/gspca/gl860/gl860.c224
1 files changed, 120 insertions, 104 deletions
diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c
index ced3b71f14e5..cb1e64ca59c9 100644
--- a/drivers/media/usb/gspca/gl860/gl860.c
+++ b/drivers/media/usb/gspca/gl860/gl860.c
@@ -58,115 +58,135 @@ MODULE_PARM_DESC(sensor,
58 58
59/*============================ webcam controls =============================*/ 59/*============================ webcam controls =============================*/
60 60
61/* Functions to get and set a control value */ 61static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
62#define SD_SETGET(thename) \ 62{
63static int sd_set_##thename(struct gspca_dev *gspca_dev, s32 val)\ 63 struct gspca_dev *gspca_dev =
64{\ 64 container_of(ctrl->handler, struct gspca_dev, ctrl_handler);
65 struct sd *sd = (struct sd *) gspca_dev;\ 65 struct sd *sd = (struct sd *) gspca_dev;
66\
67 sd->vcur.thename = val;\
68 if (gspca_dev->streaming)\
69 sd->waitSet = 1;\
70 return 0;\
71} \
72static int sd_get_##thename(struct gspca_dev *gspca_dev, s32 *val)\
73{\
74 struct sd *sd = (struct sd *) gspca_dev;\
75\
76 *val = sd->vcur.thename;\
77 return 0;\
78}
79 66
80SD_SETGET(mirror) 67 switch (ctrl->id) {
81SD_SETGET(flip) 68 case V4L2_CID_BRIGHTNESS:
82SD_SETGET(AC50Hz) 69 sd->vcur.brightness = ctrl->val;
83SD_SETGET(backlight) 70 break;
84SD_SETGET(brightness) 71 case V4L2_CID_CONTRAST:
85SD_SETGET(gamma) 72 sd->vcur.contrast = ctrl->val;
86SD_SETGET(hue) 73 break;
87SD_SETGET(saturation) 74 case V4L2_CID_SATURATION:
88SD_SETGET(sharpness) 75 sd->vcur.saturation = ctrl->val;
89SD_SETGET(whitebal) 76 break;
90SD_SETGET(contrast) 77 case V4L2_CID_HUE:
91 78 sd->vcur.hue = ctrl->val;
92#define GL860_NCTRLS 11 79 break;
93 80 case V4L2_CID_GAMMA:
94/* control table */ 81 sd->vcur.gamma = ctrl->val;
95static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; 82 break;
96static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; 83 case V4L2_CID_HFLIP:
97static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; 84 sd->vcur.mirror = ctrl->val;
98static struct ctrl sd_ctrls_ov9655[GL860_NCTRLS]; 85 break;
99 86 case V4L2_CID_VFLIP:
100#define SET_MY_CTRL(theid, \ 87 sd->vcur.flip = ctrl->val;
101 thetype, thelabel, thename) \ 88 break;
102 if (sd->vmax.thename != 0) {\ 89 case V4L2_CID_POWER_LINE_FREQUENCY:
103 sd_ctrls[nCtrls].qctrl.id = theid;\ 90 sd->vcur.AC50Hz = ctrl->val;
104 sd_ctrls[nCtrls].qctrl.type = thetype;\ 91 break;
105 strcpy(sd_ctrls[nCtrls].qctrl.name, thelabel);\ 92 case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
106 sd_ctrls[nCtrls].qctrl.minimum = 0;\ 93 sd->vcur.whitebal = ctrl->val;
107 sd_ctrls[nCtrls].qctrl.maximum = sd->vmax.thename;\ 94 break;
108 sd_ctrls[nCtrls].qctrl.default_value = sd->vcur.thename;\ 95 case V4L2_CID_SHARPNESS:
109 sd_ctrls[nCtrls].qctrl.step = \ 96 sd->vcur.sharpness = ctrl->val;
110 (sd->vmax.thename < 16) ? 1 : sd->vmax.thename/16;\ 97 break;
111 sd_ctrls[nCtrls].set = sd_set_##thename;\ 98 case V4L2_CID_BACKLIGHT_COMPENSATION:
112 sd_ctrls[nCtrls].get = sd_get_##thename;\ 99 sd->vcur.backlight = ctrl->val;
113 nCtrls++;\ 100 break;
101 default:
102 return -EINVAL;
114 } 103 }
115 104
116static int gl860_build_control_table(struct gspca_dev *gspca_dev) 105 if (gspca_dev->streaming)
106 sd->waitSet = 1;
107
108 return 0;
109}
110
111static const struct v4l2_ctrl_ops sd_ctrl_ops = {
112 .s_ctrl = sd_s_ctrl,
113};
114
115static int sd_init_controls(struct gspca_dev *gspca_dev)
117{ 116{
118 struct sd *sd = (struct sd *) gspca_dev; 117 struct sd *sd = (struct sd *) gspca_dev;
119 struct ctrl *sd_ctrls; 118 struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
120 int nCtrls = 0; 119
121 120 gspca_dev->vdev.ctrl_handler = hdl;
122 if (_MI1320_) 121 v4l2_ctrl_handler_init(hdl, 11);
123 sd_ctrls = sd_ctrls_mi1320; 122
124 else if (_MI2020_) 123 if (sd->vmax.brightness)
125 sd_ctrls = sd_ctrls_mi2020; 124 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_BRIGHTNESS,
126 else if (_OV2640_) 125 0, sd->vmax.brightness, 1,
127 sd_ctrls = sd_ctrls_ov2640; 126 sd->vcur.brightness);
128 else if (_OV9655_) 127
129 sd_ctrls = sd_ctrls_ov9655; 128 if (sd->vmax.contrast)
130 else 129 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_CONTRAST,
131 return 0; 130 0, sd->vmax.contrast, 1,
132 131 sd->vcur.contrast);
133 memset(sd_ctrls, 0, GL860_NCTRLS * sizeof(struct ctrl)); 132
134 133 if (sd->vmax.saturation)
135 SET_MY_CTRL(V4L2_CID_BRIGHTNESS, 134 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SATURATION,
136 V4L2_CTRL_TYPE_INTEGER, "Brightness", brightness) 135 0, sd->vmax.saturation, 1,
137 SET_MY_CTRL(V4L2_CID_SHARPNESS, 136 sd->vcur.saturation);
138 V4L2_CTRL_TYPE_INTEGER, "Sharpness", sharpness) 137
139 SET_MY_CTRL(V4L2_CID_CONTRAST, 138 if (sd->vmax.hue)
140 V4L2_CTRL_TYPE_INTEGER, "Contrast", contrast) 139 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HUE,
141 SET_MY_CTRL(V4L2_CID_GAMMA, 140 0, sd->vmax.hue, 1, sd->vcur.hue);
142 V4L2_CTRL_TYPE_INTEGER, "Gamma", gamma) 141
143 SET_MY_CTRL(V4L2_CID_HUE, 142 if (sd->vmax.gamma)
144 V4L2_CTRL_TYPE_INTEGER, "Palette", hue) 143 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_GAMMA,
145 SET_MY_CTRL(V4L2_CID_SATURATION, 144 0, sd->vmax.gamma, 1, sd->vcur.gamma);
146 V4L2_CTRL_TYPE_INTEGER, "Saturation", saturation) 145
147 SET_MY_CTRL(V4L2_CID_WHITE_BALANCE_TEMPERATURE, 146 if (sd->vmax.mirror)
148 V4L2_CTRL_TYPE_INTEGER, "White Bal.", whitebal) 147 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_HFLIP,
149 SET_MY_CTRL(V4L2_CID_BACKLIGHT_COMPENSATION, 148 0, sd->vmax.mirror, 1, sd->vcur.mirror);
150 V4L2_CTRL_TYPE_INTEGER, "Backlight" , backlight) 149
151 150 if (sd->vmax.flip)
152 SET_MY_CTRL(V4L2_CID_HFLIP, 151 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_VFLIP,
153 V4L2_CTRL_TYPE_BOOLEAN, "Mirror", mirror) 152 0, sd->vmax.flip, 1, sd->vcur.flip);
154 SET_MY_CTRL(V4L2_CID_VFLIP, 153
155 V4L2_CTRL_TYPE_BOOLEAN, "Flip", flip) 154 if (sd->vmax.AC50Hz)
156 SET_MY_CTRL(V4L2_CID_POWER_LINE_FREQUENCY, 155 v4l2_ctrl_new_std_menu(hdl, &sd_ctrl_ops,
157 V4L2_CTRL_TYPE_BOOLEAN, "AC power 50Hz", AC50Hz) 156 V4L2_CID_POWER_LINE_FREQUENCY,
158 157 sd->vmax.AC50Hz, 0, sd->vcur.AC50Hz);
159 return nCtrls; 158
159 if (sd->vmax.whitebal)
160 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
161 V4L2_CID_WHITE_BALANCE_TEMPERATURE,
162 0, sd->vmax.whitebal, 1, sd->vcur.whitebal);
163
164 if (sd->vmax.sharpness)
165 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, V4L2_CID_SHARPNESS,
166 0, sd->vmax.sharpness, 1,
167 sd->vcur.sharpness);
168
169 if (sd->vmax.backlight)
170 v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
171 V4L2_CID_BACKLIGHT_COMPENSATION,
172 0, sd->vmax.backlight, 1,
173 sd->vcur.backlight);
174
175 if (hdl->error) {
176 pr_err("Could not initialize controls\n");
177 return hdl->error;
178 }
179
180 return 0;
160} 181}
161 182
162/*==================== sud-driver structure initialisation =================*/ 183/*==================== sud-driver structure initialisation =================*/
163 184
164static const struct sd_desc sd_desc_mi1320 = { 185static const struct sd_desc sd_desc_mi1320 = {
165 .name = MODULE_NAME, 186 .name = MODULE_NAME,
166 .ctrls = sd_ctrls_mi1320,
167 .nctrls = GL860_NCTRLS,
168 .config = sd_config, 187 .config = sd_config,
169 .init = sd_init, 188 .init = sd_init,
189 .init_controls = sd_init_controls,
170 .isoc_init = sd_isoc_init, 190 .isoc_init = sd_isoc_init,
171 .start = sd_start, 191 .start = sd_start,
172 .stop0 = sd_stop0, 192 .stop0 = sd_stop0,
@@ -176,10 +196,9 @@ static const struct sd_desc sd_desc_mi1320 = {
176 196
177static const struct sd_desc sd_desc_mi2020 = { 197static const struct sd_desc sd_desc_mi2020 = {
178 .name = MODULE_NAME, 198 .name = MODULE_NAME,
179 .ctrls = sd_ctrls_mi2020,
180 .nctrls = GL860_NCTRLS,
181 .config = sd_config, 199 .config = sd_config,
182 .init = sd_init, 200 .init = sd_init,
201 .init_controls = sd_init_controls,
183 .isoc_init = sd_isoc_init, 202 .isoc_init = sd_isoc_init,
184 .start = sd_start, 203 .start = sd_start,
185 .stop0 = sd_stop0, 204 .stop0 = sd_stop0,
@@ -189,10 +208,9 @@ static const struct sd_desc sd_desc_mi2020 = {
189 208
190static const struct sd_desc sd_desc_ov2640 = { 209static const struct sd_desc sd_desc_ov2640 = {
191 .name = MODULE_NAME, 210 .name = MODULE_NAME,
192 .ctrls = sd_ctrls_ov2640,
193 .nctrls = GL860_NCTRLS,
194 .config = sd_config, 211 .config = sd_config,
195 .init = sd_init, 212 .init = sd_init,
213 .init_controls = sd_init_controls,
196 .isoc_init = sd_isoc_init, 214 .isoc_init = sd_isoc_init,
197 .start = sd_start, 215 .start = sd_start,
198 .stop0 = sd_stop0, 216 .stop0 = sd_stop0,
@@ -202,10 +220,9 @@ static const struct sd_desc sd_desc_ov2640 = {
202 220
203static const struct sd_desc sd_desc_ov9655 = { 221static const struct sd_desc sd_desc_ov9655 = {
204 .name = MODULE_NAME, 222 .name = MODULE_NAME,
205 .ctrls = sd_ctrls_ov9655,
206 .nctrls = GL860_NCTRLS,
207 .config = sd_config, 223 .config = sd_config,
208 .init = sd_init, 224 .init = sd_init,
225 .init_controls = sd_init_controls,
209 .isoc_init = sd_isoc_init, 226 .isoc_init = sd_isoc_init,
210 .start = sd_start, 227 .start = sd_start,
211 .stop0 = sd_stop0, 228 .stop0 = sd_stop0,
@@ -371,7 +388,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
371 dev_init_settings(gspca_dev); 388 dev_init_settings(gspca_dev);
372 if (AC50Hz != 0xff) 389 if (AC50Hz != 0xff)
373 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz; 390 ((struct sd *) gspca_dev)->vcur.AC50Hz = AC50Hz;
374 gl860_build_control_table(gspca_dev);
375 391
376 return 0; 392 return 0;
377} 393}
@@ -566,7 +582,7 @@ int gl860_RTx(struct gspca_dev *gspca_dev,
566 pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n", 582 pr_err("ctrl transfer failed %4d [p%02x r%d v%04x i%04x len%d]\n",
567 r, pref, req, val, index, len); 583 r, pref, req, val, index, len);
568 else if (len > 1 && r < len) 584 else if (len > 1 && r < len)
569 PDEBUG(D_ERR, "short ctrl transfer %d/%d", r, len); 585 PERR("short ctrl transfer %d/%d", r, len);
570 586
571 msleep(1); 587 msleep(1);
572 588