From: Robert Jarzmik <robert.jarzmik@free.fr>
To: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Cc: video4linux-list@redhat.com
Subject: Re: [PATCH v4 1/2] soc-camera: pixel format negotiation - core support
Date: Sun, 30 Nov 2008 18:33:16 +0100 [thread overview]
Message-ID: <87myfhp19f.fsf@free.fr> (raw)
In-Reply-To: <Pine.LNX.4.64.0811291822100.8352@axis700.grange> (Guennadi Liakhovetski's message of "Sat\, 29 Nov 2008 18\:31\:49 +0100 \(CET\)")
Guennadi Liakhovetski <g.liakhovetski@gmx.de> writes:
> I think, this is different. Further I think your version would produce a
> compiler warning like this:
>
> drivers/media/video/soc_camera.c: In function 'soc_camera_init_user_formats':
> drivers/media/video/soc_camera.c:219: warning: assignment from incompatible pointer type
True. Didn't see it, sorry.
> and is indeed wrong. Please fix and please test your patches before
> submitting - compile and run. Or am I wrong?
I _did_ test my patch. Even with the error, the capture_example from v4l tree
didn't trigger a bug.
--
Robert
>From f34e1b0354a8f176e235d6a8aca4bf0a0efcab2c Mon Sep 17 00:00:00 2001
From: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Date: Tue, 18 Nov 2008 20:25:48 +0100
Subject: [PATCH v4 1/2] soc-camera: pixel format negotiation - core support
Allocate and fill a list of formats, supported by this specific
camera-host combination. Use it for format enumeration. Take care to stay
backwards-compatible.
Camera hosts rely on sensor formats available, as well as
host specific translations. We add a structure so that hosts
can define a translation table and use it for format check
and setup.
Signed-off-by: Robert Jarzmik <robert.jarzmik@free.fr>
---
drivers/media/video/soc_camera.c | 93 +++++++++++++++++++++++++++++++++-----
include/media/soc_camera.h | 25 ++++++++++-
2 files changed, 105 insertions(+), 13 deletions(-)
diff --git a/drivers/media/video/soc_camera.c b/drivers/media/video/soc_camera.c
index 9db66a4..5e48c2c 100644
--- a/drivers/media/video/soc_camera.c
+++ b/drivers/media/video/soc_camera.c
@@ -47,6 +47,18 @@ const struct soc_camera_data_format *soc_camera_format_by_fourcc(
}
EXPORT_SYMBOL(soc_camera_format_by_fourcc);
+const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
+ struct soc_camera_device *icd, unsigned int fourcc)
+{
+ unsigned int i;
+
+ for (i = 0; i < icd->num_user_formats; i++)
+ if (icd->user_formats[i].host_fmt->fourcc == fourcc)
+ return icd->user_formats + i;
+ return NULL;
+}
+EXPORT_SYMBOL(soc_camera_xlate_by_fourcc);
+
static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -161,6 +173,59 @@ static int soc_camera_dqbuf(struct file *file, void *priv,
return videobuf_dqbuf(&icf->vb_vidq, p, file->f_flags & O_NONBLOCK);
}
+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;
+
+ if (!ici->ops->get_formats)
+ /*
+ * Fallback mode - the host will have to serve all
+ * sensor-provided formats one-to-one to the user
+ */
+ fmts = icd->num_formats;
+ else
+ /*
+ * 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);
+
+ if (!fmts)
+ return -ENXIO;
+
+ icd->user_formats =
+ vmalloc(fmts * sizeof(struct soc_camera_format_xlate));
+ if (!icd->user_formats)
+ return -ENOMEM;
+
+ icd->num_user_formats = fmts;
+ fmts = 0;
+
+ dev_dbg(&icd->dev, "Found %d supported formats.\n", fmts);
+
+ /* Second pass - actually fill data formats */
+ for (i = 0; i < icd->num_formats; i++)
+ if (!ici->ops->get_formats) {
+ icd->user_formats[i].host_fmt = icd->formats + i;
+ 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,
+ &icd->user_formats[fmts]);
+ }
+
+ icd->current_fmt = icd->user_formats[0].host_fmt;
+
+ return 0;
+}
+
+static void soc_camera_free_user_formats(struct soc_camera_device *icd)
+{
+ vfree(icd->user_formats);
+}
+
static int soc_camera_open(struct inode *inode, struct file *file)
{
struct video_device *vdev;
@@ -197,10 +262,12 @@ static int soc_camera_open(struct inode *inode, struct file *file)
/* Now we really have to activate the camera */
if (icd->use_count == 1) {
+ 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);
- icd->use_count--;
goto eiciadd;
}
}
@@ -216,6 +283,9 @@ static int soc_camera_open(struct inode *inode, struct file *file)
/* All errors are entered with the video_lock held */
eiciadd:
+ soc_camera_free_user_formats(icd);
+eiufmt:
+ icd->use_count--;
module_put(ici->ops->owner);
emgi:
module_put(icd->ops->owner);
@@ -234,8 +304,10 @@ static int soc_camera_close(struct inode *inode, struct file *file)
mutex_lock(&video_lock);
icd->use_count--;
- if (!icd->use_count)
+ if (!icd->use_count) {
ici->ops->remove(icd);
+ soc_camera_free_user_formats(icd);
+ }
module_put(icd->ops->owner);
module_put(ici->ops->owner);
mutex_unlock(&video_lock);
@@ -311,6 +383,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
struct soc_camera_device *icd = icf->icd;
struct soc_camera_host *ici =
to_soc_camera_host(icd->dev.parent);
+ __u32 pixfmt = f->fmt.pix.pixelformat;
int ret;
struct v4l2_rect rect;
@@ -328,14 +401,12 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
if (ret < 0) {
return ret;
} else if (!icd->current_fmt ||
- icd->current_fmt->fourcc != f->fmt.pix.pixelformat) {
- dev_err(&ici->dev, "Host driver hasn't set up current "
- "format correctly!\n");
+ icd->current_fmt->fourcc != pixfmt) {
+ dev_err(&ici->dev,
+ "Host driver hasn't set up current format correctly!\n");
return -EINVAL;
}
- /* buswidth may be further adjusted by the ici */
- icd->buswidth = icd->current_fmt->depth;
icd->width = rect.width;
icd->height = rect.height;
icf->vb_vidq.field = f->fmt.pix.field;
@@ -347,7 +418,7 @@ static int soc_camera_s_fmt_vid_cap(struct file *file, void *priv,
icd->width, icd->height);
/* set physical bus parameters */
- return ici->ops->set_bus_param(icd, f->fmt.pix.pixelformat);
+ return ici->ops->set_bus_param(icd, pixfmt);
}
static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
@@ -359,10 +430,10 @@ static int soc_camera_enum_fmt_vid_cap(struct file *file, void *priv,
WARN_ON(priv != file->private_data);
- if (f->index >= icd->num_formats)
+ if (f->index >= icd->num_user_formats)
return -EINVAL;
- format = &icd->formats[f->index];
+ format = icd->user_formats[f->index].host_fmt;
strlcpy(f->description, format->name, sizeof(f->description));
f->pixelformat = format->fourcc;
@@ -919,8 +990,6 @@ int soc_camera_video_start(struct soc_camera_device *icd)
vdev->minor = -1;
vdev->tvnorms = V4L2_STD_UNKNOWN,
- icd->current_fmt = &icd->formats[0];
-
err = video_register_device(vdev, VFL_TYPE_GRABBER, vdev->minor);
if (err < 0) {
dev_err(vdev->parent, "video_register_device failed\n");
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index dddaf45..da57ffd 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -41,6 +41,8 @@ struct soc_camera_device {
const struct soc_camera_data_format *current_fmt;
const struct soc_camera_data_format *formats;
int num_formats;
+ struct soc_camera_format_xlate *user_formats;
+ int num_user_formats;
struct module *owner;
void *host_priv; /* per-device host private data */
/* soc_camera.c private count. Only accessed with video_lock held */
@@ -65,8 +67,10 @@ struct soc_camera_host_ops {
struct module *owner;
int (*add)(struct soc_camera_device *);
void (*remove)(struct soc_camera_device *);
- int (*suspend)(struct soc_camera_device *, pm_message_t state);
+ int (*suspend)(struct soc_camera_device *, pm_message_t);
int (*resume)(struct soc_camera_device *);
+ int (*get_formats)(struct soc_camera_device *, int,
+ struct soc_camera_format_xlate *);
int (*set_fmt)(struct soc_camera_device *, __u32, struct v4l2_rect *);
int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
void (*init_videobuf)(struct videobuf_queue *,
@@ -107,6 +111,8 @@ extern void soc_camera_video_stop(struct soc_camera_device *icd);
extern const struct soc_camera_data_format *soc_camera_format_by_fourcc(
struct soc_camera_device *icd, unsigned int fourcc);
+extern const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
+ struct soc_camera_device *icd, unsigned int fourcc);
struct soc_camera_data_format {
const char *name;
@@ -115,6 +121,23 @@ struct soc_camera_data_format {
enum v4l2_colorspace colorspace;
};
+/**
+ * struct soc_camera_format_xlate - match between host and sensor formats
+ * @cam_fmt: sensor format provided by the sensor
+ * @host_fmt: host format after host translation from cam_fmt
+ * @buswidth: bus width for this format
+ *
+ * Host and sensor translation structure. Used in table of host and sensor
+ * formats matchings in soc_camera_device. A host can override the generic list
+ * generation by implementing get_formats(), and use it for format checks and
+ * format setup.
+ */
+struct soc_camera_format_xlate {
+ const struct soc_camera_data_format *cam_fmt;
+ const struct soc_camera_data_format *host_fmt;
+ unsigned char buswidth;
+};
+
struct soc_camera_ops {
struct module *owner;
int (*probe)(struct soc_camera_device *);
--
1.5.6.5
--
video4linux-list mailing list
Unsubscribe mailto:video4linux-list-request@redhat.com?subject=unsubscribe
https://www.redhat.com/mailman/listinfo/video4linux-list
next prev parent reply other threads:[~2008-11-30 17:33 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-18 19:25 [PATCH 0/2 v3] soc-camera: pixel format negotiation Guennadi Liakhovetski
2008-11-18 19:25 ` [PATCH 1/2 v3] soc-camera: pixel format negotiation - core support Guennadi Liakhovetski
2008-11-19 20:47 ` Robert Jarzmik
2008-11-20 19:53 ` Guennadi Liakhovetski
2008-11-18 19:25 ` [PATCH 2/2 v3] pxa-camera: pixel format negotiation Guennadi Liakhovetski
2008-11-19 21:29 ` Robert Jarzmik
2008-11-20 20:43 ` Guennadi Liakhovetski
2008-11-21 19:22 ` Robert Jarzmik
2008-11-21 20:03 ` Guennadi Liakhovetski
2008-11-21 20:53 ` Robert Jarzmik
2008-11-21 22:16 ` Guennadi Liakhovetski
2008-11-23 10:46 ` Robert Jarzmik
2008-11-23 15:26 ` Robert Jarzmik
2008-11-23 16:32 ` Guennadi Liakhovetski
2008-11-24 19:28 ` [PATCH 1/2] soc_camera: add format translation structure Robert Jarzmik
2008-11-24 19:28 ` [PATCH 2/2] pxa_camera: use the new " Robert Jarzmik
2008-11-27 23:00 ` Guennadi Liakhovetski
2008-11-28 23:27 ` Guennadi Liakhovetski
2008-11-29 12:30 ` Robert Jarzmik
2008-11-25 18:21 ` [PATCH 1/2] soc_camera: add format " Guennadi Liakhovetski
2008-11-27 21:27 ` Robert Jarzmik
2008-11-27 23:13 ` Guennadi Liakhovetski
2008-11-29 17:31 ` [PATCH v4 1/2] soc-camera: pixel format negotiation - core support Guennadi Liakhovetski
2008-11-30 17:33 ` Robert Jarzmik [this message]
2008-11-29 14:17 ` Robert Jarzmik
2008-11-29 14:17 ` [PATCH v4 2/2] pxa-camera: pixel format negotiation Robert Jarzmik
2008-11-29 15:49 ` Guennadi Liakhovetski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87myfhp19f.fsf@free.fr \
--to=robert.jarzmik@free.fr \
--cc=g.liakhovetski@gmx.de \
--cc=video4linux-list@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.