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: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Guennadi Liakhovetski 2009-03-13 06:08:20 -03:00 committed by Mauro Carvalho Chehab
parent 09e231b351
commit df2ed07025

View file

@ -30,6 +30,10 @@
#include <media/videobuf-core.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(devices);
static DEFINE_MUTEX(list_lock);
@ -256,6 +260,44 @@ static void soc_camera_free_user_formats(struct soc_camera_device *icd)
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)
{
struct video_device *vdev;
@ -297,6 +339,15 @@ static int soc_camera_open(struct file *file)
/* Now we really have to activate the camera */
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);
if (ret < 0)
goto eiufmt;
@ -305,6 +356,14 @@ static int soc_camera_open(struct file *file)
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)
goto esfmt;
}
mutex_unlock(&icd->video_lock);
@ -316,7 +375,12 @@ static int soc_camera_open(struct file *file)
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:
soc_camera_free_user_formats(icd);
eiufmt:
@ -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_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;
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);
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,
goto unlock;
}
ret = ici->ops->set_fmt(icd, 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);
ret = soc_camera_set_fmt(icf, f);
unlock:
mutex_unlock(&icf->vb_vidq.vb_lock);
@ -642,8 +678,8 @@ static int soc_camera_cropcap(struct file *file, void *fh,
a->bounds.height = icd->height_max;
a->defrect.left = icd->x_min;
a->defrect.top = icd->y_min;
a->defrect.width = 640;
a->defrect.height = 480;
a->defrect.width = DEFAULT_WIDTH;
a->defrect.height = DEFAULT_HEIGHT;
a->pixelaspect.numerator = 1;
a->pixelaspect.denominator = 1;