1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Broadcom BCM2835 V4L2 driver |
4 | * |
5 | * Copyright © 2013 Raspberry Pi (Trading) Ltd. |
6 | * |
7 | * Authors: Vincent Sanders @ Collabora |
8 | * Dave Stevenson @ Broadcom |
9 | * (now dave.stevenson@raspberrypi.org) |
10 | * Simon Mellor @ Broadcom |
11 | * Luke Diamand @ Broadcom |
12 | */ |
13 | |
14 | #include <linux/errno.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> |
17 | #include <linux/slab.h> |
18 | #include <media/videobuf2-vmalloc.h> |
19 | #include <media/v4l2-device.h> |
20 | #include <media/v4l2-ioctl.h> |
21 | #include <media/v4l2-ctrls.h> |
22 | #include <media/v4l2-fh.h> |
23 | #include <media/v4l2-event.h> |
24 | #include <media/v4l2-common.h> |
25 | |
26 | #include "../vchiq-mmal/mmal-common.h" |
27 | #include "../vchiq-mmal/mmal-vchiq.h" |
28 | #include "../vchiq-mmal/mmal-parameters.h" |
29 | #include "bcm2835-camera.h" |
30 | |
31 | /* The supported V4L2_CID_AUTO_EXPOSURE_BIAS values are from -4.0 to +4.0. |
32 | * MMAL values are in 1/6th increments so the MMAL range is -24 to +24. |
33 | * V4L2 docs say value "is expressed in terms of EV, drivers should interpret |
34 | * the values as 0.001 EV units, where the value 1000 stands for +1 EV." |
35 | * V4L2 is limited to a max of 32 values in a menu, so count in 1/3rds from |
36 | * -4 to +4 |
37 | */ |
38 | static const s64 [] = { |
39 | -4000, -3667, -3333, |
40 | -3000, -2667, -2333, |
41 | -2000, -1667, -1333, |
42 | -1000, -667, -333, |
43 | 0, 333, 667, |
44 | 1000, 1333, 1667, |
45 | 2000, 2333, 2667, |
46 | 3000, 3333, 3667, |
47 | 4000 |
48 | }; |
49 | |
50 | /* Supported ISO values (*1000) |
51 | * ISOO = auto ISO |
52 | */ |
53 | static const s64 [] = { |
54 | 0, 100000, 200000, 400000, 800000, |
55 | }; |
56 | |
57 | static const u32 iso_values[] = { |
58 | 0, 100, 200, 400, 800, |
59 | }; |
60 | |
61 | enum bcm2835_mmal_ctrl_type { |
62 | MMAL_CONTROL_TYPE_STD, |
63 | , |
64 | , |
65 | MMAL_CONTROL_TYPE_CLUSTER, /* special cluster entry */ |
66 | }; |
67 | |
68 | struct bcm2835_mmal_v4l2_ctrl { |
69 | u32 id; /* v4l2 control identifier */ |
70 | enum bcm2835_mmal_ctrl_type type; |
71 | /* control minimum value or |
72 | * mask for MMAL_CONTROL_TYPE_STD_MENU |
73 | */ |
74 | s64 min; |
75 | s64 max; /* maximum value of control */ |
76 | s64 def; /* default value of control */ |
77 | u64 step; /* step size of the control */ |
78 | const s64 *; /* integer menu array */ |
79 | u32 mmal_id; /* mmal parameter id */ |
80 | int (*setter)(struct bcm2835_mmal_dev *dev, struct v4l2_ctrl *ctrl, |
81 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl); |
82 | }; |
83 | |
84 | struct v4l2_to_mmal_effects_setting { |
85 | u32 v4l2_effect; |
86 | u32 mmal_effect; |
87 | s32 col_fx_enable; |
88 | s32 col_fx_fixed_cbcr; |
89 | u32 u; |
90 | u32 v; |
91 | u32 num_effect_params; |
92 | u32 effect_params[MMAL_MAX_IMAGEFX_PARAMETERS]; |
93 | }; |
94 | |
95 | static const struct v4l2_to_mmal_effects_setting |
96 | v4l2_to_mmal_effects_values[] = { |
97 | { V4L2_COLORFX_NONE, MMAL_PARAM_IMAGEFX_NONE, |
98 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
99 | { V4L2_COLORFX_BW, MMAL_PARAM_IMAGEFX_NONE, |
100 | 1, 0, 128, 128, 0, {0, 0, 0, 0, 0} }, |
101 | { V4L2_COLORFX_SEPIA, MMAL_PARAM_IMAGEFX_NONE, |
102 | 1, 0, 87, 151, 0, {0, 0, 0, 0, 0} }, |
103 | { V4L2_COLORFX_NEGATIVE, MMAL_PARAM_IMAGEFX_NEGATIVE, |
104 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
105 | { V4L2_COLORFX_EMBOSS, MMAL_PARAM_IMAGEFX_EMBOSS, |
106 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
107 | { V4L2_COLORFX_SKETCH, MMAL_PARAM_IMAGEFX_SKETCH, |
108 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
109 | { V4L2_COLORFX_SKY_BLUE, MMAL_PARAM_IMAGEFX_PASTEL, |
110 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
111 | { V4L2_COLORFX_GRASS_GREEN, MMAL_PARAM_IMAGEFX_WATERCOLOUR, |
112 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
113 | { V4L2_COLORFX_SKIN_WHITEN, MMAL_PARAM_IMAGEFX_WASHEDOUT, |
114 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
115 | { V4L2_COLORFX_VIVID, MMAL_PARAM_IMAGEFX_SATURATION, |
116 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
117 | { V4L2_COLORFX_AQUA, MMAL_PARAM_IMAGEFX_NONE, |
118 | 1, 0, 171, 121, 0, {0, 0, 0, 0, 0} }, |
119 | { V4L2_COLORFX_ART_FREEZE, MMAL_PARAM_IMAGEFX_HATCH, |
120 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
121 | { V4L2_COLORFX_SILHOUETTE, MMAL_PARAM_IMAGEFX_FILM, |
122 | 0, 0, 0, 0, 0, {0, 0, 0, 0, 0} }, |
123 | { V4L2_COLORFX_SOLARIZATION, MMAL_PARAM_IMAGEFX_SOLARIZE, |
124 | 0, 0, 0, 0, 5, {1, 128, 160, 160, 48} }, |
125 | { V4L2_COLORFX_ANTIQUE, MMAL_PARAM_IMAGEFX_COLOURBALANCE, |
126 | 0, 0, 0, 0, 3, {108, 274, 238, 0, 0} }, |
127 | { V4L2_COLORFX_SET_CBCR, MMAL_PARAM_IMAGEFX_NONE, |
128 | 1, 1, 0, 0, 0, {0, 0, 0, 0, 0} } |
129 | }; |
130 | |
131 | struct v4l2_mmal_scene_config { |
132 | enum v4l2_scene_mode v4l2_scene; |
133 | enum mmal_parameter_exposuremode exposure_mode; |
134 | enum mmal_parameter_exposuremeteringmode metering_mode; |
135 | }; |
136 | |
137 | static const struct v4l2_mmal_scene_config scene_configs[] = { |
138 | /* V4L2_SCENE_MODE_NONE automatically added */ |
139 | { |
140 | V4L2_SCENE_MODE_NIGHT, |
141 | MMAL_PARAM_EXPOSUREMODE_NIGHT, |
142 | MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE |
143 | }, |
144 | { |
145 | V4L2_SCENE_MODE_SPORTS, |
146 | MMAL_PARAM_EXPOSUREMODE_SPORTS, |
147 | MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE |
148 | }, |
149 | }; |
150 | |
151 | /* control handlers*/ |
152 | |
153 | static int ctrl_set_rational(struct bcm2835_mmal_dev *dev, |
154 | struct v4l2_ctrl *ctrl, |
155 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
156 | { |
157 | struct s32_fract rational_value; |
158 | struct vchiq_mmal_port *control; |
159 | |
160 | control = &dev->component[COMP_CAMERA]->control; |
161 | |
162 | rational_value.numerator = ctrl->val; |
163 | rational_value.denominator = 100; |
164 | |
165 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
166 | parameter: mmal_ctrl->mmal_id, |
167 | value: &rational_value, |
168 | value_size: sizeof(rational_value)); |
169 | } |
170 | |
171 | static int ctrl_set_value(struct bcm2835_mmal_dev *dev, |
172 | struct v4l2_ctrl *ctrl, |
173 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
174 | { |
175 | u32 u32_value; |
176 | struct vchiq_mmal_port *control; |
177 | |
178 | control = &dev->component[COMP_CAMERA]->control; |
179 | |
180 | u32_value = ctrl->val; |
181 | |
182 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
183 | parameter: mmal_ctrl->mmal_id, |
184 | value: &u32_value, value_size: sizeof(u32_value)); |
185 | } |
186 | |
187 | static int ctrl_set_iso(struct bcm2835_mmal_dev *dev, |
188 | struct v4l2_ctrl *ctrl, |
189 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
190 | { |
191 | u32 u32_value; |
192 | struct vchiq_mmal_port *control; |
193 | |
194 | if (ctrl->val > mmal_ctrl->max || ctrl->val < mmal_ctrl->min) |
195 | return 1; |
196 | |
197 | if (ctrl->id == V4L2_CID_ISO_SENSITIVITY) |
198 | dev->iso = iso_values[ctrl->val]; |
199 | else if (ctrl->id == V4L2_CID_ISO_SENSITIVITY_AUTO) |
200 | dev->manual_iso_enabled = |
201 | (ctrl->val == V4L2_ISO_SENSITIVITY_MANUAL); |
202 | |
203 | control = &dev->component[COMP_CAMERA]->control; |
204 | |
205 | if (dev->manual_iso_enabled) |
206 | u32_value = dev->iso; |
207 | else |
208 | u32_value = 0; |
209 | |
210 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
211 | parameter: MMAL_PARAMETER_ISO, |
212 | value: &u32_value, value_size: sizeof(u32_value)); |
213 | } |
214 | |
215 | static int ctrl_set_value_ev(struct bcm2835_mmal_dev *dev, |
216 | struct v4l2_ctrl *ctrl, |
217 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
218 | { |
219 | s32 s32_value; |
220 | struct vchiq_mmal_port *control; |
221 | |
222 | control = &dev->component[COMP_CAMERA]->control; |
223 | |
224 | s32_value = (ctrl->val - 12) * 2; /* Convert from index to 1/6ths */ |
225 | |
226 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
227 | parameter: mmal_ctrl->mmal_id, |
228 | value: &s32_value, value_size: sizeof(s32_value)); |
229 | } |
230 | |
231 | static int ctrl_set_rotate(struct bcm2835_mmal_dev *dev, |
232 | struct v4l2_ctrl *ctrl, |
233 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
234 | { |
235 | int ret; |
236 | u32 u32_value; |
237 | struct vchiq_mmal_component *camera; |
238 | |
239 | camera = dev->component[COMP_CAMERA]; |
240 | |
241 | u32_value = ((ctrl->val % 360) / 90) * 90; |
242 | |
243 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[0], |
244 | parameter: mmal_ctrl->mmal_id, |
245 | value: &u32_value, value_size: sizeof(u32_value)); |
246 | if (ret < 0) |
247 | return ret; |
248 | |
249 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[1], |
250 | parameter: mmal_ctrl->mmal_id, |
251 | value: &u32_value, value_size: sizeof(u32_value)); |
252 | if (ret < 0) |
253 | return ret; |
254 | |
255 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[2], |
256 | parameter: mmal_ctrl->mmal_id, |
257 | value: &u32_value, value_size: sizeof(u32_value)); |
258 | } |
259 | |
260 | static int ctrl_set_flip(struct bcm2835_mmal_dev *dev, |
261 | struct v4l2_ctrl *ctrl, |
262 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
263 | { |
264 | int ret; |
265 | u32 u32_value; |
266 | struct vchiq_mmal_component *camera; |
267 | |
268 | if (ctrl->id == V4L2_CID_HFLIP) |
269 | dev->hflip = ctrl->val; |
270 | else |
271 | dev->vflip = ctrl->val; |
272 | |
273 | camera = dev->component[COMP_CAMERA]; |
274 | |
275 | if (dev->hflip && dev->vflip) |
276 | u32_value = MMAL_PARAM_MIRROR_BOTH; |
277 | else if (dev->hflip) |
278 | u32_value = MMAL_PARAM_MIRROR_HORIZONTAL; |
279 | else if (dev->vflip) |
280 | u32_value = MMAL_PARAM_MIRROR_VERTICAL; |
281 | else |
282 | u32_value = MMAL_PARAM_MIRROR_NONE; |
283 | |
284 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[0], |
285 | parameter: mmal_ctrl->mmal_id, |
286 | value: &u32_value, value_size: sizeof(u32_value)); |
287 | if (ret < 0) |
288 | return ret; |
289 | |
290 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[1], |
291 | parameter: mmal_ctrl->mmal_id, |
292 | value: &u32_value, value_size: sizeof(u32_value)); |
293 | if (ret < 0) |
294 | return ret; |
295 | |
296 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: &camera->output[2], |
297 | parameter: mmal_ctrl->mmal_id, |
298 | value: &u32_value, value_size: sizeof(u32_value)); |
299 | } |
300 | |
301 | static int ctrl_set_exposure(struct bcm2835_mmal_dev *dev, |
302 | struct v4l2_ctrl *ctrl, |
303 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
304 | { |
305 | enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user; |
306 | u32 shutter_speed = 0; |
307 | struct vchiq_mmal_port *control; |
308 | int ret = 0; |
309 | |
310 | control = &dev->component[COMP_CAMERA]->control; |
311 | |
312 | if (mmal_ctrl->mmal_id == MMAL_PARAMETER_SHUTTER_SPEED) { |
313 | /* V4L2 is in 100usec increments. |
314 | * MMAL is 1usec. |
315 | */ |
316 | dev->manual_shutter_speed = ctrl->val * 100; |
317 | } else if (mmal_ctrl->mmal_id == MMAL_PARAMETER_EXPOSURE_MODE) { |
318 | switch (ctrl->val) { |
319 | case V4L2_EXPOSURE_AUTO: |
320 | exp_mode = MMAL_PARAM_EXPOSUREMODE_AUTO; |
321 | break; |
322 | |
323 | case V4L2_EXPOSURE_MANUAL: |
324 | exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF; |
325 | break; |
326 | } |
327 | dev->exposure_mode_user = exp_mode; |
328 | dev->exposure_mode_v4l2_user = ctrl->val; |
329 | } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) { |
330 | dev->exp_auto_priority = ctrl->val; |
331 | } |
332 | |
333 | if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { |
334 | if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF) |
335 | shutter_speed = dev->manual_shutter_speed; |
336 | |
337 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, |
338 | port: control, |
339 | parameter: MMAL_PARAMETER_SHUTTER_SPEED, |
340 | value: &shutter_speed, |
341 | value_size: sizeof(shutter_speed)); |
342 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, |
343 | port: control, |
344 | parameter: MMAL_PARAMETER_EXPOSURE_MODE, |
345 | value: &exp_mode, |
346 | value_size: sizeof(u32)); |
347 | dev->exposure_mode_active = exp_mode; |
348 | } |
349 | /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should |
350 | * always apply irrespective of scene mode. |
351 | */ |
352 | ret += set_framerate_params(dev); |
353 | |
354 | return ret; |
355 | } |
356 | |
357 | static int ctrl_set_metering_mode(struct bcm2835_mmal_dev *dev, |
358 | struct v4l2_ctrl *ctrl, |
359 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
360 | { |
361 | switch (ctrl->val) { |
362 | case V4L2_EXPOSURE_METERING_AVERAGE: |
363 | dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE; |
364 | break; |
365 | |
366 | case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED: |
367 | dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT; |
368 | break; |
369 | |
370 | case V4L2_EXPOSURE_METERING_SPOT: |
371 | dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT; |
372 | break; |
373 | |
374 | case V4L2_EXPOSURE_METERING_MATRIX: |
375 | dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX; |
376 | break; |
377 | } |
378 | |
379 | if (dev->scene_mode == V4L2_SCENE_MODE_NONE) { |
380 | struct vchiq_mmal_port *control; |
381 | u32 u32_value = dev->metering_mode; |
382 | |
383 | control = &dev->component[COMP_CAMERA]->control; |
384 | |
385 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
386 | parameter: mmal_ctrl->mmal_id, |
387 | value: &u32_value, value_size: sizeof(u32_value)); |
388 | } else { |
389 | return 0; |
390 | } |
391 | } |
392 | |
393 | static int ctrl_set_flicker_avoidance(struct bcm2835_mmal_dev *dev, |
394 | struct v4l2_ctrl *ctrl, |
395 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
396 | { |
397 | u32 u32_value; |
398 | struct vchiq_mmal_port *control; |
399 | |
400 | control = &dev->component[COMP_CAMERA]->control; |
401 | |
402 | switch (ctrl->val) { |
403 | case V4L2_CID_POWER_LINE_FREQUENCY_DISABLED: |
404 | u32_value = MMAL_PARAM_FLICKERAVOID_OFF; |
405 | break; |
406 | case V4L2_CID_POWER_LINE_FREQUENCY_50HZ: |
407 | u32_value = MMAL_PARAM_FLICKERAVOID_50HZ; |
408 | break; |
409 | case V4L2_CID_POWER_LINE_FREQUENCY_60HZ: |
410 | u32_value = MMAL_PARAM_FLICKERAVOID_60HZ; |
411 | break; |
412 | case V4L2_CID_POWER_LINE_FREQUENCY_AUTO: |
413 | u32_value = MMAL_PARAM_FLICKERAVOID_AUTO; |
414 | break; |
415 | } |
416 | |
417 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
418 | parameter: mmal_ctrl->mmal_id, |
419 | value: &u32_value, value_size: sizeof(u32_value)); |
420 | } |
421 | |
422 | static int ctrl_set_awb_mode(struct bcm2835_mmal_dev *dev, |
423 | struct v4l2_ctrl *ctrl, |
424 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
425 | { |
426 | u32 u32_value; |
427 | struct vchiq_mmal_port *control; |
428 | |
429 | control = &dev->component[COMP_CAMERA]->control; |
430 | |
431 | switch (ctrl->val) { |
432 | case V4L2_WHITE_BALANCE_MANUAL: |
433 | u32_value = MMAL_PARAM_AWBMODE_OFF; |
434 | break; |
435 | |
436 | case V4L2_WHITE_BALANCE_AUTO: |
437 | u32_value = MMAL_PARAM_AWBMODE_AUTO; |
438 | break; |
439 | |
440 | case V4L2_WHITE_BALANCE_INCANDESCENT: |
441 | u32_value = MMAL_PARAM_AWBMODE_INCANDESCENT; |
442 | break; |
443 | |
444 | case V4L2_WHITE_BALANCE_FLUORESCENT: |
445 | u32_value = MMAL_PARAM_AWBMODE_FLUORESCENT; |
446 | break; |
447 | |
448 | case V4L2_WHITE_BALANCE_FLUORESCENT_H: |
449 | u32_value = MMAL_PARAM_AWBMODE_TUNGSTEN; |
450 | break; |
451 | |
452 | case V4L2_WHITE_BALANCE_HORIZON: |
453 | u32_value = MMAL_PARAM_AWBMODE_HORIZON; |
454 | break; |
455 | |
456 | case V4L2_WHITE_BALANCE_DAYLIGHT: |
457 | u32_value = MMAL_PARAM_AWBMODE_SUNLIGHT; |
458 | break; |
459 | |
460 | case V4L2_WHITE_BALANCE_FLASH: |
461 | u32_value = MMAL_PARAM_AWBMODE_FLASH; |
462 | break; |
463 | |
464 | case V4L2_WHITE_BALANCE_CLOUDY: |
465 | u32_value = MMAL_PARAM_AWBMODE_CLOUDY; |
466 | break; |
467 | |
468 | case V4L2_WHITE_BALANCE_SHADE: |
469 | u32_value = MMAL_PARAM_AWBMODE_SHADE; |
470 | break; |
471 | } |
472 | |
473 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
474 | parameter: mmal_ctrl->mmal_id, |
475 | value: &u32_value, value_size: sizeof(u32_value)); |
476 | } |
477 | |
478 | static int ctrl_set_awb_gains(struct bcm2835_mmal_dev *dev, |
479 | struct v4l2_ctrl *ctrl, |
480 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
481 | { |
482 | struct vchiq_mmal_port *control; |
483 | struct mmal_parameter_awbgains gains; |
484 | |
485 | control = &dev->component[COMP_CAMERA]->control; |
486 | |
487 | if (ctrl->id == V4L2_CID_RED_BALANCE) |
488 | dev->red_gain = ctrl->val; |
489 | else if (ctrl->id == V4L2_CID_BLUE_BALANCE) |
490 | dev->blue_gain = ctrl->val; |
491 | |
492 | gains.r_gain.numerator = dev->red_gain; |
493 | gains.r_gain.denominator = 1000; |
494 | gains.b_gain.numerator = dev->blue_gain; |
495 | gains.b_gain.denominator = 1000; |
496 | |
497 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
498 | parameter: mmal_ctrl->mmal_id, |
499 | value: &gains, value_size: sizeof(gains)); |
500 | } |
501 | |
502 | static int ctrl_set_image_effect(struct bcm2835_mmal_dev *dev, |
503 | struct v4l2_ctrl *ctrl, |
504 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
505 | { |
506 | int ret = -EINVAL; |
507 | int i, j; |
508 | struct vchiq_mmal_port *control; |
509 | struct mmal_parameter_imagefx_parameters imagefx; |
510 | |
511 | for (i = 0; i < ARRAY_SIZE(v4l2_to_mmal_effects_values); i++) { |
512 | if (ctrl->val != v4l2_to_mmal_effects_values[i].v4l2_effect) |
513 | continue; |
514 | |
515 | imagefx.effect = |
516 | v4l2_to_mmal_effects_values[i].mmal_effect; |
517 | imagefx.num_effect_params = |
518 | v4l2_to_mmal_effects_values[i].num_effect_params; |
519 | |
520 | if (imagefx.num_effect_params > MMAL_MAX_IMAGEFX_PARAMETERS) |
521 | imagefx.num_effect_params = MMAL_MAX_IMAGEFX_PARAMETERS; |
522 | |
523 | for (j = 0; j < imagefx.num_effect_params; j++) |
524 | imagefx.effect_parameter[j] = |
525 | v4l2_to_mmal_effects_values[i].effect_params[j]; |
526 | |
527 | dev->colourfx.enable = |
528 | v4l2_to_mmal_effects_values[i].col_fx_enable; |
529 | if (!v4l2_to_mmal_effects_values[i].col_fx_fixed_cbcr) { |
530 | dev->colourfx.u = v4l2_to_mmal_effects_values[i].u; |
531 | dev->colourfx.v = v4l2_to_mmal_effects_values[i].v; |
532 | } |
533 | |
534 | control = &dev->component[COMP_CAMERA]->control; |
535 | |
536 | ret = vchiq_mmal_port_parameter_set( |
537 | instance: dev->instance, port: control, |
538 | parameter: MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, |
539 | value: &imagefx, value_size: sizeof(imagefx)); |
540 | if (ret) |
541 | goto exit; |
542 | |
543 | ret = vchiq_mmal_port_parameter_set( |
544 | instance: dev->instance, port: control, |
545 | parameter: MMAL_PARAMETER_COLOUR_EFFECT, |
546 | value: &dev->colourfx, value_size: sizeof(dev->colourfx)); |
547 | } |
548 | |
549 | exit: |
550 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
551 | "mmal_ctrl:%p ctrl id:0x%x ctrl val:%d imagefx:0x%x color_effect:%s u:%d v:%d ret %d(%d)\n" , |
552 | mmal_ctrl, ctrl->id, ctrl->val, imagefx.effect, |
553 | dev->colourfx.enable ? "true" : "false" , |
554 | dev->colourfx.u, dev->colourfx.v, |
555 | ret, (ret == 0 ? 0 : -EINVAL)); |
556 | return (ret == 0 ? 0 : -EINVAL); |
557 | } |
558 | |
559 | static int ctrl_set_colfx(struct bcm2835_mmal_dev *dev, |
560 | struct v4l2_ctrl *ctrl, |
561 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
562 | { |
563 | int ret; |
564 | struct vchiq_mmal_port *control; |
565 | |
566 | control = &dev->component[COMP_CAMERA]->control; |
567 | |
568 | dev->colourfx.u = (ctrl->val & 0xff00) >> 8; |
569 | dev->colourfx.v = ctrl->val & 0xff; |
570 | |
571 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
572 | parameter: MMAL_PARAMETER_COLOUR_EFFECT, |
573 | value: &dev->colourfx, |
574 | value_size: sizeof(dev->colourfx)); |
575 | |
576 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
577 | "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n" , |
578 | __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, |
579 | (ret == 0 ? 0 : -EINVAL)); |
580 | return (ret == 0 ? 0 : -EINVAL); |
581 | } |
582 | |
583 | static int ctrl_set_bitrate(struct bcm2835_mmal_dev *dev, |
584 | struct v4l2_ctrl *ctrl, |
585 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
586 | { |
587 | int ret; |
588 | struct vchiq_mmal_port *encoder_out; |
589 | |
590 | dev->capture.encode_bitrate = ctrl->val; |
591 | |
592 | encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0]; |
593 | |
594 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: encoder_out, |
595 | parameter: mmal_ctrl->mmal_id, value: &ctrl->val, |
596 | value_size: sizeof(ctrl->val)); |
597 | |
598 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
599 | "%s: After: mmal_ctrl:%p ctrl id:0x%x ctrl val:%d ret %d(%d)\n" , |
600 | __func__, mmal_ctrl, ctrl->id, ctrl->val, ret, |
601 | (ret == 0 ? 0 : -EINVAL)); |
602 | |
603 | /* |
604 | * Older firmware versions (pre July 2019) have a bug in handling |
605 | * MMAL_PARAMETER_VIDEO_BIT_RATE that result in the call |
606 | * returning -MMAL_MSG_STATUS_EINVAL. So ignore errors from this call. |
607 | */ |
608 | return 0; |
609 | } |
610 | |
611 | static int ctrl_set_bitrate_mode(struct bcm2835_mmal_dev *dev, |
612 | struct v4l2_ctrl *ctrl, |
613 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
614 | { |
615 | u32 bitrate_mode; |
616 | struct vchiq_mmal_port *encoder_out; |
617 | |
618 | encoder_out = &dev->component[COMP_VIDEO_ENCODE]->output[0]; |
619 | |
620 | dev->capture.encode_bitrate_mode = ctrl->val; |
621 | switch (ctrl->val) { |
622 | default: |
623 | case V4L2_MPEG_VIDEO_BITRATE_MODE_VBR: |
624 | bitrate_mode = MMAL_VIDEO_RATECONTROL_VARIABLE; |
625 | break; |
626 | case V4L2_MPEG_VIDEO_BITRATE_MODE_CBR: |
627 | bitrate_mode = MMAL_VIDEO_RATECONTROL_CONSTANT; |
628 | break; |
629 | } |
630 | |
631 | vchiq_mmal_port_parameter_set(instance: dev->instance, port: encoder_out, |
632 | parameter: mmal_ctrl->mmal_id, |
633 | value: &bitrate_mode, |
634 | value_size: sizeof(bitrate_mode)); |
635 | return 0; |
636 | } |
637 | |
638 | static int ctrl_set_image_encode_output(struct bcm2835_mmal_dev *dev, |
639 | struct v4l2_ctrl *ctrl, |
640 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
641 | { |
642 | u32 u32_value; |
643 | struct vchiq_mmal_port *jpeg_out; |
644 | |
645 | jpeg_out = &dev->component[COMP_IMAGE_ENCODE]->output[0]; |
646 | |
647 | u32_value = ctrl->val; |
648 | |
649 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: jpeg_out, |
650 | parameter: mmal_ctrl->mmal_id, |
651 | value: &u32_value, value_size: sizeof(u32_value)); |
652 | } |
653 | |
654 | static int ctrl_set_video_encode_param_output(struct bcm2835_mmal_dev *dev, |
655 | struct v4l2_ctrl *ctrl, |
656 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
657 | { |
658 | u32 u32_value; |
659 | struct vchiq_mmal_port *vid_enc_ctl; |
660 | |
661 | vid_enc_ctl = &dev->component[COMP_VIDEO_ENCODE]->output[0]; |
662 | |
663 | u32_value = ctrl->val; |
664 | |
665 | return vchiq_mmal_port_parameter_set(instance: dev->instance, port: vid_enc_ctl, |
666 | parameter: mmal_ctrl->mmal_id, |
667 | value: &u32_value, value_size: sizeof(u32_value)); |
668 | } |
669 | |
670 | static int ctrl_set_video_encode_profile_level(struct bcm2835_mmal_dev *dev, |
671 | struct v4l2_ctrl *ctrl, |
672 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
673 | { |
674 | struct mmal_parameter_video_profile param; |
675 | int ret = 0; |
676 | |
677 | if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_PROFILE) { |
678 | switch (ctrl->val) { |
679 | case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: |
680 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: |
681 | case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: |
682 | case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: |
683 | dev->capture.enc_profile = ctrl->val; |
684 | break; |
685 | default: |
686 | ret = -EINVAL; |
687 | break; |
688 | } |
689 | } else if (ctrl->id == V4L2_CID_MPEG_VIDEO_H264_LEVEL) { |
690 | switch (ctrl->val) { |
691 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: |
692 | case V4L2_MPEG_VIDEO_H264_LEVEL_1B: |
693 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: |
694 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: |
695 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: |
696 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: |
697 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: |
698 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: |
699 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: |
700 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: |
701 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: |
702 | case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: |
703 | dev->capture.enc_level = ctrl->val; |
704 | break; |
705 | default: |
706 | ret = -EINVAL; |
707 | break; |
708 | } |
709 | } |
710 | |
711 | if (!ret) { |
712 | switch (dev->capture.enc_profile) { |
713 | case V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE: |
714 | param.profile = MMAL_VIDEO_PROFILE_H264_BASELINE; |
715 | break; |
716 | case V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE: |
717 | param.profile = |
718 | MMAL_VIDEO_PROFILE_H264_CONSTRAINED_BASELINE; |
719 | break; |
720 | case V4L2_MPEG_VIDEO_H264_PROFILE_MAIN: |
721 | param.profile = MMAL_VIDEO_PROFILE_H264_MAIN; |
722 | break; |
723 | case V4L2_MPEG_VIDEO_H264_PROFILE_HIGH: |
724 | param.profile = MMAL_VIDEO_PROFILE_H264_HIGH; |
725 | break; |
726 | default: |
727 | /* Should never get here */ |
728 | break; |
729 | } |
730 | |
731 | switch (dev->capture.enc_level) { |
732 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_0: |
733 | param.level = MMAL_VIDEO_LEVEL_H264_1; |
734 | break; |
735 | case V4L2_MPEG_VIDEO_H264_LEVEL_1B: |
736 | param.level = MMAL_VIDEO_LEVEL_H264_1b; |
737 | break; |
738 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_1: |
739 | param.level = MMAL_VIDEO_LEVEL_H264_11; |
740 | break; |
741 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_2: |
742 | param.level = MMAL_VIDEO_LEVEL_H264_12; |
743 | break; |
744 | case V4L2_MPEG_VIDEO_H264_LEVEL_1_3: |
745 | param.level = MMAL_VIDEO_LEVEL_H264_13; |
746 | break; |
747 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_0: |
748 | param.level = MMAL_VIDEO_LEVEL_H264_2; |
749 | break; |
750 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_1: |
751 | param.level = MMAL_VIDEO_LEVEL_H264_21; |
752 | break; |
753 | case V4L2_MPEG_VIDEO_H264_LEVEL_2_2: |
754 | param.level = MMAL_VIDEO_LEVEL_H264_22; |
755 | break; |
756 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_0: |
757 | param.level = MMAL_VIDEO_LEVEL_H264_3; |
758 | break; |
759 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_1: |
760 | param.level = MMAL_VIDEO_LEVEL_H264_31; |
761 | break; |
762 | case V4L2_MPEG_VIDEO_H264_LEVEL_3_2: |
763 | param.level = MMAL_VIDEO_LEVEL_H264_32; |
764 | break; |
765 | case V4L2_MPEG_VIDEO_H264_LEVEL_4_0: |
766 | param.level = MMAL_VIDEO_LEVEL_H264_4; |
767 | break; |
768 | default: |
769 | /* Should never get here */ |
770 | break; |
771 | } |
772 | |
773 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, |
774 | port: &dev->component[COMP_VIDEO_ENCODE]->output[0], |
775 | parameter: mmal_ctrl->mmal_id, |
776 | value: ¶m, value_size: sizeof(param)); |
777 | } |
778 | return ret; |
779 | } |
780 | |
781 | static int ctrl_set_scene_mode(struct bcm2835_mmal_dev *dev, |
782 | struct v4l2_ctrl *ctrl, |
783 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl) |
784 | { |
785 | int ret = 0; |
786 | int shutter_speed; |
787 | struct vchiq_mmal_port *control; |
788 | |
789 | v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, |
790 | "scene mode selected %d, was %d\n" , ctrl->val, |
791 | dev->scene_mode); |
792 | control = &dev->component[COMP_CAMERA]->control; |
793 | |
794 | if (ctrl->val == dev->scene_mode) |
795 | return 0; |
796 | |
797 | if (ctrl->val == V4L2_SCENE_MODE_NONE) { |
798 | /* Restore all user selections */ |
799 | dev->scene_mode = V4L2_SCENE_MODE_NONE; |
800 | |
801 | if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF) |
802 | shutter_speed = dev->manual_shutter_speed; |
803 | else |
804 | shutter_speed = 0; |
805 | |
806 | v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, |
807 | "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n" , |
808 | __func__, shutter_speed, dev->exposure_mode_user, |
809 | dev->metering_mode); |
810 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, |
811 | port: control, |
812 | parameter: MMAL_PARAMETER_SHUTTER_SPEED, |
813 | value: &shutter_speed, |
814 | value_size: sizeof(shutter_speed)); |
815 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, |
816 | port: control, |
817 | parameter: MMAL_PARAMETER_EXPOSURE_MODE, |
818 | value: &dev->exposure_mode_user, |
819 | value_size: sizeof(u32)); |
820 | dev->exposure_mode_active = dev->exposure_mode_user; |
821 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, |
822 | port: control, |
823 | parameter: MMAL_PARAMETER_EXP_METERING_MODE, |
824 | value: &dev->metering_mode, |
825 | value_size: sizeof(u32)); |
826 | ret += set_framerate_params(dev); |
827 | } else { |
828 | /* Set up scene mode */ |
829 | int i; |
830 | const struct v4l2_mmal_scene_config *scene = NULL; |
831 | int shutter_speed; |
832 | enum mmal_parameter_exposuremode exposure_mode; |
833 | enum mmal_parameter_exposuremeteringmode metering_mode; |
834 | |
835 | for (i = 0; i < ARRAY_SIZE(scene_configs); i++) { |
836 | if (scene_configs[i].v4l2_scene == ctrl->val) { |
837 | scene = &scene_configs[i]; |
838 | break; |
839 | } |
840 | } |
841 | if (!scene) |
842 | return -EINVAL; |
843 | if (i >= ARRAY_SIZE(scene_configs)) |
844 | return -EINVAL; |
845 | |
846 | /* Set all the values */ |
847 | dev->scene_mode = ctrl->val; |
848 | |
849 | if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF) |
850 | shutter_speed = dev->manual_shutter_speed; |
851 | else |
852 | shutter_speed = 0; |
853 | exposure_mode = scene->exposure_mode; |
854 | metering_mode = scene->metering_mode; |
855 | |
856 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
857 | "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n" , |
858 | __func__, shutter_speed, exposure_mode, metering_mode); |
859 | |
860 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
861 | parameter: MMAL_PARAMETER_SHUTTER_SPEED, |
862 | value: &shutter_speed, |
863 | value_size: sizeof(shutter_speed)); |
864 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
865 | parameter: MMAL_PARAMETER_EXPOSURE_MODE, |
866 | value: &exposure_mode, |
867 | value_size: sizeof(u32)); |
868 | dev->exposure_mode_active = exposure_mode; |
869 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
870 | parameter: MMAL_PARAMETER_EXPOSURE_MODE, |
871 | value: &exposure_mode, |
872 | value_size: sizeof(u32)); |
873 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, port: control, |
874 | parameter: MMAL_PARAMETER_EXP_METERING_MODE, |
875 | value: &metering_mode, |
876 | value_size: sizeof(u32)); |
877 | ret += set_framerate_params(dev); |
878 | } |
879 | if (ret) { |
880 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
881 | "%s: Setting scene to %d, ret=%d\n" , |
882 | __func__, ctrl->val, ret); |
883 | ret = -EINVAL; |
884 | } |
885 | return 0; |
886 | } |
887 | |
888 | static int bcm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl) |
889 | { |
890 | struct bcm2835_mmal_dev *dev = container_of(ctrl->handler, struct bcm2835_mmal_dev, |
891 | ctrl_handler); |
892 | const struct bcm2835_mmal_v4l2_ctrl *mmal_ctrl = ctrl->priv; |
893 | int ret; |
894 | |
895 | if (!mmal_ctrl || mmal_ctrl->id != ctrl->id || !mmal_ctrl->setter) { |
896 | pr_warn("mmal_ctrl:%p ctrl id:%d\n" , mmal_ctrl, ctrl->id); |
897 | return -EINVAL; |
898 | } |
899 | |
900 | ret = mmal_ctrl->setter(dev, ctrl, mmal_ctrl); |
901 | if (ret) |
902 | pr_warn("ctrl id:%d/MMAL param %08X- returned ret %d\n" , |
903 | ctrl->id, mmal_ctrl->mmal_id, ret); |
904 | return ret; |
905 | } |
906 | |
907 | static const struct v4l2_ctrl_ops bcm2835_mmal_ctrl_ops = { |
908 | .s_ctrl = bcm2835_mmal_s_ctrl, |
909 | }; |
910 | |
911 | static const struct bcm2835_mmal_v4l2_ctrl v4l2_ctrls[V4L2_CTRL_COUNT] = { |
912 | { |
913 | .id = V4L2_CID_SATURATION, |
914 | .type = MMAL_CONTROL_TYPE_STD, |
915 | .min = -100, |
916 | .max = 100, |
917 | .def = 0, |
918 | .step = 1, |
919 | .imenu = NULL, |
920 | .mmal_id = MMAL_PARAMETER_SATURATION, |
921 | .setter = ctrl_set_rational, |
922 | }, |
923 | { |
924 | .id = V4L2_CID_SHARPNESS, |
925 | .type = MMAL_CONTROL_TYPE_STD, |
926 | .min = -100, |
927 | .max = 100, |
928 | .def = 0, |
929 | .step = 1, |
930 | .imenu = NULL, |
931 | .mmal_id = MMAL_PARAMETER_SHARPNESS, |
932 | .setter = ctrl_set_rational, |
933 | }, |
934 | { |
935 | .id = V4L2_CID_CONTRAST, |
936 | .type = MMAL_CONTROL_TYPE_STD, |
937 | .min = -100, |
938 | .max = 100, |
939 | .def = 0, |
940 | .step = 1, |
941 | .imenu = NULL, |
942 | .mmal_id = MMAL_PARAMETER_CONTRAST, |
943 | .setter = ctrl_set_rational, |
944 | }, |
945 | { |
946 | .id = V4L2_CID_BRIGHTNESS, |
947 | .type = MMAL_CONTROL_TYPE_STD, |
948 | .min = 0, |
949 | .max = 100, |
950 | .def = 50, |
951 | .step = 1, |
952 | .imenu = NULL, |
953 | .mmal_id = MMAL_PARAMETER_BRIGHTNESS, |
954 | .setter = ctrl_set_rational, |
955 | }, |
956 | { |
957 | .id = V4L2_CID_ISO_SENSITIVITY, |
958 | .type = MMAL_CONTROL_TYPE_INT_MENU, |
959 | .min = 0, |
960 | .max = ARRAY_SIZE(iso_qmenu) - 1, |
961 | .def = 0, |
962 | .step = 1, |
963 | .imenu = iso_qmenu, |
964 | .mmal_id = MMAL_PARAMETER_ISO, |
965 | .setter = ctrl_set_iso, |
966 | }, |
967 | { |
968 | .id = V4L2_CID_ISO_SENSITIVITY_AUTO, |
969 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
970 | .min = 0, |
971 | .max = V4L2_ISO_SENSITIVITY_AUTO, |
972 | .def = V4L2_ISO_SENSITIVITY_AUTO, |
973 | .step = 1, |
974 | .imenu = NULL, |
975 | .mmal_id = MMAL_PARAMETER_ISO, |
976 | .setter = ctrl_set_iso, |
977 | }, |
978 | { |
979 | .id = V4L2_CID_IMAGE_STABILIZATION, |
980 | .type = MMAL_CONTROL_TYPE_STD, |
981 | .min = 0, |
982 | .max = 1, |
983 | .def = 0, |
984 | .step = 1, |
985 | .imenu = NULL, |
986 | .mmal_id = MMAL_PARAMETER_VIDEO_STABILISATION, |
987 | .setter = ctrl_set_value, |
988 | }, |
989 | { |
990 | .id = V4L2_CID_EXPOSURE_AUTO, |
991 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
992 | .min = ~0x03, |
993 | .max = V4L2_EXPOSURE_APERTURE_PRIORITY, |
994 | .def = V4L2_EXPOSURE_AUTO, |
995 | .step = 0, |
996 | .imenu = NULL, |
997 | .mmal_id = MMAL_PARAMETER_EXPOSURE_MODE, |
998 | .setter = ctrl_set_exposure, |
999 | }, |
1000 | { |
1001 | .id = V4L2_CID_EXPOSURE_ABSOLUTE, |
1002 | .type = MMAL_CONTROL_TYPE_STD, |
1003 | /* Units of 100usecs */ |
1004 | .min = 1, |
1005 | .max = 1 * 1000 * 10, |
1006 | .def = 100 * 10, |
1007 | .step = 1, |
1008 | .imenu = NULL, |
1009 | .mmal_id = MMAL_PARAMETER_SHUTTER_SPEED, |
1010 | .setter = ctrl_set_exposure, |
1011 | }, |
1012 | { |
1013 | .id = V4L2_CID_AUTO_EXPOSURE_BIAS, |
1014 | .type = MMAL_CONTROL_TYPE_INT_MENU, |
1015 | .min = 0, |
1016 | .max = ARRAY_SIZE(ev_bias_qmenu) - 1, |
1017 | .def = (ARRAY_SIZE(ev_bias_qmenu) + 1) / 2 - 1, |
1018 | .step = 0, |
1019 | .imenu = ev_bias_qmenu, |
1020 | .mmal_id = MMAL_PARAMETER_EXPOSURE_COMP, |
1021 | .setter = ctrl_set_value_ev, |
1022 | }, |
1023 | { |
1024 | .id = V4L2_CID_EXPOSURE_AUTO_PRIORITY, |
1025 | .type = MMAL_CONTROL_TYPE_STD, |
1026 | .min = 0, |
1027 | .max = 1, |
1028 | .def = 0, |
1029 | .step = 1, |
1030 | .imenu = NULL, |
1031 | /* Dummy MMAL ID as it gets mapped into FPS range */ |
1032 | .mmal_id = 0, |
1033 | .setter = ctrl_set_exposure, |
1034 | }, |
1035 | { |
1036 | .id = V4L2_CID_EXPOSURE_METERING, |
1037 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1038 | .min = ~0xf, |
1039 | .max = V4L2_EXPOSURE_METERING_MATRIX, |
1040 | .def = V4L2_EXPOSURE_METERING_AVERAGE, |
1041 | .step = 0, |
1042 | .imenu = NULL, |
1043 | .mmal_id = MMAL_PARAMETER_EXP_METERING_MODE, |
1044 | .setter = ctrl_set_metering_mode, |
1045 | }, |
1046 | { |
1047 | .id = V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE, |
1048 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1049 | .min = ~0x3ff, |
1050 | .max = V4L2_WHITE_BALANCE_SHADE, |
1051 | .def = V4L2_WHITE_BALANCE_AUTO, |
1052 | .step = 0, |
1053 | .imenu = NULL, |
1054 | .mmal_id = MMAL_PARAMETER_AWB_MODE, |
1055 | .setter = ctrl_set_awb_mode, |
1056 | }, |
1057 | { |
1058 | .id = V4L2_CID_RED_BALANCE, |
1059 | .type = MMAL_CONTROL_TYPE_STD, |
1060 | .min = 1, |
1061 | .max = 7999, |
1062 | .def = 1000, |
1063 | .step = 1, |
1064 | .imenu = NULL, |
1065 | .mmal_id = MMAL_PARAMETER_CUSTOM_AWB_GAINS, |
1066 | .setter = ctrl_set_awb_gains, |
1067 | }, |
1068 | { |
1069 | .id = V4L2_CID_BLUE_BALANCE, |
1070 | .type = MMAL_CONTROL_TYPE_STD, |
1071 | .min = 1, |
1072 | .max = 7999, |
1073 | .def = 1000, |
1074 | .step = 1, |
1075 | .imenu = NULL, |
1076 | .mmal_id = MMAL_PARAMETER_CUSTOM_AWB_GAINS, |
1077 | .setter = ctrl_set_awb_gains, |
1078 | }, |
1079 | { |
1080 | .id = V4L2_CID_COLORFX, |
1081 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1082 | .min = 0, |
1083 | .max = V4L2_COLORFX_SET_CBCR, |
1084 | .def = V4L2_COLORFX_NONE, |
1085 | .step = 0, |
1086 | .imenu = NULL, |
1087 | .mmal_id = MMAL_PARAMETER_IMAGE_EFFECT, |
1088 | .setter = ctrl_set_image_effect, |
1089 | }, |
1090 | { |
1091 | .id = V4L2_CID_COLORFX_CBCR, |
1092 | .type = MMAL_CONTROL_TYPE_STD, |
1093 | .min = 0, |
1094 | .max = 0xffff, |
1095 | .def = 0x8080, |
1096 | .step = 1, |
1097 | .imenu = NULL, |
1098 | .mmal_id = MMAL_PARAMETER_COLOUR_EFFECT, |
1099 | .setter = ctrl_set_colfx, |
1100 | }, |
1101 | { |
1102 | .id = V4L2_CID_ROTATE, |
1103 | .type = MMAL_CONTROL_TYPE_STD, |
1104 | .min = 0, |
1105 | .max = 360, |
1106 | .def = 0, |
1107 | .step = 90, |
1108 | .imenu = NULL, |
1109 | .mmal_id = MMAL_PARAMETER_ROTATION, |
1110 | .setter = ctrl_set_rotate, |
1111 | }, |
1112 | { |
1113 | .id = V4L2_CID_HFLIP, |
1114 | .type = MMAL_CONTROL_TYPE_STD, |
1115 | .min = 0, |
1116 | .max = 1, |
1117 | .def = 0, |
1118 | .step = 1, |
1119 | .imenu = NULL, |
1120 | .mmal_id = MMAL_PARAMETER_MIRROR, |
1121 | .setter = ctrl_set_flip, |
1122 | }, |
1123 | { |
1124 | .id = V4L2_CID_VFLIP, |
1125 | .type = MMAL_CONTROL_TYPE_STD, |
1126 | .min = 0, |
1127 | .max = 1, |
1128 | .def = 0, |
1129 | .step = 1, |
1130 | .imenu = NULL, |
1131 | .mmal_id = MMAL_PARAMETER_MIRROR, |
1132 | .setter = ctrl_set_flip, |
1133 | }, |
1134 | { |
1135 | .id = V4L2_CID_MPEG_VIDEO_BITRATE_MODE, |
1136 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1137 | .min = 0, |
1138 | .max = V4L2_MPEG_VIDEO_BITRATE_MODE_CBR, |
1139 | .def = 0, |
1140 | .step = 0, |
1141 | .imenu = NULL, |
1142 | .mmal_id = MMAL_PARAMETER_RATECONTROL, |
1143 | .setter = ctrl_set_bitrate_mode, |
1144 | }, |
1145 | { |
1146 | .id = V4L2_CID_MPEG_VIDEO_BITRATE, |
1147 | .type = MMAL_CONTROL_TYPE_STD, |
1148 | .min = 25 * 1000, |
1149 | .max = 25 * 1000 * 1000, |
1150 | .def = 10 * 1000 * 1000, |
1151 | .step = 25 * 1000, |
1152 | .imenu = NULL, |
1153 | .mmal_id = MMAL_PARAMETER_VIDEO_BIT_RATE, |
1154 | .setter = ctrl_set_bitrate, |
1155 | }, |
1156 | { |
1157 | .id = V4L2_CID_JPEG_COMPRESSION_QUALITY, |
1158 | .type = MMAL_CONTROL_TYPE_STD, |
1159 | .min = 1, |
1160 | .max = 100, |
1161 | .def = 30, |
1162 | .step = 1, |
1163 | .imenu = NULL, |
1164 | .mmal_id = MMAL_PARAMETER_JPEG_Q_FACTOR, |
1165 | .setter = ctrl_set_image_encode_output, |
1166 | }, |
1167 | { |
1168 | .id = V4L2_CID_POWER_LINE_FREQUENCY, |
1169 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1170 | .min = 0, |
1171 | .max = V4L2_CID_POWER_LINE_FREQUENCY_AUTO, |
1172 | .def = 1, |
1173 | .step = 1, |
1174 | .imenu = NULL, |
1175 | .mmal_id = MMAL_PARAMETER_FLICKER_AVOID, |
1176 | .setter = ctrl_set_flicker_avoidance, |
1177 | }, |
1178 | { |
1179 | .id = V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, |
1180 | .type = MMAL_CONTROL_TYPE_STD, |
1181 | .min = 0, |
1182 | .max = 1, |
1183 | .def = 0, |
1184 | .step = 1, |
1185 | .imenu = NULL, |
1186 | .mmal_id = MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, |
1187 | .setter = ctrl_set_video_encode_param_output, |
1188 | }, |
1189 | { |
1190 | .id = V4L2_CID_MPEG_VIDEO_H264_PROFILE, |
1191 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1192 | .min = ~(BIT(V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE) | |
1193 | BIT(V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE) | |
1194 | BIT(V4L2_MPEG_VIDEO_H264_PROFILE_MAIN) | |
1195 | BIT(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH)), |
1196 | .max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, |
1197 | .def = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH, |
1198 | .step = 1, |
1199 | .imenu = NULL, |
1200 | .mmal_id = MMAL_PARAMETER_PROFILE, |
1201 | .setter = ctrl_set_video_encode_profile_level, |
1202 | }, |
1203 | { |
1204 | .id = V4L2_CID_MPEG_VIDEO_H264_LEVEL, |
1205 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1206 | .min = ~(BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_0) | |
1207 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1B) | |
1208 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_1) | |
1209 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_2) | |
1210 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_1_3) | |
1211 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_0) | |
1212 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_1) | |
1213 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_2_2) | |
1214 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_0) | |
1215 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_1) | |
1216 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_3_2) | |
1217 | BIT(V4L2_MPEG_VIDEO_H264_LEVEL_4_0)), |
1218 | .max = V4L2_MPEG_VIDEO_H264_LEVEL_4_0, |
1219 | .def = V4L2_MPEG_VIDEO_H264_LEVEL_4_0, |
1220 | .step = 1, |
1221 | .imenu = NULL, |
1222 | .mmal_id = MMAL_PARAMETER_PROFILE, |
1223 | .setter = ctrl_set_video_encode_profile_level, |
1224 | }, |
1225 | { |
1226 | .id = V4L2_CID_SCENE_MODE, |
1227 | .type = MMAL_CONTROL_TYPE_STD_MENU, |
1228 | /* mask is computed at runtime */ |
1229 | .min = -1, |
1230 | .max = V4L2_SCENE_MODE_TEXT, |
1231 | .def = V4L2_SCENE_MODE_NONE, |
1232 | .step = 1, |
1233 | .imenu = NULL, |
1234 | .mmal_id = MMAL_PARAMETER_PROFILE, |
1235 | .setter = ctrl_set_scene_mode, |
1236 | }, |
1237 | { |
1238 | .id = V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, |
1239 | .type = MMAL_CONTROL_TYPE_STD, |
1240 | .min = 0, |
1241 | .max = 0x7FFFFFFF, |
1242 | .def = 60, |
1243 | .step = 1, |
1244 | .imenu = NULL, |
1245 | .mmal_id = MMAL_PARAMETER_INTRAPERIOD, |
1246 | .setter = ctrl_set_video_encode_param_output, |
1247 | }, |
1248 | }; |
1249 | |
1250 | int bcm2835_mmal_set_all_camera_controls(struct bcm2835_mmal_dev *dev) |
1251 | { |
1252 | int c; |
1253 | int ret = 0; |
1254 | |
1255 | for (c = 0; c < V4L2_CTRL_COUNT; c++) { |
1256 | if ((dev->ctrls[c]) && (v4l2_ctrls[c].setter)) { |
1257 | ret = v4l2_ctrls[c].setter(dev, dev->ctrls[c], |
1258 | &v4l2_ctrls[c]); |
1259 | if (ret) { |
1260 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
1261 | "Failed when setting default values for ctrl %d\n" , |
1262 | c); |
1263 | break; |
1264 | } |
1265 | } |
1266 | } |
1267 | return ret; |
1268 | } |
1269 | |
1270 | int set_framerate_params(struct bcm2835_mmal_dev *dev) |
1271 | { |
1272 | struct mmal_parameter_fps_range fps_range; |
1273 | int ret; |
1274 | |
1275 | fps_range.fps_high.numerator = dev->capture.timeperframe.denominator; |
1276 | fps_range.fps_high.denominator = dev->capture.timeperframe.numerator; |
1277 | |
1278 | if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) && |
1279 | (dev->exp_auto_priority)) { |
1280 | /* Variable FPS. Define min FPS as 1fps. */ |
1281 | fps_range.fps_low.numerator = 1; |
1282 | fps_range.fps_low.denominator = 1; |
1283 | } else { |
1284 | /* Fixed FPS - set min and max to be the same */ |
1285 | fps_range.fps_low.numerator = fps_range.fps_high.numerator; |
1286 | fps_range.fps_low.denominator = fps_range.fps_high.denominator; |
1287 | } |
1288 | |
1289 | v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev, |
1290 | "Set fps range to %d/%d to %d/%d\n" , |
1291 | fps_range.fps_low.numerator, |
1292 | fps_range.fps_low.denominator, |
1293 | fps_range.fps_high.numerator, |
1294 | fps_range.fps_high.denominator); |
1295 | |
1296 | ret = vchiq_mmal_port_parameter_set(instance: dev->instance, |
1297 | port: &dev->component[COMP_CAMERA]->output[CAM_PORT_PREVIEW], |
1298 | parameter: MMAL_PARAMETER_FPS_RANGE, |
1299 | value: &fps_range, value_size: sizeof(fps_range)); |
1300 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, |
1301 | port: &dev->component[COMP_CAMERA]->output[CAM_PORT_VIDEO], |
1302 | parameter: MMAL_PARAMETER_FPS_RANGE, |
1303 | value: &fps_range, value_size: sizeof(fps_range)); |
1304 | ret += vchiq_mmal_port_parameter_set(instance: dev->instance, |
1305 | port: &dev->component[COMP_CAMERA]->output[CAM_PORT_CAPTURE], |
1306 | parameter: MMAL_PARAMETER_FPS_RANGE, |
1307 | value: &fps_range, value_size: sizeof(fps_range)); |
1308 | if (ret) |
1309 | v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev, |
1310 | "Failed to set fps ret %d\n" , ret); |
1311 | |
1312 | return ret; |
1313 | } |
1314 | |
1315 | int bcm2835_mmal_init_controls(struct bcm2835_mmal_dev *dev, struct v4l2_ctrl_handler *hdl) |
1316 | { |
1317 | int c; |
1318 | const struct bcm2835_mmal_v4l2_ctrl *ctrl; |
1319 | |
1320 | v4l2_ctrl_handler_init(hdl, V4L2_CTRL_COUNT); |
1321 | |
1322 | for (c = 0; c < V4L2_CTRL_COUNT; c++) { |
1323 | ctrl = &v4l2_ctrls[c]; |
1324 | |
1325 | switch (ctrl->type) { |
1326 | case MMAL_CONTROL_TYPE_STD: |
1327 | dev->ctrls[c] = v4l2_ctrl_new_std(hdl, ops: &bcm2835_mmal_ctrl_ops, |
1328 | id: ctrl->id, min: ctrl->min, max: ctrl->max, |
1329 | step: ctrl->step, def: ctrl->def); |
1330 | break; |
1331 | |
1332 | case MMAL_CONTROL_TYPE_STD_MENU: |
1333 | { |
1334 | u64 mask = ctrl->min; |
1335 | |
1336 | if (ctrl->id == V4L2_CID_SCENE_MODE) { |
1337 | /* Special handling to work out the mask |
1338 | * value based on the scene_configs array |
1339 | * at runtime. Reduces the chance of |
1340 | * mismatches. |
1341 | */ |
1342 | int i; |
1343 | |
1344 | mask = BIT(V4L2_SCENE_MODE_NONE); |
1345 | for (i = 0; |
1346 | i < ARRAY_SIZE(scene_configs); |
1347 | i++) { |
1348 | mask |= BIT(scene_configs[i].v4l2_scene); |
1349 | } |
1350 | mask = ~mask; |
1351 | } |
1352 | |
1353 | dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl, ops: &bcm2835_mmal_ctrl_ops, |
1354 | id: ctrl->id, max: ctrl->max, mask, |
1355 | def: ctrl->def); |
1356 | break; |
1357 | } |
1358 | |
1359 | case MMAL_CONTROL_TYPE_INT_MENU: |
1360 | dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl, ops: &bcm2835_mmal_ctrl_ops, |
1361 | id: ctrl->id, max: ctrl->max, |
1362 | def: ctrl->def, qmenu_int: ctrl->imenu); |
1363 | break; |
1364 | |
1365 | case MMAL_CONTROL_TYPE_CLUSTER: |
1366 | /* skip this entry when constructing controls */ |
1367 | continue; |
1368 | } |
1369 | |
1370 | if (hdl->error) |
1371 | break; |
1372 | |
1373 | dev->ctrls[c]->priv = (void *)ctrl; |
1374 | } |
1375 | |
1376 | if (hdl->error) { |
1377 | pr_err("error adding control %d/%d id 0x%x\n" , c, |
1378 | V4L2_CTRL_COUNT, ctrl->id); |
1379 | return hdl->error; |
1380 | } |
1381 | |
1382 | for (c = 0; c < V4L2_CTRL_COUNT; c++) { |
1383 | ctrl = &v4l2_ctrls[c]; |
1384 | |
1385 | switch (ctrl->type) { |
1386 | case MMAL_CONTROL_TYPE_CLUSTER: |
1387 | v4l2_ctrl_auto_cluster(ncontrols: ctrl->min, |
1388 | controls: &dev->ctrls[c + 1], |
1389 | manual_val: ctrl->max, |
1390 | set_volatile: ctrl->def); |
1391 | break; |
1392 | |
1393 | case MMAL_CONTROL_TYPE_STD: |
1394 | case MMAL_CONTROL_TYPE_STD_MENU: |
1395 | case MMAL_CONTROL_TYPE_INT_MENU: |
1396 | break; |
1397 | } |
1398 | } |
1399 | |
1400 | return 0; |
1401 | } |
1402 | |