Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+68 −32
Original line number Diff line number Diff line
@@ -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;