From: William Towle <william.towle@codethink.co.uk>
To: linux-kernel@lists.codethink.co.uk, linux-media@vger.kernel.org,
Guennadi Liakhovetski <g.liakhovetski@gmx.de>,
Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>,
Hans Verkuil <hverkuil@xs4all.nl>
Subject: [PATCH 6/8] WmT: adv7604 driver compatibility
Date: Thu, 29 Jan 2015 16:19:46 +0000 [thread overview]
Message-ID: <1422548388-28861-7-git-send-email-william.towle@codethink.co.uk> (raw)
In-Reply-To: <1422548388-28861-1-git-send-email-william.towle@codethink.co.uk>
Add 'struct media_pad pad' member and suitable glue code, so that
soc_camera/rcar_vin can become agnostic to whether an old or new-
style driver (wrt pad API use) can sit underneath
This version has been reworked to include appropriate constant and
datatype names for kernel v3.18
---
drivers/media/platform/soc_camera/soc_camera.c | 148 +++++++++++++++++++-
drivers/media/platform/soc_camera/soc_scale_crop.c | 43 +++++-
include/media/soc_camera.h | 1 +
3 files changed, 182 insertions(+), 10 deletions(-)
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index f4be2a1..efc20bf 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -37,8 +37,11 @@
#include <media/v4l2-ioctl.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-of.h>
+#if 0
#include <media/videobuf-core.h>
#include <media/videobuf2-core.h>
+#endif
+#include <media/v4l2-mediabus.h>
/* Default to VGA resolution */
#define DEFAULT_WIDTH 640
@@ -453,6 +456,98 @@ static int soc_camera_expbuf(struct file *file, void *priv,
return vb2_expbuf(&icd->vb2_vidq, p);
}
+static int soc_camera_init_user_formats_pad(struct soc_camera_device *icd, int src_pad_idx)
+{
+ struct v4l2_subdev *sd= soc_camera_to_subdev(icd);
+ struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+ struct v4l2_subdev_mbus_code_enum code;
+ int fmts= 0, raw_fmts, i, ret;
+
+ code.pad= src_pad_idx;
+ code.index= 0;
+
+ // subdev_has_op -> enum_mbus_code vs enum_mbus_fmt
+ if (v4l2_subdev_has_op(sd, pad, enum_mbus_code)) {
+ while (!v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code))
+ code.index++;
+ } else {
+ u32 pixcode;
+
+ while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, code.index, &pixcode))
+ {
+ code.code= pixcode;
+ code.index++;
+ }
+ }
+ raw_fmts= code.index;
+
+ if (!ici->ops->get_formats) {
+ /*
+ * Fallback mode - the host will have to serve all
+ * sensor-provided formats one-to-one to the user
+ */
+ fmts = raw_fmts;
+ }
+ else {
+ /*
+ * First pass - only count formats this host-sensor
+ * configuration can provide
+ */
+ for (i = 0; i < raw_fmts; i++) {
+ int ret = ici->ops->get_formats(icd, i, NULL);
+ if (ret < 0)
+ return ret;
+ fmts += ret;
+ }
+ }
+
+ if (!fmts)
+ return -ENXIO;
+
+ icd->user_formats =
+ vmalloc(fmts * sizeof(struct soc_camera_format_xlate));
+ if (!icd->user_formats)
+ return -ENOMEM;
+
+ dev_dbg(icd->pdev, "Found %d supported formats.\n", fmts);
+
+ /* Second pass - actually fill data formats */
+ fmts = 0;
+ for (i = 0; i < raw_fmts; i++) {
+ if (!ici->ops->get_formats) {
+ code.index= i;
+ // subdev_has_op -> enum_mbus_code vs enum_mbus_fmt
+ if (v4l2_subdev_has_op(sd, pad, enum_mbus_code)) {
+ v4l2_subdev_call(sd, pad, enum_mbus_code, NULL, &code);
+ } else {
+ u32 pixcode;
+
+ v4l2_subdev_call(sd, video, enum_mbus_fmt, code.index, &pixcode);
+ code.code= pixcode;
+ }
+ icd->user_formats[fmts].host_fmt =
+ soc_mbus_get_fmtdesc(code.code);
+ if (icd->user_formats[fmts].host_fmt)
+ icd->user_formats[fmts++].code = code.code;
+ } else {
+ ret = ici->ops->get_formats(icd, i,
+ &icd->user_formats[fmts]);
+ if (ret < 0)
+ goto egfmt;
+ fmts += ret;
+ }
+ }
+
+ icd->num_user_formats = fmts;
+ icd->current_fmt = &icd->user_formats[0];
+
+ return 0;
+
+egfmt:
+ vfree(icd->user_formats);
+ return ret;
+}
+
/* Always entered with .host_lock held */
static int soc_camera_init_user_formats(struct soc_camera_device *icd)
{
@@ -1289,6 +1384,7 @@ static int soc_camera_probe_finish(struct soc_camera_device *icd)
{
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct v4l2_mbus_framefmt mf;
+ int src_pad_idx= -1;
int ret;
sd->grp_id = soc_camera_grp_id(icd);
@@ -1307,7 +1403,30 @@ static int soc_camera_probe_finish(struct soc_camera_device *icd)
}
/* At this point client .probe() should have run already */
- ret = soc_camera_init_user_formats(icd);
+ // subdev_has_op -> enum_mbus_code vs enum_mbus_fmt
+ if (!v4l2_subdev_has_op(sd, pad, enum_mbus_code))
+ ret = soc_camera_init_user_formats(icd);
+ else {
+ ret = media_entity_init(&icd->vdev->entity, 1,
+ &icd->pad, 0);
+ if (!ret) {
+ for (src_pad_idx= 0; src_pad_idx < sd->entity.num_pads; src_pad_idx++)
+ if (sd->entity.pads[src_pad_idx].flags == MEDIA_PAD_FL_SOURCE)
+ break;
+
+ if (src_pad_idx < sd->entity.num_pads) {
+ ret = media_entity_create_link(
+ &icd->vdev->entity, 0,
+ &sd->entity, src_pad_idx,
+ MEDIA_LNK_FL_IMMUTABLE |
+ MEDIA_LNK_FL_ENABLED);
+ }
+ }
+
+ if (!ret)
+ ret = soc_camera_init_user_formats_pad(icd,
+ src_pad_idx);
+ }
if (ret < 0)
goto eusrfmt;
@@ -1318,11 +1437,28 @@ static int soc_camera_probe_finish(struct soc_camera_device *icd)
goto evidstart;
/* Try to improve our guess of a reasonable window format */
- if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
- icd->user_width = mf.width;
- icd->user_height = mf.height;
- icd->colorspace = mf.colorspace;
- icd->field = mf.field;
+ // subdev_has_op -> get_fmt vs g_mbus_fmt
+ if (v4l2_subdev_has_op(sd, pad, enum_mbus_code)
+ && v4l2_subdev_has_op(sd, pad, get_fmt)
+ && src_pad_idx != -1) {
+ struct v4l2_subdev_format sd_format;
+
+ sd_format.pad= src_pad_idx;
+ sd_format.which= V4L2_SUBDEV_FORMAT_ACTIVE;
+
+ if (!v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_format)) {
+ icd->user_width = sd_format.format.width;
+ icd->user_height = sd_format.format.height;
+ icd->colorspace = sd_format.format.colorspace;
+ icd->field = sd_format.format.field;
+ }
+ } else {
+ if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
+ icd->user_width = mf.width;
+ icd->user_height = mf.height;
+ icd->colorspace = mf.colorspace;
+ icd->field = mf.field;
+ }
}
soc_camera_remove_device(icd);
diff --git a/drivers/media/platform/soc_camera/soc_scale_crop.c b/drivers/media/platform/soc_camera/soc_scale_crop.c
index 8e74fb7..8a1ca05 100644
--- a/drivers/media/platform/soc_camera/soc_scale_crop.c
+++ b/drivers/media/platform/soc_camera/soc_scale_crop.c
@@ -224,9 +224,27 @@ static int client_s_fmt(struct soc_camera_device *icd,
bool host_1to1;
int ret;
- ret = v4l2_device_call_until_err(sd->v4l2_dev,
- soc_camera_grp_id(icd), video,
- s_mbus_fmt, mf);
+ // subdev_has_op -> set_fmt vs s_mbus_fmt
+ if (v4l2_subdev_has_op(sd, pad, set_fmt)) {
+ struct v4l2_subdev_format sd_format;
+ struct media_pad *remote_pad;
+
+ remote_pad= media_entity_remote_pad(
+ &icd->vdev->entity.pads[0]);
+ sd_format.pad = remote_pad->index;
+ sd_format.which= V4L2_SUBDEV_FORMAT_ACTIVE;
+ sd_format.format= *mf;
+
+ ret = v4l2_device_call_until_err(sd->v4l2_dev,
+ soc_camera_grp_id(icd), pad, set_fmt, NULL,
+ &sd_format);
+
+ mf->width = sd_format.format.width;
+ mf->height = sd_format.format.height;
+ } else {
+ ret = v4l2_device_call_until_err(sd->v4l2_dev,
+ soc_camera_grp_id(icd), video, s_mbus_fmt, mf);
+ }
if (ret < 0)
return ret;
@@ -264,9 +282,26 @@ static int client_s_fmt(struct soc_camera_device *icd,
tmp_h = min(2 * tmp_h, max_height);
mf->width = tmp_w;
mf->height = tmp_h;
- ret = v4l2_device_call_until_err(sd->v4l2_dev,
+ // subdev_has_op -> set_fmt vs s_mbus_fmt
+ if (v4l2_subdev_has_op(sd, pad, set_fmt)) {
+ struct v4l2_subdev_format sd_format;
+ struct media_pad *remote_pad;
+
+ remote_pad= media_entity_remote_pad(
+ &icd->vdev->entity.pads[0]);
+ sd_format.pad = remote_pad->index;
+ sd_format.which= V4L2_SUBDEV_FORMAT_ACTIVE;
+ sd_format.format= *mf;
+
+ ret = v4l2_device_call_until_err(sd->v4l2_dev,
+ soc_camera_grp_id(icd),
+ pad, set_fmt, NULL,
+ &sd_format);
+ } else {
+ ret = v4l2_device_call_until_err(sd->v4l2_dev,
soc_camera_grp_id(icd), video,
s_mbus_fmt, mf);
+ }
dev_geo(dev, "Camera scaled to %ux%u\n",
mf->width, mf->height);
if (ret < 0) {
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 2f6261f..f0c5238 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -42,6 +42,7 @@ struct soc_camera_device {
unsigned char devnum; /* Device number per host */
struct soc_camera_sense *sense; /* See comment in struct definition */
struct video_device *vdev;
+ struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
const struct soc_camera_format_xlate *current_fmt;
struct soc_camera_format_xlate *user_formats;
--
1.7.10.4
next prev parent reply other threads:[~2015-01-29 16:19 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-01-29 16:19 RFC: supporting adv7604.c under soc_camera/rcar_vin William Towle
2015-01-29 16:19 ` [PATCH 1/8] Add ability to read default input port from DT William Towle
2015-01-29 20:19 ` Jean-Michel Hautbois
2015-01-29 16:19 ` [PATCH 2/8] adv7604.c: formats, default colourspace, and IRQs William Towle
2015-01-29 16:19 ` [PATCH 3/8] WmT: document "adi,adv7612" William Towle
2015-01-29 16:19 ` [PATCH 4/8] WmT: m-5mols_core style pad handling for adv7604 William Towle
2015-01-29 20:23 ` Jean-Michel Hautbois
2015-02-04 14:14 ` William Towle
2015-02-04 14:40 ` Hans Verkuil
2015-01-29 16:19 ` [PATCH 5/8] media: rcar_vin: Add RGB888_1X24 input format support William Towle
2015-01-29 17:05 ` Sergei Shtylyov
2015-01-29 18:18 ` Guennadi Liakhovetski
2015-01-29 18:28 ` Sergei Shtylyov
2015-01-29 20:19 ` Guennadi Liakhovetski
2015-01-29 20:36 ` Sergei Shtylyov
2015-01-29 20:57 ` Guennadi Liakhovetski
2015-01-29 21:11 ` Guennadi Liakhovetski
2015-02-01 18:29 ` Guennadi Liakhovetski
2015-01-29 16:19 ` William Towle [this message]
2015-01-31 23:56 ` [PATCH 6/8] WmT: adv7604 driver compatibility Guennadi Liakhovetski
2015-02-01 11:26 ` Guennadi Liakhovetski
2015-02-02 10:01 ` Laurent Pinchart
2015-02-02 10:09 ` Hans Verkuil
2015-02-03 15:22 ` Laurent Pinchart
2015-02-03 15:24 ` Hans Verkuil
2015-02-03 15:29 ` Lars-Peter Clausen
2015-02-03 15:56 ` Laurent Pinchart
2015-02-03 15:55 ` Laurent Pinchart
2015-01-29 16:19 ` [PATCH 7/8] WmT: rcar_vin new ADV7612 support William Towle
2015-02-01 11:44 ` Guennadi Liakhovetski
2015-01-29 16:19 ` [PATCH 8/8] WmT: dts/i vin0/adv7612 (HDMI) William Towle
2015-01-29 16:51 ` Sergei Shtylyov
2015-02-01 15:51 ` RFC: supporting adv7604.c under soc_camera/rcar_vin Guennadi Liakhovetski
2015-03-04 9:51 ` [Linux-kernel] " William Towle
2015-03-04 10:19 ` Hans Verkuil
2015-03-05 8:58 ` William Towle
2015-03-25 9:55 ` William Towle
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=1422548388-28861-7-git-send-email-william.towle@codethink.co.uk \
--to=william.towle@codethink.co.uk \
--cc=g.liakhovetski@gmx.de \
--cc=hverkuil@xs4all.nl \
--cc=linux-kernel@lists.codethink.co.uk \
--cc=linux-media@vger.kernel.org \
--cc=sergei.shtylyov@cogentembedded.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).