Commit df2ed070 authored by Guennadi Liakhovetski's avatar Guennadi Liakhovetski Committed by Mauro Carvalho Chehab

V4L/DVB (11025): soc-camera: configure drivers with a default format on open

Currently soc-camera doesn't set up any image format without an explicit S_FMT.
It seems this should be supported, since, for example, capture-example.c from
v4l2-apps by default doesn't issue an S_FMT. This patch configures a default
image format on open().
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 09e231b3
...@@ -30,6 +30,10 @@ ...@@ -30,6 +30,10 @@
#include <media/videobuf-core.h> #include <media/videobuf-core.h>
#include <media/soc_camera.h> #include <media/soc_camera.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
static LIST_HEAD(hosts); static LIST_HEAD(hosts);
static LIST_HEAD(devices); static LIST_HEAD(devices);
static DEFINE_MUTEX(list_lock); static DEFINE_MUTEX(list_lock);
...@@ -256,6 +260,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd) ...@@ -256,6 +260,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
vfree(icd->user_formats); vfree(icd->user_formats);
} }
/* Called with .vb_lock held */
static int soc_camera_set_fmt(struct soc_camera_file *icf,
struct v4l2_format *f)
{
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_pix_format *pix = &f->fmt.pix;
int ret;
/* We always call try_fmt() before set_fmt() or set_crop() */
ret = ici->ops->try_fmt(icd, f);
if (ret < 0)
return ret;
ret = ici->ops->set_fmt(icd, f);
if (ret < 0) {
return ret;
} else if (!icd->current_fmt ||
icd->current_fmt->fourcc != pix->pixelformat) {
dev_err(&ici->dev,
"Host driver hasn't set up current format correctly!\n");
return -EINVAL;
}
icd->width = pix->width;
icd->height = pix->height;
icf->vb_vidq.field = pix->field;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
f->type);
dev_dbg(&icd->dev, "set width: %d height: %d\n",
icd->width, icd->height);
/* set physical bus parameters */
return ici->ops->set_bus_param(icd, pix->pixelformat);
}
static int soc_camera_open(struct file *file) static int soc_camera_open(struct file *file)
{ {
struct video_device *vdev; struct video_device *vdev;
...@@ -297,6 +339,15 @@ static int soc_camera_open(struct file *file) ...@@ -297,6 +339,15 @@ static int soc_camera_open(struct file *file)
/* Now we really have to activate the camera */ /* Now we really have to activate the camera */
if (icd->use_count == 1) { if (icd->use_count == 1) {
struct v4l2_format f = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.fmt.pix = {
.width = DEFAULT_WIDTH,
.height = DEFAULT_HEIGHT,
.field = V4L2_FIELD_ANY,
},
};
ret = soc_camera_init_user_formats(icd); ret = soc_camera_init_user_formats(icd);
if (ret < 0) if (ret < 0)
goto eiufmt; goto eiufmt;
...@@ -305,6 +356,14 @@ static int soc_camera_open(struct file *file) ...@@ -305,6 +356,14 @@ static int soc_camera_open(struct file *file)
dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret); dev_err(&icd->dev, "Couldn't activate the camera: %d\n", ret);
goto eiciadd; 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)
goto esfmt;
} }
mutex_unlock(&icd->video_lock); mutex_unlock(&icd->video_lock);
...@@ -316,7 +375,12 @@ static int soc_camera_open(struct file *file) ...@@ -316,7 +375,12 @@ static int soc_camera_open(struct file *file)
return 0; return 0;
/* First two errors are entered with the .video_lock held */ /*
* First three errors are entered with the .video_lock held
* and use_count == 1
*/
esfmt:
ici->ops->remove(icd);
eiciadd: eiciadd:
soc_camera_free_user_formats(icd); soc_camera_free_user_formats(icd);
eiufmt: eiufmt:
...@@ -415,16 +479,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -415,16 +479,10 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
{ {
struct soc_camera_file *icf = file->private_data; struct soc_camera_file *icf = file->private_data;
struct soc_camera_device *icd = icf->icd; struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
struct v4l2_pix_format *pix = &f->fmt.pix;
int ret; int ret;
WARN_ON(priv != file->private_data); WARN_ON(priv != file->private_data);
ret = soc_camera_try_fmt_vid_cap(file, priv, f);
if (ret < 0)
return ret;
mutex_lock(&icf->vb_vidq.vb_lock); mutex_lock(&icf->vb_vidq.vb_lock);
if (videobuf_queue_is_busy(&icf->vb_vidq)) { if (videobuf_queue_is_busy(&icf->vb_vidq)) {
...@@ -433,29 +491,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -433,29 +491,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
goto unlock; goto unlock;
} }
ret = ici->ops->set_fmt(icd, f); ret = soc_camera_set_fmt(icf, f);
if (ret < 0) {
goto unlock;
} else if (!icd->current_fmt ||
icd->current_fmt->fourcc != pix->pixelformat) {
dev_err(&ici->dev,
"Host driver hasn't set up current format correctly!\n");
ret = -EINVAL;
goto unlock;
}
icd->width = f->fmt.pix.width;
icd->height = f->fmt.pix.height;
icf->vb_vidq.field = pix->field;
if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
f->type);
dev_dbg(&icd->dev, "set width: %d height: %d\n",
icd->width, icd->height);
/* set physical bus parameters */
ret = ici->ops->set_bus_param(icd, pix->pixelformat);
unlock: unlock:
mutex_unlock(&icf->vb_vidq.vb_lock); mutex_unlock(&icf->vb_vidq.vb_lock);
...@@ -642,8 +678,8 @@ static int soc_camera_cropcap(struct file *file, void *fh, ...@@ -642,8 +678,8 @@ static int soc_camera_cropcap(struct file *file, void *fh,
a->bounds.height = icd->height_max; a->bounds.height = icd->height_max;
a->defrect.left = icd->x_min; a->defrect.left = icd->x_min;
a->defrect.top = icd->y_min; a->defrect.top = icd->y_min;
a->defrect.width = 640; a->defrect.width = DEFAULT_WIDTH;
a->defrect.height = 480; a->defrect.height = DEFAULT_HEIGHT;
a->pixelaspect.numerator = 1; a->pixelaspect.numerator = 1;
a->pixelaspect.denominator = 1; a->pixelaspect.denominator = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment