diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2009-03-13 05:08:20 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2009-03-30 11:43:21 -0400 |
commit | 09e231b35173313cd92e27532e5028f2042dcee4 (patch) | |
tree | 3ecda063aa52f954d2f797921bdce131d7f1cc28 /drivers/media/video/mt9t031.c | |
parent | 1cd3c0fa927084549005fc22e54d99684b314f14 (diff) |
V4L/DVB (11024): soc-camera: separate S_FMT and S_CROP operations
As host and camera drivers become more complex, differences between S_FMT and
S_CROP functionality grow, this patch separates them.
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9t031.c')
-rw-r--r-- | drivers/media/video/mt9t031.c | 84 |
1 files changed, 53 insertions, 31 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index acc1fa9db67d..677be18df9b3 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c | |||
@@ -213,36 +213,14 @@ static void recalculate_limits(struct soc_camera_device *icd, | |||
213 | icd->height_max = MT9T031_MAX_HEIGHT / yskip; | 213 | icd->height_max = MT9T031_MAX_HEIGHT / yskip; |
214 | } | 214 | } |
215 | 215 | ||
216 | static int mt9t031_set_fmt(struct soc_camera_device *icd, | 216 | static int mt9t031_set_params(struct soc_camera_device *icd, |
217 | __u32 pixfmt, struct v4l2_rect *rect) | 217 | struct v4l2_rect *rect, u16 xskip, u16 yskip) |
218 | { | 218 | { |
219 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | 219 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); |
220 | int ret; | 220 | int ret; |
221 | u16 xbin, ybin, width, height, left, top; | ||
221 | const u16 hblank = MT9T031_HORIZONTAL_BLANK, | 222 | const u16 hblank = MT9T031_HORIZONTAL_BLANK, |
222 | vblank = MT9T031_VERTICAL_BLANK; | 223 | vblank = MT9T031_VERTICAL_BLANK; |
223 | u16 xbin, xskip, ybin, yskip, width, height, left, top; | ||
224 | |||
225 | if (pixfmt) { | ||
226 | /* | ||
227 | * try_fmt has put rectangle within limits. | ||
228 | * S_FMT - use binning and skipping for scaling, recalculate | ||
229 | * limits, used for cropping | ||
230 | */ | ||
231 | /* Is this more optimal than just a division? */ | ||
232 | for (xskip = 8; xskip > 1; xskip--) | ||
233 | if (rect->width * xskip <= MT9T031_MAX_WIDTH) | ||
234 | break; | ||
235 | |||
236 | for (yskip = 8; yskip > 1; yskip--) | ||
237 | if (rect->height * yskip <= MT9T031_MAX_HEIGHT) | ||
238 | break; | ||
239 | |||
240 | recalculate_limits(icd, xskip, yskip); | ||
241 | } else { | ||
242 | /* CROP - no change in scaling, or in limits */ | ||
243 | xskip = mt9t031->xskip; | ||
244 | yskip = mt9t031->yskip; | ||
245 | } | ||
246 | 224 | ||
247 | /* Make sure we don't exceed sensor limits */ | 225 | /* Make sure we don't exceed sensor limits */ |
248 | if (rect->left + rect->width > icd->width_max) | 226 | if (rect->left + rect->width > icd->width_max) |
@@ -289,7 +267,7 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, | |||
289 | if (ret >= 0) | 267 | if (ret >= 0) |
290 | ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); | 268 | ret = reg_write(icd, MT9T031_VERTICAL_BLANKING, vblank); |
291 | 269 | ||
292 | if (pixfmt) { | 270 | if (yskip != mt9t031->yskip || xskip != mt9t031->xskip) { |
293 | /* Binning, skipping */ | 271 | /* Binning, skipping */ |
294 | if (ret >= 0) | 272 | if (ret >= 0) |
295 | ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, | 273 | ret = reg_write(icd, MT9T031_COLUMN_ADDRESS_MODE, |
@@ -325,15 +303,58 @@ static int mt9t031_set_fmt(struct soc_camera_device *icd, | |||
325 | } | 303 | } |
326 | } | 304 | } |
327 | 305 | ||
328 | if (!ret && pixfmt) { | 306 | /* Re-enable register update, commit all changes */ |
307 | if (ret >= 0) | ||
308 | ret = reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); | ||
309 | |||
310 | return ret < 0 ? ret : 0; | ||
311 | } | ||
312 | |||
313 | static int mt9t031_set_crop(struct soc_camera_device *icd, | ||
314 | struct v4l2_rect *rect) | ||
315 | { | ||
316 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | ||
317 | |||
318 | /* CROP - no change in scaling, or in limits */ | ||
319 | return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip); | ||
320 | } | ||
321 | |||
322 | static int mt9t031_set_fmt(struct soc_camera_device *icd, | ||
323 | struct v4l2_format *f) | ||
324 | { | ||
325 | struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd); | ||
326 | int ret; | ||
327 | u16 xskip, yskip; | ||
328 | struct v4l2_rect rect = { | ||
329 | .left = icd->x_current, | ||
330 | .top = icd->y_current, | ||
331 | .width = f->fmt.pix.width, | ||
332 | .height = f->fmt.pix.height, | ||
333 | }; | ||
334 | |||
335 | /* | ||
336 | * try_fmt has put rectangle within limits. | ||
337 | * S_FMT - use binning and skipping for scaling, recalculate | ||
338 | * limits, used for cropping | ||
339 | */ | ||
340 | /* Is this more optimal than just a division? */ | ||
341 | for (xskip = 8; xskip > 1; xskip--) | ||
342 | if (rect.width * xskip <= MT9T031_MAX_WIDTH) | ||
343 | break; | ||
344 | |||
345 | for (yskip = 8; yskip > 1; yskip--) | ||
346 | if (rect.height * yskip <= MT9T031_MAX_HEIGHT) | ||
347 | break; | ||
348 | |||
349 | recalculate_limits(icd, xskip, yskip); | ||
350 | |||
351 | ret = mt9t031_set_params(icd, &rect, xskip, yskip); | ||
352 | if (!ret) { | ||
329 | mt9t031->xskip = xskip; | 353 | mt9t031->xskip = xskip; |
330 | mt9t031->yskip = yskip; | 354 | mt9t031->yskip = yskip; |
331 | } | 355 | } |
332 | 356 | ||
333 | /* Re-enable register update, commit all changes */ | 357 | return ret; |
334 | reg_clear(icd, MT9T031_OUTPUT_CONTROL, 1); | ||
335 | |||
336 | return ret < 0 ? ret : 0; | ||
337 | } | 358 | } |
338 | 359 | ||
339 | static int mt9t031_try_fmt(struct soc_camera_device *icd, | 360 | static int mt9t031_try_fmt(struct soc_camera_device *icd, |
@@ -470,6 +491,7 @@ static struct soc_camera_ops mt9t031_ops = { | |||
470 | .release = mt9t031_release, | 491 | .release = mt9t031_release, |
471 | .start_capture = mt9t031_start_capture, | 492 | .start_capture = mt9t031_start_capture, |
472 | .stop_capture = mt9t031_stop_capture, | 493 | .stop_capture = mt9t031_stop_capture, |
494 | .set_crop = mt9t031_set_crop, | ||
473 | .set_fmt = mt9t031_set_fmt, | 495 | .set_fmt = mt9t031_set_fmt, |
474 | .try_fmt = mt9t031_try_fmt, | 496 | .try_fmt = mt9t031_try_fmt, |
475 | .set_bus_param = mt9t031_set_bus_param, | 497 | .set_bus_param = mt9t031_set_bus_param, |