summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/soc_camera.c39
-rw-r--r--include/media/soc_camera.h1
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,
icd->width = pix->width;
icd->height = pix->height;
- icf->vb_vidq.field = pix->field;
+ icf->vb_vidq.field =
+ icd->field = pix->field;
+
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
f->type);
@@ -339,27 +341,24 @@ static int soc_camera_open(struct file *file)
/* Now we really have to activate the camera */
if (icd->use_count == 1) {
+ /* Restore parameters before the last close() per V4L2 API */
struct v4l2_format f = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt.pix = {
- .width = DEFAULT_WIDTH,
- .height = DEFAULT_HEIGHT,
- .field = V4L2_FIELD_ANY,
+ .width = icd->width,
+ .height = icd->height,
+ .field = icd->field,
+ .pixelformat = icd->current_fmt->fourcc,
+ .colorspace = icd->current_fmt->colorspace,
},
};
- ret = soc_camera_init_user_formats(icd);
- if (ret < 0)
- goto eiufmt;
ret = ici->ops->add(icd);
if (ret < 0) {
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
goto eiciadd;
}
- f.fmt.pix.pixelformat = icd->current_fmt->fourcc;
- f.fmt.pix.colorspace = icd->current_fmt->colorspace;
-
/* Try to configure with default parameters */
ret = soc_camera_set_fmt(icf, &f);
if (ret < 0)
@@ -382,8 +381,6 @@ static int soc_camera_open(struct file *file)
esfmt:
ici->ops->remove(icd);
eiciadd:
- soc_camera_free_user_formats(icd);
-eiufmt:
icd->use_count--;
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
@@ -403,10 +400,9 @@ static int soc_camera_close(struct file *file)
mutex_lock(&icd->video_lock);
icd->use_count--;
- if (!icd->use_count) {
+ if (!icd->use_count)
ici->ops->remove(icd);
- soc_camera_free_user_formats(icd);
- }
+
mutex_unlock(&icd->video_lock);
module_put(icd->ops->owner);
@@ -874,9 +870,18 @@ static int soc_camera_probe(struct device *dev)
qctrl = soc_camera_find_qctrl(icd->ops, V4L2_CID_EXPOSURE);
icd->exposure = qctrl ? qctrl->default_value :
(unsigned short)~0;
+
+ ret = soc_camera_init_user_formats(icd);
+ if (ret < 0)
+ goto eiufmt;
+
+ icd->height = DEFAULT_HEIGHT;
+ icd->width = DEFAULT_WIDTH;
+ icd->field = V4L2_FIELD_ANY;
}
- ici->ops->remove(icd);
+eiufmt:
+ ici->ops->remove(icd);
eiadd:
mutex_unlock(&icd->video_lock);
module_put(ici->ops->owner);
@@ -895,6 +900,8 @@ static int soc_camera_remove(struct device *dev)
if (icd->ops->remove)
icd->ops->remove(icd);
+ soc_camera_free_user_formats(icd);
+
return 0;
}
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 {
int num_formats;
struct soc_camera_format_xlate *user_formats;
int num_user_formats;
+ enum v4l2_field field; /* Preserve field over close() */
struct module *owner;
void *host_priv; /* Per-device host private data */
/* soc_camera.c private count. Only accessed with .video_lock held */