aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9t031.c
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2009-03-13 05:08:20 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-03-30 11:43:21 -0400
commit09e231b35173313cd92e27532e5028f2042dcee4 (patch)
tree3ecda063aa52f954d2f797921bdce131d7f1cc28 /drivers/media/video/mt9t031.c
parent1cd3c0fa927084549005fc22e54d99684b314f14 (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.c84
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
216static int mt9t031_set_fmt(struct soc_camera_device *icd, 216static 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
313static 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
322static 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
339static int mt9t031_try_fmt(struct soc_camera_device *icd, 360static 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,