diff options
-rw-r--r-- | drivers/media/video/soc_camera.c | 39 | ||||
-rw-r--r-- | include/media/soc_camera.h | 1 |
2 files changed, 24 insertions, 16 deletions
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c index fcd6b2ce9c19..6d8bfd4d97e2 100644 --- a/drivers/media/video/soc_camera.c +++ b/drivers/media/video/soc_camera.c | |||
@@ -286,7 +286,9 @@ static int soc_camera_set_fmt(struct soc_camera_file *icf, | |||
286 | 286 | ||
287 | icd->width = pix->width; | 287 | icd->width = pix->width; |
288 | icd->height = pix->height; | 288 | icd->height = pix->height; |
289 | icf->vb_vidq.field = pix->field; | 289 | icf->vb_vidq.field = |
290 | icd->field = pix->field; | ||
291 | |||
290 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | 292 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) |
291 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", | 293 | dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n", |
292 | f->type); | 294 | f->type); |
@@ -339,27 +341,24 @@ static int soc_camera_open(struct file *file) | |||
339 | 341 | ||
340 | /* Now we really have to activate the camera */ | 342 | /* Now we really have to activate the camera */ |
341 | if (icd->use_count == 1) { | 343 | if (icd->use_count == 1) { |
344 | /* Restore parameters before the last close() per V4L2 API */ | ||
342 | struct v4l2_format f = { | 345 | struct v4l2_format f = { |
343 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, | 346 | .type = V4L2_BUF_TYPE_VIDEO_CAPTURE, |
344 | .fmt.pix = { | 347 | .fmt.pix = { |
345 | .width = DEFAULT_WIDTH, | 348 | .width = icd->width, |
346 | .height = DEFAULT_HEIGHT, | 349 | .height = icd->height, |
347 | .field = V4L2_FIELD_ANY, | 350 | .field = icd->field, |
351 | .pixelformat = icd->current_fmt->fourcc, | ||
352 | .colorspace = icd->current_fmt->colorspace, | ||
348 | }, | 353 | }, |
349 | }; | 354 | }; |
350 | 355 | ||
351 | ret = soc_camera_init_user_formats(icd); | ||
352 | if (ret < 0) | ||
353 | goto eiufmt; | ||
354 | ret = ici->ops->add(icd); | 356 | ret = ici->ops->add(icd); |
355 | if (ret < 0) { | 357 | if (ret < 0) { |
356 | dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); | 358 | dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); |
357 | goto eiciadd; | 359 | goto eiciadd; |
358 | } | 360 | } |
359 | 361 | ||
360 | f.fmt.pix.pixelformat = icd->current_fmt->fourcc; | ||
361 | f.fmt.pix.colorspace = icd->current_fmt->colorspace; | ||
362 | |||
363 | /* Try to configure with default parameters */ | 362 | /* Try to configure with default parameters */ |
364 | ret = soc_camera_set_fmt(icf, &f); | 363 | ret = soc_camera_set_fmt(icf, &f); |
365 | if (ret < 0) | 364 | if (ret < 0) |
@@ -382,8 +381,6 @@ static int soc_camera_open(struct file *file) | |||
382 | esfmt: | 381 | esfmt: |
383 | ici->ops->remove(icd); | 382 | ici->ops->remove(icd); |
384 | eiciadd: | 383 | eiciadd: |
385 | soc_camera_free_user_formats(icd); | ||
386 | eiufmt: | ||
387 | icd->use_count--; | 384 | icd->use_count--; |
388 | mutex_unlock(&icd->video_lock); | 385 | mutex_unlock(&icd->video_lock); |
389 | module_put(ici->ops->owner); | 386 | module_put(ici->ops->owner); |
@@ -403,10 +400,9 @@ static int soc_camera_close(struct file *file) | |||
403 | 400 | ||
404 | mutex_lock(&icd->video_lock); | 401 | mutex_lock(&icd->video_lock); |
405 | icd->use_count--; | 402 | icd->use_count--; |
406 | if (!icd->use_count) { | 403 | if (!icd->use_count) |
407 | ici->ops->remove(icd); | 404 | ici->ops->remove(icd); |
408 | soc_camera_free_user_formats(icd); | 405 | |
409 | } | ||
410 | mutex_unlock(&icd->video_lock); | 406 | mutex_unlock(&icd->video_lock); |
411 | 407 | ||
412 | module_put(icd->ops->owner); | 408 | module_put(icd->ops->owner); |
@@ -874,9 +870,18 @@ static int soc_camera_probe(struct device *dev) | |||
874 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); | 870 | qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE); |
875 | icd->exposure = qctrl ? qctrl->default_value : | 871 | icd->exposure = qctrl ? qctrl->default_value : |
876 | (unsigned short)~0; | 872 | (unsigned short)~0; |
873 | |||
874 | ret = soc_camera_init_user_formats(icd); | ||
875 | if (ret < 0) | ||
876 | goto eiufmt; | ||
877 | |||
878 | icd->height = DEFAULT_HEIGHT; | ||
879 | icd->width = DEFAULT_WIDTH; | ||
880 | icd->field = V4L2_FIELD_ANY; | ||
877 | } | 881 | } |
878 | ici->ops->remove(icd); | ||
879 | 882 | ||
883 | eiufmt: | ||
884 | ici->ops->remove(icd); | ||
880 | eiadd: | 885 | eiadd: |
881 | mutex_unlock(&icd->video_lock); | 886 | mutex_unlock(&icd->video_lock); |
882 | module_put(ici->ops->owner); | 887 | module_put(ici->ops->owner); |
@@ -895,6 +900,8 @@ static int soc_camera_remove(struct device *dev) | |||
895 | if (icd->ops->remove) | 900 | if (icd->ops->remove) |
896 | icd->ops->remove(icd); | 901 | icd->ops->remove(icd); |
897 | 902 | ||
903 | soc_camera_free_user_formats(icd); | ||
904 | |||
898 | return 0; | 905 | return 0; |
899 | } | 906 | } |
900 | 907 | ||
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h index e9eb60740aaa..013c81875d76 100644 --- a/include/media/soc_camera.h +++ b/include/media/soc_camera.h | |||
@@ -45,6 +45,7 @@ struct soc_camera_device { | |||
45 | int num_formats; | 45 | int num_formats; |
46 | struct soc_camera_format_xlate *user_formats; | 46 | struct soc_camera_format_xlate *user_formats; |
47 | int num_user_formats; | 47 | int num_user_formats; |
48 | enum v4l2_field field; /* Preserve field over close() */ | ||
48 | struct module *owner; | 49 | struct module *owner; |
49 | void *host_priv; /* Per-device host private data */ | 50 | void *host_priv; /* Per-device host private data */ |
50 | /* soc_camera.c private count. Only accessed with .video_lock held */ | 51 | /* soc_camera.c private count. Only accessed with .video_lock held */ |