brcm2708: update against latest rpi-3.10.y branch
[openwrt.git] / target / linux / brcm2708 / patches-3.10 / 0173-V4L2-Initial-pass-at-scene-modes.patch
1 From ba09044961948d93db7aa166f2829d46e81e875a Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dsteve@broadcom.com>
3 Date: Fri, 14 Feb 2014 17:12:08 +0000
4 Subject: [PATCH 173/174] V4L2: Initial pass at scene modes.
5
6 Only supports exposure mode and metering modes.
7
8 Signed-off-by: Dave Stevenson <dsteve@broadcom.com>
9 ---
10  drivers/media/platform/bcm2835/bcm2835-camera.h |  10 +-
11  drivers/media/platform/bcm2835/controls.c       | 225 ++++++++++++++++++++----
12  2 files changed, 199 insertions(+), 36 deletions(-)
13
14 --- a/drivers/media/platform/bcm2835/bcm2835-camera.h
15 +++ b/drivers/media/platform/bcm2835/bcm2835-camera.h
16 @@ -15,7 +15,7 @@
17   * core driver device
18   */
19  
20 -#define V4L2_CTRL_COUNT 24 /* number of v4l controls */
21 +#define V4L2_CTRL_COUNT 25 /* number of v4l controls */
22  
23  enum {
24         MMAL_COMPONENT_CAMERA = 0,
25 @@ -45,11 +45,15 @@ struct bm2835_mmal_dev {
26         /* controls */
27         struct v4l2_ctrl_handler  ctrl_handler;
28         struct v4l2_ctrl          *ctrls[V4L2_CTRL_COUNT];
29 +       enum v4l2_scene_mode      scene_mode;
30         struct mmal_colourfx      colourfx;
31         int                       hflip;
32         int                       vflip;
33 -       enum mmal_parameter_exposuremode exposure_mode;
34 -       enum v4l2_exposure_auto_type exposure_mode_v4l2;
35 +       enum mmal_parameter_exposuremode exposure_mode_user;
36 +       enum v4l2_exposure_auto_type exposure_mode_v4l2_user;
37 +       /* active exposure mode may differ if selected via a scene mode */
38 +       enum mmal_parameter_exposuremode exposure_mode_active;
39 +       enum mmal_parameter_exposuremeteringmode metering_mode;
40         unsigned int              manual_shutter_speed;
41         bool                      exp_auto_priority;
42  
43 --- a/drivers/media/platform/bcm2835/controls.c
44 +++ b/drivers/media/platform/bcm2835/controls.c
45 @@ -145,6 +145,25 @@ static const struct v4l2_to_mmal_effects
46                 1,   1,    0,    0,   0, {0, 0, 0, 0, 0} }
47  };
48  
49 +struct v4l2_mmal_scene_config {
50 +       enum v4l2_scene_mode                    v4l2_scene;
51 +       enum mmal_parameter_exposuremode        exposure_mode;
52 +       enum mmal_parameter_exposuremeteringmode metering_mode;
53 +};
54 +
55 +static const struct v4l2_mmal_scene_config scene_configs[] = {
56 +       /* V4L2_SCENE_MODE_NONE automatically added */
57 +       {
58 +               V4L2_SCENE_MODE_NIGHT,
59 +               MMAL_PARAM_EXPOSUREMODE_NIGHT,
60 +               MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
61 +       },
62 +       {
63 +               V4L2_SCENE_MODE_SPORTS,
64 +               MMAL_PARAM_EXPOSUREMODE_SPORTS,
65 +               MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE
66 +       },
67 +};
68  
69  /* control handlers*/
70  
71 @@ -296,7 +315,7 @@ static int ctrl_set_exposure(struct bm28
72                       struct v4l2_ctrl *ctrl,
73                       const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
74  {
75 -       enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode;
76 +       enum mmal_parameter_exposuremode exp_mode = dev->exposure_mode_user;
77         u32 shutter_speed = 0;
78         struct vchiq_mmal_port *control;
79         int ret = 0;
80 @@ -317,31 +336,32 @@ static int ctrl_set_exposure(struct bm28
81                 case V4L2_EXPOSURE_MANUAL:
82                         exp_mode = MMAL_PARAM_EXPOSUREMODE_OFF;
83                         break;
84 -
85 -               case V4L2_EXPOSURE_SHUTTER_PRIORITY:
86 -                       exp_mode = MMAL_PARAM_EXPOSUREMODE_SPORTS;
87 -                       break;
88 -
89 -               case V4L2_EXPOSURE_APERTURE_PRIORITY:
90 -                       exp_mode = MMAL_PARAM_EXPOSUREMODE_NIGHT;
91 -                       break;
92 -
93                 }
94 -               dev->exposure_mode = exp_mode;
95 -               dev->exposure_mode_v4l2 = ctrl->val;
96 +               dev->exposure_mode_user = exp_mode;
97 +               dev->exposure_mode_v4l2_user = ctrl->val;
98         } else if (mmal_ctrl->id == V4L2_CID_EXPOSURE_AUTO_PRIORITY) {
99                 dev->exp_auto_priority = ctrl->val;
100         }
101  
102 -       if (dev->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
103 -               shutter_speed = dev->manual_shutter_speed;
104 +       if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
105 +               if (exp_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
106 +                       shutter_speed = dev->manual_shutter_speed;
107  
108 -       ret = vchiq_mmal_port_parameter_set(dev->instance, control,
109 -                                    MMAL_PARAMETER_SHUTTER_SPEED,
110 -                                    &shutter_speed, sizeof(shutter_speed));
111 -       ret += vchiq_mmal_port_parameter_set(dev->instance, control,
112 -                                            MMAL_PARAMETER_EXPOSURE_MODE,
113 -                                            &exp_mode, sizeof(u32));
114 +               ret = vchiq_mmal_port_parameter_set(dev->instance,
115 +                                       control,
116 +                                       MMAL_PARAMETER_SHUTTER_SPEED,
117 +                                       &shutter_speed,
118 +                                       sizeof(shutter_speed));
119 +               ret += vchiq_mmal_port_parameter_set(dev->instance,
120 +                                       control,
121 +                                       MMAL_PARAMETER_EXPOSURE_MODE,
122 +                                       &exp_mode,
123 +                                       sizeof(u32));
124 +               dev->exposure_mode_active = exp_mode;
125 +       }
126 +       /* exposure_dynamic_framerate (V4L2_CID_EXPOSURE_AUTO_PRIORITY) should
127 +        * always apply irrespective of scene mode.
128 +        */
129         ret += set_framerate_params(dev);
130  
131         return ret;
132 @@ -351,35 +371,38 @@ static int ctrl_set_metering_mode(struct
133                            struct v4l2_ctrl *ctrl,
134                            const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
135  {
136 -       u32 u32_value;
137 -       struct vchiq_mmal_port *control;
138 -
139 -       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
140 -
141         switch (ctrl->val) {
142         case V4L2_EXPOSURE_METERING_AVERAGE:
143 -               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
144 +               dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
145                 break;
146  
147         case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
148 -               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
149 +               dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_BACKLIT;
150                 break;
151  
152         case V4L2_EXPOSURE_METERING_SPOT:
153 -               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
154 +               dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_SPOT;
155                 break;
156  
157         /* todo matrix weighting not added to Linux API till 3.9
158         case V4L2_EXPOSURE_METERING_MATRIX:
159 -               u32_value = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
160 +               dev->metering_mode = MMAL_PARAM_EXPOSUREMETERINGMODE_MATRIX;
161                 break;
162         */
163  
164         }
165  
166 -       return vchiq_mmal_port_parameter_set(dev->instance, control,
167 +       if (dev->scene_mode == V4L2_SCENE_MODE_NONE) {
168 +               struct vchiq_mmal_port *control;
169 +               u32 u32_value = dev->metering_mode;
170 +
171 +               control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
172 +
173 +               return vchiq_mmal_port_parameter_set(dev->instance, control,
174                                              mmal_ctrl->mmal_id,
175                                              &u32_value, sizeof(u32_value));
176 +       } else
177 +               return 0;
178  }
179  
180  static int ctrl_set_flicker_avoidance(struct bm2835_mmal_dev *dev,
181 @@ -738,6 +761,113 @@ static int ctrl_set_video_encode_profile
182         return ret;
183  }
184  
185 +static int ctrl_set_scene_mode(struct bm2835_mmal_dev *dev,
186 +                     struct v4l2_ctrl *ctrl,
187 +                     const struct bm2835_mmal_v4l2_ctrl *mmal_ctrl)
188 +{
189 +       int ret = 0;
190 +       int shutter_speed;
191 +       struct vchiq_mmal_port *control;
192 +
193 +       v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
194 +               "scene mode selected %d, was %d\n", ctrl->val,
195 +               dev->scene_mode);
196 +       control = &dev->component[MMAL_COMPONENT_CAMERA]->control;
197 +
198 +       if (ctrl->val == dev->scene_mode)
199 +               return 0;
200 +
201 +       if (ctrl->val == V4L2_SCENE_MODE_NONE) {
202 +               /* Restore all user selections */
203 +               dev->scene_mode = V4L2_SCENE_MODE_NONE;
204 +
205 +               if (dev->exposure_mode_user == MMAL_PARAM_EXPOSUREMODE_OFF)
206 +                       shutter_speed = dev->manual_shutter_speed;
207 +               else
208 +                       shutter_speed = 0;
209 +
210 +               v4l2_dbg(0, bcm2835_v4l2_debug, &dev->v4l2_dev,
211 +                       "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
212 +                       __func__, shutter_speed, dev->exposure_mode_user,
213 +                       dev->metering_mode);
214 +               ret = vchiq_mmal_port_parameter_set(dev->instance,
215 +                                       control,
216 +                                       MMAL_PARAMETER_SHUTTER_SPEED,
217 +                                       &shutter_speed,
218 +                                       sizeof(shutter_speed));
219 +               ret += vchiq_mmal_port_parameter_set(dev->instance,
220 +                                       control,
221 +                                       MMAL_PARAMETER_EXPOSURE_MODE,
222 +                                       &dev->exposure_mode_user,
223 +                                       sizeof(u32));
224 +               dev->exposure_mode_active = dev->exposure_mode_user;
225 +               ret += vchiq_mmal_port_parameter_set(dev->instance,
226 +                                       control,
227 +                                       MMAL_PARAMETER_EXP_METERING_MODE,
228 +                                       &dev->metering_mode,
229 +                                       sizeof(u32));
230 +               ret += set_framerate_params(dev);
231 +       } else {
232 +               /* Set up scene mode */
233 +               int i;
234 +               const struct v4l2_mmal_scene_config *scene = NULL;
235 +               int shutter_speed;
236 +               enum mmal_parameter_exposuremode exposure_mode;
237 +               enum mmal_parameter_exposuremeteringmode metering_mode;
238 +
239 +               for (i = 0; i < ARRAY_SIZE(scene_configs); i++) {
240 +                       if (scene_configs[i].v4l2_scene ==
241 +                               ctrl->val) {
242 +                               scene = &scene_configs[i];
243 +                               break;
244 +                       }
245 +               }
246 +               if (i >= ARRAY_SIZE(scene_configs))
247 +                       return -EINVAL;
248 +
249 +               /* Set all the values */
250 +               dev->scene_mode = ctrl->val;
251 +
252 +               if (scene->exposure_mode == MMAL_PARAM_EXPOSUREMODE_OFF)
253 +                       shutter_speed = dev->manual_shutter_speed;
254 +               else
255 +                       shutter_speed = 0;
256 +               exposure_mode = scene->exposure_mode;
257 +               metering_mode = scene->metering_mode;
258 +
259 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
260 +                       "%s: scene mode none: shut_speed %d, exp_mode %d, metering %d\n",
261 +                       __func__, shutter_speed, exposure_mode, metering_mode);
262 +
263 +               ret = vchiq_mmal_port_parameter_set(dev->instance, control,
264 +                                       MMAL_PARAMETER_SHUTTER_SPEED,
265 +                                       &shutter_speed,
266 +                                       sizeof(shutter_speed));
267 +               ret += vchiq_mmal_port_parameter_set(dev->instance,
268 +                                       control,
269 +                                       MMAL_PARAMETER_EXPOSURE_MODE,
270 +                                       &exposure_mode,
271 +                                       sizeof(u32));
272 +               dev->exposure_mode_active = exposure_mode;
273 +               ret += vchiq_mmal_port_parameter_set(dev->instance, control,
274 +                                       MMAL_PARAMETER_EXPOSURE_MODE,
275 +                                       &exposure_mode,
276 +                                       sizeof(u32));
277 +               ret += vchiq_mmal_port_parameter_set(dev->instance, control,
278 +                                       MMAL_PARAMETER_EXP_METERING_MODE,
279 +                                       &metering_mode,
280 +                                       sizeof(u32));
281 +               ret += set_framerate_params(dev);
282 +       }
283 +       if (ret) {
284 +               v4l2_dbg(1, bcm2835_v4l2_debug, &dev->v4l2_dev,
285 +                       "%s: Setting scene to %d, ret=%d\n",
286 +                       __func__, ctrl->val, ret);
287 +               ret = -EINVAL;
288 +       }
289 +       return 0;
290 +}
291 +
292  static int bm2835_mmal_s_ctrl(struct v4l2_ctrl *ctrl)
293  {
294         struct bm2835_mmal_dev *dev =
295 @@ -973,6 +1103,15 @@ static const struct bm2835_mmal_v4l2_ctr
296                 &ctrl_set_video_encode_profile_level,
297                 false
298         },
299 +       {
300 +               V4L2_CID_SCENE_MODE, MMAL_CONTROL_TYPE_STD_MENU,
301 +               -1,     /* Min is computed at runtime */
302 +               V4L2_SCENE_MODE_TEXT,
303 +               V4L2_SCENE_MODE_NONE, 1, NULL,
304 +               MMAL_PARAMETER_PROFILE,
305 +               &ctrl_set_scene_mode,
306 +               false
307 +       },
308  };
309  
310  int bm2835_mmal_set_all_camera_controls(struct bm2835_mmal_dev *dev)
311 @@ -1000,8 +1139,7 @@ int set_framerate_params(struct bm2835_m
312         struct mmal_parameter_fps_range fps_range;
313         int ret;
314  
315 -       if ((dev->exposure_mode_v4l2 == V4L2_EXPOSURE_AUTO ||
316 -            dev->exposure_mode_v4l2 == V4L2_EXPOSURE_APERTURE_PRIORITY) &&
317 +       if ((dev->exposure_mode_active != MMAL_PARAM_EXPOSUREMODE_OFF) &&
318              (dev->exp_auto_priority)) {
319                 /* Variable FPS. Define min FPS as 1fps.
320                  * Max as max defined FPS.
321 @@ -1049,6 +1187,7 @@ int set_framerate_params(struct bm2835_m
322         return ret;
323  
324  }
325 +
326  int bm2835_mmal_init_controls(struct bm2835_mmal_dev *dev,
327                               struct v4l2_ctrl_handler *hdl)
328  {
329 @@ -1068,10 +1207,30 @@ int bm2835_mmal_init_controls(struct bm2
330                         break;
331  
332                 case MMAL_CONTROL_TYPE_STD_MENU:
333 +               {
334 +                       int mask = ctrl->min;
335 +
336 +                       if (ctrl->id == V4L2_CID_SCENE_MODE) {
337 +                               /* Special handling to work out the mask
338 +                                * value based on the scene_configs array
339 +                                * at runtime. Reduces the chance of
340 +                                * mismatches.
341 +                                */
342 +                               int i;
343 +                               mask = 1<<V4L2_SCENE_MODE_NONE;
344 +                               for (i = 0;
345 +                                    i < ARRAY_SIZE(scene_configs);
346 +                                    i++) {
347 +                                       mask |= 1<<scene_configs[i].v4l2_scene;
348 +                               }
349 +                               mask = ~mask;
350 +                       }
351 +
352                         dev->ctrls[c] = v4l2_ctrl_new_std_menu(hdl,
353                         &bm2835_mmal_ctrl_ops, ctrl->id,
354 -                       ctrl->max, ctrl->min, ctrl->def);
355 +                       ctrl->max, mask, ctrl->def);
356                         break;
357 +               }
358  
359                 case MMAL_CONTROL_TYPE_INT_MENU:
360                         dev->ctrls[c] = v4l2_ctrl_new_int_menu(hdl,