907bab5cfd4a34773b7e882017e6abee4dbfb6d0
[oweals/openwrt.git] /
1 From d9d333b717f220439868edd533994f2709b3a95f Mon Sep 17 00:00:00 2001
2 From: David Plowman <david.plowman@raspberrypi.com>
3 Date: Wed, 29 Jan 2020 15:31:23 +0000
4 Subject: [PATCH] media: ov5647: Add V4L2 controls for analogue gain,
5  exposure and AWB
6
7 Added basic v4l2_ctrl_handler infrastructure (there was none
8 previously).
9
10 Added controls to let AWB/AEC/AGC run in the sensor's auto mode or
11 manually. Also controls to set exposure (in lines) and analogue gain
12 (as a register code) from user code.
13
14 Also delete registers (just the one) from the VGA mode register set
15 that are now controlled by the new V4L2 controls.
16
17 Signed-off-by: David Plowman <david.plowman@raspberrypi.com>
18 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
19 ---
20  drivers/media/i2c/ov5647.c | 175 ++++++++++++++++++++++++++++++++++++-
21  1 file changed, 174 insertions(+), 1 deletion(-)
22
23 --- a/drivers/media/i2c/ov5647.c
24 +++ b/drivers/media/i2c/ov5647.c
25 @@ -29,11 +29,13 @@
26  #include <linux/of_graph.h>
27  #include <linux/slab.h>
28  #include <linux/videodev2.h>
29 +#include <media/v4l2-ctrls.h>
30  #include <media/v4l2-device.h>
31  #include <media/v4l2-fwnode.h>
32  #include <media/v4l2-image-sizes.h>
33  #include <media/v4l2-mediabus.h>
34  
35 +
36  #define SENSOR_NAME "ov5647"
37  
38  /*
39 @@ -53,9 +55,16 @@
40  #define OV5647_REG_CHIPID_H            0x300A
41  #define OV5647_REG_CHIPID_L            0x300B
42  #define OV5640_REG_PAD_OUT             0x300D
43 +#define OV5647_REG_EXP_HI              0x3500
44 +#define OV5647_REG_EXP_MID             0x3501
45 +#define OV5647_REG_EXP_LO              0x3502
46 +#define OV5647_REG_AEC_AGC             0x3503
47 +#define OV5647_REG_GAIN_HI             0x350A
48 +#define OV5647_REG_GAIN_LO             0x350B
49  #define OV5647_REG_FRAME_OFF_NUMBER    0x4202
50  #define OV5647_REG_MIPI_CTRL00         0x4800
51  #define OV5647_REG_MIPI_CTRL14         0x4814
52 +#define OV5647_REG_AWB                 0x5001
53  
54  #define REG_TERM 0xfffe
55  #define VAL_TERM 0xfe
56 @@ -101,6 +110,7 @@ struct ov5647 {
57         struct clk                      *xclk;
58         struct gpio_desc                *pwdn;
59         unsigned int                    flags;
60 +       struct v4l2_ctrl_handler        ctrls;
61  };
62  
63  static inline struct ov5647 *to_state(struct v4l2_subdev *sd)
64 @@ -135,7 +145,6 @@ static struct regval_list ov5647_640x480
65         {0x3612, 0x59},
66         {0x3618, 0x00},
67         {0x5000, 0x06},
68 -       {0x5001, 0x01},
69         {0x5002, 0x41},
70         {0x5003, 0x08},
71         {0x5a00, 0x08},
72 @@ -372,6 +381,11 @@ static int ov5647_stream_on(struct v4l2_
73                 return ret;
74         }
75  
76 +       /* Apply customized values from user when stream starts */
77 +       ret =  __v4l2_ctrl_handler_setup(sd->ctrl_handler);
78 +       if (ret)
79 +               return ret;
80 +
81         if (ov5647->flags & V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK)
82                 val |= MIPI_CTRL00_CLOCK_LANE_GATE |
83                        MIPI_CTRL00_LINE_SYNC_ENABLE;
84 @@ -753,6 +767,120 @@ static int ov5647_parse_dt(struct device
85         return ret;
86  }
87  
88 +static int ov5647_s_auto_white_balance(struct v4l2_subdev *sd, u32 val)
89 +{
90 +       /* non-zero turns on AWB */
91 +       return ov5647_write(sd, OV5647_REG_AWB, val ? 1 : 0);
92 +}
93 +
94 +static int ov5647_s_autogain(struct v4l2_subdev *sd, u32 val)
95 +{
96 +       int ret;
97 +       u8 reg;
98 +
99 +       /* non-zero turns on AGC by clearing bit 1 */
100 +       ret = ov5647_read(sd, OV5647_REG_AEC_AGC, &reg);
101 +       if (ret == 0)
102 +               ret = ov5647_write(sd, OV5647_REG_AEC_AGC,
103 +                                  val ? reg & ~2 : reg | 2);
104 +
105 +       return ret;
106 +}
107 +
108 +static int ov5647_s_exposure_auto(struct v4l2_subdev *sd, u32 val)
109 +{
110 +       int ret;
111 +       u8 reg;
112 +
113 +       /* Everything except V4L2_EXPOSURE_MANUAL turns on AEC by
114 +        * clearing bit 0
115 +        */
116 +       ret = ov5647_read(sd, OV5647_REG_AEC_AGC, &reg);
117 +       if (ret == 0)
118 +               ret = ov5647_write(sd, OV5647_REG_AEC_AGC,
119 +                                  val == V4L2_EXPOSURE_MANUAL ?
120 +                                  reg | 1 : reg & ~1);
121 +
122 +       return ret;
123 +}
124 +
125 +static int ov5647_s_analogue_gain(struct v4l2_subdev *sd, u32 val)
126 +{
127 +       int ret;
128 +
129 +       /* 10 bits of gain, 2 in the high register */
130 +       ret = ov5647_write(sd, OV5647_REG_GAIN_HI, (val >> 8) & 3);
131 +       if (ret == 0)
132 +               ret = ov5647_write(sd, OV5647_REG_GAIN_LO, val & 0xff);
133 +
134 +       return ret;
135 +}
136 +
137 +static int ov5647_s_exposure(struct v4l2_subdev *sd, u32 val)
138 +{
139 +       int ret;
140 +
141 +       /* Sensor has 20 bits, but the bottom 4 bits are fractions of a line
142 +        * which we leave as zero (and don't receive in "val").
143 +        */
144 +       ret = ov5647_write(sd, OV5647_REG_EXP_HI, (val >> 12) & 0xf);
145 +       if (ret == 0)
146 +               ov5647_write(sd, OV5647_REG_EXP_MID, (val >> 4) & 0xff);
147 +       if (ret == 0)
148 +               ov5647_write(sd, OV5647_REG_EXP_LO, (val & 0xf) << 4);
149 +
150 +       return ret;
151 +}
152 +
153 +static int ov5647_s_ctrl(struct v4l2_ctrl *ctrl)
154 +{
155 +       struct ov5647 *state = container_of(ctrl->handler,
156 +                                            struct ov5647, ctrls);
157 +       struct v4l2_subdev *sd = &state->sd;
158 +       struct i2c_client *client = v4l2_get_subdevdata(sd);
159 +       int ret = 0;
160 +
161 +       /* v4l2_ctrl_lock() locks our own mutex */
162 +
163 +       /*
164 +        * If the device is not powered up by the host driver do
165 +        * not apply any controls to H/W at this time. Instead
166 +        * the controls will be restored right after power-up.
167 +        */
168 +       if (state->power_count == 0)
169 +               return 0;
170 +
171 +       switch (ctrl->id) {
172 +       case V4L2_CID_AUTO_WHITE_BALANCE:
173 +               ret = ov5647_s_auto_white_balance(sd, ctrl->val);
174 +               break;
175 +       case V4L2_CID_AUTOGAIN:
176 +               ret = ov5647_s_autogain(sd, ctrl->val);
177 +               break;
178 +       case V4L2_CID_EXPOSURE_AUTO:
179 +               ret = ov5647_s_exposure_auto(sd, ctrl->val);
180 +               break;
181 +       case V4L2_CID_ANALOGUE_GAIN:
182 +               ret = ov5647_s_analogue_gain(sd, ctrl->val);
183 +               break;
184 +       case V4L2_CID_EXPOSURE:
185 +               ret = ov5647_s_exposure(sd, ctrl->val);
186 +               break;
187 +       default:
188 +               dev_info(&client->dev,
189 +                        "ctrl(id:0x%x,val:0x%x) is not handled\n",
190 +                        ctrl->id, ctrl->val);
191 +               ret = -EINVAL;
192 +               break;
193 +       }
194 +
195 +       return ret;
196 +}
197 +
198 +static const struct v4l2_ctrl_ops ov5647_ctrl_ops = {
199 +       .s_ctrl = ov5647_s_ctrl,
200 +};
201 +
202  static int ov5647_probe(struct i2c_client *client)
203  {
204         struct device *dev = &client->dev;
205 @@ -761,6 +889,7 @@ static int ov5647_probe(struct i2c_clien
206         struct v4l2_subdev *sd;
207         struct device_node *np = client->dev.of_node;
208         u32 xclk_freq;
209 +       struct v4l2_ctrl *ctrl;
210  
211         sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
212         if (!sensor)
213 @@ -793,6 +922,48 @@ static int ov5647_probe(struct i2c_clien
214  
215         mutex_init(&sensor->lock);
216  
217 +       /* Initialise controls. */
218 +       v4l2_ctrl_handler_init(&sensor->ctrls, 3);
219 +       v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
220 +                         V4L2_CID_AUTOGAIN,
221 +                         0,  /* min */
222 +                         1,  /* max */
223 +                         1,  /* step */
224 +                         1); /* default */
225 +       v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
226 +                         V4L2_CID_AUTO_WHITE_BALANCE,
227 +                         0,  /* min */
228 +                         1,  /* max */
229 +                         1,  /* step */
230 +                         1); /* default */
231 +       v4l2_ctrl_new_std_menu(&sensor->ctrls, &ov5647_ctrl_ops,
232 +                              V4L2_CID_EXPOSURE_AUTO,
233 +                              V4L2_EXPOSURE_MANUAL,  /* max */
234 +                              0,                     /* skip_mask */
235 +                              V4L2_EXPOSURE_AUTO);   /* default */
236 +       ctrl = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
237 +                                V4L2_CID_EXPOSURE,
238 +                                4,     /* min lines */
239 +                                65535, /* max lines (4+8+4 bits)*/
240 +                                1,     /* step */
241 +                                1000); /* default number of lines */
242 +       ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
243 +       ctrl = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
244 +                                V4L2_CID_ANALOGUE_GAIN,
245 +                                16,   /* min, 16 = 1.0x */
246 +                                1023, /* max (10 bits) */
247 +                                1,    /* step */
248 +                                32);  /* default, 32 = 2.0x */
249 +       ctrl->flags |= V4L2_CTRL_FLAG_EXECUTE_ON_WRITE;
250 +
251 +       if (sensor->ctrls.error) {
252 +               ret = sensor->ctrls.error;
253 +               dev_err(&client->dev, "%s control init failed (%d)\n",
254 +                       __func__, ret);
255 +               goto error;
256 +       }
257 +       sensor->sd.ctrl_handler = &sensor->ctrls;
258 +
259         /* Set the default mode before we init the subdev */
260         sensor->mode = OV5647_DEFAULT_MODE;
261  
262 @@ -828,6 +999,7 @@ static int ov5647_probe(struct i2c_clien
263  error:
264         media_entity_cleanup(&sd->entity);
265  mutex_remove:
266 +       v4l2_ctrl_handler_free(&sensor->ctrls);
267         mutex_destroy(&sensor->lock);
268         return ret;
269  }
270 @@ -839,6 +1011,7 @@ static int ov5647_remove(struct i2c_clie
271  
272         v4l2_async_unregister_subdev(&ov5647->sd);
273         media_entity_cleanup(&ov5647->sd.entity);
274 +       v4l2_ctrl_handler_free(&ov5647->ctrls);
275         v4l2_device_unregister_subdev(sd);
276         mutex_destroy(&ov5647->lock);
277