diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2012-05-09 10:53:09 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-05-14 13:35:04 -0400 |
commit | 9346459ae0317ec6a6930b4566417e033f74a2bf (patch) | |
tree | f8ab68ecd9e66fb504ef7483526d27b5d44c2250 /drivers/media/video/m5mols | |
parent | dd9c471dd37c25127236dd36cd1f55c488228cf1 (diff) |
[media] m5mols: Add 3A lock control
Add control for locking automatic exposure, focus and white balance
adjustments. While at it, tidy up the data structure documentation.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/m5mols')
-rw-r--r-- | drivers/media/video/m5mols/m5mols.h | 10 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_capture.c | 7 | ||||
-rw-r--r-- | drivers/media/video/m5mols/m5mols_controls.c | 89 |
3 files changed, 60 insertions, 46 deletions
diff --git a/drivers/media/video/m5mols/m5mols.h b/drivers/media/video/m5mols/m5mols.h index 00f8d3162bdc..bb589917b65b 100644 --- a/drivers/media/video/m5mols/m5mols.h +++ b/drivers/media/video/m5mols/m5mols.h | |||
@@ -158,7 +158,7 @@ struct m5mols_version { | |||
158 | * @ffmt: current fmt according to resolution type | 158 | * @ffmt: current fmt according to resolution type |
159 | * @res_type: current resolution type | 159 | * @res_type: current resolution type |
160 | * @irq_waitq: waitqueue for the capture | 160 | * @irq_waitq: waitqueue for the capture |
161 | * @flags: state variable for the interrupt handler | 161 | * @irq_done: set to 1 in the interrupt handler |
162 | * @handle: control handler | 162 | * @handle: control handler |
163 | * @auto_exposure: auto/manual exposure control | 163 | * @auto_exposure: auto/manual exposure control |
164 | * @exposure_bias: exposure compensation control | 164 | * @exposure_bias: exposure compensation control |
@@ -167,6 +167,7 @@ struct m5mols_version { | |||
167 | * @auto_iso: auto/manual ISO sensitivity control | 167 | * @auto_iso: auto/manual ISO sensitivity control |
168 | * @iso: manual ISO sensitivity control | 168 | * @iso: manual ISO sensitivity control |
169 | * @auto_wb: auto white balance control | 169 | * @auto_wb: auto white balance control |
170 | * @lock_3a: 3A lock control | ||
170 | * @colorfx: color effect control | 171 | * @colorfx: color effect control |
171 | * @saturation: saturation control | 172 | * @saturation: saturation control |
172 | * @zoom: zoom control | 173 | * @zoom: zoom control |
@@ -175,11 +176,9 @@ struct m5mols_version { | |||
175 | * @jpeg_quality: JPEG compression quality control | 176 | * @jpeg_quality: JPEG compression quality control |
176 | * @ver: information of the version | 177 | * @ver: information of the version |
177 | * @cap: the capture mode attributes | 178 | * @cap: the capture mode attributes |
178 | * @power: current sensor's power status | ||
179 | * @isp_ready: 1 when the ISP controller has completed booting | 179 | * @isp_ready: 1 when the ISP controller has completed booting |
180 | * @power: current sensor's power status | ||
180 | * @ctrl_sync: 1 when the control handler state is restored in H/W | 181 | * @ctrl_sync: 1 when the control handler state is restored in H/W |
181 | * @lock_ae: true means the Auto Exposure is locked | ||
182 | * @lock_awb: true means the Aut WhiteBalance is locked | ||
183 | * @resolution: register value for current resolution | 182 | * @resolution: register value for current resolution |
184 | * @mode: register value for current operation mode | 183 | * @mode: register value for current operation mode |
185 | * @set_power: optional power callback to the board code | 184 | * @set_power: optional power callback to the board code |
@@ -209,6 +208,7 @@ struct m5mols_info { | |||
209 | }; | 208 | }; |
210 | struct v4l2_ctrl *auto_wb; | 209 | struct v4l2_ctrl *auto_wb; |
211 | 210 | ||
211 | struct v4l2_ctrl *lock_3a; | ||
212 | struct v4l2_ctrl *colorfx; | 212 | struct v4l2_ctrl *colorfx; |
213 | struct v4l2_ctrl *saturation; | 213 | struct v4l2_ctrl *saturation; |
214 | struct v4l2_ctrl *zoom; | 214 | struct v4l2_ctrl *zoom; |
@@ -223,8 +223,6 @@ struct m5mols_info { | |||
223 | unsigned int power:1; | 223 | unsigned int power:1; |
224 | unsigned int ctrl_sync:1; | 224 | unsigned int ctrl_sync:1; |
225 | 225 | ||
226 | bool lock_ae; | ||
227 | bool lock_awb; | ||
228 | u8 resolution; | 226 | u8 resolution; |
229 | u8 mode; | 227 | u8 mode; |
230 | 228 | ||
diff --git a/drivers/media/video/m5mols/m5mols_capture.c b/drivers/media/video/m5mols/m5mols_capture.c index 4f27aed11722..cb243bd278ce 100644 --- a/drivers/media/video/m5mols/m5mols_capture.c +++ b/drivers/media/video/m5mols/m5mols_capture.c | |||
@@ -106,7 +106,6 @@ static int m5mols_capture_info(struct m5mols_info *info) | |||
106 | int m5mols_start_capture(struct m5mols_info *info) | 106 | int m5mols_start_capture(struct m5mols_info *info) |
107 | { | 107 | { |
108 | struct v4l2_subdev *sd = &info->sd; | 108 | struct v4l2_subdev *sd = &info->sd; |
109 | u8 resolution = info->resolution; | ||
110 | int ret; | 109 | int ret; |
111 | 110 | ||
112 | /* | 111 | /* |
@@ -120,16 +119,12 @@ int m5mols_start_capture(struct m5mols_info *info) | |||
120 | if (!ret) | 119 | if (!ret) |
121 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); | 120 | ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); |
122 | if (!ret) | 121 | if (!ret) |
123 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution); | 122 | ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); |
124 | if (!ret) | ||
125 | ret = m5mols_lock_3a(info, true); | ||
126 | if (!ret) | 123 | if (!ret) |
127 | ret = m5mols_set_mode(info, REG_CAPTURE); | 124 | ret = m5mols_set_mode(info, REG_CAPTURE); |
128 | if (!ret) | 125 | if (!ret) |
129 | /* Wait until a frame is captured to ISP internal memory */ | 126 | /* Wait until a frame is captured to ISP internal memory */ |
130 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); | 127 | ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); |
131 | if (!ret) | ||
132 | ret = m5mols_lock_3a(info, false); | ||
133 | if (ret) | 128 | if (ret) |
134 | return ret; | 129 | return ret; |
135 | 130 | ||
diff --git a/drivers/media/video/m5mols/m5mols_controls.c b/drivers/media/video/m5mols/m5mols_controls.c index 1c3b1e0a7bba..392a028730e2 100644 --- a/drivers/media/video/m5mols/m5mols_controls.c +++ b/drivers/media/video/m5mols/m5mols_controls.c | |||
@@ -139,7 +139,7 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) | |||
139 | if (mode > REG_SCENE_CANDLE) | 139 | if (mode > REG_SCENE_CANDLE) |
140 | return -EINVAL; | 140 | return -EINVAL; |
141 | 141 | ||
142 | ret = m5mols_lock_3a(info, false); | 142 | ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0); |
143 | if (!ret) | 143 | if (!ret) |
144 | ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); | 144 | ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); |
145 | if (!ret) | 145 | if (!ret) |
@@ -186,42 +186,34 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) | |||
186 | return ret; | 186 | return ret; |
187 | } | 187 | } |
188 | 188 | ||
189 | static int m5mols_lock_ae(struct m5mols_info *info, bool lock) | 189 | static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl) |
190 | { | 190 | { |
191 | bool af_lock = ctrl->val & V4L2_LOCK_FOCUS; | ||
191 | int ret = 0; | 192 | int ret = 0; |
192 | 193 | ||
193 | if (info->lock_ae != lock) | 194 | if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) { |
194 | ret = m5mols_write(&info->sd, AE_LOCK, | 195 | bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE; |
195 | lock ? REG_AE_LOCK : REG_AE_UNLOCK); | ||
196 | if (!ret) | ||
197 | info->lock_ae = lock; | ||
198 | 196 | ||
199 | return ret; | 197 | ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ? |
200 | } | 198 | REG_AE_LOCK : REG_AE_UNLOCK); |
201 | 199 | if (ret) | |
202 | static int m5mols_lock_awb(struct m5mols_info *info, bool lock) | 200 | return ret; |
203 | { | 201 | } |
204 | int ret = 0; | ||
205 | 202 | ||
206 | if (info->lock_awb != lock) | 203 | if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE) |
207 | ret = m5mols_write(&info->sd, AWB_LOCK, | 204 | && info->auto_wb->val) { |
208 | lock ? REG_AWB_LOCK : REG_AWB_UNLOCK); | 205 | bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE; |
209 | if (!ret) | ||
210 | info->lock_awb = lock; | ||
211 | 206 | ||
212 | return ret; | 207 | ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ? |
213 | } | 208 | REG_AWB_LOCK : REG_AWB_UNLOCK); |
209 | if (ret) | ||
210 | return ret; | ||
211 | } | ||
214 | 212 | ||
215 | /* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */ | 213 | if (!info->ver.af || !af_lock) |
216 | int m5mols_lock_3a(struct m5mols_info *info, bool lock) | 214 | return ret; |
217 | { | ||
218 | int ret; | ||
219 | 215 | ||
220 | ret = m5mols_lock_ae(info, lock); | 216 | if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS) |
221 | if (!ret) | ||
222 | ret = m5mols_lock_awb(info, lock); | ||
223 | /* Don't need to handle unlocking AF */ | ||
224 | if (!ret && is_available_af(info) && lock) | ||
225 | ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); | 217 | ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP); |
226 | 218 | ||
227 | return ret; | 219 | return ret; |
@@ -249,13 +241,13 @@ static int m5mols_set_metering_mode(struct m5mols_info *info, int mode) | |||
249 | static int m5mols_set_exposure(struct m5mols_info *info, int exposure) | 241 | static int m5mols_set_exposure(struct m5mols_info *info, int exposure) |
250 | { | 242 | { |
251 | struct v4l2_subdev *sd = &info->sd; | 243 | struct v4l2_subdev *sd = &info->sd; |
252 | int ret; | 244 | int ret = 0; |
253 | |||
254 | ret = m5mols_lock_ae(info, exposure != V4L2_EXPOSURE_AUTO); | ||
255 | if (ret < 0) | ||
256 | return ret; | ||
257 | 245 | ||
258 | if (exposure == V4L2_EXPOSURE_AUTO) { | 246 | if (exposure == V4L2_EXPOSURE_AUTO) { |
247 | /* Unlock auto exposure */ | ||
248 | info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE; | ||
249 | m5mols_3a_lock(info, info->lock_3a); | ||
250 | |||
259 | ret = m5mols_set_metering_mode(info, info->metering->val); | 251 | ret = m5mols_set_metering_mode(info, info->metering->val); |
260 | if (ret < 0) | 252 | if (ret < 0) |
261 | return ret; | 253 | return ret; |
@@ -429,6 +421,26 @@ static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl) | |||
429 | if (status != REG_ISO_AUTO) | 421 | if (status != REG_ISO_AUTO) |
430 | info->iso->val = status - 1; | 422 | info->iso->val = status - 1; |
431 | break; | 423 | break; |
424 | |||
425 | case V4L2_CID_3A_LOCK: | ||
426 | ctrl->val &= ~0x7; | ||
427 | |||
428 | ret = m5mols_read_u8(sd, AE_LOCK, &status); | ||
429 | if (ret) | ||
430 | return ret; | ||
431 | if (status) | ||
432 | info->lock_3a->val |= V4L2_LOCK_EXPOSURE; | ||
433 | |||
434 | ret = m5mols_read_u8(sd, AWB_LOCK, &status); | ||
435 | if (ret) | ||
436 | return ret; | ||
437 | if (status) | ||
438 | info->lock_3a->val |= V4L2_LOCK_EXPOSURE; | ||
439 | |||
440 | ret = m5mols_read_u8(sd, AF_EXECUTE, &status); | ||
441 | if (!status) | ||
442 | info->lock_3a->val |= V4L2_LOCK_EXPOSURE; | ||
443 | break; | ||
432 | } | 444 | } |
433 | 445 | ||
434 | return ret; | 446 | return ret; |
@@ -461,6 +473,10 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl) | |||
461 | } | 473 | } |
462 | 474 | ||
463 | switch (ctrl->id) { | 475 | switch (ctrl->id) { |
476 | case V4L2_CID_3A_LOCK: | ||
477 | ret = m5mols_3a_lock(info, ctrl); | ||
478 | break; | ||
479 | |||
464 | case V4L2_CID_ZOOM_ABSOLUTE: | 480 | case V4L2_CID_ZOOM_ABSOLUTE: |
465 | ret = m5mols_write(sd, MON_ZOOM, ctrl->val); | 481 | ret = m5mols_write(sd, MON_ZOOM, ctrl->val); |
466 | break; | 482 | break; |
@@ -585,6 +601,9 @@ int m5mols_init_controls(struct v4l2_subdev *sd) | |||
585 | info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, | 601 | info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, |
586 | V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80); | 602 | V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80); |
587 | 603 | ||
604 | info->lock_3a = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops, | ||
605 | V4L2_CID_3A_LOCK, 0, 0x7, 0, 0); | ||
606 | |||
588 | if (info->handle.error) { | 607 | if (info->handle.error) { |
589 | int ret = info->handle.error; | 608 | int ret = info->handle.error; |
590 | v4l2_err(sd, "Failed to initialize controls: %d\n", ret); | 609 | v4l2_err(sd, "Failed to initialize controls: %d\n", ret); |
@@ -597,6 +616,8 @@ int m5mols_init_controls(struct v4l2_subdev *sd) | |||
597 | V4L2_CTRL_FLAG_UPDATE; | 616 | V4L2_CTRL_FLAG_UPDATE; |
598 | v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false); | 617 | v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false); |
599 | 618 | ||
619 | info->lock_3a->flags |= V4L2_CTRL_FLAG_VOLATILE; | ||
620 | |||
600 | m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER); | 621 | m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER); |
601 | m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER); | 622 | m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER); |
602 | m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR); | 623 | m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR); |