diff options
Diffstat (limited to 'drivers/media/usb/gspca/gl860/gl860.c')
-rw-r--r-- | drivers/media/usb/gspca/gl860/gl860.c | 224 |
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 */ | 61 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
62 | #define SD_SETGET(thename) \ | 62 | { |
63 | static 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 | } \ | ||
72 | static 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 | ||
80 | SD_SETGET(mirror) | 67 | switch (ctrl->id) { |
81 | SD_SETGET(flip) | 68 | case V4L2_CID_BRIGHTNESS: |
82 | SD_SETGET(AC50Hz) | 69 | sd->vcur.brightness = ctrl->val; |
83 | SD_SETGET(backlight) | 70 | break; |
84 | SD_SETGET(brightness) | 71 | case V4L2_CID_CONTRAST: |
85 | SD_SETGET(gamma) | 72 | sd->vcur.contrast = ctrl->val; |
86 | SD_SETGET(hue) | 73 | break; |
87 | SD_SETGET(saturation) | 74 | case V4L2_CID_SATURATION: |
88 | SD_SETGET(sharpness) | 75 | sd->vcur.saturation = ctrl->val; |
89 | SD_SETGET(whitebal) | 76 | break; |
90 | SD_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; |
95 | static struct ctrl sd_ctrls_mi1320[GL860_NCTRLS]; | 82 | break; |
96 | static struct ctrl sd_ctrls_mi2020[GL860_NCTRLS]; | 83 | case V4L2_CID_HFLIP: |
97 | static struct ctrl sd_ctrls_ov2640[GL860_NCTRLS]; | 84 | sd->vcur.mirror = ctrl->val; |
98 | static 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 | ||
116 | static 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 | |||
111 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { | ||
112 | .s_ctrl = sd_s_ctrl, | ||
113 | }; | ||
114 | |||
115 | static 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 | ||
164 | static const struct sd_desc sd_desc_mi1320 = { | 185 | static 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 | ||
177 | static const struct sd_desc sd_desc_mi2020 = { | 197 | static 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 | ||
190 | static const struct sd_desc sd_desc_ov2640 = { | 209 | static 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 | ||
203 | static const struct sd_desc sd_desc_ov9655 = { | 221 | static 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 | ||