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

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

V4L/DVB (12519): soc-camera: put pixel format initialisation back in probe, add .put_formats()



The move of format translation initialisation into soc_camera_open() was
temporary for the soc-camera as platform driver intermediate step, put it back
into soc_camera_probe(). Also add a .put_formats() method to
soc_camera_host_ops to free any resources host driver might have allocated in
.get_formats().

Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 0d205b6a
Loading
Loading
Loading
Loading
+35 −15
Original line number Diff line number Diff line
@@ -211,7 +211,7 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
	int i, fmts = 0;
	int i, fmts = 0, ret;

	if (!ici->ops->get_formats)
		/*
@@ -224,8 +224,12 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
		 * First pass - only count formats this host-sensor
		 * configuration can provide
		 */
		for (i = 0; i < icd->num_formats; i++)
			fmts += ici->ops->get_formats(icd, i, NULL);
		for (i = 0; i < icd->num_formats; i++) {
			ret = ici->ops->get_formats(icd, i, NULL);
			if (ret < 0)
				return ret;
			fmts += ret;
		}

	if (!fmts)
		return -ENXIO;
@@ -247,19 +251,32 @@ static int soc_camera_init_user_formats(struct soc_camera_device *icd)
			icd->user_formats[i].cam_fmt = icd->formats + i;
			icd->user_formats[i].buswidth = icd->formats[i].depth;
		} else {
			fmts += ici->ops->get_formats(icd, i,
			ret = ici->ops->get_formats(icd, i,
						    &icd->user_formats[fmts]);
			if (ret < 0)
				goto egfmt;
			fmts += ret;
		}

	icd->current_fmt = icd->user_formats[0].host_fmt;

	return 0;

egfmt:
	icd->num_user_formats = 0;
	vfree(icd->user_formats);
	return ret;
}

/* Always entered with .video_lock held */
static void soc_camera_free_user_formats(struct soc_camera_device *icd)
{
	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);

	if (ici->ops->put_formats)
		ici->ops->put_formats(icd);
	icd->current_fmt = NULL;
	icd->num_user_formats = 0;
	vfree(icd->user_formats);
	icd->user_formats = NULL;
}
@@ -344,16 +361,11 @@ static int soc_camera_open(struct file *file)
				.width		= icd->rect_current.width,
				.height		= icd->rect_current.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;

		f.fmt.pix.pixelformat	= icd->current_fmt->fourcc;
		f.fmt.pix.colorspace	= icd->current_fmt->colorspace;

		if (icl->power) {
			ret = icl->power(icd->pdev, 1);
			if (ret < 0)
@@ -404,8 +416,6 @@ static int soc_camera_open(struct file *file)
	if (icl->power)
		icl->power(icd->pdev, 0);
epower:
	soc_camera_free_user_formats(icd);
eiufmt:
	icd->use_count--;
	mutex_unlock(&icd->video_lock);
	module_put(ici->ops->owner);
@@ -431,7 +441,6 @@ static int soc_camera_close(struct file *file)
		ici->ops->remove(icd);
		if (icl->power)
			icl->power(icd->pdev, 0);
		soc_camera_free_user_formats(icd);
	}

	mutex_unlock(&icd->video_lock);
@@ -954,6 +963,14 @@ static int soc_camera_probe(struct device *dev)
		}
	}

	/* At this point client .probe() should have run already */
	ret = soc_camera_init_user_formats(icd);
	if (ret < 0)
		goto eiufmt;

	icd->rect_current = icd->rect_max;
	icd->field = V4L2_FIELD_ANY;

	/* ..._video_start() will create a device node, so we have to protect */
	mutex_lock(&icd->video_lock);

@@ -978,6 +995,8 @@ static int soc_camera_probe(struct device *dev)

evidstart:
	mutex_unlock(&icd->video_lock);
	soc_camera_free_user_formats(icd);
eiufmt:
	if (icl->board_info) {
		soc_camera_free_i2c(icd);
	} else {
@@ -1023,6 +1042,7 @@ static int soc_camera_remove(struct device *dev)
			module_put(drv->owner);
		}
	}
	soc_camera_free_user_formats(icd);

	return 0;
}
+7 −0
Original line number Diff line number Diff line
@@ -67,8 +67,15 @@ struct soc_camera_host_ops {
	void (*remove)(struct soc_camera_device *);
	int (*suspend)(struct soc_camera_device *, pm_message_t);
	int (*resume)(struct soc_camera_device *);
	/*
	 * .get_formats() is called for each client device format, but
	 * .put_formats() is only called once. Further, if any of the calls to
	 * .get_formats() fail, .put_formats() will not be called at all, the
	 * failing .get_formats() must then clean up internally.
	 */
	int (*get_formats)(struct soc_camera_device *, int,
			   struct soc_camera_format_xlate *);
	void (*put_formats)(struct soc_camera_device *);
	int (*set_crop)(struct soc_camera_device *, struct v4l2_rect *);
	int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
	int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);