Re: [RESEND PATCH v3 02/17] media: v4l2-fwnode: Pass notifier to v4l2_async_register_fwnode_subdev()

2020-02-28 Thread Steve Longerbeam

Hi Sakari,

On 2/25/20 7:07 AM, Sakari Ailus wrote:

Hi Steve,

On Sat, Feb 15, 2020 at 11:41:21AM -0800, Steve Longerbeam wrote:

Instead of allocating a notifier in v4l2_async_register_fwnode_subdev(),
have the caller provide one. This allows the caller to implement
notifier ops (bind, unbind).

The caller is now responsible for first initializing its notifier with a
call to v4l2_async_notifier_init().

Signed-off-by: Steve Longerbeam 

Instead of improving v4l2_async_register_fwnode_subdev(), could you convert
the users (IMX driver in this case) to call the preferred APIs instead? As
the lines below show, v4l2_async_register_fwnode_subdev() has only two
users left --- the other one of which is the IMX driver. After converting
these two, we could just remove this API.

See e.g. drivers/media/pci/intel/ipu3/ipu3-cio2.c and
drivers/media/platform/omap3isp/isp.c for examples.


Shouldn't v4l2_async_notifier_add_fwnode_remote_subdev() check for the 
availability of the remote before adding it to the notifier's asd list, 
as in:


diff --git a/drivers/media/v4l2-core/v4l2-async.c 
b/drivers/media/v4l2-core/v4l2-async.c

index 8bde33c21ce4..b48ed68c6c6c 100644
--- a/drivers/media/v4l2-core/v4l2-async.c
+++ b/drivers/media/v4l2-core/v4l2-async.c
@@ -615,7 +615,7 @@ v4l2_async_notifier_add_fwnode_remote_subdev(struct 
v4l2_async_notifier *notif,

    int ret;

    remote = fwnode_graph_get_remote_port_parent(endpoint);
-   if (!remote)
+   if (!remote || !fwnode_device_is_available(remote))
    return -ENOTCONN;

    asd->match_type = V4L2_ASYNC_MATCH_FWNODE;


Otherwise we are back to the problem that the notifier will never 
complete because the remote's driver is not probed.


Steve




---
Changes in v3:
- added the missing calls to unregister/cleanup the new subdev notifiers.
   Reported by Rui Silva.
---
  drivers/media/platform/video-mux.c |  8 +++-
  drivers/media/v4l2-core/v4l2-fwnode.c  | 11 +--
  drivers/staging/media/imx/imx6-mipi-csi2.c |  7 ++-
  drivers/staging/media/imx/imx7-media-csi.c |  7 ++-
  drivers/staging/media/imx/imx7-mipi-csis.c |  9 -
  include/media/v4l2-fwnode.h| 12 
  6 files changed, 36 insertions(+), 18 deletions(-)


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [RESEND PATCH v3 02/17] media: v4l2-fwnode: Pass notifier to v4l2_async_register_fwnode_subdev()

2020-02-26 Thread Steve Longerbeam

Hi Sakari,

Thanks for the feedback.


On 2/25/20 7:07 AM, Sakari Ailus wrote:

Hi Steve,

On Sat, Feb 15, 2020 at 11:41:21AM -0800, Steve Longerbeam wrote:

Instead of allocating a notifier in v4l2_async_register_fwnode_subdev(),
have the caller provide one. This allows the caller to implement
notifier ops (bind, unbind).

The caller is now responsible for first initializing its notifier with a
call to v4l2_async_notifier_init().

Signed-off-by: Steve Longerbeam 

Instead of improving v4l2_async_register_fwnode_subdev(), could you convert
the users (IMX driver in this case) to call the preferred APIs instead?


I presume you mean using v4l2_async_notifier_add_fwnode_remote_subdev(). 
Ok, I'll convert to use that API.


Steve


  As
the lines below show, v4l2_async_register_fwnode_subdev() has only two
users left --- the other one of which is the IMX driver. After converting
these two, we could just remove this API.

See e.g. drivers/media/pci/intel/ipu3/ipu3-cio2.c and
drivers/media/platform/omap3isp/isp.c for examples.


---
Changes in v3:
- added the missing calls to unregister/cleanup the new subdev notifiers.
   Reported by Rui Silva.
---
  drivers/media/platform/video-mux.c |  8 +++-
  drivers/media/v4l2-core/v4l2-fwnode.c  | 11 +--
  drivers/staging/media/imx/imx6-mipi-csi2.c |  7 ++-
  drivers/staging/media/imx/imx7-media-csi.c |  7 ++-
  drivers/staging/media/imx/imx7-mipi-csis.c |  9 -
  include/media/v4l2-fwnode.h| 12 
  6 files changed, 36 insertions(+), 18 deletions(-)


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 16/17] media: imx: silence a couple debug messages

2020-02-15 Thread Steve Longerbeam
Convert to dev_dbg the "subdev bound" and IPU-internal media-link
creation messages.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-dev-common.c  | 4 +++-
 drivers/staging/media/imx/imx-media-dev.c | 2 +-
 drivers/staging/media/imx/imx-media-internal-sd.c | 6 +++---
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index f7ad3cbbeec2..b23bbfab388a 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -24,7 +24,9 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier 
*notifier,
  struct v4l2_subdev *sd,
  struct v4l2_async_subdev *asd)
 {
-   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+
+   dev_dbg(imxmd->md.dev, "subdev %s bound\n", sd->name);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-dev.c 
b/drivers/staging/media/imx/imx-media-dev.c
index 2c3c2adca683..6d2205461e56 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -32,7 +32,7 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier 
*notifier,
return ret;
}
 
-   v4l2_info(>v4l2_dev, "subdev %s bound\n", sd->name);
+   dev_dbg(imxmd->md.dev, "subdev %s bound\n", sd->name);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c 
b/drivers/staging/media/imx/imx-media-internal-sd.c
index d4237e1a4241..da4109b2fd13 100644
--- a/drivers/staging/media/imx/imx-media-internal-sd.c
+++ b/drivers/staging/media/imx/imx-media-internal-sd.c
@@ -142,9 +142,9 @@ static int create_internal_link(struct imx_media_dev *imxmd,
   >entity.pads[link->remote_pad]))
return 0;
 
-   v4l2_info(>v4l2_dev, "%s:%d -> %s:%d\n",
- src->name, link->local_pad,
- sink->name, link->remote_pad);
+   dev_dbg(imxmd->md.dev, "%s:%d -> %s:%d\n",
+   src->name, link->local_pad,
+   sink->name, link->remote_pad);
 
ret = media_create_pad_link(>entity, link->local_pad,
>entity, link->remote_pad, 0);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 12/17] media: imx: csi: Add missing notifier unregister/cleanup

2020-02-15 Thread Steve Longerbeam
Add the missing calls to unregister and cleanup the subdev notifier in
imx_csi_remove().

Fixes: c893500a16baf ("media: imx: csi: Register a subdev notifier")
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 3e2afdd59276..bea6a70cc353 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -2030,6 +2030,8 @@ static int imx_csi_remove(struct platform_device *pdev)
 
v4l2_ctrl_handler_free(>ctrl_hdlr);
mutex_destroy(>lock);
+   v4l2_async_notifier_unregister(>notifier);
+   v4l2_async_notifier_cleanup(>notifier);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(>entity);
 
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 14/17] media: imx: csi: Lookup upstream endpoint with imx_media_get_pad_fwnode

2020-02-15 Thread Steve Longerbeam
Fix the 1:1 port-id:pad-index assumption for the upstream subdevice, by
searching the upstream subdevice's endpoints for one that maps to the
pad's index. This is carried out by a new reverse mapping function
imx_media_get_pad_fwnode().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c   | 22 --
 drivers/staging/media/imx/imx-media-utils.c | 33 +
 drivers/staging/media/imx/imx-media.h   |  1 +
 drivers/staging/media/imx/imx7-media-csi.c  | 25 +---
 4 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 2a8f01375f78..7d4c1c9640dd 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -164,7 +164,7 @@ static inline bool requires_passthrough(struct 
v4l2_fwnode_endpoint *ep,
 static int csi_get_upstream_endpoint(struct csi_priv *priv,
 struct v4l2_fwnode_endpoint *ep)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity *src;
struct v4l2_subdev *sd;
struct media_pad *pad;
@@ -203,23 +203,13 @@ static int csi_get_upstream_endpoint(struct csi_priv 
*priv,
if (!pad)
return -ENODEV;
 
-   sd = media_entity_to_v4l2_subdev(pad->entity);
+   endpoint = imx_media_get_pad_fwnode(pad);
+   if (IS_ERR(endpoint))
+   return PTR_ERR(endpoint);
 
-   /*
-* NOTE: this assumes an OF-graph port id is the same as a
-* media pad index.
-*/
-   port = of_graph_get_port_by_id(sd->dev->of_node, pad->index);
-   if (!port)
-   return -ENODEV;
-
-   endpoint = of_get_next_child(port, NULL);
-   of_node_put(port);
-   if (!endpoint)
-   return -ENODEV;
+   v4l2_fwnode_endpoint_parse(endpoint, ep);
 
-   v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ep);
-   of_node_put(endpoint);
+   fwnode_handle_put(endpoint);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index 87152bd9af22..61752c6b074d 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -1007,6 +1007,39 @@ imx_media_pipeline_video_device(struct media_entity 
*start_entity,
 }
 EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
 
+/*
+ * Find a fwnode endpoint that maps to the given subdevice's pad.
+ * If there are multiple endpoints that map to the pad, only the
+ * first endpoint encountered is returned.
+ *
+ * On success the refcount of the returned fwnode endpoint is
+ * incremented.
+ */
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad)
+{
+   struct fwnode_handle *endpoint;
+   struct v4l2_subdev *sd;
+
+   if (!is_media_entity_v4l2_subdev(pad->entity))
+   return ERR_PTR(-ENODEV);
+
+   sd = media_entity_to_v4l2_subdev(pad->entity);
+
+   fwnode_graph_for_each_endpoint(dev_fwnode(sd->dev), endpoint) {
+   int pad_idx = media_entity_get_fwnode_pad(>entity,
+ endpoint,
+ pad->flags);
+   if (pad_idx < 0)
+   continue;
+
+   if (pad_idx == pad->index)
+   return endpoint;
+   }
+
+   return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(imx_media_get_pad_fwnode);
+
 /*
  * Turn current pipeline streaming on/off starting from entity.
  */
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index f90a65ba4ced..5f23d852122f 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -205,6 +205,7 @@ imx_media_pipeline_subdev(struct media_entity 
*start_entity, u32 grp_id,
 struct video_device *
 imx_media_pipeline_video_device(struct media_entity *start_entity,
enum v4l2_buf_type buftype, bool upstream);
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad);
 
 struct imx_media_dma_buf {
void  *virt;
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index cf9f675c53a3..f2ed13aca2b0 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -439,9 +439,8 @@ static int imx7_csi_get_upstream_endpoint(struct imx7_csi 
*csi,
  struct v4l2_fwnode_endpoint *ep,
  bool skip_mux)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity *src;
-   struct v4l2_subdev *sd;
struct media_pad *pad;
 
if 

[RESEND PATCH v3 13/17] media: imx: csi: Create media links in bound notifier

2020-02-15 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
---
 drivers/staging/media/imx/imx-media-csi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index bea6a70cc353..2a8f01375f78 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -120,6 +120,11 @@ static inline struct csi_priv *sd_to_dev(struct 
v4l2_subdev *sdev)
return container_of(sdev, struct csi_priv, sd);
 }
 
+static inline struct csi_priv *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_priv, notifier);
+}
+
 static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep)
 {
return ep->bus_type != V4L2_MBUS_CSI2_DPHY;
@@ -1896,6 +1901,20 @@ static int imx_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
 }
 
+static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier,
+   struct v4l2_subdev *sd,
+   struct v4l2_async_subdev *asd)
+{
+   struct csi_priv *priv = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI_SINK_PAD];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations csi_notify_ops = {
+   .bound = imx_csi_notify_bound,
+};
+
 static int imx_csi_async_register(struct csi_priv *priv)
 {
struct fwnode_handle *fwnode;
@@ -1904,6 +1923,8 @@ static int imx_csi_async_register(struct csi_priv *priv)
 
v4l2_async_notifier_init(>notifier);
 
+   priv->notifier.ops = _notify_ops;
+
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 15/17] media: imx: Create missing links from CSI-2 receiver

2020-02-15 Thread Steve Longerbeam
The entities external to the i.MX6 IPU and i.MX7 now create the links
to their fwnode-endpoint connected entities in their notifier bound
callbacks. Which means imx_media_create_of_links() and
imx_media_create_csi_of_links() are no longer needed and are removed.

However there is still one case in which imx-media needs to create
fwnode-endpoint based links at probe completion. The v4l2-async framework
does not allow multiple subdevice notifiers to contain a duplicate
subdevice in their asd_list. Only the first subdev notifier that discovers
and adds that one subdevice to its asd_list will receive a bound callback
for it. Other subdevices that also have firmware endpoint connections to
this duplicate subdevice will not have it in their asd_list, and thus will
never receive a bound callback for it. In the case of imx-media, the one
duplicate subdevice in question is the i.MX6 MIPI CSI-2 receiver.

Until there is a solution to that problem, rewrite imx_media_create_links()
to add the missing links from the CSI-2 receiver to the CSIs and CSI muxes.
The function is renamed imx_media_create_csi2_links().

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_links().
Changes in v2:
- this is a rewrite of v1 "media: imx: Use media_create_fwnode_links for
  external links", which only adds the missing CSI-2 receiver links.
---
 .../staging/media/imx/imx-media-dev-common.c  |  46 +++
 drivers/staging/media/imx/imx-media-of.c  | 114 --
 drivers/staging/media/imx/imx-media.h |   4 -
 3 files changed, 17 insertions(+), 147 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 66b505f7e8df..f7ad3cbbeec2 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -30,41 +30,31 @@ static int imx_media_subdev_bound(struct 
v4l2_async_notifier *notifier,
 }
 
 /*
- * Create the media links for all subdevs that registered.
+ * Create the missing media links from the CSI-2 receiver.
  * Called after all async subdevs have bound.
  */
-static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+static void imx_media_create_csi2_links(struct imx_media_dev *imxmd)
 {
-   struct imx_media_dev *imxmd = notifier2dev(notifier);
-   struct v4l2_subdev *sd;
+   struct v4l2_subdev *sd, *csi2 = NULL;
 
list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
-   switch (sd->grp_id) {
-   case IMX_MEDIA_GRP_ID_IPU_VDIC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
-   /*
-* links have already been created for the
-* sync-registered subdevs.
-*/
-   break;
-   case IMX_MEDIA_GRP_ID_IPU_CSI0:
-   case IMX_MEDIA_GRP_ID_IPU_CSI1:
-   case IMX_MEDIA_GRP_ID_CSI:
-   imx_media_create_csi_of_links(imxmd, sd);
-   break;
-   default:
-   /*
-* if this subdev has fwnode links, create media
-* links for them.
-*/
-   imx_media_create_of_links(imxmd, sd);
+   if (sd->grp_id == IMX_MEDIA_GRP_ID_CSI2) {
+   csi2 = sd;
break;
}
}
+   if (!csi2)
+   return;
 
-   return 0;
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   /* skip if not a CSI or a video mux */
+   if (!(sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) &&
+   !(sd->grp_id & IMX_MEDIA_GRP_ID_CSI) &&
+   sd->entity.function != MEDIA_ENT_F_VID_MUX)
+   continue;
+
+   imx_media_create_fwnode_pad_links(csi2, sd);
+   }
 }
 
 /*
@@ -196,9 +186,7 @@ int imx_media_probe_complete(struct v4l2_async_notifier 
*notifier)
 
mutex_lock(>mutex);
 
-   ret = imx_media_create_links(notifier);
-   if (ret)
-   goto unlock;
+   imx_media_create_csi2_links(imxmd);
 
ret = imx_media_create_pad_vdev_lists(imxmd);
if (ret)
diff --git a/drivers/staging/media/imx/imx-media-of.c 
b/drivers/staging/media/imx/imx-media-of.c
index 2d3efd2a6dde..82e13e972e23 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -74,117 +74,3 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
return ret;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_of_subdevs);
-
-/*
- * Create a single media link to/from sd using a fwnode link.
- *
- * NOTE: this function assumes an OF port node is equiv

[RESEND PATCH v3 17/17] media: imx: TODO: Remove media link creation todos

2020-02-15 Thread Steve Longerbeam
Remove the TODO items regarding media link creation, these issues are
resolved by moving media link creation to individual entity bound
callbacks and the implementation of the get_fwnode_pad operation.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/TODO | 29 -
 1 file changed, 29 deletions(-)

diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 6f29b5ca5324..a371cdedcdb0 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -17,35 +17,6 @@
   decided whether this feature is useful enough to make it generally
   available by exporting to v4l2-core.
 
-- After all async subdevices have been bound, v4l2_fwnode_parse_link()
-  is used to form the media links between the devices discovered in
-  the OF graph.
-
-  While this approach allows support for arbitrary OF graphs, there
-  are some assumptions for this to work:
-
-  1. If a port owned by a device in the graph has endpoint nodes, the
- port is treated as a media pad.
-
- This presents problems for devices that don't make this port = pad
- assumption. Examples are SMIAPP compatible cameras which define only
- a single output port node, but which define multiple pads owned
- by multiple subdevices (pixel-array, binner, scaler). Or video
- decoders (entity function MEDIA_ENT_F_ATV_DECODER), which also define
- only a single output port node, but define multiple pads for video,
- VBI, and audio out.
-
- A workaround at present is to set the port reg properties to
- correspond to the media pad index that the port represents. A
- possible long-term solution is to implement a subdev API that
- maps a port id to a media pad index.
-
-  2. Every endpoint of a port owned by a device in the graph is treated
- as a media link.
-
- Which means a port must not contain mixed-use endpoints, they
- must all refer to media links between V4L2 subdevices.
-
 - i.MX7: all of the above, since it uses the imx media core
 
 - i.MX7: use Frame Interval Monitor
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 11/17] media: imx: csi: Embed notifier in struct csi_priv

2020-02-15 Thread Steve Longerbeam
Embed the notifier in 'struct csi_priv', instead of dynamically allocating
it, to make it possible to retrieve csi_priv in a notifier callback op.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 25 +--
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index dc5fe25fe7b8..3e2afdd59276 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -58,6 +58,8 @@ struct csi_priv {
struct ipu_soc *ipu;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
+   struct v4l2_async_notifier notifier;
+
/* the video device at IDMAC output pad */
struct imx_media_video_dev *vdev;
struct imx_media_fim *fim;
@@ -1896,31 +1898,28 @@ static int imx_csi_parse_endpoint(struct device *dev,
 
 static int imx_csi_async_register(struct csi_priv *priv)
 {
-   struct v4l2_async_notifier *notifier;
struct fwnode_handle *fwnode;
unsigned int port;
int ret;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
+   v4l2_async_notifier_init(>notifier);
 
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
ret = fwnode_property_read_u32(fwnode, "reg", );
if (ret < 0)
-   goto out_free;
+   return ret;
 
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
-   priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+   priv->dev->parent, >notifier,
+   sizeof(struct v4l2_async_subdev),
port, imx_csi_parse_endpoint);
if (ret < 0)
goto out_cleanup;
 
-   ret = v4l2_async_subdev_notifier_register(>sd, notifier);
+   ret = v4l2_async_subdev_notifier_register(>sd,
+ >notifier);
if (ret < 0)
goto out_cleanup;
 
@@ -1928,16 +1927,12 @@ static int imx_csi_async_register(struct csi_priv *priv)
if (ret < 0)
goto out_unregister;
 
-   priv->sd.subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
-   v4l2_async_notifier_unregister(notifier);
+   v4l2_async_notifier_unregister(>notifier);
 out_cleanup:
-   v4l2_async_notifier_cleanup(notifier);
-out_free:
-   kfree(notifier);
+   v4l2_async_notifier_cleanup(>notifier);
 
return ret;
 }
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 10/17] media: imx7-media-csi: Create media links in bound notifier

2020-02-15 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
Reviewed-by: Rui Miguel Silva 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
Changes in v2:
- Rename notifier_to_dev() to imx7_csi_notifier_to_dev() and remove
  unnecessary inline. Suggested by Rui Silva.
---
 drivers/staging/media/imx/imx7-media-csi.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index dc6d1a28fde7..cf9f675c53a3 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -196,6 +196,12 @@ struct imx7_csi {
struct completion last_eof_completion;
 };
 
+static struct imx7_csi *
+imx7_csi_notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx7_csi, notifier);
+}
+
 static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
 {
return readl(csi->regbase + offset);
@@ -1187,6 +1193,20 @@ static int imx7_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
 }
 
+static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[IMX7_CSI_PAD_SINK];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
+   .bound = imx7_csi_notify_bound,
+};
+
 static int imx7_csi_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -1269,6 +1289,8 @@ static int imx7_csi_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi->notifier.ops = _csi_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(>sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
NULL, 0,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 06/17] media: imx: Add imx_media_create_fwnode_pad_link()

2020-02-15 Thread Steve Longerbeam
Add functions to create media links between a source and sink subdevice
based on fwnode endpoint connections between them.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-utils.c | 91 +
 drivers/staging/media/imx/imx-media.h   |  4 +
 2 files changed, 95 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index 0788a1874557..87152bd9af22 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -729,6 +729,97 @@ void imx_media_grp_id_to_sd_name(char *sd_name, int sz, 
u32 grp_id, int ipu_id)
 }
 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
 
+/*
+ * Look for and create a single fwnode link that connects a source
+ * subdevice to a sink pad.
+ */
+int imx_media_create_fwnode_pad_link(struct v4l2_subdev *src_sd,
+struct media_pad *sink)
+{
+   struct fwnode_handle *endpoint;
+
+   /* loop thru the source's fwnode endpoints */
+   fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
+   struct fwnode_handle *remote_ep;
+   int src_idx, sink_idx, ret;
+   struct media_pad *src;
+
+   remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
+   if (!remote_ep)
+   continue;
+
+   /*
+* ask the sink entity to verify that this fwnode link
+* actually does connect with the entity, and if so that
+* it connects to its requested sink pad.
+*/
+   sink_idx = media_entity_get_fwnode_pad(sink->entity,
+  remote_ep,
+  MEDIA_PAD_FL_SINK);
+   fwnode_handle_put(remote_ep);
+
+   if (sink_idx < 0 || sink_idx != sink->index)
+   continue;
+
+   src_idx = media_entity_get_fwnode_pad(_sd->entity,
+ endpoint,
+ MEDIA_PAD_FL_SOURCE);
+   if (src_idx < 0)
+   continue;
+
+   /*
+* found the fwnode link that works, create the media
+* link for it.
+*/
+
+   fwnode_handle_put(endpoint);
+
+   src = _sd->entity.pads[src_idx];
+
+   /* success if it already exists */
+   if (media_entity_find_link(src, sink))
+   return 0;
+
+   dev_dbg(src_sd->dev, "%s:%d -> %s:%d\n",
+   src_sd->entity.name, src_idx,
+   sink->entity->name, sink_idx);
+
+   ret = media_create_pad_link(_sd->entity, src_idx,
+   sink->entity, sink_idx, 0);
+   if (ret)
+   dev_err(src_sd->dev,
+   "%s:%d -> %s:%d failed with %d\n",
+   src_sd->entity.name, src_idx,
+   sink->entity->name, sink_idx, ret);
+
+   return ret;
+   }
+
+   return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(imx_media_create_fwnode_pad_link);
+
+int imx_media_create_fwnode_pad_links(struct v4l2_subdev *src_sd,
+ struct v4l2_subdev *sink_sd)
+{
+   int i;
+
+   for (i = 0; i < sink_sd->entity.num_pads; i++) {
+   struct media_pad *pad = _sd->entity.pads[i];
+   int ret;
+
+   if (!(pad->flags & MEDIA_PAD_FL_SINK))
+   continue;
+
+   ret = imx_media_create_fwnode_pad_link(src_sd, pad);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(imx_media_create_fwnode_pad_links);
+
 struct v4l2_subdev *
 imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
struct fwnode_handle *fwnode)
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index 11861191324a..f90a65ba4ced 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -183,6 +183,10 @@ int imx_media_ipu_image_to_mbus_fmt(struct 
v4l2_mbus_framefmt *mbus,
struct ipu_image *image);
 void imx_media_grp_id_to_sd_name(char *sd_name, int sz,
 u32 grp_id, int ipu_id);
+int imx_media_create_fwnode_pad_link(struct v4l2_subdev *src_sd,
+struct media_pad *sink);
+int imx_media_create_fwnode_pad_links(struct v4l2_subdev *src_sd,
+ struct v4l2_subdev *sink_sd);
 struct v4l2_subdev *
 imx_media_find_subde

[RESEND PATCH v3 09/17] media: imx7-mipi-csis: Create media links in bound notifier

2020-02-15 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
Changes in v2:
- Move notifier_to_csis_state() next to mipi_sd_to_csis_state(), remove
  unnecessary inline, and rename to mipi_notifier_to_csis_state().
  Suggested by Rui Silva.
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 4c54456318ea..d3a83577efed 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -317,6 +317,12 @@ static int mipi_csis_dump_regs(struct csi_state *state)
return 0;
 }
 
+static struct csi_state *
+mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_state, notifier);
+}
+
 static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
 {
return container_of(sdev, struct csi_state, mipi_sd);
@@ -848,6 +854,20 @@ static int mipi_csis_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   struct csi_state *state = mipi_notifier_to_csis_state(notifier);
+   struct media_pad *sink = >mipi_sd.entity.pads[CSIS_PAD_SINK];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
+   .bound = mipi_csis_notify_bound,
+};
+
 static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
 struct platform_device *pdev,
 const struct v4l2_subdev_ops *ops)
@@ -886,6 +906,8 @@ static int mipi_csis_subdev_init(struct v4l2_subdev 
*mipi_sd,
 
v4l2_async_notifier_init(>notifier);
 
+   state->notifier.ops = _csis_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(mipi_sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
_port, 1,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 04/17] media: imx: mipi csi-2: Implement get_fwnode_pad op

2020-02-15 Thread Steve Longerbeam
Implement get_fwnode_pad operation. If the endpoint is owned by the MIPI
CSI-2 receiver, return the endpoint's port number. The MIPI CSI-2 receiver
maps port numbers and pad indexes 1:1.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 28 ++
 1 file changed, 28 insertions(+)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index c1d1afeea53a..e27a342751fc 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -507,9 +507,37 @@ static int csi2_registered(struct v4l2_subdev *sd)
  640, 480, 0, V4L2_FIELD_NONE, NULL);
 }
 
+static int csi2_get_fwnode_pad(struct media_entity *entity,
+  struct fwnode_endpoint *endpoint)
+{
+   struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+   struct csi2_dev *csi2 = sd_to_dev(sd);
+   struct fwnode_handle *csi2_ep;
+
+   /*
+* If the endpoint is one of ours, return the endpoint's port
+* number. This device maps port numbers and pad indexes 1:1.
+*/
+   fwnode_graph_for_each_endpoint(dev_fwnode(csi2->dev), csi2_ep) {
+   if (endpoint->local_fwnode == csi2_ep) {
+   struct fwnode_endpoint fwep;
+   int ret;
+
+   ret = fwnode_graph_parse_endpoint(csi2_ep, );
+
+   fwnode_handle_put(csi2_ep);
+
+   return ret ? ret : fwep.port;
+   }
+   }
+
+   return -ENXIO;
+}
+
 static const struct media_entity_operations csi2_entity_ops = {
.link_setup = csi2_link_setup,
.link_validate = v4l2_subdev_link_validate,
+   .get_fwnode_pad = csi2_get_fwnode_pad,
 };
 
 static const struct v4l2_subdev_video_ops csi2_video_ops = {
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 03/17] media: imx: csi: Implement get_fwnode_pad op

2020-02-15 Thread Steve Longerbeam
The CSI does not have a 1:1 relationship between fwnode port numbers and
pad indexes. In fact the CSI fwnode device is itself a port which is the
sink, containing only a single fwnode endpoint. Implement media_entity
operation get_fwnode_pad to first verify the given endpoint is the CSI's
sink endpoint, and if so return the CSI sink pad index.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index b60ed4f22f6d..dc5fe25fe7b8 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1825,9 +1825,32 @@ static void csi_unregistered(struct v4l2_subdev *sd)
ipu_csi_put(priv->csi);
 }
 
+/*
+ * The CSI has only one fwnode endpoint, at the sink pad. Verify the
+ * endpoint belongs to us, and return CSI_SINK_PAD.
+ */
+static int csi_get_fwnode_pad(struct media_entity *entity,
+ struct fwnode_endpoint *endpoint)
+{
+   struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+   struct fwnode_handle *csi_port = dev_fwnode(priv->dev);
+   struct fwnode_handle *csi_ep;
+   int ret;
+
+   csi_ep = fwnode_get_next_child_node(csi_port, NULL);
+
+   ret = endpoint->local_fwnode == csi_ep ? CSI_SINK_PAD : -ENXIO;
+
+   fwnode_handle_put(csi_ep);
+
+   return ret;
+}
+
 static const struct media_entity_operations csi_entity_ops = {
.link_setup = csi_link_setup,
.link_validate = v4l2_subdev_link_validate,
+   .get_fwnode_pad = csi_get_fwnode_pad,
 };
 
 static const struct v4l2_subdev_core_ops csi_core_ops = {
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[RESEND PATCH v3 02/17] media: v4l2-fwnode: Pass notifier to v4l2_async_register_fwnode_subdev()

2020-02-15 Thread Steve Longerbeam
Instead of allocating a notifier in v4l2_async_register_fwnode_subdev(),
have the caller provide one. This allows the caller to implement
notifier ops (bind, unbind).

The caller is now responsible for first initializing its notifier with a
call to v4l2_async_notifier_init().

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- added the missing calls to unregister/cleanup the new subdev notifiers.
  Reported by Rui Silva.
---
 drivers/media/platform/video-mux.c |  8 +++-
 drivers/media/v4l2-core/v4l2-fwnode.c  | 11 +--
 drivers/staging/media/imx/imx6-mipi-csi2.c |  7 ++-
 drivers/staging/media/imx/imx7-media-csi.c |  7 ++-
 drivers/staging/media/imx/imx7-mipi-csis.c |  9 -
 include/media/v4l2-fwnode.h| 12 
 6 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/video-mux.c 
b/drivers/media/platform/video-mux.c
index ddd0e338f9e4..3d2a5c2b4c08 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -21,6 +21,7 @@
 
 struct video_mux {
struct v4l2_subdev subdev;
+   struct v4l2_async_notifier notifier;
struct media_pad *pads;
struct v4l2_mbus_framefmt *format_mbus;
struct mux_control *mux;
@@ -354,8 +355,11 @@ static int video_mux_async_register(struct video_mux *vmux,
for (i = 0; i < num_input_pads; i++)
ports[i] = i;
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >subdev, sizeof(struct v4l2_async_subdev),
+   >subdev, >notifier,
+   sizeof(struct v4l2_async_subdev),
ports, num_input_pads, video_mux_parse_endpoint);
 
kfree(ports);
@@ -442,6 +446,8 @@ static int video_mux_remove(struct platform_device *pdev)
struct video_mux *vmux = platform_get_drvdata(pdev);
struct v4l2_subdev *sd = >subdev;
 
+   v4l2_async_notifier_unregister(>notifier);
+   v4l2_async_notifier_cleanup(>notifier);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(>entity);
 
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c 
b/drivers/media/v4l2-core/v4l2-fwnode.c
index 6ece4320e1d2..ae2cc4d6faf6 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1164,12 +1164,12 @@ int v4l2_async_register_subdev_sensor_common(struct 
v4l2_subdev *sd)
 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
 
 int v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd,
+ struct v4l2_async_notifier *notifier,
  size_t asd_struct_size,
  unsigned int *ports,
  unsigned int num_ports,
  parse_endpoint_func parse_endpoint)
 {
-   struct v4l2_async_notifier *notifier;
struct device *dev = sd->dev;
struct fwnode_handle *fwnode;
int ret;
@@ -1181,12 +1181,6 @@ int v4l2_async_register_fwnode_subdev(struct v4l2_subdev 
*sd,
if (!fwnode_device_is_available(fwnode))
return -ENODEV;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
-
if (!ports) {
ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, notifier,
 
asd_struct_size,
@@ -1211,15 +1205,12 @@ int v4l2_async_register_fwnode_subdev(struct 
v4l2_subdev *sd,
if (ret < 0)
goto out_unregister;
 
-   sd->subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
v4l2_async_notifier_unregister(notifier);
 out_cleanup:
v4l2_async_notifier_cleanup(notifier);
-   kfree(notifier);
 
return ret;
 }
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index cd3dd6e33ef0..c1d1afeea53a 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -35,6 +35,7 @@
 struct csi2_dev {
struct device  *dev;
struct v4l2_subdev  sd;
+   struct v4l2_async_notifier notifier;
struct media_pad   pad[CSI2_NUM_PADS];
struct clk *dphy_clk;
struct clk *pllref_clk;
@@ -636,8 +637,10 @@ static int csi2_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, >sd);
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >sd, sizeof(struct v4l2_async_subdev),
+   >sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
if (ret)
goto dphy_off;
@@ -658,6 +661,8 @@ 

[RESEND PATCH v3 08/17] media: imx: mipi csi-2: Create media links in bound notifier

2020-02-15 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link()
  that creates a single link.
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index e27a342751fc..fddf6388348a 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -91,6 +91,11 @@ static inline struct csi2_dev *sd_to_dev(struct v4l2_subdev 
*sdev)
return container_of(sdev, struct csi2_dev, sd);
 }
 
+static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi2_dev, notifier);
+}
+
 /*
  * The required sequence of MIPI CSI-2 startup as specified in the i.MX6
  * reference manual is as follows:
@@ -584,6 +589,20 @@ static int csi2_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct csi2_dev *csi2 = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI2_SINK_PAD];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations csi2_notify_ops = {
+   .bound = csi2_notify_bound,
+};
+
 static int csi2_probe(struct platform_device *pdev)
 {
unsigned int sink_port = 0;
@@ -667,6 +686,8 @@ static int csi2_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi2->notifier.ops = _notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(
>sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 16/17] media: imx: silence a couple debug messages

2020-02-04 Thread Steve Longerbeam
Convert to dev_dbg the "subdev bound" and IPU-internal media-link
creation messages.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-dev-common.c  | 4 +++-
 drivers/staging/media/imx/imx-media-dev.c | 2 +-
 drivers/staging/media/imx/imx-media-internal-sd.c | 6 +++---
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index f7ad3cbbeec2..b23bbfab388a 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -24,7 +24,9 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier 
*notifier,
  struct v4l2_subdev *sd,
  struct v4l2_async_subdev *asd)
 {
-   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+
+   dev_dbg(imxmd->md.dev, "subdev %s bound\n", sd->name);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-dev.c 
b/drivers/staging/media/imx/imx-media-dev.c
index 2c3c2adca683..6d2205461e56 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -32,7 +32,7 @@ static int imx_media_subdev_bound(struct v4l2_async_notifier 
*notifier,
return ret;
}
 
-   v4l2_info(>v4l2_dev, "subdev %s bound\n", sd->name);
+   dev_dbg(imxmd->md.dev, "subdev %s bound\n", sd->name);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-internal-sd.c 
b/drivers/staging/media/imx/imx-media-internal-sd.c
index d4237e1a4241..da4109b2fd13 100644
--- a/drivers/staging/media/imx/imx-media-internal-sd.c
+++ b/drivers/staging/media/imx/imx-media-internal-sd.c
@@ -142,9 +142,9 @@ static int create_internal_link(struct imx_media_dev *imxmd,
   >entity.pads[link->remote_pad]))
return 0;
 
-   v4l2_info(>v4l2_dev, "%s:%d -> %s:%d\n",
- src->name, link->local_pad,
- sink->name, link->remote_pad);
+   dev_dbg(imxmd->md.dev, "%s:%d -> %s:%d\n",
+   src->name, link->local_pad,
+   sink->name, link->remote_pad);
 
ret = media_create_pad_link(>entity, link->local_pad,
>entity, link->remote_pad, 0);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 08/17] media: imx: mipi csi-2: Create media links in bound notifier

2020-02-04 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link()
  that creates a single link.
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index e27a342751fc..fddf6388348a 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -91,6 +91,11 @@ static inline struct csi2_dev *sd_to_dev(struct v4l2_subdev 
*sdev)
return container_of(sdev, struct csi2_dev, sd);
 }
 
+static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi2_dev, notifier);
+}
+
 /*
  * The required sequence of MIPI CSI-2 startup as specified in the i.MX6
  * reference manual is as follows:
@@ -584,6 +589,20 @@ static int csi2_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct csi2_dev *csi2 = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI2_SINK_PAD];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations csi2_notify_ops = {
+   .bound = csi2_notify_bound,
+};
+
 static int csi2_probe(struct platform_device *pdev)
 {
unsigned int sink_port = 0;
@@ -667,6 +686,8 @@ static int csi2_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi2->notifier.ops = _notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(
>sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 06/17] media: imx: Add imx_media_create_fwnode_pad_link()

2020-02-04 Thread Steve Longerbeam
Add functions to create media links between a source and sink subdevice
based on fwnode endpoint connections between them.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-utils.c | 91 +
 drivers/staging/media/imx/imx-media.h   |  4 +
 2 files changed, 95 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index 0788a1874557..87152bd9af22 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -729,6 +729,97 @@ void imx_media_grp_id_to_sd_name(char *sd_name, int sz, 
u32 grp_id, int ipu_id)
 }
 EXPORT_SYMBOL_GPL(imx_media_grp_id_to_sd_name);
 
+/*
+ * Look for and create a single fwnode link that connects a source
+ * subdevice to a sink pad.
+ */
+int imx_media_create_fwnode_pad_link(struct v4l2_subdev *src_sd,
+struct media_pad *sink)
+{
+   struct fwnode_handle *endpoint;
+
+   /* loop thru the source's fwnode endpoints */
+   fwnode_graph_for_each_endpoint(dev_fwnode(src_sd->dev), endpoint) {
+   struct fwnode_handle *remote_ep;
+   int src_idx, sink_idx, ret;
+   struct media_pad *src;
+
+   remote_ep = fwnode_graph_get_remote_endpoint(endpoint);
+   if (!remote_ep)
+   continue;
+
+   /*
+* ask the sink entity to verify that this fwnode link
+* actually does connect with the entity, and if so that
+* it connects to its requested sink pad.
+*/
+   sink_idx = media_entity_get_fwnode_pad(sink->entity,
+  remote_ep,
+  MEDIA_PAD_FL_SINK);
+   fwnode_handle_put(remote_ep);
+
+   if (sink_idx < 0 || sink_idx != sink->index)
+   continue;
+
+   src_idx = media_entity_get_fwnode_pad(_sd->entity,
+ endpoint,
+ MEDIA_PAD_FL_SOURCE);
+   if (src_idx < 0)
+   continue;
+
+   /*
+* found the fwnode link that works, create the media
+* link for it.
+*/
+
+   fwnode_handle_put(endpoint);
+
+   src = _sd->entity.pads[src_idx];
+
+   /* success if it already exists */
+   if (media_entity_find_link(src, sink))
+   return 0;
+
+   dev_dbg(src_sd->dev, "%s:%d -> %s:%d\n",
+   src_sd->entity.name, src_idx,
+   sink->entity->name, sink_idx);
+
+   ret = media_create_pad_link(_sd->entity, src_idx,
+   sink->entity, sink_idx, 0);
+   if (ret)
+   dev_err(src_sd->dev,
+   "%s:%d -> %s:%d failed with %d\n",
+   src_sd->entity.name, src_idx,
+   sink->entity->name, sink_idx, ret);
+
+   return ret;
+   }
+
+   return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(imx_media_create_fwnode_pad_link);
+
+int imx_media_create_fwnode_pad_links(struct v4l2_subdev *src_sd,
+ struct v4l2_subdev *sink_sd)
+{
+   int i;
+
+   for (i = 0; i < sink_sd->entity.num_pads; i++) {
+   struct media_pad *pad = _sd->entity.pads[i];
+   int ret;
+
+   if (!(pad->flags & MEDIA_PAD_FL_SINK))
+   continue;
+
+   ret = imx_media_create_fwnode_pad_link(src_sd, pad);
+   if (ret)
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(imx_media_create_fwnode_pad_links);
+
 struct v4l2_subdev *
 imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
struct fwnode_handle *fwnode)
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index 11861191324a..f90a65ba4ced 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -183,6 +183,10 @@ int imx_media_ipu_image_to_mbus_fmt(struct 
v4l2_mbus_framefmt *mbus,
struct ipu_image *image);
 void imx_media_grp_id_to_sd_name(char *sd_name, int sz,
 u32 grp_id, int ipu_id);
+int imx_media_create_fwnode_pad_link(struct v4l2_subdev *src_sd,
+struct media_pad *sink);
+int imx_media_create_fwnode_pad_links(struct v4l2_subdev *src_sd,
+ struct v4l2_subdev *sink_sd);
 struct v4l2_subdev *
 imx_media_find_subde

[PATCH v3 10/17] media: imx7-media-csi: Create media links in bound notifier

2020-02-04 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
Reviewed-by: Rui Miguel Silva 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
Changes in v2:
- Rename notifier_to_dev() to imx7_csi_notifier_to_dev() and remove
  unnecessary inline. Suggested by Rui Silva.
---
 drivers/staging/media/imx/imx7-media-csi.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index dc6d1a28fde7..cf9f675c53a3 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -196,6 +196,12 @@ struct imx7_csi {
struct completion last_eof_completion;
 };
 
+static struct imx7_csi *
+imx7_csi_notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx7_csi, notifier);
+}
+
 static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
 {
return readl(csi->regbase + offset);
@@ -1187,6 +1193,20 @@ static int imx7_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
 }
 
+static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct imx7_csi *csi = imx7_csi_notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[IMX7_CSI_PAD_SINK];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
+   .bound = imx7_csi_notify_bound,
+};
+
 static int imx7_csi_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -1269,6 +1289,8 @@ static int imx7_csi_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi->notifier.ops = _csi_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(>sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
NULL, 0,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 13/17] media: imx: csi: Create media links in bound notifier

2020-02-04 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
---
 drivers/staging/media/imx/imx-media-csi.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index bea6a70cc353..2a8f01375f78 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -120,6 +120,11 @@ static inline struct csi_priv *sd_to_dev(struct 
v4l2_subdev *sdev)
return container_of(sdev, struct csi_priv, sd);
 }
 
+static inline struct csi_priv *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_priv, notifier);
+}
+
 static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep)
 {
return ep->bus_type != V4L2_MBUS_CSI2_DPHY;
@@ -1896,6 +1901,20 @@ static int imx_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
 }
 
+static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier,
+   struct v4l2_subdev *sd,
+   struct v4l2_async_subdev *asd)
+{
+   struct csi_priv *priv = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI_SINK_PAD];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations csi_notify_ops = {
+   .bound = imx_csi_notify_bound,
+};
+
 static int imx_csi_async_register(struct csi_priv *priv)
 {
struct fwnode_handle *fwnode;
@@ -1904,6 +1923,8 @@ static int imx_csi_async_register(struct csi_priv *priv)
 
v4l2_async_notifier_init(>notifier);
 
+   priv->notifier.ops = _notify_ops;
+
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 03/17] media: imx: csi: Implement get_fwnode_pad op

2020-02-04 Thread Steve Longerbeam
The CSI does not have a 1:1 relationship between fwnode port numbers and
pad indexes. In fact the CSI fwnode device is itself a port which is the
sink, containing only a single fwnode endpoint. Implement media_entity
operation get_fwnode_pad to first verify the given endpoint is the CSI's
sink endpoint, and if so return the CSI sink pad index.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index b60ed4f22f6d..dc5fe25fe7b8 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1825,9 +1825,32 @@ static void csi_unregistered(struct v4l2_subdev *sd)
ipu_csi_put(priv->csi);
 }
 
+/*
+ * The CSI has only one fwnode endpoint, at the sink pad. Verify the
+ * endpoint belongs to us, and return CSI_SINK_PAD.
+ */
+static int csi_get_fwnode_pad(struct media_entity *entity,
+ struct fwnode_endpoint *endpoint)
+{
+   struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+   struct fwnode_handle *csi_port = dev_fwnode(priv->dev);
+   struct fwnode_handle *csi_ep;
+   int ret;
+
+   csi_ep = fwnode_get_next_child_node(csi_port, NULL);
+
+   ret = endpoint->local_fwnode == csi_ep ? CSI_SINK_PAD : -ENXIO;
+
+   fwnode_handle_put(csi_ep);
+
+   return ret;
+}
+
 static const struct media_entity_operations csi_entity_ops = {
.link_setup = csi_link_setup,
.link_validate = v4l2_subdev_link_validate,
+   .get_fwnode_pad = csi_get_fwnode_pad,
 };
 
 static const struct v4l2_subdev_core_ops csi_core_ops = {
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 17/17] media: imx: TODO: Remove media link creation todos

2020-02-04 Thread Steve Longerbeam
Remove the TODO items regarding media link creation, these issues are
resolved by moving media link creation to individual entity bound
callbacks and the implementation of the get_fwnode_pad operation.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/TODO | 29 -
 1 file changed, 29 deletions(-)

diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 6f29b5ca5324..a371cdedcdb0 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -17,35 +17,6 @@
   decided whether this feature is useful enough to make it generally
   available by exporting to v4l2-core.
 
-- After all async subdevices have been bound, v4l2_fwnode_parse_link()
-  is used to form the media links between the devices discovered in
-  the OF graph.
-
-  While this approach allows support for arbitrary OF graphs, there
-  are some assumptions for this to work:
-
-  1. If a port owned by a device in the graph has endpoint nodes, the
- port is treated as a media pad.
-
- This presents problems for devices that don't make this port = pad
- assumption. Examples are SMIAPP compatible cameras which define only
- a single output port node, but which define multiple pads owned
- by multiple subdevices (pixel-array, binner, scaler). Or video
- decoders (entity function MEDIA_ENT_F_ATV_DECODER), which also define
- only a single output port node, but define multiple pads for video,
- VBI, and audio out.
-
- A workaround at present is to set the port reg properties to
- correspond to the media pad index that the port represents. A
- possible long-term solution is to implement a subdev API that
- maps a port id to a media pad index.
-
-  2. Every endpoint of a port owned by a device in the graph is treated
- as a media link.
-
- Which means a port must not contain mixed-use endpoints, they
- must all refer to media links between V4L2 subdevices.
-
 - i.MX7: all of the above, since it uses the imx media core
 
 - i.MX7: use Frame Interval Monitor
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 11/17] media: imx: csi: Embed notifier in struct csi_priv

2020-02-04 Thread Steve Longerbeam
Embed the notifier in 'struct csi_priv', instead of dynamically allocating
it, to make it possible to retrieve csi_priv in a notifier callback op.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 25 +--
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index dc5fe25fe7b8..3e2afdd59276 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -58,6 +58,8 @@ struct csi_priv {
struct ipu_soc *ipu;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
+   struct v4l2_async_notifier notifier;
+
/* the video device at IDMAC output pad */
struct imx_media_video_dev *vdev;
struct imx_media_fim *fim;
@@ -1896,31 +1898,28 @@ static int imx_csi_parse_endpoint(struct device *dev,
 
 static int imx_csi_async_register(struct csi_priv *priv)
 {
-   struct v4l2_async_notifier *notifier;
struct fwnode_handle *fwnode;
unsigned int port;
int ret;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
+   v4l2_async_notifier_init(>notifier);
 
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
ret = fwnode_property_read_u32(fwnode, "reg", );
if (ret < 0)
-   goto out_free;
+   return ret;
 
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
-   priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+   priv->dev->parent, >notifier,
+   sizeof(struct v4l2_async_subdev),
port, imx_csi_parse_endpoint);
if (ret < 0)
goto out_cleanup;
 
-   ret = v4l2_async_subdev_notifier_register(>sd, notifier);
+   ret = v4l2_async_subdev_notifier_register(>sd,
+ >notifier);
if (ret < 0)
goto out_cleanup;
 
@@ -1928,16 +1927,12 @@ static int imx_csi_async_register(struct csi_priv *priv)
if (ret < 0)
goto out_unregister;
 
-   priv->sd.subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
-   v4l2_async_notifier_unregister(notifier);
+   v4l2_async_notifier_unregister(>notifier);
 out_cleanup:
-   v4l2_async_notifier_cleanup(notifier);
-out_free:
-   kfree(notifier);
+   v4l2_async_notifier_cleanup(>notifier);
 
return ret;
 }
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 09/17] media: imx7-mipi-csis: Create media links in bound notifier

2020-02-04 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_link().
Changes in v2:
- Move notifier_to_csis_state() next to mipi_sd_to_csis_state(), remove
  unnecessary inline, and rename to mipi_notifier_to_csis_state().
  Suggested by Rui Silva.
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 4c54456318ea..d3a83577efed 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -317,6 +317,12 @@ static int mipi_csis_dump_regs(struct csi_state *state)
return 0;
 }
 
+static struct csi_state *
+mipi_notifier_to_csis_state(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_state, notifier);
+}
+
 static struct csi_state *mipi_sd_to_csis_state(struct v4l2_subdev *sdev)
 {
return container_of(sdev, struct csi_state, mipi_sd);
@@ -848,6 +854,20 @@ static int mipi_csis_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   struct csi_state *state = mipi_notifier_to_csis_state(notifier);
+   struct media_pad *sink = >mipi_sd.entity.pads[CSIS_PAD_SINK];
+
+   return imx_media_create_fwnode_pad_link(sd, sink);
+}
+
+static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
+   .bound = mipi_csis_notify_bound,
+};
+
 static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
 struct platform_device *pdev,
 const struct v4l2_subdev_ops *ops)
@@ -886,6 +906,8 @@ static int mipi_csis_subdev_init(struct v4l2_subdev 
*mipi_sd,
 
v4l2_async_notifier_init(>notifier);
 
+   state->notifier.ops = _csis_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(mipi_sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
_port, 1,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 02/17] media: v4l2-fwnode: Pass notifier to v4l2_async_register_fwnode_subdev()

2020-02-04 Thread Steve Longerbeam
Instead of allocating a notifier in v4l2_async_register_fwnode_subdev(),
have the caller provide one. This allows the caller to implement
notifier ops (bind, unbind).

The caller is now responsible for first initializing its notifier with a
call to v4l2_async_notifier_init().

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- added the missing calls to unregister/cleanup the new subdev notifiers.
  Reported by Rui Silva.
---
 drivers/media/platform/video-mux.c |  8 +++-
 drivers/media/v4l2-core/v4l2-fwnode.c  | 11 +--
 drivers/staging/media/imx/imx6-mipi-csi2.c |  7 ++-
 drivers/staging/media/imx/imx7-media-csi.c |  7 ++-
 drivers/staging/media/imx/imx7-mipi-csis.c |  9 -
 include/media/v4l2-fwnode.h| 12 
 6 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/video-mux.c 
b/drivers/media/platform/video-mux.c
index ddd0e338f9e4..3d2a5c2b4c08 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -21,6 +21,7 @@
 
 struct video_mux {
struct v4l2_subdev subdev;
+   struct v4l2_async_notifier notifier;
struct media_pad *pads;
struct v4l2_mbus_framefmt *format_mbus;
struct mux_control *mux;
@@ -354,8 +355,11 @@ static int video_mux_async_register(struct video_mux *vmux,
for (i = 0; i < num_input_pads; i++)
ports[i] = i;
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >subdev, sizeof(struct v4l2_async_subdev),
+   >subdev, >notifier,
+   sizeof(struct v4l2_async_subdev),
ports, num_input_pads, video_mux_parse_endpoint);
 
kfree(ports);
@@ -442,6 +446,8 @@ static int video_mux_remove(struct platform_device *pdev)
struct video_mux *vmux = platform_get_drvdata(pdev);
struct v4l2_subdev *sd = >subdev;
 
+   v4l2_async_notifier_unregister(>notifier);
+   v4l2_async_notifier_cleanup(>notifier);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(>entity);
 
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c 
b/drivers/media/v4l2-core/v4l2-fwnode.c
index 6ece4320e1d2..ae2cc4d6faf6 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1164,12 +1164,12 @@ int v4l2_async_register_subdev_sensor_common(struct 
v4l2_subdev *sd)
 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
 
 int v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd,
+ struct v4l2_async_notifier *notifier,
  size_t asd_struct_size,
  unsigned int *ports,
  unsigned int num_ports,
  parse_endpoint_func parse_endpoint)
 {
-   struct v4l2_async_notifier *notifier;
struct device *dev = sd->dev;
struct fwnode_handle *fwnode;
int ret;
@@ -1181,12 +1181,6 @@ int v4l2_async_register_fwnode_subdev(struct v4l2_subdev 
*sd,
if (!fwnode_device_is_available(fwnode))
return -ENODEV;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
-
if (!ports) {
ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, notifier,
 
asd_struct_size,
@@ -1211,15 +1205,12 @@ int v4l2_async_register_fwnode_subdev(struct 
v4l2_subdev *sd,
if (ret < 0)
goto out_unregister;
 
-   sd->subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
v4l2_async_notifier_unregister(notifier);
 out_cleanup:
v4l2_async_notifier_cleanup(notifier);
-   kfree(notifier);
 
return ret;
 }
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index cd3dd6e33ef0..c1d1afeea53a 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -35,6 +35,7 @@
 struct csi2_dev {
struct device  *dev;
struct v4l2_subdev  sd;
+   struct v4l2_async_notifier notifier;
struct media_pad   pad[CSI2_NUM_PADS];
struct clk *dphy_clk;
struct clk *pllref_clk;
@@ -636,8 +637,10 @@ static int csi2_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, >sd);
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >sd, sizeof(struct v4l2_async_subdev),
+   >sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
if (ret)
goto dphy_off;
@@ -658,6 +661,8 @@ 

[PATCH v3 04/17] media: imx: mipi csi-2: Implement get_fwnode_pad op

2020-02-04 Thread Steve Longerbeam
Implement get_fwnode_pad operation. If the endpoint is owned by the MIPI
CSI-2 receiver, return the endpoint's port number. The MIPI CSI-2 receiver
maps port numbers and pad indexes 1:1.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 28 ++
 1 file changed, 28 insertions(+)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index c1d1afeea53a..e27a342751fc 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -507,9 +507,37 @@ static int csi2_registered(struct v4l2_subdev *sd)
  640, 480, 0, V4L2_FIELD_NONE, NULL);
 }
 
+static int csi2_get_fwnode_pad(struct media_entity *entity,
+  struct fwnode_endpoint *endpoint)
+{
+   struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+   struct csi2_dev *csi2 = sd_to_dev(sd);
+   struct fwnode_handle *csi2_ep;
+
+   /*
+* If the endpoint is one of ours, return the endpoint's port
+* number. This device maps port numbers and pad indexes 1:1.
+*/
+   fwnode_graph_for_each_endpoint(dev_fwnode(csi2->dev), csi2_ep) {
+   if (endpoint->local_fwnode == csi2_ep) {
+   struct fwnode_endpoint fwep;
+   int ret;
+
+   ret = fwnode_graph_parse_endpoint(csi2_ep, );
+
+   fwnode_handle_put(csi2_ep);
+
+   return ret ? ret : fwep.port;
+   }
+   }
+
+   return -ENXIO;
+}
+
 static const struct media_entity_operations csi2_entity_ops = {
.link_setup = csi2_link_setup,
.link_validate = v4l2_subdev_link_validate,
+   .get_fwnode_pad = csi2_get_fwnode_pad,
 };
 
 static const struct v4l2_subdev_video_ops csi2_video_ops = {
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 12/17] media: imx: csi: Add missing notifier unregister/cleanup

2020-02-04 Thread Steve Longerbeam
Add the missing calls to unregister and cleanup the subdev notifier in
imx_csi_remove().

Fixes: c893500a16baf ("media: imx: csi: Register a subdev notifier")
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 3e2afdd59276..bea6a70cc353 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -2030,6 +2030,8 @@ static int imx_csi_remove(struct platform_device *pdev)
 
v4l2_ctrl_handler_free(>ctrl_hdlr);
mutex_destroy(>lock);
+   v4l2_async_notifier_unregister(>notifier);
+   v4l2_async_notifier_cleanup(>notifier);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(>entity);
 
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 14/17] media: imx: csi: Lookup upstream endpoint with imx_media_get_pad_fwnode

2020-02-04 Thread Steve Longerbeam
Fix the 1:1 port-id:pad-index assumption for the upstream subdevice, by
searching the upstream subdevice's endpoints for one that maps to the
pad's index. This is carried out by a new reverse mapping function
imx_media_get_pad_fwnode().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c   | 22 --
 drivers/staging/media/imx/imx-media-utils.c | 33 +
 drivers/staging/media/imx/imx-media.h   |  1 +
 drivers/staging/media/imx/imx7-media-csi.c  | 25 +---
 4 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 2a8f01375f78..7d4c1c9640dd 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -164,7 +164,7 @@ static inline bool requires_passthrough(struct 
v4l2_fwnode_endpoint *ep,
 static int csi_get_upstream_endpoint(struct csi_priv *priv,
 struct v4l2_fwnode_endpoint *ep)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity *src;
struct v4l2_subdev *sd;
struct media_pad *pad;
@@ -203,23 +203,13 @@ static int csi_get_upstream_endpoint(struct csi_priv 
*priv,
if (!pad)
return -ENODEV;
 
-   sd = media_entity_to_v4l2_subdev(pad->entity);
+   endpoint = imx_media_get_pad_fwnode(pad);
+   if (IS_ERR(endpoint))
+   return PTR_ERR(endpoint);
 
-   /*
-* NOTE: this assumes an OF-graph port id is the same as a
-* media pad index.
-*/
-   port = of_graph_get_port_by_id(sd->dev->of_node, pad->index);
-   if (!port)
-   return -ENODEV;
-
-   endpoint = of_get_next_child(port, NULL);
-   of_node_put(port);
-   if (!endpoint)
-   return -ENODEV;
+   v4l2_fwnode_endpoint_parse(endpoint, ep);
 
-   v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ep);
-   of_node_put(endpoint);
+   fwnode_handle_put(endpoint);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index 87152bd9af22..61752c6b074d 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -1007,6 +1007,39 @@ imx_media_pipeline_video_device(struct media_entity 
*start_entity,
 }
 EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
 
+/*
+ * Find a fwnode endpoint that maps to the given subdevice's pad.
+ * If there are multiple endpoints that map to the pad, only the
+ * first endpoint encountered is returned.
+ *
+ * On success the refcount of the returned fwnode endpoint is
+ * incremented.
+ */
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad)
+{
+   struct fwnode_handle *endpoint;
+   struct v4l2_subdev *sd;
+
+   if (!is_media_entity_v4l2_subdev(pad->entity))
+   return ERR_PTR(-ENODEV);
+
+   sd = media_entity_to_v4l2_subdev(pad->entity);
+
+   fwnode_graph_for_each_endpoint(dev_fwnode(sd->dev), endpoint) {
+   int pad_idx = media_entity_get_fwnode_pad(>entity,
+ endpoint,
+ pad->flags);
+   if (pad_idx < 0)
+   continue;
+
+   if (pad_idx == pad->index)
+   return endpoint;
+   }
+
+   return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(imx_media_get_pad_fwnode);
+
 /*
  * Turn current pipeline streaming on/off starting from entity.
  */
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index f90a65ba4ced..5f23d852122f 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -205,6 +205,7 @@ imx_media_pipeline_subdev(struct media_entity 
*start_entity, u32 grp_id,
 struct video_device *
 imx_media_pipeline_video_device(struct media_entity *start_entity,
enum v4l2_buf_type buftype, bool upstream);
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad);
 
 struct imx_media_dma_buf {
void  *virt;
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index cf9f675c53a3..f2ed13aca2b0 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -439,9 +439,8 @@ static int imx7_csi_get_upstream_endpoint(struct imx7_csi 
*csi,
  struct v4l2_fwnode_endpoint *ep,
  bool skip_mux)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity *src;
-   struct v4l2_subdev *sd;
struct media_pad *pad;
 
if 

[PATCH v3 15/17] media: imx: Create missing links from CSI-2 receiver

2020-02-04 Thread Steve Longerbeam
The entities external to the i.MX6 IPU and i.MX7 now create the links
to their fwnode-endpoint connected entities in their notifier bound
callbacks. Which means imx_media_create_of_links() and
imx_media_create_csi_of_links() are no longer needed and are removed.

However there is still one case in which imx-media needs to create
fwnode-endpoint based links at probe completion. The v4l2-async framework
does not allow multiple subdevice notifiers to contain a duplicate
subdevice in their asd_list. Only the first subdev notifier that discovers
and adds that one subdevice to its asd_list will receive a bound callback
for it. Other subdevices that also have firmware endpoint connections to
this duplicate subdevice will not have it in their asd_list, and thus will
never receive a bound callback for it. In the case of imx-media, the one
duplicate subdevice in question is the i.MX6 MIPI CSI-2 receiver.

Until there is a solution to that problem, rewrite imx_media_create_links()
to add the missing links from the CSI-2 receiver to the CSIs and CSI muxes.
The function is renamed imx_media_create_csi2_links().

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- call a local imx-media utility imx_media_create_fwnode_pad_links().
Changes in v2:
- this is a rewrite of v1 "media: imx: Use media_create_fwnode_links for
  external links", which only adds the missing CSI-2 receiver links.
---
 .../staging/media/imx/imx-media-dev-common.c  |  46 +++
 drivers/staging/media/imx/imx-media-of.c  | 114 --
 drivers/staging/media/imx/imx-media.h |   4 -
 3 files changed, 17 insertions(+), 147 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 66b505f7e8df..f7ad3cbbeec2 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -30,41 +30,31 @@ static int imx_media_subdev_bound(struct 
v4l2_async_notifier *notifier,
 }
 
 /*
- * Create the media links for all subdevs that registered.
+ * Create the missing media links from the CSI-2 receiver.
  * Called after all async subdevs have bound.
  */
-static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+static void imx_media_create_csi2_links(struct imx_media_dev *imxmd)
 {
-   struct imx_media_dev *imxmd = notifier2dev(notifier);
-   struct v4l2_subdev *sd;
+   struct v4l2_subdev *sd, *csi2 = NULL;
 
list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
-   switch (sd->grp_id) {
-   case IMX_MEDIA_GRP_ID_IPU_VDIC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
-   /*
-* links have already been created for the
-* sync-registered subdevs.
-*/
-   break;
-   case IMX_MEDIA_GRP_ID_IPU_CSI0:
-   case IMX_MEDIA_GRP_ID_IPU_CSI1:
-   case IMX_MEDIA_GRP_ID_CSI:
-   imx_media_create_csi_of_links(imxmd, sd);
-   break;
-   default:
-   /*
-* if this subdev has fwnode links, create media
-* links for them.
-*/
-   imx_media_create_of_links(imxmd, sd);
+   if (sd->grp_id == IMX_MEDIA_GRP_ID_CSI2) {
+   csi2 = sd;
break;
}
}
+   if (!csi2)
+   return;
 
-   return 0;
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   /* skip if not a CSI or a video mux */
+   if (!(sd->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) &&
+   !(sd->grp_id & IMX_MEDIA_GRP_ID_CSI) &&
+   sd->entity.function != MEDIA_ENT_F_VID_MUX)
+   continue;
+
+   imx_media_create_fwnode_pad_links(csi2, sd);
+   }
 }
 
 /*
@@ -196,9 +186,7 @@ int imx_media_probe_complete(struct v4l2_async_notifier 
*notifier)
 
mutex_lock(>mutex);
 
-   ret = imx_media_create_links(notifier);
-   if (ret)
-   goto unlock;
+   imx_media_create_csi2_links(imxmd);
 
ret = imx_media_create_pad_vdev_lists(imxmd);
if (ret)
diff --git a/drivers/staging/media/imx/imx-media-of.c 
b/drivers/staging/media/imx/imx-media-of.c
index 2d3efd2a6dde..82e13e972e23 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -74,117 +74,3 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
return ret;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_of_subdevs);
-
-/*
- * Create a single media link to/from sd using a fwnode link.
- *
- * NOTE: this function assumes an OF port node is equiv

Re: [PATCH] media: imx7-mipi-csis: remove subdev_notifier

2019-12-12 Thread Steve Longerbeam




On 12/12/19 11:17 AM, Rui Miguel Silva wrote:

It was defined a notifier in the csi_state structure that is never
allocated. And besides that it's unregister in the remove, even though
it is a no-op, just remove both.

Fixes: 7807063b862b ("media: staging/imx7: add MIPI CSI-2 receiver subdev for 
i.MX7")
Reported-by: Hans Verkuil 
Suggested-by: Dan Carpenter 
Suggested-by: Philipp Zabel 
Signed-off-by: Rui Miguel Silva 


Reviewed-by: Steve Longerbeam 


---
  drivers/staging/media/imx/imx7-mipi-csis.c | 3 ---
  1 file changed, 3 deletions(-)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index 99166afca071..383abecb3bec 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -251,8 +251,6 @@ struct csi_state {
  
  	struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
  
-	struct v4l2_async_notifier subdev_notifier;

-
struct csis_hw_reset hw_reset;
struct regulator *mipi_phy_regulator;
bool sink_linked;
@@ -1104,7 +1102,6 @@ static int mipi_csis_remove(struct platform_device *pdev)
  
  	mipi_csis_debugfs_exit(state);

v4l2_async_unregister_subdev(>mipi_sd);
-   v4l2_async_notifier_unregister(>subdev_notifier);
  
  	pm_runtime_disable(>dev);

mipi_csis_pm_suspend(>dev, true);


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH] media: imx7-mipi-csis: Add the missed v4l2_async_notifier_cleanup in remove

2019-12-12 Thread Steve Longerbeam




On 12/12/19 11:08 AM, Rui Miguel Silva wrote:

Hi Dan,
Thanks for the inputs.
On Thu, Dec 12, 2019 at 02:51:34PM +0300, Dan Carpenter wrote:

On Mon, Dec 09, 2019 at 04:58:28PM +0800, Chuhong Yuan wrote:

All drivers in imx call v4l2_async_notifier_cleanup() after
unregistering the notifier except this driver.  This should be a
miss and we need to add the call to fix it.

Signed-off-by: Chuhong Yuan  ---
drivers/staging/media/imx/imx7-mipi-csis.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c
b/drivers/staging/media/imx/imx7-mipi-csis.c index
99166afca071..2bfa85bb84e7 100644 ---
a/drivers/staging/media/imx/imx7-mipi-csis.c +++
b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -1105,6 +1105,7 @@
static int mipi_csis_remove(struct platform_device *pdev)
mipi_csis_debugfs_exit(state);
v4l2_async_unregister_subdev(>mipi_sd);
v4l2_async_notifier_unregister(>subdev_notifier); +
v4l2_async_notifier_cleanup(>subdev_notifier);
  

In this case the "state->subdev_notifier" was never initialized or
used so both v4l2_async_notifier_unregister() and
v4l2_async_notifier_cleanup() are no-ops.

I have applied this patch on top of Steve's series [0], since by the
timeline I was expecting to be applied before this one, that series
adds a bound notifier, even though, it is not named the same, eheh.

That trigged me to think that this cleanup was correct since a
notifier was initialized in probe.

But as you say, it is a no-ops in the end.

@Steve, that said, it looks that in [0], you will need to add some
unregister and cleanup for the notifiers that you are adding in
several places.


Well, turns out I had failed to notice that an async notifier was 
already included in 'struct imx7_csi' as 'subdev_notifier', even though 
it was unused. So I ended up creating a duplicate 'notifier'. I'll 
cleaning that up in v3 of [0].


Steve


A patch to fix this will follow.

--
Cheers,
  Rui



[0]: https://patchwork.kernel.org/project/linux-media/list/?series=207517


We should just delete "subdev_notifier".

regards, dan carpenter

___ devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH v8 5/5] media: imx: Try colorimetry at both sink and source pads

2019-10-22 Thread Steve Longerbeam

Hi Laurent, Rui,

Besides field type ANY, the imx7 CSI should probably be dealing with 
other field type conversions as well. I may be mistaken, but like the 
imx6, the imx7 does not have the ability to detect whether a captured 
field is a top field or a bottom field, so it can't support ALTERNATE 
mode. It should probably capture two consecutive fields and in that case 
and report seq-tb or seq-bt at its output. Also the imx6 supports 
interlacing field lines, if that is the case for imx7 it should also 
support converting ALTERNATE to INTERLACED at its output.


Steve


On 10/22/19 6:34 AM, Rui Miguel Silva wrote:

Hi Laurent,
On Tue 22 Oct 2019 at 02:44, Laurent Pinchart wrote:

Hi Steve,

On Tue, May 21, 2019 at 06:03:17PM -0700, Steve Longerbeam wrote:

Retask imx_media_fill_default_mbus_fields() to try colorimetry parameters,
renaming it to to imx_media_try_colorimetry(), and call it at both sink and
source pad try_fmt's. The unrelated check for uninitialized field value is
moved out to appropriate places in each subdev try_fmt.

The IC now supports Rec.709 and BT.601 Y'CbCr encoding, and both limited
and full range quantization for both YUV and RGB space, so allow those
for pipelines that route through the IC.

Signed-off-by: Steve Longerbeam 
---
Changes in v7:
- squashed with "media: imx: Allow Rec.709 encoding for IC routes".
- remove the RGB full-range quantization restriction for IC routes.
---
  drivers/staging/media/imx/imx-ic-prp.c  |  6 +-
  drivers/staging/media/imx/imx-ic-prpencvf.c |  8 +--
  drivers/staging/media/imx/imx-media-csi.c   | 19 +++---
  drivers/staging/media/imx/imx-media-utils.c | 73 ++---
  drivers/staging/media/imx/imx-media-vdic.c  |  5 +-
  drivers/staging/media/imx/imx-media.h   |  5 +-
  drivers/staging/media/imx/imx7-media-csi.c  |  8 +--
  7 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 10ffe00f1a54..f87fe0203720 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
sdformat->format.code = cc->codes[0];
}

-   imx_media_fill_default_mbus_fields(>format, infmt,
-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
break;
case PRP_SRC_PAD_PRPENC:
case PRP_SRC_PAD_PRPVF:
@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
break;
}

+   imx_media_try_colorimetry(>format, true);
+
fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
  out:
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index e8b36a181ccc..f2fe3c11c70e 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv,
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func;
-   sdformat->format.quantization = infmt->quantization;
-   sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
} else {
v4l_bound_align_image(>format.width,
  MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv,
  MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
  S_ALIGN);

-   imx_media_fill_default_mbus_fields(>format, infmt,
-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
}
+
+   imx_media_try_colorimetry(>format, true);
  }

  static int prp_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 1d248aca40a9..dce4addadff4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv,
struct v4l2_mbus_framefmt *infmt =
__csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);

-   /* no restrictions on sink pad field type */
-   if (sdformat->pad == CSI_SINK_PAD)
+   /*
+* no restrictions on sink pad field type except must
+* be initialized.
+*/
+   if (sdformat->pad == CSI_SINK_PAD) {
+   if (sdf

Re: [PATCH v8 5/5] media: imx: Try colorimetry at both sink and source pads

2019-10-21 Thread Steve Longerbeam



On 10/21/19 8:26 PM, Steve Longerbeam wrote:

Hi Laurent,

On 10/21/19 6:44 PM, Laurent Pinchart wrote:

Hi Steve,

On Tue, May 21, 2019 at 06:03:17PM -0700, Steve Longerbeam wrote:
Retask imx_media_fill_default_mbus_fields() to try colorimetry 
parameters,
renaming it to to imx_media_try_colorimetry(), and call it at both 
sink and
source pad try_fmt's. The unrelated check for uninitialized field 
value is

moved out to appropriate places in each subdev try_fmt.

The IC now supports Rec.709 and BT.601 Y'CbCr encoding, and both 
limited

and full range quantization for both YUV and RGB space, so allow those
for pipelines that route through the IC.

Signed-off-by: Steve Longerbeam 
---
Changes in v7:
- squashed with "media: imx: Allow Rec.709 encoding for IC routes".
- remove the RGB full-range quantization restriction for IC routes.
---
  drivers/staging/media/imx/imx-ic-prp.c  |  6 +-
  drivers/staging/media/imx/imx-ic-prpencvf.c |  8 +--
  drivers/staging/media/imx/imx-media-csi.c   | 19 +++---
  drivers/staging/media/imx/imx-media-utils.c | 73 
++---

  drivers/staging/media/imx/imx-media-vdic.c  |  5 +-
  drivers/staging/media/imx/imx-media.h   |  5 +-
  drivers/staging/media/imx/imx7-media-csi.c  |  8 +--
  7 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c

index 10ffe00f1a54..f87fe0203720 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
  sdformat->format.code = cc->codes[0];
  }
  - imx_media_fill_default_mbus_fields(>format, infmt,
-   true);
+    if (sdformat->format.field == V4L2_FIELD_ANY)
+    sdformat->format.field = V4L2_FIELD_NONE;
  break;
  case PRP_SRC_PAD_PRPENC:
  case PRP_SRC_PAD_PRPVF:
@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
  break;
  }
  +    imx_media_try_colorimetry(>format, true);
+
  fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
  *fmt = sdformat->format;
  out:
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c

index e8b36a181ccc..f2fe3c11c70e 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv,
  /* propagate colorimetry from sink */
  sdformat->format.colorspace = infmt->colorspace;
  sdformat->format.xfer_func = infmt->xfer_func;
-    sdformat->format.quantization = infmt->quantization;
-    sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
  } else {
v4l_bound_align_image(>format.width,
    MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv,
    MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
    S_ALIGN);
  - imx_media_fill_default_mbus_fields(>format, infmt,
-   true);
+    if (sdformat->format.field == V4L2_FIELD_ANY)
+    sdformat->format.field = V4L2_FIELD_NONE;
  }
+
+    imx_media_try_colorimetry(>format, true);
  }
    static int prp_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c

index 1d248aca40a9..dce4addadff4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv,
  struct v4l2_mbus_framefmt *infmt =
  __csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
  -    /* no restrictions on sink pad field type */
-    if (sdformat->pad == CSI_SINK_PAD)
+    /*
+ * no restrictions on sink pad field type except must
+ * be initialized.
+ */
+    if (sdformat->pad == CSI_SINK_PAD) {
+    if (sdformat->format.field == V4L2_FIELD_ANY)
+    sdformat->format.field = V4L2_FIELD_NONE;
  return;
+    }
    switch (infmt->field) {
  case V4L2_FIELD_SEQ_TB:
@@ -1455,8 +1461,6 @@ static void csi_try_fmt(struct csi_priv *priv,
  /* propagate colorimetry from sink */
  sdformat->format.colorspace = infmt->colorspace;
  sdformat->format.xfer_func = infmt->xfer_func;
-    sdformat->format.quantization = infmt->quantization;
-    sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
    break;
  case CSI_SINK_PAD:
@@ -1476,10 +1480,6 @@ static void csi_try_fmt(struct csi_priv *priv,
    csi_try_field(priv, cfg, sdformat);
  -    imx_media_fill_default_mbus_fields(
-    >format, infmt,
-    priv->active_output_pad == CSI_SRC_PA

Re: [PATCH v8 5/5] media: imx: Try colorimetry at both sink and source pads

2019-10-21 Thread Steve Longerbeam

Hi Laurent,

On 10/21/19 6:44 PM, Laurent Pinchart wrote:

Hi Steve,

On Tue, May 21, 2019 at 06:03:17PM -0700, Steve Longerbeam wrote:

Retask imx_media_fill_default_mbus_fields() to try colorimetry parameters,
renaming it to to imx_media_try_colorimetry(), and call it at both sink and
source pad try_fmt's. The unrelated check for uninitialized field value is
moved out to appropriate places in each subdev try_fmt.

The IC now supports Rec.709 and BT.601 Y'CbCr encoding, and both limited
and full range quantization for both YUV and RGB space, so allow those
for pipelines that route through the IC.

Signed-off-by: Steve Longerbeam 
---
Changes in v7:
- squashed with "media: imx: Allow Rec.709 encoding for IC routes".
- remove the RGB full-range quantization restriction for IC routes.
---
  drivers/staging/media/imx/imx-ic-prp.c  |  6 +-
  drivers/staging/media/imx/imx-ic-prpencvf.c |  8 +--
  drivers/staging/media/imx/imx-media-csi.c   | 19 +++---
  drivers/staging/media/imx/imx-media-utils.c | 73 ++---
  drivers/staging/media/imx/imx-media-vdic.c  |  5 +-
  drivers/staging/media/imx/imx-media.h   |  5 +-
  drivers/staging/media/imx/imx7-media-csi.c  |  8 +--
  7 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 10ffe00f1a54..f87fe0203720 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
sdformat->format.code = cc->codes[0];
}
  
-		imx_media_fill_default_mbus_fields(>format, infmt,

-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
break;
case PRP_SRC_PAD_PRPENC:
case PRP_SRC_PAD_PRPVF:
@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
break;
}
  
+	imx_media_try_colorimetry(>format, true);

+
fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
  out:
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index e8b36a181ccc..f2fe3c11c70e 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv,
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func;
-   sdformat->format.quantization = infmt->quantization;
-   sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
} else {
v4l_bound_align_image(>format.width,
  MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv,
  MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
  S_ALIGN);
  
-		imx_media_fill_default_mbus_fields(>format, infmt,

-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
}
+
+   imx_media_try_colorimetry(>format, true);
  }
  
  static int prp_set_fmt(struct v4l2_subdev *sd,

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 1d248aca40a9..dce4addadff4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv,
struct v4l2_mbus_framefmt *infmt =
__csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
  
-	/* no restrictions on sink pad field type */

-   if (sdformat->pad == CSI_SINK_PAD)
+   /*
+* no restrictions on sink pad field type except must
+* be initialized.
+*/
+   if (sdformat->pad == CSI_SINK_PAD) {
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
return;
+   }
  
  	switch (infmt->field) {

case V4L2_FIELD_SEQ_TB:
@@ -1455,8 +1461,6 @@ static void csi_try_fmt(struct csi_priv *priv,
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func;
-   sdformat->format.quantization = infmt->quantization;
-   sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
  
  		break;

case CSI_SI

Re: [PATCH 15/22] media: imx7-media-csi: Create media links in bound notifier

2019-09-02 Thread Steve Longerbeam

Hi Rui,

On 9/2/19 2:38 AM, Rui Miguel Silva wrote:

Hi Steve,
On Tue 06 Aug 2019 at 00:34, Steve Longerbeam wrote:

Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
---
  drivers/staging/media/imx/imx7-media-csi.c | 24 ++
  1 file changed, 24 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index a1c96c52a606..f71ac485f780 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -196,6 +196,11 @@ struct imx7_csi {
struct completion last_eof_completion;
  };

+static inline struct imx7_csi *notifier_to_dev(struct v4l2_async_notifier *n)


As the other one add the namespace for the function name:
imx7_csi_notifier_to_dev

other than this, looks good to me.


Thanks for the review. I will make those changes in next rev.

Steve





+{
+   return container_of(n, struct imx7_csi, notifier);
+}
+
  static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
  {
return readl(csi->regbase + offset);
@@ -1173,6 +1178,23 @@ static int imx7_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
  }

+static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct imx7_csi *csi = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[IMX7_CSI_PAD_SINK];
+
+   return media_create_fwnode_pad_links(sink,
+dev_fwnode(csi->sd.dev),
+>entity,
+dev_fwnode(sd->dev), 0);
+}
+
+static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
+   .bound = imx7_csi_notify_bound,
+};
+
  static int imx7_csi_probe(struct platform_device *pdev)
  {
struct device *dev = >dev;
@@ -1253,6 +1275,8 @@ static int imx7_csi_probe(struct platform_device *pdev)

v4l2_async_notifier_init(>notifier);

+   csi->notifier.ops = _csi_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(>sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
NULL, 0,


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 2/2] media: imx: Move pads init to probe

2019-08-24 Thread Steve Longerbeam
If a subdevice is unregistered and then registered again without the
driver being removed and re-probed (which will happen when the media
device is removed and re-probed without also removing/re-probing the
subdevice), media_device_register_entity() is called with a non-zero
entity->num_pads, and then the subdevice's .registered callback calls
media_entity_pads_init(). Thus the subdevice's pad objects are added
to the media device pad list twice, causing list corruption.

One way to fix this would be to create media_entity_pads_destroy(),
and call it in the subdevice's .unregistered callback. But calling
media_entity_pads_init() in the .registered callbacks was done for
legacy reasons and is no longer necessary, so move the call to
media_entity_pads_init() into the subdevice's probe functions. This
fixes the duplicate pad obejcts in the media device pad list.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prp.c| 25 ++---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 28 +--
 drivers/staging/media/imx/imx-media-capture.c | 15 +-
 drivers/staging/media/imx/imx-media-csi.c | 21 +++---
 drivers/staging/media/imx/imx-media-vdic.c| 27 --
 drivers/staging/media/imx/imx6-mipi-csi2.c| 27 --
 drivers/staging/media/imx/imx7-media-csi.c| 18 ++--
 drivers/staging/media/imx/imx7-mipi-csis.c| 23 +--
 8 files changed, 81 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 35e60a120dc1..2a4f77e83ed3 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -428,32 +428,19 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
return 0;
 }
 
-/*
- * retrieve our pads parsed from the OF graph by the media device
- */
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   int i, ret;
u32 code;
 
-   for (i = 0; i < PRP_NUM_PADS; i++) {
-   priv->pad[i].flags = (i == PRP_SINK_PAD) ?
-   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
-   }
-
/* init default frame interval */
priv->frame_interval.numerator = 1;
priv->frame_interval.denominator = 30;
 
/* set a default mbus format  */
imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
-   ret = imx_media_init_mbus_fmt(>format_mbus, 640, 480, code,
- V4L2_FIELD_NONE, NULL);
-   if (ret)
-   return ret;
-
-   return media_entity_pads_init(>entity, PRP_NUM_PADS, priv->pad);
+   return imx_media_init_mbus_fmt(>format_mbus, 640, 480, code,
+  V4L2_FIELD_NONE, NULL);
 }
 
 static const struct v4l2_subdev_pad_ops prp_pad_ops = {
@@ -487,6 +474,7 @@ static const struct v4l2_subdev_internal_ops 
prp_internal_ops = {
 static int prp_init(struct imx_ic_priv *ic_priv)
 {
struct prp_priv *priv;
+   int i;
 
priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -496,7 +484,12 @@ static int prp_init(struct imx_ic_priv *ic_priv)
ic_priv->task_priv = priv;
priv->ic_priv = ic_priv;
 
-   return 0;
+   for (i = 0; i < PRP_NUM_PADS; i++)
+   priv->pad[i].flags = (i == PRP_SINK_PAD) ?
+   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+
+   return media_entity_pads_init(_priv->sd.entity, PRP_NUM_PADS,
+ priv->pad);
 }
 
 static void prp_remove(struct imx_ic_priv *ic_priv)
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index f8a0b21fcd02..09c4e3f33807 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1240,9 +1240,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
return 0;
 }
 
-/*
- * retrieve our pads parsed from the OF graph by the media device
- */
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
@@ -1250,12 +1247,9 @@ static int prp_registered(struct v4l2_subdev *sd)
int i, ret;
u32 code;
 
+   /* set a default mbus format  */
+   imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
-   priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
-   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
-
-   /* set a default mbus format  */
-   imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
ret = imx_media_init_mbus_fmt(>format_mbus[i],
  640, 480, code, V4L2_FIELD_NONE,
  >cc[i]);
@@ -1267,11 +1261,6 @@ st

[PATCH v2 1/2] media: imx: Move capture device init to registered

2019-08-24 Thread Steve Longerbeam
If the CSI is unregistered and then registered again without the
driver being removed and re-probed (which will happen when the media
device is removed and re-probed without also removing/re-probing the
CSI), the result is the kobject error and backtrace "tried to init an
initialized object". This is because the video device is left in an
initialized state after being unregistered, thus the video device's
underlying kobject is also left in an initialized state when the device
is registered again.

Fix this by moving imx_media_capture_device_init() and _remove()
into csi_registered() and csi_unregistered(). This will create a new
un-initialized video device when the CSI is re-registered. Do this for
all the subdevices that register a capture device.

Reported-by: Russell King 
Signed-off-by: Steve Longerbeam 
---
Changes in v2:
Add missing local var ic_priv in prp_registered().
Reported-by: kbuild test robot 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 25 -
 drivers/staging/media/imx/imx-media-csi.c   | 20 ++---
 drivers/staging/media/imx/imx7-media-csi.c  | 22 +-
 3 files changed, 38 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 67ffa46a8e96..f8a0b21fcd02 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1246,6 +1246,7 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
+   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
@@ -1271,17 +1272,26 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
+   priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
+  _priv->sd,
+  PRPENCVF_SRC_PAD);
+   if (IS_ERR(priv->vdev))
+   return PTR_ERR(priv->vdev);
+
ret = imx_media_capture_device_register(priv->vdev);
if (ret)
-   return ret;
+   goto remove_vdev;
 
ret = prp_init_controls(priv);
if (ret)
-   goto unreg;
+   goto unreg_vdev;
 
return 0;
-unreg:
+
+unreg_vdev:
imx_media_capture_device_unregister(priv->vdev);
+remove_vdev:
+   imx_media_capture_device_remove(priv->vdev);
return ret;
 }
 
@@ -1290,6 +1300,8 @@ static void prp_unregistered(struct v4l2_subdev *sd)
struct prp_priv *priv = sd_to_priv(sd);
 
imx_media_capture_device_unregister(priv->vdev);
+   imx_media_capture_device_remove(priv->vdev);
+
v4l2_ctrl_handler_free(>ctrl_hdlr);
 }
 
@@ -1336,12 +1348,6 @@ static int prp_init(struct imx_ic_priv *ic_priv)
spin_lock_init(>irqlock);
timer_setup(>eof_timeout_timer, prp_eof_timeout, 0);
 
-   priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
-  _priv->sd,
-  PRPENCVF_SRC_PAD);
-   if (IS_ERR(priv->vdev))
-   return PTR_ERR(priv->vdev);
-
mutex_init(>lock);
 
return 0;
@@ -1352,7 +1358,6 @@ static void prp_remove(struct imx_ic_priv *ic_priv)
struct prp_priv *priv = ic_priv->task_priv;
 
mutex_destroy(>lock);
-   imx_media_capture_device_remove(priv->vdev);
 }
 
 struct imx_ic_ops imx_ic_prpencvf_ops = {
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 367e39f5b382..b3f1cf08a102 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1797,12 +1797,22 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
+   priv->vdev = imx_media_capture_device_init(priv->sd.dev,
+  >sd,
+  CSI_SRC_PAD_IDMAC);
+   if (IS_ERR(priv->vdev)) {
+   ret = PTR_ERR(priv->vdev);
+   goto free_fim;
+   }
+
ret = imx_media_capture_device_register(priv->vdev);
if (ret)
-   goto free_fim;
+   goto remove_vdev;
 
return 0;
 
+remove_vdev:
+   imx_media_capture_device_remove(priv->vdev);
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
@@ -1816,6 +1826,7 @@ static void csi_unregistered(struct v4l2_subdev *sd)
struct csi_priv *priv = v4l2_get_subdevdata(sd);
 
imx_media_capture_device_unregister(priv->vdev);
+   imx_media_capture_device_remove(priv->vdev);
 
if (priv->fim)

[PATCH 2/2] media: imx: Move pads init to probe

2019-08-23 Thread Steve Longerbeam
If a subdevice is unregistered and then registered again without the
driver being removed and re-probed (which will happen when the media
device is removed and re-probed without also removing/re-probing the
subdevice), media_device_register_entity() is called with a non-zero
entity->num_pads, and then the subdevice's .registered callback calls
media_entity_pads_init(). Thus the subdevice's pad objects are added
to the media device pad list twice, causing list corruption.

One way to fix this would be to create media_entity_pads_destroy(),
and call it in the subdevice's .unregistered callback. But calling
media_entity_pads_init() in the .registered callbacks was done for
legacy reasons and is no longer necessary, so move the call to
media_entity_pads_init() into the subdevice's probe functions. This
fixes the duplicate pad obejcts in the media device pad list.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prp.c| 25 ++--
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 29 ++-
 drivers/staging/media/imx/imx-media-capture.c | 15 +-
 drivers/staging/media/imx/imx-media-csi.c | 21 +++---
 drivers/staging/media/imx/imx-media-vdic.c| 27 +++--
 drivers/staging/media/imx/imx6-mipi-csi2.c| 27 -
 drivers/staging/media/imx/imx7-media-csi.c| 18 +++-
 drivers/staging/media/imx/imx7-mipi-csis.c| 23 +--
 8 files changed, 82 insertions(+), 103 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 35e60a120dc1..2a4f77e83ed3 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -428,32 +428,19 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
return 0;
 }
 
-/*
- * retrieve our pads parsed from the OF graph by the media device
- */
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   int i, ret;
u32 code;
 
-   for (i = 0; i < PRP_NUM_PADS; i++) {
-   priv->pad[i].flags = (i == PRP_SINK_PAD) ?
-   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
-   }
-
/* init default frame interval */
priv->frame_interval.numerator = 1;
priv->frame_interval.denominator = 30;
 
/* set a default mbus format  */
imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
-   ret = imx_media_init_mbus_fmt(>format_mbus, 640, 480, code,
- V4L2_FIELD_NONE, NULL);
-   if (ret)
-   return ret;
-
-   return media_entity_pads_init(>entity, PRP_NUM_PADS, priv->pad);
+   return imx_media_init_mbus_fmt(>format_mbus, 640, 480, code,
+  V4L2_FIELD_NONE, NULL);
 }
 
 static const struct v4l2_subdev_pad_ops prp_pad_ops = {
@@ -487,6 +474,7 @@ static const struct v4l2_subdev_internal_ops 
prp_internal_ops = {
 static int prp_init(struct imx_ic_priv *ic_priv)
 {
struct prp_priv *priv;
+   int i;
 
priv = devm_kzalloc(ic_priv->ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -496,7 +484,12 @@ static int prp_init(struct imx_ic_priv *ic_priv)
ic_priv->task_priv = priv;
priv->ic_priv = ic_priv;
 
-   return 0;
+   for (i = 0; i < PRP_NUM_PADS; i++)
+   priv->pad[i].flags = (i == PRP_SINK_PAD) ?
+   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
+
+   return media_entity_pads_init(_priv->sd.entity, PRP_NUM_PADS,
+ priv->pad);
 }
 
 static void prp_remove(struct imx_ic_priv *ic_priv)
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 301f5fce53c0..09c4e3f33807 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1240,21 +1240,16 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
return 0;
 }
 
-/*
- * retrieve our pads parsed from the OF graph by the media device
- */
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
+   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
+   /* set a default mbus format  */
+   imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
for (i = 0; i < PRPENCVF_NUM_PADS; i++) {
-   priv->pad[i].flags = (i == PRPENCVF_SINK_PAD) ?
-   MEDIA_PAD_FL_SINK : MEDIA_PAD_FL_SOURCE;
-
-   /* set a default mbus format  */
-   imx_media_enum_ipu_format(, 0, CS_SEL_YUV);
ret = imx_media_init_mbus_fmt(>format_mbus[i],
  640, 480, code, V4L2_FIELD_NONE,
  >cc[i]);
@@ -1266,11 +1261,6 @@

[PATCH 1/2] media: imx: Move capture device init to registered

2019-08-23 Thread Steve Longerbeam
If the CSI is unregistered and then registered again without the
driver being removed and re-probed (which will happen when the media
device is removed and re-probed without also removing/re-probing the
CSI), the result is the kobject error and backtrace "tried to init an
initialized object". This is because the video device is left in an
initialized state after being unregistered, thus the video device's
underlying kobject is also left in an initialized state when the device
is registered again.

Fix this by moving imx_media_capture_device_init() and _remove()
into csi_registered() and csi_unregistered(). This will create a new
un-initialized video device when the CSI is re-registered. Do this for
all the subdevices that register a capture device.

Reported-by: Russell King 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 24 -
 drivers/staging/media/imx/imx-media-csi.c   | 20 ++---
 drivers/staging/media/imx/imx7-media-csi.c  | 22 +--
 3 files changed, 37 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 67ffa46a8e96..301f5fce53c0 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1271,17 +1271,26 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
+   priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
+  _priv->sd,
+  PRPENCVF_SRC_PAD);
+   if (IS_ERR(priv->vdev))
+   return PTR_ERR(priv->vdev);
+
ret = imx_media_capture_device_register(priv->vdev);
if (ret)
-   return ret;
+   goto remove_vdev;
 
ret = prp_init_controls(priv);
if (ret)
-   goto unreg;
+   goto unreg_vdev;
 
return 0;
-unreg:
+
+unreg_vdev:
imx_media_capture_device_unregister(priv->vdev);
+remove_vdev:
+   imx_media_capture_device_remove(priv->vdev);
return ret;
 }
 
@@ -1290,6 +1299,8 @@ static void prp_unregistered(struct v4l2_subdev *sd)
struct prp_priv *priv = sd_to_priv(sd);
 
imx_media_capture_device_unregister(priv->vdev);
+   imx_media_capture_device_remove(priv->vdev);
+
v4l2_ctrl_handler_free(>ctrl_hdlr);
 }
 
@@ -1336,12 +1347,6 @@ static int prp_init(struct imx_ic_priv *ic_priv)
spin_lock_init(>irqlock);
timer_setup(>eof_timeout_timer, prp_eof_timeout, 0);
 
-   priv->vdev = imx_media_capture_device_init(ic_priv->ipu_dev,
-  _priv->sd,
-  PRPENCVF_SRC_PAD);
-   if (IS_ERR(priv->vdev))
-   return PTR_ERR(priv->vdev);
-
mutex_init(>lock);
 
return 0;
@@ -1352,7 +1357,6 @@ static void prp_remove(struct imx_ic_priv *ic_priv)
struct prp_priv *priv = ic_priv->task_priv;
 
mutex_destroy(>lock);
-   imx_media_capture_device_remove(priv->vdev);
 }
 
 struct imx_ic_ops imx_ic_prpencvf_ops = {
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 367e39f5b382..b3f1cf08a102 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1797,12 +1797,22 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
+   priv->vdev = imx_media_capture_device_init(priv->sd.dev,
+  >sd,
+  CSI_SRC_PAD_IDMAC);
+   if (IS_ERR(priv->vdev)) {
+   ret = PTR_ERR(priv->vdev);
+   goto free_fim;
+   }
+
ret = imx_media_capture_device_register(priv->vdev);
if (ret)
-   goto free_fim;
+   goto remove_vdev;
 
return 0;
 
+remove_vdev:
+   imx_media_capture_device_remove(priv->vdev);
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
@@ -1816,6 +1826,7 @@ static void csi_unregistered(struct v4l2_subdev *sd)
struct csi_priv *priv = v4l2_get_subdevdata(sd);
 
imx_media_capture_device_unregister(priv->vdev);
+   imx_media_capture_device_remove(priv->vdev);
 
if (priv->fim)
imx_media_fim_free(priv->fim);
@@ -1963,11 +1974,6 @@ static int imx_csi_probe(struct platform_device *pdev)
imx_media_grp_id_to_sd_name(priv->sd.name, sizeof(priv->sd.name),
priv->sd.grp_id, ipu_get_num(priv->ipu));
 
-   priv->vdev = imx_media_capture_device_init(priv->sd.dev, >sd,
-

Re: [BUG] removing and reinserting imx-media causes kernel to explode

2019-08-18 Thread Steve Longerbeam



On 8/14/19 2:25 AM, Russell King - ARM Linux admin wrote:

I just did this:

rmmod imx-media
modprobe imx-media

and was greeted by the below kernel messages.


Yes this needs fixing, the CSI needs to check first that it is already 
registered before going through the ->registered() steps. Posting a patch.



   I don't think this has
been the first issue I found with the iMX media stuff involving a module
unload/reload cycle - may I suggest that this is added to the testing
regime for this code?  Thanks.


I do test module unload/reload cycles, but v4l2-async does not support 
re-registering subdevices unless the subdevice is basically completely 
removed and re-probed, so there won't be a working media device if only 
imx-media is reloaded. So I have always unloaded/reloaded all modules 
for every entity in the graph, i.e.:


rmmod imx6_media imx6_media_csi imx6_mipi_csi2 ov5640 video_mux 
imx_media_common


(replace ov5640 with your imx219 sensor).

But I'll make sure to test single module unload/reload cycles in the future.

But note after applying the patch mentioned above to CSI ->registered() 
callback, there are list corruption backtraces, see [1]. The root cause 
is that both media_device_register_entity() and media_entity_pads_init() 
add the same graph objects for the entity's pads, so duplicate pad 
objects are added to the media device pads list. Removing the pad object 
creation in media_device_register_entity() fixes the list corruption. 
Sending a patch for that also.


This is a problem for any entity that sets its ->num_pads to a non-zero 
value before media_device_register_entity() is called. For example, the 
following will produce the same list corruption backtrace:


rmmod video-mux
modprobe video-mux
rmmod video-mux

Steve

[1]
rmmod imx6-media
modprobe imx6-media
rmmod imx6-media

[  249.387953] WARNING: CPU: 2 PID: 843 at lib/list_debug.c:53 
__list_del_entry_valid+0xa0/0xdc
[  249.396442] list_del corruption. prev->next should be e8fb0510, but 
was e93b5914
[  249.404076] Modules linked in: imx6_media_csi(C) imx6_media(C-) 
imx6_mipi_csi2(C) bnep dw_hdmi_ahb_audio dw_hdmi_cec ov5640 mux_mmio 
video_mux mux_core dw_hdmi_imx dw_hdmi coda_vpu cec imx_vdoa 
videobuf2_vmalloc imx_media_common(C) v4l2_fwnode imx_ldb imxdrm 
imx_ipu_v3 [last unloaded: imx6_media_csi]
[  249.430956] CPU: 2 PID: 843 Comm: rmmod Tainted: G C    
5.3.0-rc4-01115-g62119fd20fda #5

[  249.440115] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[  249.446689] [] (unwind_backtrace) from [] 
(show_stack+0x10/0x14)
[  249.454462] [] (show_stack) from [] 
(dump_stack+0xd8/0x110)
[  249.461804] [] (dump_stack) from [] 
(__warn+0xe0/0x10c)
[  249.468789] [] (__warn) from [] 
(warn_slowpath_fmt+0x44/0x6c)
[  249.476301] [] (warn_slowpath_fmt) from [] 
(__list_del_entry_valid+0xa0/0xdc)
[  249.485207] [] (__list_del_entry_valid) from [] 
(media_gobj_destroy.part.4+0x30/0x64)
[  249.494802] [] (media_gobj_destroy.part.4) from 
[] (__media_device_unregister_entity+0xa8/0xcc)
[  249.505259] [] (__media_device_unregister_entity) from 
[] (media_device_unregister_entity+0x2c/0x38)
[  249.516157] [] (media_device_unregister_entity) from 
[] (v4l2_device_unregister_subdev+0x90/0xb4)
[  249.526793] [] (v4l2_device_unregister_subdev) from 
[] (v4l2_async_cleanup+0x10/0x3c)
[  249.536382] [] (v4l2_async_cleanup) from [] 
(v4l2_async_notifier_unbind_all_subdevs+0x9c/0x10c)
[  249.546840] [] (v4l2_async_notifier_unbind_all_subdevs) 
from [] (v4l2_async_notifier_unbind_all_subdevs+0x6c/0x10c)
[  249.559035] [] (v4l2_async_notifier_unbind_all_subdevs) 
from [] (__v4l2_async_notifier_unregister.part.4+0xc/0x44)
[  249.571140] [] (__v4l2_async_notifier_unregister.part.4) 
from [] (v4l2_async_notifier_unregister+0x30/0x50)
[  249.582665] [] (v4l2_async_notifier_unregister) from 
[] (imx_media_remove+0x20/0x54 [imx6_media])
[  249.593389] [] (imx_media_remove [imx6_media]) from 
[] (platform_drv_remove+0x20/0x40)
[  249.603068] [] (platform_drv_remove) from [] 
(device_release_driver_internal+0xdc/0x1ac)
[  249.612917] [] (device_release_driver_internal) from 
[] (driver_detach+0x44/0x80)
[  249.622164] [] (driver_detach) from [] 
(bus_remove_driver+0x5c/0xd8)
[  249.630287] [] (bus_remove_driver) from [] 
(sys_delete_module+0x17c/0x20c)
[  249.638926] [] (sys_delete_module) from [] 
(ret_fast_syscall+0x0/0x28)

[  249.647205] Exception stack(0xe90d5fa8 to 0xe90d5ff0)
[  249.652278] 5fa0:   beed5d6c 0003 01401134 
0800 4f13b6f4 2002
[  249.660475] 5fc0: beed5d6c 0003 beed5b80 0081 beed5e78 
0001  014010f8

[  249.668669] 5fe0: 0003b2c4 beed5b4c 0001f248 4f1012dc
[  249.673859] irq event stamp: 4113
[  249.677267] hardirqs last  enabled at (4131): [] 
console_unlock+0x408/0x5f8
[  249.685125] hardirqs last disabled at (4138): [] 
console_unlock+0x88/0x5f8
[  249.692970] softirqs last  enabled at (4154): [] 
__do_softirq+0x360/0x524
[  249.700735] softirqs last disabled at 

Re: [PATCH 04/22] media: Move v4l2_fwnode_parse_link from v4l2 to driver base

2019-08-15 Thread Steve Longerbeam




On 8/14/19 4:15 PM, Russell King - ARM Linux admin wrote:

On Wed, Aug 14, 2019 at 04:00:30PM -0700, Steve Longerbeam wrote:


On 8/14/19 3:04 PM, Russell King - ARM Linux admin wrote:

On Wed, Aug 14, 2019 at 12:04:41PM -0700, Steve Longerbeam wrote:

On 8/14/19 3:30 AM, Russell King - ARM Linux admin wrote:

On Tue, Aug 06, 2019 at 09:53:41AM -0700, Steve Longerbeam wrote:

The full patchset doesn't seem to be up yet, but see [1] for the cover
letter.

Was the entire series copied to the mailing lists, or just selected
patches?  I only saw 4, 9, 11 and 13-22 via lakml.

The whole series was posted to the linux-media ML, see [1]. At the time,
none of the linux-media ML archives had the whole series.


In the absence of the other patches, will this solve imx-media binding
the internal subdevs of sensor devices to the CSI2 interface?

"internal subdevs of sensor devices" ?? That doesn't make any sense.

Sorry, but it makes complete sense when you consider that sensor
devices may have more than one subdev, but there should be only one
that is the "output" to whatever the camera is attached to.  The
other subdevs are internal to the sensor.

Ah, thanks for the clarification. Yes, by "internal subdevs" I understand
what you mean now. The adv748x and smiapp are examples.


subdevs are not purely the remit of SoC drivers.

So there is no binding of internal subdevs to the receiver CSI-2. The
receiver CSI-2 subdev will create media links to the subdev that has an
externally exposed fwnode endpoint that connects with the CSI-2 sink pad.

Maybe - with 5.2, I get:

- entity 15: imx6-mipi-csi2 (5 pads, 6 links)
  type V4L2 subdev subtype Unknown flags 0
  device node name /dev/v4l-subdev2
 pad0: Sink
...
 <- "imx219 0-0010":0 []
 <- "imx219 pixel 0-0010":0 []

Adding some debug in gives:

[   11.963362] imx-media: imx_media_create_of_links() for imx6-mipi-csi2
[   11.963396] imx-media: create_of_link(): 
/soc/aips-bus@200/iomuxc-gpr@20e/ipu1_csi0_mux
[   11.963422] imx-media: create_of_link(): /soc/ipu@240
[   11.963450] imx-media: create_of_link(): /soc/ipu@280
[   11.963478] imx-media: create_of_link(): 
/soc/aips-bus@200/iomuxc-gpr@20e/ipu2_csi1_mux
[   11.963489] imx-media: imx6-mipi-csi2:4 -> ipu2_csi1_mux:0
[   11.963522] imx-media: create_of_link(): 
/soc/aips-bus@210/i2c@21a/camera@10
[   11.963533] imx-media: imx219 0-0010:0 -> imx6-mipi-csi2:0
[   11.963549] imx-media: imx_media_create_of_links() for imx219 pixel 0-0010
[   11.963577] imx-media: create_of_link(): /soc/aips-bus@210/mipi@21dc000
[   11.963587] imx-media: imx219 pixel 0-0010:0 -> imx6-mipi-csi2:0
[   11.963602] imx-media: imx_media_create_of_links() for imx219 0-0010

Note that it's not created by imx6-mipi-csi2, but by imx-media delving
around in the imx219 subdevs.

 From what I can see, smiapp does the same thing that I do in imx219 -
sets the subdev->dev member to point at the struct device, which then
means that v4l2_device_register_subdev() will associate the same fwnode
with both "imx219 pixel 0-0010" and "imx219 0-0010".


Ok, understood.

I realize imx_media_create_of_link() is a bit intrusive, and that's one 
of the things I'm trying to get rid of in this patchset. Unfortunately 
it's there for a reason which is described in patch 0021. But to explain 
here, the imx6-mipi-csi2 receiver outputs its four virtual channels on 
four separate source pads, and those connect to four different 
subdevices (video mux's and CSI's), and the problem is that only the 
first subdev that adds imx6-mipi-csi2 to its notifier asd list will get 
a notifier bind() callback (where links can be created to 
imx6-mipi-csi2) -- the other subdevs don't contain it in their asd lists 
so they never create the links to imx6-mipi-csi2. So until the 
requirement in v4l2-async that no notifiers can contain the same asd in 
its list is relaxed, this function will have to remain, but I can make 
it less intrusive (only create the missing links from imx6-mipi-csi2). 
I'm not able to find a cleaner workaround at the moment.


Steve

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/22] media: Move v4l2_fwnode_parse_link from v4l2 to driver base

2019-08-14 Thread Steve Longerbeam




On 8/14/19 3:04 PM, Russell King - ARM Linux admin wrote:

On Wed, Aug 14, 2019 at 12:04:41PM -0700, Steve Longerbeam wrote:


On 8/14/19 3:30 AM, Russell King - ARM Linux admin wrote:

On Tue, Aug 06, 2019 at 09:53:41AM -0700, Steve Longerbeam wrote:

The full patchset doesn't seem to be up yet, but see [1] for the cover
letter.

Was the entire series copied to the mailing lists, or just selected
patches?  I only saw 4, 9, 11 and 13-22 via lakml.

The whole series was posted to the linux-media ML, see [1]. At the time,
none of the linux-media ML archives had the whole series.


In the absence of the other patches, will this solve imx-media binding
the internal subdevs of sensor devices to the CSI2 interface?

"internal subdevs of sensor devices" ?? That doesn't make any sense.

Sorry, but it makes complete sense when you consider that sensor
devices may have more than one subdev, but there should be only one
that is the "output" to whatever the camera is attached to.  The
other subdevs are internal to the sensor.


Ah, thanks for the clarification. Yes, by "internal subdevs" I 
understand what you mean now. The adv748x and smiapp are examples.




subdevs are not purely the remit of SoC drivers.


So there is no binding of internal subdevs to the receiver CSI-2. The 
receiver CSI-2 subdev will create media links to the subdev that has an 
externally exposed fwnode endpoint that connects with the CSI-2 sink pad.


Steve

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: [PATCH 04/22] media: Move v4l2_fwnode_parse_link from v4l2 to driver base

2019-08-14 Thread Steve Longerbeam




On 8/14/19 3:30 AM, Russell King - ARM Linux admin wrote:

On Tue, Aug 06, 2019 at 09:53:41AM -0700, Steve Longerbeam wrote:

The full patchset doesn't seem to be up yet, but see [1] for the cover
letter.

Was the entire series copied to the mailing lists, or just selected
patches?  I only saw 4, 9, 11 and 13-22 via lakml.


The whole series was posted to the linux-media ML, see [1]. At the time, 
none of the linux-media ML archives had the whole series.



In the absence of the other patches, will this solve imx-media binding
the internal subdevs of sensor devices to the CSI2 interface?


"internal subdevs of sensor devices" ?? That doesn't make any sense.

Sensors are external to the SoC, there are no "internal" sensor devices.

Not sure what you mean by "binding" either in this context, but external 
sensors can connect via fwnode endpoint, and later translated to media 
link, to the receiver CSI-2 sink.


Steve

[1] https://www.spinics.net/lists/linux-media/msg155160.html
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: imx: mipi csi-2: Release DPHY reset in s_power

2019-08-10 Thread Steve Longerbeam
Some CSI-2 transmitters may only set their data lanes to LP-11 state for
a very short time after being powered on, after which they transition
the lanes to high speed mode.

If that occurs, the lanes will likely be in HS mode long before the imx6
DPHY receiver is initialized and brought out of reset at stream on.
According to the imx6 reference manual, the lanes need to be in LP-11
state at least for some period after the DPHY reset is released. This
might mean that the state machine in the DPHY core (a Synopsys DesignWare
core) needs to detect a LP-11 to HS transition on the lanes before it can
proceed to detect a clock on the clock lane and begin to accept packets.

In an attempt to accommodate such sensors, carry out steps 1-5 in the
s_power op (moved out of s_stream op). This moves steps 1-5 closer in
time to after the sensor is powered ON by v4l2_pipeline_pm_use(), and
provides a better chance that the receiver DPHY will catch an early
LP-11 to HS transition.

This works because the graph walk stack used by v4l2_pipeline_pm_use()
is setup such that the transmitter s_power op is called immediately
before the receiver's s_power op.

For sensors that can persist LP-11 state until stream on, then this
should still work fine. The receiver will detect the HS transition
at step 6, when streaming is enabled at the transmitter.

Tested on imx6q SabreSD with OV5640.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 93 +-
 1 file changed, 73 insertions(+), 20 deletions(-)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index f29e28df36ed..06345de9f060 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -47,6 +47,7 @@ struct csi2_dev {
 
struct v4l2_mbus_framefmt format_mbus;
 
+   int power_count;
int stream_count;
struct v4l2_subdev  *src_sd;
boolsink_linked[CSI2_NUM_SRC_PADS];
@@ -113,9 +114,10 @@ static inline struct csi2_dev *sd_to_dev(struct 
v4l2_subdev *sdev)
  * 7. CSI2 Controller programming - Read the PHY status register (PHY_STATE)
  *to confirm that the D-PHY is receiving a clock on the D-PHY clock lane.
  *
- * All steps 3 through 7 are carried out by csi2_s_stream(ON) here. Step
- * 6 is accomplished by calling the source subdev's s_stream(ON) between
- * steps 5 and 7.
+ * Steps 3 through 5 are carried out by csi2_s_power(ON) here.
+ *
+ * Steps 6 and 7 are carried out by stream(ON) here. Step 6 is accomplished
+ * by calling the source subdev's s_stream(ON).
  */
 
 static void csi2_enable(struct csi2_dev *csi2, bool enable)
@@ -295,7 +297,7 @@ static void csi2ipu_gasket_init(struct csi2_dev *csi2)
writel(reg, csi2->base + CSI2IPU_GASKET);
 }
 
-static int csi2_start(struct csi2_dev *csi2)
+static int csi2_power_on(struct csi2_dev *csi2)
 {
int ret;
 
@@ -320,41 +322,87 @@ static int csi2_start(struct csi2_dev *csi2)
if (ret)
goto err_assert_reset;
 
+   return 0;
+
+err_assert_reset:
+   csi2_enable(csi2, false);
+err_disable_clk:
+   clk_disable_unprepare(csi2->pix_clk);
+   return ret;
+}
+
+static void csi2_power_off(struct csi2_dev *csi2)
+{
+   csi2_enable(csi2, false);
+   clk_disable_unprepare(csi2->pix_clk);
+}
+
+static int csi2_stream_on(struct csi2_dev *csi2)
+{
+   int ret;
+
/* Step 6 */
ret = v4l2_subdev_call(csi2->src_sd, video, s_stream, 1);
ret = (ret && ret != -ENOIOCTLCMD) ? ret : 0;
if (ret)
-   goto err_assert_reset;
+   return ret;
 
/* Step 7 */
ret = csi2_dphy_wait_clock_lane(csi2);
if (ret)
-   goto err_stop_upstream;
-
-   return 0;
+   v4l2_subdev_call(csi2->src_sd, video, s_stream, 0);
 
-err_stop_upstream:
-   v4l2_subdev_call(csi2->src_sd, video, s_stream, 0);
-err_assert_reset:
-   csi2_enable(csi2, false);
-err_disable_clk:
-   clk_disable_unprepare(csi2->pix_clk);
return ret;
 }
 
-static void csi2_stop(struct csi2_dev *csi2)
+static void csi2_stream_off(struct csi2_dev *csi2)
 {
/* stop upstream */
v4l2_subdev_call(csi2->src_sd, video, s_stream, 0);
-
-   csi2_enable(csi2, false);
-   clk_disable_unprepare(csi2->pix_clk);
 }
 
 /*
  * V4L2 subdev operations.
  */
 
+static int csi2_s_power(struct v4l2_subdev *sd, int on)
+{
+   struct csi2_dev *csi2 = sd_to_dev(sd);
+   int ret = 0;
+
+   mutex_lock(>lock);
+
+   if (!csi2->src_sd) {
+   ret = -EPIPE;
+   goto out;
+   }
+
+   /*
+* power on/off only if power_count is going from
+* 0 to 1 / 1 to 0.
+*/
+   if (csi2->power_count != !on)
+   goto update_count;
+
+   dev_d

Re: [PATCH 04/22] media: Move v4l2_fwnode_parse_link from v4l2 to driver base

2019-08-06 Thread Steve Longerbeam

Hi Andy,

On 8/5/19 11:41 PM, Andy Shevchenko wrote:

On Tue, Aug 6, 2019 at 2:37 AM Steve Longerbeam  wrote:

There is nothing v4l2-specific about v4l2_fwnode_{parse|put}_link().
Make these functions more generally available by moving them to driver
base, with the appropriate name changes to the functions and struct.

In the process embed a 'struct fwnode_endpoint' in 'struct fwnode_link'
for both sides of the link, and make use of fwnode_graph_parse_endpoint()
to fully parse both endpoints. Rename members local_node and
remote_node to more descriptive local_port_parent and
remote_port_parent.


May I ask if it's going to be used outside of v4l2?


It could be, I can see fwnode_graph_parse_link() being useful in DRM, 
for example. But at this, only media core and v4l2 are making use of it.


This patch was created so that fwnode links can be parsed in a new media 
core function that forms media links from fwnode links.


The full patchset doesn't seem to be up yet, but see [1] for the cover 
letter.


Steve

[1] https://www.mail-archive.com/linux-media@vger.kernel.org/msg148910.html
___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 20/22] media: imx: Add is_ipu_internal_subdev()

2019-08-05 Thread Steve Longerbeam
Add a convenience inline function that returns true if the given
subdevice is one of the i.MX5/6 IPU-internal subdevices.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index d75b3c80101a..c42a2cafb8fb 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -282,4 +282,12 @@ void imx_media_capture_device_error(struct 
imx_media_video_dev *vdev);
 #define IMX_MEDIA_GRP_ID_IPU_IC_PRPENC BIT(14)
 #define IMX_MEDIA_GRP_ID_IPU_IC_PRPVF  BIT(15)
 
+static inline bool is_ipu_internal_subdev(struct v4l2_subdev *sd)
+{
+   return sd->grp_id == IMX_MEDIA_GRP_ID_IPU_VDIC ||
+   sd->grp_id == IMX_MEDIA_GRP_ID_IPU_IC_PRP ||
+   sd->grp_id == IMX_MEDIA_GRP_ID_IPU_IC_PRPENC ||
+   sd->grp_id == IMX_MEDIA_GRP_ID_IPU_IC_PRPVF;
+}
+
 #endif
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 13/22] media: imx: mipi csi-2: Create media links in bound notifier

2019-08-05 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx6-mipi-csi2.c | 24 ++
 1 file changed, 24 insertions(+)

diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 408ee2765e77..5b2258156781 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -91,6 +91,11 @@ static inline struct csi2_dev *sd_to_dev(struct v4l2_subdev 
*sdev)
return container_of(sdev, struct csi2_dev, sd);
 }
 
+static inline struct csi2_dev *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi2_dev, notifier);
+}
+
 /*
  * The required sequence of MIPI CSI-2 startup as specified in the i.MX6
  * reference manual is as follows:
@@ -573,6 +578,23 @@ static int csi2_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int csi2_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct csi2_dev *csi2 = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI2_SINK_PAD];
+
+   return media_create_fwnode_pad_links(sink,
+dev_fwnode(csi2->dev),
+>entity,
+dev_fwnode(sd->dev), 0);
+}
+
+static const struct v4l2_async_notifier_operations csi2_notify_ops = {
+   .bound = csi2_notify_bound,
+};
+
 static int csi2_probe(struct platform_device *pdev)
 {
unsigned int sink_port = 0;
@@ -646,6 +668,8 @@ static int csi2_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi2->notifier.ops = _notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(
>sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 19/22] media: imx: csi: Lookup endpoint fwnode with media_entity_get_fwnode_pad

2019-08-05 Thread Steve Longerbeam
Fix the 1:1 port-id:pad-index assumption for the upstream subdevice
connected to a CSI via one of the subdevice's pads, by searching the
upstream subdevice's endpoints for one that maps to the pad's index,
using media_entity_get_fwnode_pad(). This is carried out by a new
reverse mapping function imx_media_get_pad_fwnode().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c   | 22 --
 drivers/staging/media/imx/imx-media-utils.c | 33 +
 drivers/staging/media/imx/imx-media.h   |  1 +
 drivers/staging/media/imx/imx7-media-csi.c  | 25 +---
 4 files changed, 47 insertions(+), 34 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 37b10cbf3c1a..38e70082ff2d 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -164,7 +164,7 @@ static inline bool requires_passthrough(struct 
v4l2_fwnode_endpoint *ep,
 static int csi_get_upstream_endpoint(struct csi_priv *priv,
 struct v4l2_fwnode_endpoint *ep)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity *src;
struct v4l2_subdev *sd;
struct media_pad *pad;
@@ -203,23 +203,13 @@ static int csi_get_upstream_endpoint(struct csi_priv 
*priv,
if (!pad)
return -ENODEV;
 
-   sd = media_entity_to_v4l2_subdev(pad->entity);
+   endpoint = imx_media_get_pad_fwnode(pad);
+   if (IS_ERR(endpoint))
+   return PTR_ERR(endpoint);
 
-   /*
-* NOTE: this assumes an OF-graph port id is the same as a
-* media pad index.
-*/
-   port = of_graph_get_port_by_id(sd->dev->of_node, pad->index);
-   if (!port)
-   return -ENODEV;
-
-   endpoint = of_get_next_child(port, NULL);
-   of_node_put(port);
-   if (!endpoint)
-   return -ENODEV;
+   v4l2_fwnode_endpoint_parse(endpoint, ep);
 
-   v4l2_fwnode_endpoint_parse(of_fwnode_handle(endpoint), ep);
-   of_node_put(endpoint);
+   fwnode_handle_put(endpoint);
 
return 0;
 }
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index 4cc6a7462ae2..2e4f27c214c4 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -908,6 +908,39 @@ imx_media_pipeline_video_device(struct media_entity 
*start_entity,
 }
 EXPORT_SYMBOL_GPL(imx_media_pipeline_video_device);
 
+/*
+ * Find a fwnode endpoint that maps to the given subdevice's pad.
+ * If there are multiple endpoints that map to the pad, only the
+ * first endpoint encountered is returned.
+ *
+ * On success the refcount of the returned fwnode endpoint is
+ * incremented.
+ */
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad)
+{
+   struct fwnode_handle *endpoint;
+   struct v4l2_subdev *sd;
+
+   if (!is_media_entity_v4l2_subdev(pad->entity))
+   return ERR_PTR(-ENODEV);
+
+   sd = media_entity_to_v4l2_subdev(pad->entity);
+
+   fwnode_graph_for_each_endpoint(dev_fwnode(sd->dev), endpoint) {
+   int pad_idx = media_entity_get_fwnode_pad(>entity,
+ endpoint,
+ pad->flags);
+   if (pad_idx < 0)
+   continue;
+
+   if (pad_idx == pad->index)
+   return endpoint;
+   }
+
+   return ERR_PTR(-ENODEV);
+}
+EXPORT_SYMBOL_GPL(imx_media_get_pad_fwnode);
+
 /*
  * Turn current pipeline streaming on/off starting from entity.
  */
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index 4d124a86b358..d75b3c80101a 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -195,6 +195,7 @@ imx_media_pipeline_subdev(struct media_entity 
*start_entity, u32 grp_id,
 struct video_device *
 imx_media_pipeline_video_device(struct media_entity *start_entity,
enum v4l2_buf_type buftype, bool upstream);
+struct fwnode_handle *imx_media_get_pad_fwnode(struct media_pad *pad);
 
 struct imx_media_dma_buf {
void  *virt;
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index f71ac485f780..50826e637cb5 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -438,9 +438,8 @@ static int imx7_csi_get_upstream_endpoint(struct imx7_csi 
*csi,
  struct v4l2_fwnode_endpoint *ep,
  bool skip_mux)
 {
-   struct device_node *endpoint, *port;
+   struct fwnode_handle *endpoint;
struct media_entity

[PATCH 11/22] media: v4l2-fwnode: Pass notifier to v4l2_async_register_fwnode_subdev()

2019-08-05 Thread Steve Longerbeam
Instead of allocating a notifier in v4l2_async_register_fwnode_subdev(),
have the caller provide one. This allows the caller to implement
notifier ops (bind, unbind).

The caller is now responsible for first initializing its notifier with a
call to v4l2_async_notifier_init().

Signed-off-by: Steve Longerbeam 
---
 drivers/media/platform/video-mux.c |  6 +-
 drivers/media/v4l2-core/v4l2-fwnode.c  | 11 +--
 drivers/staging/media/imx/imx6-mipi-csi2.c |  5 -
 drivers/staging/media/imx/imx7-media-csi.c |  5 -
 drivers/staging/media/imx/imx7-mipi-csis.c |  5 -
 include/media/v4l2-fwnode.h| 12 
 6 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/drivers/media/platform/video-mux.c 
b/drivers/media/platform/video-mux.c
index ddd0e338f9e4..ca1cef783646 100644
--- a/drivers/media/platform/video-mux.c
+++ b/drivers/media/platform/video-mux.c
@@ -21,6 +21,7 @@
 
 struct video_mux {
struct v4l2_subdev subdev;
+   struct v4l2_async_notifier notifier;
struct media_pad *pads;
struct v4l2_mbus_framefmt *format_mbus;
struct mux_control *mux;
@@ -354,8 +355,11 @@ static int video_mux_async_register(struct video_mux *vmux,
for (i = 0; i < num_input_pads; i++)
ports[i] = i;
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >subdev, sizeof(struct v4l2_async_subdev),
+   >subdev, >notifier,
+   sizeof(struct v4l2_async_subdev),
ports, num_input_pads, video_mux_parse_endpoint);
 
kfree(ports);
diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c 
b/drivers/media/v4l2-core/v4l2-fwnode.c
index 5d4ce4aa3fdc..8f5b3fdea061 100644
--- a/drivers/media/v4l2-core/v4l2-fwnode.c
+++ b/drivers/media/v4l2-core/v4l2-fwnode.c
@@ -1124,12 +1124,12 @@ int v4l2_async_register_subdev_sensor_common(struct 
v4l2_subdev *sd)
 EXPORT_SYMBOL_GPL(v4l2_async_register_subdev_sensor_common);
 
 int v4l2_async_register_fwnode_subdev(struct v4l2_subdev *sd,
+ struct v4l2_async_notifier *notifier,
  size_t asd_struct_size,
  unsigned int *ports,
  unsigned int num_ports,
  parse_endpoint_func parse_endpoint)
 {
-   struct v4l2_async_notifier *notifier;
struct device *dev = sd->dev;
struct fwnode_handle *fwnode;
int ret;
@@ -1141,12 +1141,6 @@ int v4l2_async_register_fwnode_subdev(struct v4l2_subdev 
*sd,
if (!fwnode_device_is_available(fwnode))
return -ENODEV;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
-
if (!ports) {
ret = v4l2_async_notifier_parse_fwnode_endpoints(dev, notifier,
 
asd_struct_size,
@@ -1171,15 +1165,12 @@ int v4l2_async_register_fwnode_subdev(struct 
v4l2_subdev *sd,
if (ret < 0)
goto out_unregister;
 
-   sd->subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
v4l2_async_notifier_unregister(notifier);
 out_cleanup:
v4l2_async_notifier_cleanup(notifier);
-   kfree(notifier);
 
return ret;
 }
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c 
b/drivers/staging/media/imx/imx6-mipi-csi2.c
index f29e28df36ed..408ee2765e77 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -35,6 +35,7 @@
 struct csi2_dev {
struct device  *dev;
struct v4l2_subdev  sd;
+   struct v4l2_async_notifier notifier;
struct media_pad   pad[CSI2_NUM_PADS];
struct clk *dphy_clk;
struct clk *pllref_clk;
@@ -643,8 +644,10 @@ static int csi2_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, >sd);
 
+   v4l2_async_notifier_init(>notifier);
+
ret = v4l2_async_register_fwnode_subdev(
-   >sd, sizeof(struct v4l2_async_subdev),
+   >sd, >notifier, sizeof(struct v4l2_async_subdev),
_port, 1, csi2_parse_endpoint);
if (ret)
goto dphy_off;
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 500b4c08d967..a1c96c52a606 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -155,6 +155,7 @@
 struct imx7_csi {
struct device *dev;
struct v4l2_subdev sd;
+   struct v4l2_async_notifier notifier;
struct imx_media_video_dev *vdev;
struct imx_media_dev *imxmd;
struct media_pad pad[IMX7_CSI_PADS_NUM];
@@ -1250,7 +125

[PATCH 16/22] media: imx: csi: Implement get_fwnode_pad

2019-08-05 Thread Steve Longerbeam
The CSI does not have a 1:1 relationship between fwnode port numbers and
pad indexes. In fact the CSI fwnode device is itself a port which is the
sink, containing only a single fwnode endpoint. Implement media_entity
operation get_fwnode_pad to first verify the given endpoint is the CSI's
sink endpoint, and if so return the CSI sink pad index.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 367e39f5b382..e193f66fa230 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1824,9 +1824,32 @@ static void csi_unregistered(struct v4l2_subdev *sd)
ipu_csi_put(priv->csi);
 }
 
+/*
+ * The CSI has only one fwnode endpoint, at the sink pad. Verify the
+ * endpoint belongs to us, and return CSI_SINK_PAD.
+ */
+static int csi_get_fwnode_pad(struct media_entity *entity,
+ struct fwnode_endpoint *endpoint)
+{
+   struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+   struct csi_priv *priv = v4l2_get_subdevdata(sd);
+   struct fwnode_handle *csi_port = dev_fwnode(priv->dev);
+   struct fwnode_handle *csi_ep;
+   int ret;
+
+   csi_ep = fwnode_get_next_child_node(csi_port, NULL);
+
+   ret = endpoint->local_fwnode == csi_ep ? CSI_SINK_PAD : -ENXIO;
+
+   fwnode_handle_put(csi_ep);
+
+   return ret;
+}
+
 static const struct media_entity_operations csi_entity_ops = {
.link_setup = csi_link_setup,
.link_validate = v4l2_subdev_link_validate,
+   .get_fwnode_pad = csi_get_fwnode_pad,
 };
 
 static const struct v4l2_subdev_core_ops csi_core_ops = {
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 22/22] media: imx: TODO: Remove issues regarding media link creation

2019-08-05 Thread Steve Longerbeam
Remove the TODO items regarding media link creation, these issues are
resolved after exporting media link creation to individual entity bound
callbacks and the use of media_create_fwnode_links(),
media_create_fwnode_pad_links(), and media_entity_get_fwnode_pad().

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/TODO | 29 -
 1 file changed, 29 deletions(-)

diff --git a/drivers/staging/media/imx/TODO b/drivers/staging/media/imx/TODO
index 6f29b5ca5324..a371cdedcdb0 100644
--- a/drivers/staging/media/imx/TODO
+++ b/drivers/staging/media/imx/TODO
@@ -17,35 +17,6 @@
   decided whether this feature is useful enough to make it generally
   available by exporting to v4l2-core.
 
-- After all async subdevices have been bound, v4l2_fwnode_parse_link()
-  is used to form the media links between the devices discovered in
-  the OF graph.
-
-  While this approach allows support for arbitrary OF graphs, there
-  are some assumptions for this to work:
-
-  1. If a port owned by a device in the graph has endpoint nodes, the
- port is treated as a media pad.
-
- This presents problems for devices that don't make this port = pad
- assumption. Examples are SMIAPP compatible cameras which define only
- a single output port node, but which define multiple pads owned
- by multiple subdevices (pixel-array, binner, scaler). Or video
- decoders (entity function MEDIA_ENT_F_ATV_DECODER), which also define
- only a single output port node, but define multiple pads for video,
- VBI, and audio out.
-
- A workaround at present is to set the port reg properties to
- correspond to the media pad index that the port represents. A
- possible long-term solution is to implement a subdev API that
- maps a port id to a media pad index.
-
-  2. Every endpoint of a port owned by a device in the graph is treated
- as a media link.
-
- Which means a port must not contain mixed-use endpoints, they
- must all refer to media links between V4L2 subdevices.
-
 - i.MX7: all of the above, since it uses the imx media core
 
 - i.MX7: use Frame Interval Monitor
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 15/22] media: imx7-media-csi: Create media links in bound notifier

2019-08-05 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx7-media-csi.c | 24 ++
 1 file changed, 24 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index a1c96c52a606..f71ac485f780 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -196,6 +196,11 @@ struct imx7_csi {
struct completion last_eof_completion;
 };
 
+static inline struct imx7_csi *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx7_csi, notifier);
+}
+
 static u32 imx7_csi_reg_read(struct imx7_csi *csi, unsigned int offset)
 {
return readl(csi->regbase + offset);
@@ -1173,6 +1178,23 @@ static int imx7_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -EINVAL;
 }
 
+static int imx7_csi_notify_bound(struct v4l2_async_notifier *notifier,
+struct v4l2_subdev *sd,
+struct v4l2_async_subdev *asd)
+{
+   struct imx7_csi *csi = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[IMX7_CSI_PAD_SINK];
+
+   return media_create_fwnode_pad_links(sink,
+dev_fwnode(csi->sd.dev),
+>entity,
+dev_fwnode(sd->dev), 0);
+}
+
+static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = {
+   .bound = imx7_csi_notify_bound,
+};
+
 static int imx7_csi_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
@@ -1253,6 +1275,8 @@ static int imx7_csi_probe(struct platform_device *pdev)
 
v4l2_async_notifier_init(>notifier);
 
+   csi->notifier.ops = _csi_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(>sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
NULL, 0,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 21/22] media: imx: Use media_create_fwnode_links for external links

2019-08-05 Thread Steve Longerbeam
The entities external to the i.MX6 IPU and i.MX7 now create the links
to their fwnode-endpoint connected entities in their notifier bound
callbacks.

This should mean that there is no longer a need for the imx-media driver
to create these external fwnode-endpoint based links. But the v4l2-async
framework does not allow multiple subdevice notifiers to contain a
duplicate subdevice in their asd_list. Only the first subdev notifier that
discovers and adds that one subdevice to its asd_list will receive a bound
callback for it. Other subdevices that also have firmware endpoint
connections to this duplicate subdevice will not have it in their asd_list,
and thus will never receive a bound callback for it.

Until there is a solution to that problem, imx_media_create_links() is
still needed to create media links for subdevices that never received a
bound callback.

But media_create_fwnode_links() can now be used to do that work, so
imx_media_create_of_links() and imx_media_create_csi_of_links() are
removed.

Signed-off-by: Steve Longerbeam 
---
 .../staging/media/imx/imx-media-dev-common.c  |  49 
 drivers/staging/media/imx/imx-media-of.c  | 113 --
 drivers/staging/media/imx/imx-media.h |   4 -
 3 files changed, 27 insertions(+), 139 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 66b505f7e8df..4dbe983af030 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -36,31 +36,36 @@ static int imx_media_subdev_bound(struct 
v4l2_async_notifier *notifier,
 static int imx_media_create_links(struct v4l2_async_notifier *notifier)
 {
struct imx_media_dev *imxmd = notifier2dev(notifier);
-   struct v4l2_subdev *sd;
+   struct fwnode_handle *sda_fwnode, *sdb_fwnode;
+   struct v4l2_subdev *sda, *sdb;
+
+   list_for_each_entry(sda, >v4l2_dev.subdevs, list) {
+   /* links have already been created for the IPU subdevs */
+   if (is_ipu_internal_subdev(sda))
+   continue;
+
+   sda_fwnode = (sda->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) ?
+   dev_fwnode(sda->dev->parent) :
+   dev_fwnode(sda->dev);
+
+   list_for_each_entry(sdb, >v4l2_dev.subdevs, list) {
+   if (sda == sdb)
+   continue;
+   if (is_ipu_internal_subdev(sdb))
+   continue;
+
+   sdb_fwnode = (sdb->grp_id & IMX_MEDIA_GRP_ID_IPU_CSI) ?
+   dev_fwnode(sdb->dev->parent) :
+   dev_fwnode(sdb->dev);
 
-   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
-   switch (sd->grp_id) {
-   case IMX_MEDIA_GRP_ID_IPU_VDIC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
-   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
-   /*
-* links have already been created for the
-* sync-registered subdevs.
-*/
-   break;
-   case IMX_MEDIA_GRP_ID_IPU_CSI0:
-   case IMX_MEDIA_GRP_ID_IPU_CSI1:
-   case IMX_MEDIA_GRP_ID_CSI:
-   imx_media_create_csi_of_links(imxmd, sd);
-   break;
-   default:
/*
-* if this subdev has fwnode links, create media
-* links for them.
+* if there are fwnode endpoint connections between
+* these subdevs, create media links for them.
 */
-   imx_media_create_of_links(imxmd, sd);
-   break;
+   __media_create_fwnode_links(>entity,
+   sda_fwnode,
+   >entity,
+   sdb_fwnode, 0);
}
}
 
diff --git a/drivers/staging/media/imx/imx-media-of.c 
b/drivers/staging/media/imx/imx-media-of.c
index 736c954a8ff5..82e13e972e23 100644
--- a/drivers/staging/media/imx/imx-media-of.c
+++ b/drivers/staging/media/imx/imx-media-of.c
@@ -74,116 +74,3 @@ int imx_media_add_of_subdevs(struct imx_media_dev *imxmd,
return ret;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_of_subdevs);
-
-/*
- * Create a single media link to/from sd using a fwnode link.
- *
- * NOTE: this function assumes an OF port node is equivalent to
- * a media pad (port id equal to media pad index), and that an
- * OF endpoint node is equivalent to a media link.
- */
-static int create_of_link(struct imx_media_dev *imxmd

[PATCH 17/22] media: imx: csi: Embed notifier in struct csi_priv

2019-08-05 Thread Steve Longerbeam
Embed the notifier in 'struct csi_priv', instead of dynamically allocating
it, to make it possible to retrieve csi_priv in a notifier callback op.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 25 +--
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index e193f66fa230..b39d79e63ac2 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -58,6 +58,8 @@ struct csi_priv {
struct ipu_soc *ipu;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
+   struct v4l2_async_notifier notifier;
+
/* the video device at IDMAC output pad */
struct imx_media_video_dev *vdev;
struct imx_media_fim *fim;
@@ -1895,31 +1897,28 @@ static int imx_csi_parse_endpoint(struct device *dev,
 
 static int imx_csi_async_register(struct csi_priv *priv)
 {
-   struct v4l2_async_notifier *notifier;
struct fwnode_handle *fwnode;
unsigned int port;
int ret;
 
-   notifier = kzalloc(sizeof(*notifier), GFP_KERNEL);
-   if (!notifier)
-   return -ENOMEM;
-
-   v4l2_async_notifier_init(notifier);
+   v4l2_async_notifier_init(>notifier);
 
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
ret = fwnode_property_read_u32(fwnode, "reg", );
if (ret < 0)
-   goto out_free;
+   return ret;
 
ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
-   priv->dev->parent, notifier, sizeof(struct v4l2_async_subdev),
+   priv->dev->parent, >notifier,
+   sizeof(struct v4l2_async_subdev),
port, imx_csi_parse_endpoint);
if (ret < 0)
goto out_cleanup;
 
-   ret = v4l2_async_subdev_notifier_register(>sd, notifier);
+   ret = v4l2_async_subdev_notifier_register(>sd,
+ >notifier);
if (ret < 0)
goto out_cleanup;
 
@@ -1927,16 +1926,12 @@ static int imx_csi_async_register(struct csi_priv *priv)
if (ret < 0)
goto out_unregister;
 
-   priv->sd.subdev_notifier = notifier;
-
return 0;
 
 out_unregister:
-   v4l2_async_notifier_unregister(notifier);
+   v4l2_async_notifier_unregister(>notifier);
 out_cleanup:
-   v4l2_async_notifier_cleanup(notifier);
-out_free:
-   kfree(notifier);
+   v4l2_async_notifier_cleanup(>notifier);
 
return ret;
 }
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 18/22] media: imx: csi: Create media links in bound notifier

2019-08-05 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the CSI sink pad.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-csi.c | 24 +++
 1 file changed, 24 insertions(+)

diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index b39d79e63ac2..37b10cbf3c1a 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -120,6 +120,11 @@ static inline struct csi_priv *sd_to_dev(struct 
v4l2_subdev *sdev)
return container_of(sdev, struct csi_priv, sd);
 }
 
+static inline struct csi_priv *notifier_to_dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_priv, notifier);
+}
+
 static inline bool is_parallel_bus(struct v4l2_fwnode_endpoint *ep)
 {
return ep->bus_type != V4L2_MBUS_CSI2_DPHY;
@@ -1895,6 +1900,23 @@ static int imx_csi_parse_endpoint(struct device *dev,
return fwnode_device_is_available(asd->match.fwnode) ? 0 : -ENOTCONN;
 }
 
+static int imx_csi_notify_bound(struct v4l2_async_notifier *notifier,
+   struct v4l2_subdev *sd,
+   struct v4l2_async_subdev *asd)
+{
+   struct csi_priv *priv = notifier_to_dev(notifier);
+   struct media_pad *sink = >sd.entity.pads[CSI_SINK_PAD];
+
+   return media_create_fwnode_pad_links(sink,
+dev_fwnode(priv->dev->parent),
+>entity,
+dev_fwnode(sd->dev), 0);
+}
+
+static const struct v4l2_async_notifier_operations csi_notify_ops = {
+   .bound = imx_csi_notify_bound,
+};
+
 static int imx_csi_async_register(struct csi_priv *priv)
 {
struct fwnode_handle *fwnode;
@@ -1903,6 +1925,8 @@ static int imx_csi_async_register(struct csi_priv *priv)
 
v4l2_async_notifier_init(>notifier);
 
+   priv->notifier.ops = _notify_ops;
+
fwnode = dev_fwnode(priv->dev);
 
/* get this CSI's port id */
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 04/22] media: Move v4l2_fwnode_parse_link from v4l2 to driver base

2019-08-05 Thread Steve Longerbeam
There is nothing v4l2-specific about v4l2_fwnode_{parse|put}_link().
Make these functions more generally available by moving them to driver
base, with the appropriate name changes to the functions and struct.

In the process embed a 'struct fwnode_endpoint' in 'struct fwnode_link'
for both sides of the link, and make use of fwnode_graph_parse_endpoint()
to fully parse both endpoints. Rename members local_node and
remote_node to more descriptive local_port_parent and
remote_port_parent.

Signed-off-by: Steve Longerbeam 
---
 drivers/base/property.c | 63 +++
 drivers/media/platform/xilinx/xilinx-vipp.c | 69 +++--
 drivers/media/v4l2-core/v4l2-fwnode.c   | 39 
 drivers/staging/media/imx/imx-media-of.c| 49 +++
 include/linux/fwnode.h  | 14 +
 include/linux/property.h|  5 ++
 include/media/v4l2-fwnode.h | 44 -
 7 files changed, 141 insertions(+), 142 deletions(-)

diff --git a/drivers/base/property.c b/drivers/base/property.c
index 81bd01ed4042..dd82cd150d84 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -1100,6 +1100,69 @@ int fwnode_graph_parse_endpoint(const struct 
fwnode_handle *fwnode,
 }
 EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
 
+/**
+ * fwnode_graph_parse_link() - parse a link between two endpoints
+ * @local_endpoint: the endpoint's fwnode at the local end of the link
+ * @link: pointer to the fwnode link data structure
+ *
+ * Fill the link structure with the parsed local and remote endpoint info
+ * and the local and remote port parent nodes.
+ *
+ * A reference is taken to both the local and remote port parent nodes,
+ * the caller must use fwnode_graph_put_link() to drop the references
+ * when done with the link.
+ *
+ * Return: 0 on success, or -ENOLINK if the remote endpoint fwnode
+ * can't be found.
+ */
+int fwnode_graph_parse_link(struct fwnode_handle *local_endpoint,
+   struct fwnode_link *link)
+{
+   struct fwnode_handle *remote_endpoint;
+   int ret;
+
+   memset(link, 0, sizeof(*link));
+
+   ret = fwnode_graph_parse_endpoint(local_endpoint, >local);
+   if (ret < 0)
+   return ret;
+
+   remote_endpoint = fwnode_graph_get_remote_endpoint(local_endpoint);
+   if (!remote_endpoint)
+   return -ENOLINK;
+
+   ret = fwnode_graph_parse_endpoint(remote_endpoint, >remote);
+   if (ret < 0) {
+   fwnode_handle_put(remote_endpoint);
+   return ret;
+   }
+
+   link->local_port_parent =
+   fwnode_graph_get_port_parent(local_endpoint);
+   link->remote_port_parent =
+   fwnode_graph_get_port_parent(remote_endpoint);
+
+   fwnode_handle_put(remote_endpoint);
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_parse_link);
+
+/**
+ * fwnode_graph_put_link() - drop references to port parent nodes in a link
+ * @link: pointer to the fwnode link data structure
+ *
+ * Drop references to the local and remote port parent nodes in the link.
+ * This function must be called on every link parsed with
+ * fwnode_graph_parse_link().
+ */
+void fwnode_graph_put_link(struct fwnode_link *link)
+{
+   fwnode_handle_put(link->local_port_parent);
+   fwnode_handle_put(link->remote_port_parent);
+}
+EXPORT_SYMBOL_GPL(fwnode_graph_put_link);
+
 const void *device_get_match_data(struct device *dev)
 {
return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev);
diff --git a/drivers/media/platform/xilinx/xilinx-vipp.c 
b/drivers/media/platform/xilinx/xilinx-vipp.c
index cc2856efea59..9c0dfc694478 100644
--- a/drivers/media/platform/xilinx/xilinx-vipp.c
+++ b/drivers/media/platform/xilinx/xilinx-vipp.c
@@ -74,7 +74,7 @@ static int xvip_graph_build_one(struct xvip_composite_device 
*xdev,
struct media_pad *local_pad;
struct media_pad *remote_pad;
struct xvip_graph_entity *ent;
-   struct v4l2_fwnode_link link;
+   struct fwnode_link link;
struct fwnode_handle *ep = NULL;
int ret = 0;
 
@@ -89,7 +89,7 @@ static int xvip_graph_build_one(struct xvip_composite_device 
*xdev,
 
dev_dbg(xdev->dev, "processing endpoint %p\n", ep);
 
-   ret = v4l2_fwnode_parse_link(ep, );
+   ret = fwnode_graph_parse_link(ep, );
if (ret < 0) {
dev_err(xdev->dev, "failed to parse link for %p\n",
ep);
@@ -99,54 +99,55 @@ static int xvip_graph_build_one(struct 
xvip_composite_device *xdev,
/* Skip sink ports, they will be processed from the other end of
 * the link.
 */
-   if (link.local_port >= local->num_pads) {
+   if (link.local.port >= local->num_pads) {
  

[PATCH 14/22] media: imx7-mipi-csis: Create media links in bound notifier

2019-08-05 Thread Steve Longerbeam
Implement a notifier bound op to register media links from the remote
sub-device's source pad(s) to the mipi csi-2 receiver sink pad.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx7-mipi-csis.c | 25 ++
 1 file changed, 25 insertions(+)

diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c 
b/drivers/staging/media/imx/imx7-mipi-csis.c
index f71d9183cad2..e03b2317a1ac 100644
--- a/drivers/staging/media/imx/imx7-mipi-csis.c
+++ b/drivers/staging/media/imx/imx7-mipi-csis.c
@@ -259,6 +259,12 @@ struct csi_state {
bool sink_linked;
 };
 
+static inline struct csi_state *
+notifier_to_csis_state(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct csi_state, notifier);
+}
+
 struct csis_pix_format {
unsigned int pix_width_alignment;
u32 code;
@@ -863,6 +869,23 @@ static int mipi_csis_parse_endpoint(struct device *dev,
return 0;
 }
 
+static int mipi_csis_notify_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   struct csi_state *state = notifier_to_csis_state(notifier);
+   struct media_pad *sink = >mipi_sd.entity.pads[CSIS_PAD_SINK];
+
+   return media_create_fwnode_pad_links(sink,
+dev_fwnode(state->mipi_sd.dev),
+>entity,
+dev_fwnode(sd->dev), 0);
+}
+
+static const struct v4l2_async_notifier_operations mipi_csis_notify_ops = {
+   .bound = mipi_csis_notify_bound,
+};
+
 static int mipi_csis_subdev_init(struct v4l2_subdev *mipi_sd,
 struct platform_device *pdev,
 const struct v4l2_subdev_ops *ops)
@@ -895,6 +918,8 @@ static int mipi_csis_subdev_init(struct v4l2_subdev 
*mipi_sd,
 
v4l2_async_notifier_init(>notifier);
 
+   state->notifier.ops = _csis_notify_ops;
+
ret = v4l2_async_register_fwnode_subdev(mipi_sd, >notifier,
sizeof(struct 
v4l2_async_subdev),
_port, 1,
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH] media: staging/imx: Fix NULL deref in find_pipeline_entity()

2019-06-26 Thread Steve Longerbeam
Fix a cut error in find_pipeline_entity(). The start entity must be
passed to media_entity_to_video_device() in find_pipeline_entity(), not
pad->entity. The pad is only put to use later, after determining the start
entity is not the entity being searched for.

Fixes: 3ef46bc97ca2 ("media: staging/imx: Improve pipeline searching")

Reported-by: Colin Ian King 
Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-utils.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index b5b8a3b7730a..6fb88c22ee27 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -842,7 +842,7 @@ find_pipeline_entity(struct media_entity *start, u32 grp_id,
if (sd->grp_id & grp_id)
return >entity;
} else if (buftype && is_media_entity_v4l2_video_device(start)) {
-   vfd = media_entity_to_video_device(pad->entity);
+   vfd = media_entity_to_video_device(start);
if (buftype == vfd->queue->type)
return >entity;
}
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


Re: media: staging/imx: Improve pipeline searching (bug report)

2019-06-26 Thread Steve Longerbeam

Thanks for catching,

On 6/26/19 11:27 AM, Colin Ian King wrote:

Hi,

Static analysis with Coverity on Linux next has found a potential issue
with the following commit:

commit 3ef46bc97ca2c918b7657a08220c7340a9bb07a2
Author: Steve Longerbeam 
Date:   Fri May 10 17:50:11 2019 -0400

 media: staging/imx: Improve pipeline searching


The issue is in drivers/staging/media/imx/imx-media-utils.c in function
find_pipeline_entity:

 struct media_pad *pad = NULL;

pad is assigned a NULL

 struct video_device *vfd;
 struct v4l2_subdev *sd;

 if (grp_id && is_media_entity_v4l2_subdev(start)) {
 sd = media_entity_to_v4l2_subdev(start);
 if (sd->grp_id & grp_id)
 return >entity;
 } else if (buftype && is_media_entity_v4l2_video_device(start)) {
 vfd = media_entity_to_video_device(pad->entity);

..and above the null pad is being dereferenced causing a kernel oops.


yes, this is a typo and should be:

vfd = media_entity_to_video_device(start);


Sending a patch...

Steve

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v8 2/5] gpu: ipu-v3: ipu-ic: Fully describe colorspace conversions

2019-05-21 Thread Steve Longerbeam
Only providing the input and output RGB/YUV space to the IC task init
functions is not sufficient. To fully characterize a colorspace
conversion, the Y'CbCr encoding standard, and quantization also
need to be specified.

Define a 'struct ipu_ic_colorspace' that includes all the above.

This allows to actually enforce the fact that the IC:

- can only encode to/from YUV and RGB full range. A follow-up patch will
  remove this restriction.
- can only encode using BT.601 standard. A follow-up patch will add
  Rec.709 encoding support.

The determination of the CSC coefficients based on the input/output
'struct ipu_ic_colorspace' are moved to a new exported function
ipu_ic_calc_csc(), and 'struct ic_csc_params' is exported as
'struct ipu_ic_csc_params'. ipu_ic_calc_csc() fills a 'struct ipu_ic_csc'
with the input/output 'struct ipu_ic_colorspace' and the calculated
'struct ic_csc_params' from those input/output colorspaces.

The functions ipu_ic_task_init(_rsc)() now take a filled 'struct
ipu_ic_csc'.

The existing CSC coefficient tables and ipu_ic_calc_csc() are moved
to a new module ipu-ic-csc.c. This is in preparation for adding more
coefficient tables for limited range quantization and more encoding
standards.

The existing ycbcr2rgb and inverse rgb2ycbcr tables defined the BT.601
Y'CbCr encoding coefficients. The rgb2ycbcr table specifically described
the BT.601 encoding from full range RGB to full range YUV. Table
comments have been added in ipu-ic-csc.c to make this more clear.

The ycbcr2rgb inverse table described encoding YUV limited range to RGB
full range. To be consistent with the rgb2ycbcr table, this table is
converted to YUV full range to RGB full range, and the comments are
expanded in ipu-ic-csc.c.

The ic_csc_rgb2rgb table was just an identity matrix, so it is renamed
'identity' in ipu-ic-csc.c.

Signed-off-by: Steve Longerbeam 
---
Changes in v8:
- remove Fixes: and cc: stable. This patch is too difficult to backport
  to stable trees.
Changes in v7:
- squashed with "gpu: ipu-v3: ipu-ic: Fix BT.601 coefficients".
- moved the coefficient tables and calc_csc_coeffs() to a new
  module ipu-ic-csc.c, and added exported ipu_ic_calc_csc() to it.
- drop v4l2_colorspace (chromaticities) from 'struct ipu_ic_colorspace'.
  It's implied that xfer_func (gamma function) must be the same for input
  and output, so make that implicit for chromaticities too.
- drop passing priv to calc_csc_coeffs(), was only used to print error
  messages.
- removed the inverse_encode boolean in calc_csc_coeffs().
- express negative coefficients as true signed int's, for better
  readability.
- tweak inverse coeff in comments, no change to rounded table values.
---
 drivers/gpu/ipu-v3/Makefile |   4 +-
 drivers/gpu/ipu-v3/ipu-ic-csc.c | 129 ++
 drivers/gpu/ipu-v3/ipu-ic.c | 138 +++-
 drivers/gpu/ipu-v3/ipu-image-convert.c  |  28 ++--
 drivers/staging/media/imx/imx-ic-prpencvf.c |  34 -
 include/video/imx-ipu-v3.h  |  56 +++-
 6 files changed, 271 insertions(+), 118 deletions(-)
 create mode 100644 drivers/gpu/ipu-v3/ipu-ic-csc.c

diff --git a/drivers/gpu/ipu-v3/Makefile b/drivers/gpu/ipu-v3/Makefile
index 7cc8b47e488b..5fe5ef20701a 100644
--- a/drivers/gpu/ipu-v3/Makefile
+++ b/drivers/gpu/ipu-v3/Makefile
@@ -2,8 +2,8 @@
 obj-$(CONFIG_IMX_IPUV3_CORE) += imx-ipu-v3.o
 
 imx-ipu-v3-objs := ipu-common.o ipu-cpmem.o ipu-csi.o ipu-dc.o ipu-di.o \
-   ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-image-convert.o \
-   ipu-smfc.o ipu-vdi.o
+   ipu-dp.o ipu-dmfc.o ipu-ic.o ipu-ic-csc.o \
+   ipu-image-convert.o ipu-smfc.o ipu-vdi.o
 
 ifdef CONFIG_DRM
imx-ipu-v3-objs += ipu-pre.o ipu-prg.o
diff --git a/drivers/gpu/ipu-v3/ipu-ic-csc.c b/drivers/gpu/ipu-v3/ipu-ic-csc.c
new file mode 100644
index ..5fb469cd64fe
--- /dev/null
+++ b/drivers/gpu/ipu-v3/ipu-ic-csc.c
@@ -0,0 +1,129 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Mentor Graphics Inc.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "ipu-prv.h"
+
+/* identity matrix */
+static const struct ipu_ic_csc_params identity = {
+   .coeff = {
+   {  128,0,0, },
+   {0,  128,0, },
+   {0,0,  128, },
+   },
+   .offset = { 0, 0, 0, },
+   .scale = 2,
+};
+
+static const struct ipu_ic_csc_params *rgb2rgb[] = {
+   ,
+};
+
+static const struct ipu_ic_csc_params *yuv2yuv[] = {
+   ,
+};
+
+/*
+ * BT.601 RGB full-range to YUV full-range
+ *
+ * Y =  .2990 * R + .5870 * G + .1140 * B
+ * U = -.1687 * R - .3313 * G + .5000 * B + 128
+ * V =  .5000 * R - .4187 * G - .0813 * B + 128
+ */
+static const struct ipu_ic_csc_params rgbf2yuvf_601 = {
+   .coeff = {
+   {   77,  150,   29, },
+   {  -43,  -85,  128, },
+   {  128, -107,  -21, },
+   },
+

[PATCH v8 5/5] media: imx: Try colorimetry at both sink and source pads

2019-05-21 Thread Steve Longerbeam
Retask imx_media_fill_default_mbus_fields() to try colorimetry parameters,
renaming it to to imx_media_try_colorimetry(), and call it at both sink and
source pad try_fmt's. The unrelated check for uninitialized field value is
moved out to appropriate places in each subdev try_fmt.

The IC now supports Rec.709 and BT.601 Y'CbCr encoding, and both limited
and full range quantization for both YUV and RGB space, so allow those
for pipelines that route through the IC.

Signed-off-by: Steve Longerbeam 
---
Changes in v7:
- squashed with "media: imx: Allow Rec.709 encoding for IC routes".
- remove the RGB full-range quantization restriction for IC routes.
---
 drivers/staging/media/imx/imx-ic-prp.c  |  6 +-
 drivers/staging/media/imx/imx-ic-prpencvf.c |  8 +--
 drivers/staging/media/imx/imx-media-csi.c   | 19 +++---
 drivers/staging/media/imx/imx-media-utils.c | 73 ++---
 drivers/staging/media/imx/imx-media-vdic.c  |  5 +-
 drivers/staging/media/imx/imx-media.h   |  5 +-
 drivers/staging/media/imx/imx7-media-csi.c  |  8 +--
 7 files changed, 62 insertions(+), 62 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 10ffe00f1a54..f87fe0203720 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -193,8 +193,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
sdformat->format.code = cc->codes[0];
}
 
-   imx_media_fill_default_mbus_fields(>format, infmt,
-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
break;
case PRP_SRC_PAD_PRPENC:
case PRP_SRC_PAD_PRPVF:
@@ -203,6 +203,8 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
break;
}
 
+   imx_media_try_colorimetry(>format, true);
+
fmt = __prp_get_fmt(priv, cfg, sdformat->pad, sdformat->which);
*fmt = sdformat->format;
 out:
diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index e8b36a181ccc..f2fe3c11c70e 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -907,8 +907,6 @@ static void prp_try_fmt(struct prp_priv *priv,
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func;
-   sdformat->format.quantization = infmt->quantization;
-   sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
} else {
v4l_bound_align_image(>format.width,
  MIN_W_SINK, MAX_W_SINK, W_ALIGN_SINK,
@@ -916,9 +914,11 @@ static void prp_try_fmt(struct prp_priv *priv,
  MIN_H_SINK, MAX_H_SINK, H_ALIGN_SINK,
  S_ALIGN);
 
-   imx_media_fill_default_mbus_fields(>format, infmt,
-  true);
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
}
+
+   imx_media_try_colorimetry(>format, true);
 }
 
 static int prp_set_fmt(struct v4l2_subdev *sd,
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 1d248aca40a9..dce4addadff4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1375,9 +1375,15 @@ static void csi_try_field(struct csi_priv *priv,
struct v4l2_mbus_framefmt *infmt =
__csi_get_fmt(priv, cfg, CSI_SINK_PAD, sdformat->which);
 
-   /* no restrictions on sink pad field type */
-   if (sdformat->pad == CSI_SINK_PAD)
+   /*
+* no restrictions on sink pad field type except must
+* be initialized.
+*/
+   if (sdformat->pad == CSI_SINK_PAD) {
+   if (sdformat->format.field == V4L2_FIELD_ANY)
+   sdformat->format.field = V4L2_FIELD_NONE;
return;
+   }
 
switch (infmt->field) {
case V4L2_FIELD_SEQ_TB:
@@ -1455,8 +1461,6 @@ static void csi_try_fmt(struct csi_priv *priv,
/* propagate colorimetry from sink */
sdformat->format.colorspace = infmt->colorspace;
sdformat->format.xfer_func = infmt->xfer_func;
-   sdformat->format.quantization = infmt->quantization;
-   sdformat->format.ycbcr_enc = infmt->ycbcr_enc;
 
break;
case CSI_SINK_PAD:
@@ -1476,10 +1480,6 @@ static void csi_try_fmt(struct csi_priv *priv,
 
csi_try_fi

[PATCH v5 7/9] media: staging/imx: Re-organize modules

2019-05-10 Thread Steve Longerbeam
Re-organize modules, and which objects are linked into those modules, so
that:

- imx6-media (renamed from imx-media) is the media driver module for
  imx5/6 only, and has no symbol exports.

- imx6-media-csi (renamed from imx-media-csi) is the subdev driver
  module for imx5/6 CSI. It is now linked direcly with imx-media-fim,
  since only the imx5/6 CSI makes use of the frame interval monitor.

- imx-media-common now only contains common code between imx5/6 and imx7
  media drivers. It contains imx-media-utils, imx-media-of,
  imx-media-dev-common, and imx-media-capture. In order to acheive that,
  some functions common to imx5/6 and imx7 have been moved out of
  imx-media-dev.c and into imx-media-dev-common.c.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/Makefile|  14 +-
 .../staging/media/imx/imx-media-dev-common.c  | 345 +-
 drivers/staging/media/imx/imx-media-dev.c | 340 +
 drivers/staging/media/imx/imx-media-fim.c |   5 -
 drivers/staging/media/imx/imx-media-of.c  |   3 +
 drivers/staging/media/imx/imx-media.h |  16 +-
 drivers/staging/media/imx/imx7-media-csi.c|   4 +-
 7 files changed, 369 insertions(+), 358 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index 86f0c81b6a3b..aa6c4b4ad37e 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
-imx-media-objs += imx-media-dev-common.o
-imx-media-common-objs := imx-media-utils.o imx-media-fim.o
 
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
+imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
+   imx-media-of.o imx-media-utils.o
+
+imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
+
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
 
-obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
+obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 6cd93419b81d..89dc4ec8dadb 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -8,9 +8,342 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "imx-media.h"
 
-static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx_media_dev, notifier);
+}
+
+/* async subdev bound notifier */
+static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+
+   return 0;
+}
+
+/*
+ * Create the media links for all subdevs that registered.
+ * Called after all async subdevs have bound.
+ */
+static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+{
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+   struct v4l2_subdev *sd;
+
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   switch (sd->grp_id) {
+   case IMX_MEDIA_GRP_ID_IPU_VDIC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
+   /*
+* links have already been created for the
+* sync-registered subdevs.
+*/
+   break;
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
+   case IMX_MEDIA_GRP_ID_CSI:
+   imx_media_create_csi_of_links(imxmd, sd);
+   break;
+   default:
+   /*
+* if this subdev has fwnode links, create media
+* links for them.
+*/
+   imx_media_create_of_links(imxmd, sd);
+   break;
+   }
+   }
+
+   return 0;
+}
+
+/*
+ * adds given video device to given imx-media source pad vdev list.
+ * Continues upstream from the pad entity's sink pads.
+ */
+static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd,
+

[PATCH v5 5/9] Revert "media: imx: Set capture compose rectangle in capture_device_set_format"

2019-05-10 Thread Steve Longerbeam
Rvert this commit, as imx_media_capture_device_set_format() will be
removed. The arguments to mx_media_mbus_fmt_to_pix_fmt() and
imx_media_capture_device_set_format() in imx7_csi_set_fmt() are also
reverted.

This reverts commit 5964cbd8692252615370b77eb96764dd70c2f837.

Signed-off-by: Steve Longerbeam 
---
Chnges in v3:
- revert to previous args in imx7_csi_set_fmt().
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 ++--
 drivers/staging/media/imx/imx-media-capture.c | 24 +--
 drivers/staging/media/imx/imx-media-csi.c |  5 ++--
 drivers/staging/media/imx/imx-media-utils.c   | 20 
 drivers/staging/media/imx/imx-media.h |  6 ++---
 drivers/staging/media/imx/imx7-media-csi.c|  5 ++--
 6 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 8242d88dfb82..afaa3a8b15e9 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -910,7 +910,6 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
-   struct v4l2_rect vdev_compose;
int ret = 0;
 
if (sdformat->pad >= PRPENCVF_NUM_PADS)
@@ -952,11 +951,11 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[sdformat->pad] = cc;
 
/* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt, _compose,
+   imx_media_mbus_fmt_to_pix_fmt(_fmt,
  >format_mbus[PRPENCVF_SRC_PAD],
  priv->cc[PRPENCVF_SRC_PAD]);
mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt, _compose);
+   imx_media_capture_device_set_format(vdev, _fmt);
 
return 0;
 out:
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 335084a6b0cd..555f6204660b 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,8 +205,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f,
-struct v4l2_rect *compose)
+struct v4l2_format *f)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -246,8 +245,7 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
}
}
 
-   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, compose,
- _src->format, cc);
+   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
return 0;
 }
@@ -265,7 +263,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
+   return __capture_try_fmt_vid_cap(priv, _src, f);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -273,7 +271,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
-   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -287,14 +284,17 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
+   ret = __capture_try_fmt_vid_cap(priv, _src, f);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose = compose;
+   priv->vdev.compose.left = 0;
+   priv->vdev.compose.top = 0;
+   priv->vdev.compose.width = fmt_src.format.width;
+   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -655,8 +655,7 @@ static struct video_device capture_videodev = {
 };
 
 void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
-const struct v4l2_pix_format *pix,
-const struct v4l2_rect *compose)
+struct v4l2_pix_format *pix)
 {
struct capture_priv *priv = to_capture_priv(vdev);
 
@@ -664,7 +663,6 @@ void imx_media_capture_device_set_format(struct 
imx_media_video_dev *vdev,
priv->vdev.fmt.fmt.pix = *pix;
priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SE

[PATCH v5 3/9] media: staging/imx: Pass device to alloc/free_dma_buf

2019-05-10 Thread Steve Longerbeam
Allocate and free a DMA coherent buffer in imx_media_alloc/free_dma_buf()
from the given device. This allows DMA alloc and free using a device
that is backed by real hardware, which for the imx5/6/7 CSI is the CSI
unit, and for the internal IPU sub-devices, is the parent IPU.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 18 +-
 drivers/staging/media/imx/imx-media-csi.c   |  6 +++---
 drivers/staging/media/imx/imx-media-utils.c | 13 ++---
 drivers/staging/media/imx/imx-media.h   |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c  |  4 ++--
 5 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 069cce512280..ddcd87a17c71 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -464,13 +464,13 @@ static int prp_setup_rotation(struct prp_priv *priv)
incc = priv->cc[PRPENCVF_SINK_PAD];
outcc = vdev->cc;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[0],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[0],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
return ret;
}
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[1],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[1],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
@@ -543,9 +543,9 @@ static int prp_setup_rotation(struct prp_priv *priv)
 unsetup_vb2:
prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 free_rot1:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 free_rot0:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
return ret;
 }
 
@@ -563,8 +563,8 @@ static void prp_unsetup_rotation(struct prp_priv *priv)
 
ipu_ic_disable(priv->ic);
 
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 }
 
 static int prp_setup_norotation(struct prp_priv *priv)
@@ -656,7 +656,7 @@ static int prp_start(struct prp_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -726,7 +726,7 @@ static int prp_start(struct prp_priv *priv)
 out_unsetup:
prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_underrun:
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 out_put_ipu:
prp_put_ipu_resources(priv);
return ret;
@@ -763,7 +763,7 @@ static void prp_stop(struct prp_priv *priv)
 
prp_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeout_timer);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 93b107eab5f5..ea3d13103c91 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -612,7 +612,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(priv->dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -666,7 +666,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 out_unsetup:
csi_idmac_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_dma_buf:
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 out_put_ipu:
csi_idmac_put_ipu_resources(priv);
return ret;
@@ -698,7 +698,7 @@ static void csi_idmac_stop(struct csi_priv *priv)
 
csi_idmac_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeou

[PATCH v5 6/9] media: staging/imx: Remove capture_device_set_format

2019-05-10 Thread Steve Longerbeam
Don't propagate the source pad format to the connected capture device.
It's now the responsibility of userspace to call VIDIOC_S_FMT on the
capture device to ensure the capture format and compose rectangle
are compatible with the connected source. To check this, validate
the capture format with the source before streaming starts.

Signed-off-by: Steve Longerbeam 
---
Changes in v4:
- add **cc arg to __capture_try_fmt_vid_cap() to validate colorspace,
  instead of calling ipu_pixelformat_to_colorspace().
- add error message if capture format validation failed.
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 16 +
 drivers/staging/media/imx/imx-media-capture.c | 71 +--
 drivers/staging/media/imx/imx-media-csi.c | 16 +
 drivers/staging/media/imx/imx-media.h |  2 -
 drivers/staging/media/imx/imx7-media-csi.c| 17 +
 5 files changed, 55 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index afaa3a8b15e9..63334fd61492 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -906,9 +906,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
   struct v4l2_subdev_format *sdformat)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *cc;
-   struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
 
@@ -945,19 +943,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[PRPENCVF_SRC_PAD] = outcc;
}
 
-   if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
-   goto out;
-
-   priv->cc[sdformat->pad] = cc;
+   if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+   priv->cc[sdformat->pad] = cc;
 
-   /* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt,
- >format_mbus[PRPENCVF_SRC_PAD],
- priv->cc[PRPENCVF_SRC_PAD]);
-   mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt);
-
-   return 0;
 out:
mutex_unlock(>lock);
return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 555f6204660b..8a908c3e5e60 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,7 +205,9 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f)
+struct v4l2_format *f,
+const struct imx_media_pixfmt **retcc,
+struct v4l2_rect *compose)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -247,6 +249,16 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
 
imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
+   if (retcc)
+   *retcc = cc;
+
+   if (compose) {
+   compose->left = 0;
+   compose->top = 0;
+   compose->width = fmt_src->format.width;
+   compose->height = fmt_src->format.height;
+   }
+
return 0;
 }
 
@@ -263,7 +275,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f);
+   return __capture_try_fmt_vid_cap(priv, _src, f, NULL, NULL);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -284,17 +296,12 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f);
+   ret = __capture_try_fmt_vid_cap(priv, _src, f, >vdev.cc,
+   >vdev.compose);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
-   priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
- CS_SEL_ANY, true);
-   priv->vdev.compose.left = 0;
-   priv->vdev.compose.top = 0;
-   priv->vdev.compose.width = fmt_src.format.width;
-   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -524,6 +531,33 @@ static void capture_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(>q_lock, flags);
 }
 
+static int capture_validate_fmt(struct capture_priv *priv)
+{
+   struct v4l2_subdev_format fmt_src;
+   const struct imx_medi

[PATCH v5 8/9] media: staging/imx: Improve pipeline searching

2019-05-10 Thread Steve Longerbeam
Export find_pipeline_pad(), renaming to imx_media_pipeline_pad(), and
extend its functionality to allow searching for video devices in the
enabled pipeline in addition to sub-devices.

As part of this:

- Rename imx_media_find_mipi_csi2_channel() to
  imx_media_pipeline_csi2_channel().

- Remove imx_media_find_upstream_pad(), it is redundant now.

- Rename imx_media_find_upstream_subdev() to imx_media_pipeline_subdev()
  with an additional boolean argument for searching upstream or downstream.

- Add imx_media_pipeline_video_device() which is analogous to
  imx_media_pipeline_subdev() but searches for video devices.

- Remove imxmd pointer arg from all of the functions above, it was
  never used in those functions. With that change the i.MX5/6 CSI,
  VDIC, and IC sub-devices no longer require the media_device.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-common.c |   4 +-
 drivers/staging/media/imx/imx-ic-prp.c|   4 +-
 drivers/staging/media/imx/imx-ic.h|   1 -
 drivers/staging/media/imx/imx-media-csi.c |  13 +-
 drivers/staging/media/imx/imx-media-fim.c |   4 -
 .../staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media-utils.c   | 128 ++
 drivers/staging/media/imx/imx-media-vdic.c|   5 +-
 drivers/staging/media/imx/imx-media.h |  20 +--
 drivers/staging/media/imx/imx7-media-csi.c|   2 +-
 10 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index ad0c291db03c..37734984beb4 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -22,12 +22,11 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
  struct device *ipu_dev,
  struct ipu_soc *ipu,
  u32 grp_id)
 {
-   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
@@ -37,7 +36,6 @@ struct v4l2_subdev *imx_media_ic_register(struct 
imx_media_dev *imxmd,
 
priv->ipu_dev = ipu_dev;
priv->ipu = ipu;
-   priv->md = imxmd;
 
/* get our IC task id */
switch (grp_id) {
diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 663db200e594..1432776a33f9 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -302,8 +302,8 @@ static int prp_link_validate(struct v4l2_subdev *sd,
if (ret)
return ret;
 
-   csi = imx_media_find_upstream_subdev(ic_priv->md, _priv->sd.entity,
-IMX_MEDIA_GRP_ID_IPU_CSI);
+   csi = imx_media_pipeline_subdev(_priv->sd.entity,
+   IMX_MEDIA_GRP_ID_IPU_CSI, true);
if (IS_ERR(csi))
csi = NULL;
 
diff --git a/drivers/staging/media/imx/imx-ic.h 
b/drivers/staging/media/imx/imx-ic.h
index 1dcbb37aeada..ff2f66f11982 100644
--- a/drivers/staging/media/imx/imx-ic.h
+++ b/drivers/staging/media/imx/imx-ic.h
@@ -16,7 +16,6 @@
 struct imx_ic_priv {
struct device *ipu_dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
inttask_id;
void   *task_priv;
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 68c2b1a3066a..555904759078 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -60,7 +60,6 @@ struct csi_skip_desc {
 struct csi_priv {
struct device *dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
/* the video device at IDMAC output pad */
@@ -182,8 +181,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
 * CSI-2 receiver if it is in the path, otherwise stay
 * with video mux.
 */
-   sd = imx_media_find_upstream_subdev(priv->md, src,
-   IMX_MEDIA_GRP_ID_CSI2);
+   sd = imx_media_pipeline_subdev(src, IMX_MEDIA_GRP_ID_CSI2,
+  true);
if (!IS_ERR(sd))
src = >entity;
}
@@ -197,7 +196,7 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
src = >sd.entity;
 
/* get source pad of entity directly upstream from src */
-   pad = imx_media_find_upstream_pad(priv->md, src, 0);
+   pad = imx_m

[PATCH v5 2/9] media: staging/imx: Switch to sync registration for IPU subdevs

2019-05-10 Thread Steve Longerbeam
Because the IPU sub-devices VDIC and IC are not present in the
device-tree, platform devices were created for them instead. This
allowed these sub-devices to be added to the media device's async
notifier and registered asynchronously along with the other
sub-devices that do have a device-tree presence (CSI and devices
external to the IPU and SoC).

But that approach isn't really necessary. The IPU sub-devices don't
actually require a backing device (sd->dev is allowed to be NULL).
And that approach can't get around the fact that the IPU sub-devices
are not part of a device hierarchy, which makes it awkward to retrieve
the parent IPU of these devices.

By registering them synchronously, they can be registered from the CSI
async bound notifier, so the init function for them can be given the CSI
subdev, who's dev->parent is the IPU. That is a somewhat cleaner way
to retrieve the parent IPU.

So convert to synchronous registration for the VDIC and IC task
sub-devices, at the time a CSI sub-device is bound. There is no longer
a backing device for them (sd->dev is NULL), but that's ok. Also
set the VDIC/IC sub-device owner as the IPU, so that a reference can
be taken on the IPU module.

Since the VDIC and IC task drivers are no longer platform drivers,
they are now statically linked to imx-media module.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- statically link VDIC and IC task objects to imx-media module in
  Makefile.
---
 drivers/staging/media/imx/Makefile|   6 +-
 drivers/staging/media/imx/imx-ic-common.c |  70 ++--
 drivers/staging/media/imx/imx-ic-prp.c|  34 +-
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  70 ++--
 drivers/staging/media/imx/imx-ic.h|   7 +-
 drivers/staging/media/imx/imx-media-capture.c |   7 +-
 drivers/staging/media/imx/imx-media-csi.c |   2 +-
 drivers/staging/media/imx/imx-media-dev.c | 121 +-
 .../staging/media/imx/imx-media-internal-sd.c | 356 --
 drivers/staging/media/imx/imx-media-of.c  |  38 +-
 drivers/staging/media/imx/imx-media-vdic.c|  85 ++---
 drivers/staging/media/imx/imx-media.h |  67 ++--
 drivers/staging/media/imx/imx7-media-csi.c|   3 +-
 13 files changed, 327 insertions(+), 539 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index d2d909a36239..86f0c81b6a3b 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
+imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+   imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
 imx-media-objs += imx-media-dev-common.o
 imx-media-common-objs := imx-media-utils.o imx-media-fim.o
-imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
 
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index 1addb0893c57..ad0c291db03c 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -8,8 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include 
-#include 
 #include 
 #include 
 #include "imx-media.h"
@@ -24,23 +22,25 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-static int imx_ic_probe(struct platform_device *pdev)
+struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+ struct device *ipu_dev,
+ struct ipu_soc *ipu,
+ u32 grp_id)
 {
-   struct imx_media_ipu_internal_sd_pdata *pdata;
+   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
-   priv = devm_kzalloc(>dev, sizeof(*priv), GFP_KERNEL);
+   priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
-   platform_set_drvdata(pdev, >sd);
-   priv->dev = >dev;
+   priv->ipu_dev = ipu_dev;
+   priv->ipu = ipu;
+   priv->md = imxmd;
 
-   /* get our ipu_id, grp_id and IC task id */
-   pdata = priv->dev->platform_data;
-   priv->ipu_id = pdata->ipu_id;
-   switch (pdata->grp_id) {
+   /* get our IC task id */
+   switch (grp_id) {
case IMX_MEDIA_GRP_

[PATCH v5 4/9] media: staging/imx: Move add_video_device into capture_device_register

2019-05-10 Thread Steve Longerbeam
Move imx_media_add_video_device() into imx_media_capture_device_register().
Also the former has no error conditions to convert to void.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 -
 drivers/staging/media/imx/imx-media-capture.c |  3 +++
 drivers/staging/media/imx/imx-media-csi.c |  7 +--
 drivers/staging/media/imx/imx-media-utils.c   |  9 -
 drivers/staging/media/imx/imx-media.h |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c| 12 +---
 6 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index ddcd87a17c71..8242d88dfb82 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1241,7 +1241,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
@@ -1271,10 +1270,6 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
-   ret = imx_media_add_video_device(ic_priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
ret = prp_init_controls(priv);
if (ret)
goto unreg;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 211ec4df2066..335084a6b0cd 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -780,6 +780,9 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 
vfd->ctrl_handler = >ctrl_hdlr;
 
+   /* add vdev to the video device list */
+   imx_media_add_video_device(priv->md, vdev);
+
return 0;
 unreg:
video_unregister_device(vfd);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index ea3d13103c91..c70fa6b509ae 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1820,13 +1820,8 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
-   ret = imx_media_add_video_device(priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
return 0;
-unreg:
-   imx_media_capture_device_unregister(priv->vdev);
+
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index c52aa59acd05..8a6e57652402 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -767,18 +767,17 @@ imx_media_find_subdev_by_devname(struct imx_media_dev 
*imxmd,
 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
 
 /*
- * Adds a video device to the master video device list. This is called by
- * an async subdev that owns a video device when it is registered.
+ * Adds a video device to the master video device list. This is called
+ * when a video device is registered.
  */
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev)
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev)
 {
mutex_lock(>mutex);
 
list_add_tail(>list, >vdev_list);
 
mutex_unlock(>mutex);
-   return 0;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
 
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index ba2d75bcc4c9..71e20f53ed7b 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -189,8 +189,8 @@ imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
 struct v4l2_subdev *
 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
 const char *devname);
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev);
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev);
 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
 struct media_entity *start_entity);
 struct media_pad *
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 96d01d8af874..f2037aba6e0e 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1126,17 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
 
-   ret = imx_media_capture

[PATCH v5 1/9] Revert "media: staging/imx: add media device to capture register"

2019-05-10 Thread Steve Longerbeam
The imx6-specific subdevs that register a capture device will no
longer hold a reference to the media device, so this commit must be
reverted.

This reverts commit 16204b8a1c1af77725533b77936e6c73953486ae.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 2 +-
 drivers/staging/media/imx/imx-media-capture.c | 6 +++---
 drivers/staging/media/imx/imx-media-csi.c | 2 +-
 drivers/staging/media/imx/imx-media.h | 3 +--
 drivers/staging/media/imx/imx7-media-csi.c| 2 +-
 5 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 3ca1422f6154..5c8e6ad8c025 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1270,7 +1270,7 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
-   ret = imx_media_capture_device_register(priv->md, priv->vdev);
+   ret = imx_media_capture_device_register(priv->vdev);
if (ret)
return ret;
 
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 7688238a3396..9703c85b19c4 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -706,8 +706,7 @@ void imx_media_capture_device_error(struct 
imx_media_video_dev *vdev)
 }
 EXPORT_SYMBOL_GPL(imx_media_capture_device_error);
 
-int imx_media_capture_device_register(struct imx_media_dev *md,
- struct imx_media_video_dev *vdev)
+int imx_media_capture_device_register(struct imx_media_video_dev *vdev)
 {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
@@ -716,7 +715,8 @@ int imx_media_capture_device_register(struct imx_media_dev 
*md,
struct v4l2_subdev_format fmt_src;
int ret;
 
-   priv->md = md;
+   /* get media device */
+   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
 
vfd->v4l2_dev = sd->v4l2_dev;
 
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index c33d714ed953..41965d8b56c4 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1816,7 +1816,7 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
-   ret = imx_media_capture_device_register(priv->md, priv->vdev);
+   ret = imx_media_capture_device_register(priv->vdev);
if (ret)
goto free_fim;
 
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index fc5d969ded79..dd603a6b3a70 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -272,8 +272,7 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd,
 struct imx_media_video_dev *
 imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad);
 void imx_media_capture_device_remove(struct imx_media_video_dev *vdev);
-int imx_media_capture_device_register(struct imx_media_dev *md,
- struct imx_media_video_dev *vdev);
+int imx_media_capture_device_register(struct imx_media_video_dev *vdev);
 void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev);
 struct imx_media_buffer *
 imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev);
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index a708a0340eb1..18eb5d3ecf10 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1126,7 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
 
-   ret = imx_media_capture_device_register(csi->imxmd, csi->vdev);
+   ret = imx_media_capture_device_register(csi->vdev);
if (ret < 0)
return ret;
 
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v5 9/9] media: staging/imx: Don't set driver data for v4l2_dev

2019-05-10 Thread Steve Longerbeam
The media device is already available via multiple methods, there is no
need to set driver data for v4l2_dev to the media device.

In imx_media_link_notify(), get media device from link->graph_obj.mdev.

In imx_media_capture_device_register(), get media device from
v4l2_dev->mdev.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-capture.c| 5 +++--
 drivers/staging/media/imx/imx-media-dev-common.c | 7 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 8a908c3e5e60..ea7f2decfc16 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -735,15 +735,16 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
+   struct v4l2_device *v4l2_dev = sd->v4l2_dev;
struct video_device *vfd = vdev->vfd;
struct vb2_queue *vq = >q;
struct v4l2_subdev_format fmt_src;
int ret;
 
/* get media device */
-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+   priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md);
 
-   vfd->v4l2_dev = sd->v4l2_dev;
+   vfd->v4l2_dev = v4l2_dev;
 
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret) {
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 89dc4ec8dadb..66b505f7e8df 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -260,10 +260,11 @@ static int imx_media_inherit_controls(struct 
imx_media_dev *imxmd,
 static int imx_media_link_notify(struct media_link *link, u32 flags,
 unsigned int notification)
 {
+   struct imx_media_dev *imxmd = container_of(link->graph_obj.mdev,
+  struct imx_media_dev, md);
struct media_entity *source = link->source->entity;
struct imx_media_pad_vdev *pad_vdev;
struct list_head *pad_vdev_list;
-   struct imx_media_dev *imxmd;
struct video_device *vfd;
struct v4l2_subdev *sd;
int pad_idx, ret;
@@ -279,8 +280,6 @@ static int imx_media_link_notify(struct media_link *link, 
u32 flags,
sd = media_entity_to_v4l2_subdev(source);
pad_idx = link->source->index;
 
-   imxmd = dev_get_drvdata(sd->v4l2_dev->dev);
-
pad_vdev_list = to_pad_vdev_list(sd, pad_idx);
if (!pad_vdev_list) {
/* nothing to do if source sd has no pad vdev list */
@@ -384,8 +383,6 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
goto cleanup;
}
 
-   dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
-
INIT_LIST_HEAD(>vdev_list);
 
v4l2_async_notifier_init(>notifier);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 7/8] media: staging/imx: Improve pipeline searching

2019-05-03 Thread Steve Longerbeam
Export find_pipeline_pad(), renaming to imx_media_pipeline_pad(), and
extend its functionality to allow searching for video devices in the
enabled pipeline in addition to sub-devices.

As part of this:

- Rename imx_media_find_mipi_csi2_channel() to
  imx_media_pipeline_csi2_channel().

- Remove imx_media_find_upstream_pad(), it is redundant now.

- Rename imx_media_find_upstream_subdev() to imx_media_pipeline_subdev()
  with an additional boolean argument for searching upstream or downstream.

- Add imx_media_pipeline_video_device() which is analogous to
  imx_media_pipeline_subdev() but searches for video devices.

- Remove imxmd pointer arg from all of the functions above, it was
  never used in those functions. With that change the i.MX5/6 CSI,
  VDIC, and IC sub-devices no longer require the media_device.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-common.c |   4 +-
 drivers/staging/media/imx/imx-ic-prp.c|   4 +-
 drivers/staging/media/imx/imx-ic.h|   1 -
 drivers/staging/media/imx/imx-media-csi.c |  13 +-
 drivers/staging/media/imx/imx-media-fim.c |   4 -
 .../staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media-utils.c   | 128 ++
 drivers/staging/media/imx/imx-media-vdic.c|   5 +-
 drivers/staging/media/imx/imx-media.h |  20 +--
 drivers/staging/media/imx/imx7-media-csi.c|   2 +-
 10 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index ad0c291db03c..37734984beb4 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -22,12 +22,11 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
  struct device *ipu_dev,
  struct ipu_soc *ipu,
  u32 grp_id)
 {
-   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
@@ -37,7 +36,6 @@ struct v4l2_subdev *imx_media_ic_register(struct 
imx_media_dev *imxmd,
 
priv->ipu_dev = ipu_dev;
priv->ipu = ipu;
-   priv->md = imxmd;
 
/* get our IC task id */
switch (grp_id) {
diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 663db200e594..1432776a33f9 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -302,8 +302,8 @@ static int prp_link_validate(struct v4l2_subdev *sd,
if (ret)
return ret;
 
-   csi = imx_media_find_upstream_subdev(ic_priv->md, _priv->sd.entity,
-IMX_MEDIA_GRP_ID_IPU_CSI);
+   csi = imx_media_pipeline_subdev(_priv->sd.entity,
+   IMX_MEDIA_GRP_ID_IPU_CSI, true);
if (IS_ERR(csi))
csi = NULL;
 
diff --git a/drivers/staging/media/imx/imx-ic.h 
b/drivers/staging/media/imx/imx-ic.h
index 1dcbb37aeada..ff2f66f11982 100644
--- a/drivers/staging/media/imx/imx-ic.h
+++ b/drivers/staging/media/imx/imx-ic.h
@@ -16,7 +16,6 @@
 struct imx_ic_priv {
struct device *ipu_dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
inttask_id;
void   *task_priv;
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 68c2b1a3066a..555904759078 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -60,7 +60,6 @@ struct csi_skip_desc {
 struct csi_priv {
struct device *dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
/* the video device at IDMAC output pad */
@@ -182,8 +181,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
 * CSI-2 receiver if it is in the path, otherwise stay
 * with video mux.
 */
-   sd = imx_media_find_upstream_subdev(priv->md, src,
-   IMX_MEDIA_GRP_ID_CSI2);
+   sd = imx_media_pipeline_subdev(src, IMX_MEDIA_GRP_ID_CSI2,
+  true);
if (!IS_ERR(sd))
src = >entity;
}
@@ -197,7 +196,7 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
src = >sd.entity;
 
/* get source pad of entity directly upstream from src */
-   pad = imx_media_find_upstream_pad(priv->md, src, 0);
+   pad = imx_m

[PATCH v4 3/8] media: staging/imx: Move add_video_device into capture_device_register

2019-05-03 Thread Steve Longerbeam
Move imx_media_add_video_device() into imx_media_capture_device_register().
Also the former has no error conditions to convert to void.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 -
 drivers/staging/media/imx/imx-media-capture.c |  3 +++
 drivers/staging/media/imx/imx-media-csi.c |  7 +--
 drivers/staging/media/imx/imx-media-utils.c   |  9 -
 drivers/staging/media/imx/imx-media.h |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c| 12 +---
 6 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index ddcd87a17c71..8242d88dfb82 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1241,7 +1241,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
@@ -1271,10 +1270,6 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
-   ret = imx_media_add_video_device(ic_priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
ret = prp_init_controls(priv);
if (ret)
goto unreg;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 211ec4df2066..335084a6b0cd 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -780,6 +780,9 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 
vfd->ctrl_handler = >ctrl_hdlr;
 
+   /* add vdev to the video device list */
+   imx_media_add_video_device(priv->md, vdev);
+
return 0;
 unreg:
video_unregister_device(vfd);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index ea3d13103c91..c70fa6b509ae 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1820,13 +1820,8 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
-   ret = imx_media_add_video_device(priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
return 0;
-unreg:
-   imx_media_capture_device_unregister(priv->vdev);
+
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index c52aa59acd05..8a6e57652402 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -767,18 +767,17 @@ imx_media_find_subdev_by_devname(struct imx_media_dev 
*imxmd,
 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
 
 /*
- * Adds a video device to the master video device list. This is called by
- * an async subdev that owns a video device when it is registered.
+ * Adds a video device to the master video device list. This is called
+ * when a video device is registered.
  */
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev)
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev)
 {
mutex_lock(>mutex);
 
list_add_tail(>list, >vdev_list);
 
mutex_unlock(>mutex);
-   return 0;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
 
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index ba2d75bcc4c9..71e20f53ed7b 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -189,8 +189,8 @@ imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
 struct v4l2_subdev *
 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
 const char *devname);
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev);
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev);
 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
 struct media_entity *start_entity);
 struct media_pad *
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 96d01d8af874..f2037aba6e0e 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1126,17 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
 
-   ret = imx_media_capture

[PATCH v4 8/8] media: staging/imx: Don't set driver data for v4l2_dev

2019-05-03 Thread Steve Longerbeam
The media device is already available via multiple methods, there is no
need to set driver data for v4l2_dev to the media device.

In imx_media_link_notify(), get media device from link->graph_obj.mdev.

In imx_media_capture_device_register(), get media device from
v4l2_dev->mdev.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-capture.c| 5 +++--
 drivers/staging/media/imx/imx-media-dev-common.c | 7 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 8a908c3e5e60..ea7f2decfc16 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -735,15 +735,16 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
+   struct v4l2_device *v4l2_dev = sd->v4l2_dev;
struct video_device *vfd = vdev->vfd;
struct vb2_queue *vq = >q;
struct v4l2_subdev_format fmt_src;
int ret;
 
/* get media device */
-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+   priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md);
 
-   vfd->v4l2_dev = sd->v4l2_dev;
+   vfd->v4l2_dev = v4l2_dev;
 
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret) {
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 89dc4ec8dadb..66b505f7e8df 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -260,10 +260,11 @@ static int imx_media_inherit_controls(struct 
imx_media_dev *imxmd,
 static int imx_media_link_notify(struct media_link *link, u32 flags,
 unsigned int notification)
 {
+   struct imx_media_dev *imxmd = container_of(link->graph_obj.mdev,
+  struct imx_media_dev, md);
struct media_entity *source = link->source->entity;
struct imx_media_pad_vdev *pad_vdev;
struct list_head *pad_vdev_list;
-   struct imx_media_dev *imxmd;
struct video_device *vfd;
struct v4l2_subdev *sd;
int pad_idx, ret;
@@ -279,8 +280,6 @@ static int imx_media_link_notify(struct media_link *link, 
u32 flags,
sd = media_entity_to_v4l2_subdev(source);
pad_idx = link->source->index;
 
-   imxmd = dev_get_drvdata(sd->v4l2_dev->dev);
-
pad_vdev_list = to_pad_vdev_list(sd, pad_idx);
if (!pad_vdev_list) {
/* nothing to do if source sd has no pad vdev list */
@@ -384,8 +383,6 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
goto cleanup;
}
 
-   dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
-
INIT_LIST_HEAD(>vdev_list);
 
v4l2_async_notifier_init(>notifier);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v4 6/8] media: staging/imx: Re-organize modules

2019-05-03 Thread Steve Longerbeam
Re-organize modules, and which objects are linked into those modules, so
that:

- imx6-media (renamed from imx-media) is the media driver module for
  imx5/6 only, and has no symbol exports.

- imx6-media-csi (renamed from imx-media-csi) is the subdev driver
  module for imx5/6 CSI. It is now linked direcly with imx-media-fim,
  since only the imx5/6 CSI makes use of the frame interval monitor.

- imx-media-common now only contains common code between imx5/6 and imx7
  media drivers. It contains imx-media-utils, imx-media-of,
  imx-media-dev-common, and imx-media-capture. In order to acheive that,
  some functions common to imx5/6 and imx7 have been moved out of
  imx-media-dev.c and into imx-media-dev-common.c.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/Makefile|  14 +-
 .../staging/media/imx/imx-media-dev-common.c  | 345 +-
 drivers/staging/media/imx/imx-media-dev.c | 340 +
 drivers/staging/media/imx/imx-media-fim.c |   5 -
 drivers/staging/media/imx/imx-media-of.c  |   3 +
 drivers/staging/media/imx/imx-media.h |  16 +-
 drivers/staging/media/imx/imx7-media-csi.c|   4 +-
 7 files changed, 369 insertions(+), 358 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index 86f0c81b6a3b..aa6c4b4ad37e 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
-imx-media-objs += imx-media-dev-common.o
-imx-media-common-objs := imx-media-utils.o imx-media-fim.o
 
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
+imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
+   imx-media-of.o imx-media-utils.o
+
+imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
+
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
 
-obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
+obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 6cd93419b81d..89dc4ec8dadb 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -8,9 +8,342 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "imx-media.h"
 
-static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx_media_dev, notifier);
+}
+
+/* async subdev bound notifier */
+static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+
+   return 0;
+}
+
+/*
+ * Create the media links for all subdevs that registered.
+ * Called after all async subdevs have bound.
+ */
+static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+{
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+   struct v4l2_subdev *sd;
+
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   switch (sd->grp_id) {
+   case IMX_MEDIA_GRP_ID_IPU_VDIC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
+   /*
+* links have already been created for the
+* sync-registered subdevs.
+*/
+   break;
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
+   case IMX_MEDIA_GRP_ID_CSI:
+   imx_media_create_csi_of_links(imxmd, sd);
+   break;
+   default:
+   /*
+* if this subdev has fwnode links, create media
+* links for them.
+*/
+   imx_media_create_of_links(imxmd, sd);
+   break;
+   }
+   }
+
+   return 0;
+}
+
+/*
+ * adds given video device to given imx-media source pad vdev list.
+ * Continues upstream from the pad entity's sink pads.
+ */
+static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd,
+

[PATCH v4 2/8] media: staging/imx: Pass device to alloc/free_dma_buf

2019-05-03 Thread Steve Longerbeam
Allocate and free a DMA coherent buffer in imx_media_alloc/free_dma_buf()
from the given device. This allows DMA alloc and free using a device
that is backed by real hardware, which for the imx5/6/7 CSI is the CSI
unit, and for the internal IPU sub-devices, is the parent IPU.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 18 +-
 drivers/staging/media/imx/imx-media-csi.c   |  6 +++---
 drivers/staging/media/imx/imx-media-utils.c | 13 ++---
 drivers/staging/media/imx/imx-media.h   |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c  |  4 ++--
 5 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 069cce512280..ddcd87a17c71 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -464,13 +464,13 @@ static int prp_setup_rotation(struct prp_priv *priv)
incc = priv->cc[PRPENCVF_SINK_PAD];
outcc = vdev->cc;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[0],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[0],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
return ret;
}
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[1],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[1],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
@@ -543,9 +543,9 @@ static int prp_setup_rotation(struct prp_priv *priv)
 unsetup_vb2:
prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 free_rot1:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 free_rot0:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
return ret;
 }
 
@@ -563,8 +563,8 @@ static void prp_unsetup_rotation(struct prp_priv *priv)
 
ipu_ic_disable(priv->ic);
 
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 }
 
 static int prp_setup_norotation(struct prp_priv *priv)
@@ -656,7 +656,7 @@ static int prp_start(struct prp_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -726,7 +726,7 @@ static int prp_start(struct prp_priv *priv)
 out_unsetup:
prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_underrun:
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 out_put_ipu:
prp_put_ipu_resources(priv);
return ret;
@@ -763,7 +763,7 @@ static void prp_stop(struct prp_priv *priv)
 
prp_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeout_timer);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 93b107eab5f5..ea3d13103c91 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -612,7 +612,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(priv->dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -666,7 +666,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 out_unsetup:
csi_idmac_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_dma_buf:
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 out_put_ipu:
csi_idmac_put_ipu_resources(priv);
return ret;
@@ -698,7 +698,7 @@ static void csi_idmac_stop(struct csi_priv *priv)
 
csi_idmac_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeou

[PATCH v4 4/8] Revert "media: imx: Set capture compose rectangle in capture_device_set_format"

2019-05-03 Thread Steve Longerbeam
Rvert this commit, as imx_media_capture_device_set_format() will be
removed. The arguments to mx_media_mbus_fmt_to_pix_fmt() and
imx_media_capture_device_set_format() in imx7_csi_set_fmt() are also
reverted.

This reverts commit 5964cbd8692252615370b77eb96764dd70c2f837.

Signed-off-by: Steve Longerbeam 
---
Chnges in v3:
- revert to previous args in imx7_csi_set_fmt().
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 ++--
 drivers/staging/media/imx/imx-media-capture.c | 24 +--
 drivers/staging/media/imx/imx-media-csi.c |  5 ++--
 drivers/staging/media/imx/imx-media-utils.c   | 20 
 drivers/staging/media/imx/imx-media.h |  6 ++---
 drivers/staging/media/imx/imx7-media-csi.c|  5 ++--
 6 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 8242d88dfb82..afaa3a8b15e9 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -910,7 +910,6 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
-   struct v4l2_rect vdev_compose;
int ret = 0;
 
if (sdformat->pad >= PRPENCVF_NUM_PADS)
@@ -952,11 +951,11 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[sdformat->pad] = cc;
 
/* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt, _compose,
+   imx_media_mbus_fmt_to_pix_fmt(_fmt,
  >format_mbus[PRPENCVF_SRC_PAD],
  priv->cc[PRPENCVF_SRC_PAD]);
mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt, _compose);
+   imx_media_capture_device_set_format(vdev, _fmt);
 
return 0;
 out:
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 335084a6b0cd..555f6204660b 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,8 +205,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f,
-struct v4l2_rect *compose)
+struct v4l2_format *f)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -246,8 +245,7 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
}
}
 
-   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, compose,
- _src->format, cc);
+   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
return 0;
 }
@@ -265,7 +263,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
+   return __capture_try_fmt_vid_cap(priv, _src, f);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -273,7 +271,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
-   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -287,14 +284,17 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
+   ret = __capture_try_fmt_vid_cap(priv, _src, f);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose = compose;
+   priv->vdev.compose.left = 0;
+   priv->vdev.compose.top = 0;
+   priv->vdev.compose.width = fmt_src.format.width;
+   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -655,8 +655,7 @@ static struct video_device capture_videodev = {
 };
 
 void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
-const struct v4l2_pix_format *pix,
-const struct v4l2_rect *compose)
+struct v4l2_pix_format *pix)
 {
struct capture_priv *priv = to_capture_priv(vdev);
 
@@ -664,7 +663,6 @@ void imx_media_capture_device_set_format(struct 
imx_media_video_dev *vdev,
priv->vdev.fmt.fmt.pix = *pix;
priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SE

[PATCH v4 5/8] media: staging/imx: Remove capture_device_set_format

2019-05-03 Thread Steve Longerbeam
Don't propagate the source pad format to the connected capture device.
It's now the responsibility of userspace to call VIDIOC_S_FMT on the
capture device to ensure the capture format and compose rectangle
are compatible with the connected source. To check this, validate
the capture format with the source before streaming starts.

Signed-off-by: Steve Longerbeam 
---
Changes in v4:
- add **cc arg to __capture_try_fmt_vid_cap() to validate colorspace,
  instead of calling ipu_pixelformat_to_colorspace().
- add error message if capture format validation failed.
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 16 +
 drivers/staging/media/imx/imx-media-capture.c | 71 +--
 drivers/staging/media/imx/imx-media-csi.c | 16 +
 drivers/staging/media/imx/imx-media.h |  2 -
 drivers/staging/media/imx/imx7-media-csi.c| 17 +
 5 files changed, 55 insertions(+), 67 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index afaa3a8b15e9..63334fd61492 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -906,9 +906,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
   struct v4l2_subdev_format *sdformat)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *cc;
-   struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
 
@@ -945,19 +943,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[PRPENCVF_SRC_PAD] = outcc;
}
 
-   if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
-   goto out;
-
-   priv->cc[sdformat->pad] = cc;
+   if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+   priv->cc[sdformat->pad] = cc;
 
-   /* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt,
- >format_mbus[PRPENCVF_SRC_PAD],
- priv->cc[PRPENCVF_SRC_PAD]);
-   mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt);
-
-   return 0;
 out:
mutex_unlock(>lock);
return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 555f6204660b..8a908c3e5e60 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,7 +205,9 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f)
+struct v4l2_format *f,
+const struct imx_media_pixfmt **retcc,
+struct v4l2_rect *compose)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -247,6 +249,16 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
 
imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
+   if (retcc)
+   *retcc = cc;
+
+   if (compose) {
+   compose->left = 0;
+   compose->top = 0;
+   compose->width = fmt_src->format.width;
+   compose->height = fmt_src->format.height;
+   }
+
return 0;
 }
 
@@ -263,7 +275,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f);
+   return __capture_try_fmt_vid_cap(priv, _src, f, NULL, NULL);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -284,17 +296,12 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f);
+   ret = __capture_try_fmt_vid_cap(priv, _src, f, >vdev.cc,
+   >vdev.compose);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
-   priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
- CS_SEL_ANY, true);
-   priv->vdev.compose.left = 0;
-   priv->vdev.compose.top = 0;
-   priv->vdev.compose.width = fmt_src.format.width;
-   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -524,6 +531,33 @@ static void capture_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(>q_lock, flags);
 }
 
+static int capture_validate_fmt(struct capture_priv *priv)
+{
+   struct v4l2_subdev_format fmt_src;
+   const struct imx_medi

[PATCH v4 1/8] media: staging/imx: Switch to sync registration for IPU subdevs

2019-05-03 Thread Steve Longerbeam
Because the IPU sub-devices VDIC and IC are not present in the
device-tree, platform devices were created for them instead. This
allowed these sub-devices to be added to the media device's async
notifier and registered asynchronously along with the other
sub-devices that do have a device-tree presence (CSI and devices
external to the IPU and SoC).

But that approach isn't really necessary. The IPU sub-devices don't
actually require a backing device (sd->dev is allowed to be NULL).
And that approach can't get around the fact that the IPU sub-devices
are not part of a device hierarchy, which makes it awkward to retrieve
the parent IPU of these devices.

By registering them synchronously, they can be registered from the CSI
async bound notifier, so the init function for them can be given the CSI
subdev, who's dev->parent is the IPU. That is a somewhat cleaner way
to retrieve the parent IPU.

So convert to synchronous registration for the VDIC and IC task
sub-devices, at the time a CSI sub-device is bound. There is no longer
a backing device for them (sd->dev is NULL), but that's ok. Also
set the VDIC/IC sub-device owner as the IPU, so that a reference can
be taken on the IPU module.

Since the VDIC and IC task drivers are no longer platform drivers,
they are now statically linked to imx-media module.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- statically link VDIC and IC task objects to imx-media module in
  Makefile.
---
 drivers/staging/media/imx/Makefile|   6 +-
 drivers/staging/media/imx/imx-ic-common.c |  70 ++--
 drivers/staging/media/imx/imx-ic-prp.c|  34 +-
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  70 ++--
 drivers/staging/media/imx/imx-ic.h|   7 +-
 drivers/staging/media/imx/imx-media-capture.c |   7 +-
 drivers/staging/media/imx/imx-media-csi.c |   2 +-
 drivers/staging/media/imx/imx-media-dev.c | 121 +-
 .../staging/media/imx/imx-media-internal-sd.c | 356 --
 drivers/staging/media/imx/imx-media-of.c  |  38 +-
 drivers/staging/media/imx/imx-media-vdic.c|  85 ++---
 drivers/staging/media/imx/imx-media.h |  67 ++--
 drivers/staging/media/imx/imx7-media-csi.c|   3 +-
 13 files changed, 327 insertions(+), 539 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index d2d909a36239..86f0c81b6a3b 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
+imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+   imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
 imx-media-objs += imx-media-dev-common.o
 imx-media-common-objs := imx-media-utils.o imx-media-fim.o
-imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
 
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index 1addb0893c57..ad0c291db03c 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -8,8 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include 
-#include 
 #include 
 #include 
 #include "imx-media.h"
@@ -24,23 +22,25 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-static int imx_ic_probe(struct platform_device *pdev)
+struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+ struct device *ipu_dev,
+ struct ipu_soc *ipu,
+ u32 grp_id)
 {
-   struct imx_media_ipu_internal_sd_pdata *pdata;
+   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
-   priv = devm_kzalloc(>dev, sizeof(*priv), GFP_KERNEL);
+   priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
-   platform_set_drvdata(pdev, >sd);
-   priv->dev = >dev;
+   priv->ipu_dev = ipu_dev;
+   priv->ipu = ipu;
+   priv->md = imxmd;
 
-   /* get our ipu_id, grp_id and IC task id */
-   pdata = priv->dev->platform_data;
-   priv->ipu_id = pdata->ipu_id;
-   switch (pdata->grp_id) {
+   /* get our IC task id */
+   switch (grp_id) {
case IMX_MEDIA_GRP_

Re: [PATCH v3 5/8] media: staging/imx: Remove capture_device_set_format

2019-05-02 Thread Steve Longerbeam




On 5/2/19 3:01 AM, Rui Miguel Silva wrote:

Hi Steve,
Thanks for v3 with bisect fixed.

On Tue 30 Apr 2019 at 23:50, Steve Longerbeam wrote:

Don't propagate the source pad format to the connected capture device.
It's now the responsibility of userspace to call VIDIOC_S_FMT on the
capture device to ensure the capture format and compose rectangle
are compatible with the connected source. To check this, validate
the capture format with the source before streaming starts.

Signed-off-by: Steve Longerbeam 
---
  drivers/staging/media/imx/imx-ic-prpencvf.c   | 16 +
  drivers/staging/media/imx/imx-media-capture.c | 64 +--
  drivers/staging/media/imx/imx-media-csi.c | 16 +
  drivers/staging/media/imx/imx-media.h |  2 -
  drivers/staging/media/imx/imx7-media-csi.c| 17 +
  5 files changed, 50 insertions(+), 65 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index afaa3a8b15e9..63334fd61492 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -906,9 +906,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
   struct v4l2_subdev_format *sdformat)
  {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *cc;
-   struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
  
@@ -945,19 +943,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,

priv->cc[PRPENCVF_SRC_PAD] = outcc;
}
  
-	if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)

-   goto out;
-
-   priv->cc[sdformat->pad] = cc;
+   if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+   priv->cc[sdformat->pad] = cc;
  
-	/* propagate output pad format to capture device */

-   imx_media_mbus_fmt_to_pix_fmt(_fmt,
- >format_mbus[PRPENCVF_SRC_PAD],
- priv->cc[PRPENCVF_SRC_PAD]);
-   mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt);
-
-   return 0;
  out:
mutex_unlock(>lock);
return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 555f6204660b..b77a67bda47c 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,7 +205,8 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
  
  static int __capture_try_fmt_vid_cap(struct capture_priv *priv,

 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f)
+struct v4l2_format *f,
+struct v4l2_rect *compose)
  {
const struct imx_media_pixfmt *cc, *cc_src;
  
@@ -247,6 +248,13 @@ static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
  
  	imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
  
+	if (compose) {

+   compose->left = 0;
+   compose->top = 0;
+   compose->width = fmt_src->format.width;
+   compose->height = fmt_src->format.height;
+   }
+
return 0;
  }
  
@@ -263,7 +271,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void *fh,

if (ret)
return ret;
  
-	return __capture_try_fmt_vid_cap(priv, _src, f);

+   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
  }
  
  static int capture_s_fmt_vid_cap(struct file *file, void *fh,

@@ -271,6 +279,7 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
  {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
+   struct v4l2_rect compose;
int ret;
  
  	if (vb2_is_busy(>q)) {

@@ -284,17 +293,14 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
  
-	ret = __capture_try_fmt_vid_cap(priv, _src, f);

+   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
if (ret)
return ret;
  
  	priv->vdev.fmt.fmt.pix = f->fmt.pix;

priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose.left = 0;
-   priv->vdev.compose.top = 0;
-   priv->vdev.compose.width = fmt_src.format.width;
-   priv->vdev.compose.height = fmt_src.format.height;
+   priv->vdev.compose = compose;
  
  	return 0;

  }
@@ -524,6 +530,33 @@ static void capture_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(>q_lock, flags);
  }
  
+static int capture_validate_fmt(struct capture_priv *priv)

+{
+   struct v4l2_subdev_fo

[PATCH v3 7/8] media: staging/imx: Improve pipeline searching

2019-04-30 Thread Steve Longerbeam
Export find_pipeline_pad(), renaming to imx_media_pipeline_pad(), and
extend its functionality to allow searching for video devices in the
enabled pipeline in addition to sub-devices.

As part of this:

- Rename imx_media_find_mipi_csi2_channel() to
  imx_media_pipeline_csi2_channel().

- Remove imx_media_find_upstream_pad(), it is redundant now.

- Rename imx_media_find_upstream_subdev() to imx_media_pipeline_subdev()
  with an additional boolean argument for searching upstream or downstream.

- Add imx_media_pipeline_video_device() which is analogous to
  imx_media_pipeline_subdev() but searches for video devices.

- Remove imxmd pointer arg from all of the functions above, it was
  never used in those functions. With that change the i.MX5/6 CSI,
  VDIC, and IC sub-devices no longer require the media_device.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-common.c |   4 +-
 drivers/staging/media/imx/imx-ic-prp.c|   4 +-
 drivers/staging/media/imx/imx-ic.h|   1 -
 drivers/staging/media/imx/imx-media-csi.c |  13 +-
 drivers/staging/media/imx/imx-media-fim.c |   4 -
 .../staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media-utils.c   | 128 ++
 drivers/staging/media/imx/imx-media-vdic.c|   5 +-
 drivers/staging/media/imx/imx-media.h |  20 +--
 drivers/staging/media/imx/imx7-media-csi.c|   2 +-
 10 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index ad0c291db03c..37734984beb4 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -22,12 +22,11 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
  struct device *ipu_dev,
  struct ipu_soc *ipu,
  u32 grp_id)
 {
-   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
@@ -37,7 +36,6 @@ struct v4l2_subdev *imx_media_ic_register(struct 
imx_media_dev *imxmd,
 
priv->ipu_dev = ipu_dev;
priv->ipu = ipu;
-   priv->md = imxmd;
 
/* get our IC task id */
switch (grp_id) {
diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 663db200e594..1432776a33f9 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -302,8 +302,8 @@ static int prp_link_validate(struct v4l2_subdev *sd,
if (ret)
return ret;
 
-   csi = imx_media_find_upstream_subdev(ic_priv->md, _priv->sd.entity,
-IMX_MEDIA_GRP_ID_IPU_CSI);
+   csi = imx_media_pipeline_subdev(_priv->sd.entity,
+   IMX_MEDIA_GRP_ID_IPU_CSI, true);
if (IS_ERR(csi))
csi = NULL;
 
diff --git a/drivers/staging/media/imx/imx-ic.h 
b/drivers/staging/media/imx/imx-ic.h
index 1dcbb37aeada..ff2f66f11982 100644
--- a/drivers/staging/media/imx/imx-ic.h
+++ b/drivers/staging/media/imx/imx-ic.h
@@ -16,7 +16,6 @@
 struct imx_ic_priv {
struct device *ipu_dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
inttask_id;
void   *task_priv;
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 68c2b1a3066a..555904759078 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -60,7 +60,6 @@ struct csi_skip_desc {
 struct csi_priv {
struct device *dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
/* the video device at IDMAC output pad */
@@ -182,8 +181,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
 * CSI-2 receiver if it is in the path, otherwise stay
 * with video mux.
 */
-   sd = imx_media_find_upstream_subdev(priv->md, src,
-   IMX_MEDIA_GRP_ID_CSI2);
+   sd = imx_media_pipeline_subdev(src, IMX_MEDIA_GRP_ID_CSI2,
+  true);
if (!IS_ERR(sd))
src = >entity;
}
@@ -197,7 +196,7 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
src = >sd.entity;
 
/* get source pad of entity directly upstream from src */
-   pad = imx_media_find_upstream_pad(priv->md, src, 0);
+   pad = imx_m

[PATCH v3 2/8] media: staging/imx: Pass device to alloc/free_dma_buf

2019-04-30 Thread Steve Longerbeam
Allocate and free a DMA coherent buffer in imx_media_alloc/free_dma_buf()
from the given device. This allows DMA alloc and free using a device
that is backed by real hardware, which for the imx5/6/7 CSI is the CSI
unit, and for the internal IPU sub-devices, is the parent IPU.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 18 +-
 drivers/staging/media/imx/imx-media-csi.c   |  6 +++---
 drivers/staging/media/imx/imx-media-utils.c | 13 ++---
 drivers/staging/media/imx/imx-media.h   |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c  |  4 ++--
 5 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 069cce512280..ddcd87a17c71 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -464,13 +464,13 @@ static int prp_setup_rotation(struct prp_priv *priv)
incc = priv->cc[PRPENCVF_SINK_PAD];
outcc = vdev->cc;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[0],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[0],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
return ret;
}
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[1],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[1],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
@@ -543,9 +543,9 @@ static int prp_setup_rotation(struct prp_priv *priv)
 unsetup_vb2:
prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 free_rot1:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 free_rot0:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
return ret;
 }
 
@@ -563,8 +563,8 @@ static void prp_unsetup_rotation(struct prp_priv *priv)
 
ipu_ic_disable(priv->ic);
 
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 }
 
 static int prp_setup_norotation(struct prp_priv *priv)
@@ -656,7 +656,7 @@ static int prp_start(struct prp_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -726,7 +726,7 @@ static int prp_start(struct prp_priv *priv)
 out_unsetup:
prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_underrun:
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 out_put_ipu:
prp_put_ipu_resources(priv);
return ret;
@@ -763,7 +763,7 @@ static void prp_stop(struct prp_priv *priv)
 
prp_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeout_timer);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 93b107eab5f5..ea3d13103c91 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -612,7 +612,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(priv->dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -666,7 +666,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 out_unsetup:
csi_idmac_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_dma_buf:
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 out_put_ipu:
csi_idmac_put_ipu_resources(priv);
return ret;
@@ -698,7 +698,7 @@ static void csi_idmac_stop(struct csi_priv *priv)
 
csi_idmac_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeou

[PATCH v3 1/8] media: staging/imx: Switch to sync registration for IPU subdevs

2019-04-30 Thread Steve Longerbeam
Because the IPU sub-devices VDIC and IC are not present in the
device-tree, platform devices were created for them instead. This
allowed these sub-devices to be added to the media device's async
notifier and registered asynchronously along with the other
sub-devices that do have a device-tree presence (CSI and devices
external to the IPU and SoC).

But that approach isn't really necessary. The IPU sub-devices don't
actually require a backing device (sd->dev is allowed to be NULL).
And that approach can't get around the fact that the IPU sub-devices
are not part of a device hierarchy, which makes it awkward to retrieve
the parent IPU of these devices.

By registering them synchronously, they can be registered from the CSI
async bound notifier, so the init function for them can be given the CSI
subdev, who's dev->parent is the IPU. That is a somewhat cleaner way
to retrieve the parent IPU.

So convert to synchronous registration for the VDIC and IC task
sub-devices, at the time a CSI sub-device is bound. There is no longer
a backing device for them (sd->dev is NULL), but that's ok. Also
set the VDIC/IC sub-device owner as the IPU, so that a reference can
be taken on the IPU module.

Since the VDIC and IC task drivers are no longer platform drivers,
they are now statically linked to imx-media module.

Signed-off-by: Steve Longerbeam 
---
Changes in v3:
- statically link VDIC and IC task objects to imx-media module in
  Makefile.
---
 drivers/staging/media/imx/Makefile|   6 +-
 drivers/staging/media/imx/imx-ic-common.c |  70 ++--
 drivers/staging/media/imx/imx-ic-prp.c|  34 +-
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  70 ++--
 drivers/staging/media/imx/imx-ic.h|   7 +-
 drivers/staging/media/imx/imx-media-capture.c |   7 +-
 drivers/staging/media/imx/imx-media-csi.c |   2 +-
 drivers/staging/media/imx/imx-media-dev.c | 121 +-
 .../staging/media/imx/imx-media-internal-sd.c | 356 --
 drivers/staging/media/imx/imx-media-of.c  |  38 +-
 drivers/staging/media/imx/imx-media-vdic.c|  85 ++---
 drivers/staging/media/imx/imx-media.h |  67 ++--
 drivers/staging/media/imx/imx7-media-csi.c|   3 +-
 13 files changed, 327 insertions(+), 539 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index d2d909a36239..86f0c81b6a3b 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,12 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
+imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+   imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
 imx-media-objs += imx-media-dev-common.o
 imx-media-common-objs := imx-media-utils.o imx-media-fim.o
-imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
 
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index 1addb0893c57..ad0c291db03c 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -8,8 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include 
-#include 
 #include 
 #include 
 #include "imx-media.h"
@@ -24,23 +22,25 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-static int imx_ic_probe(struct platform_device *pdev)
+struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+ struct device *ipu_dev,
+ struct ipu_soc *ipu,
+ u32 grp_id)
 {
-   struct imx_media_ipu_internal_sd_pdata *pdata;
+   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
-   priv = devm_kzalloc(>dev, sizeof(*priv), GFP_KERNEL);
+   priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
-   platform_set_drvdata(pdev, >sd);
-   priv->dev = >dev;
+   priv->ipu_dev = ipu_dev;
+   priv->ipu = ipu;
+   priv->md = imxmd;
 
-   /* get our ipu_id, grp_id and IC task id */
-   pdata = priv->dev->platform_data;
-   priv->ipu_id = pdata->ipu_id;
-   switch (pdata->grp_id) {
+   /* get our IC task id */
+   switch (grp_id) {
case IMX_MEDIA_GRP_

[PATCH v3 8/8] media: staging/imx: Don't set driver data for v4l2_dev

2019-04-30 Thread Steve Longerbeam
The media device is already available via multiple methods, there is no
need to set driver data for v4l2_dev to the media device.

In imx_media_link_notify(), get media device from link->graph_obj.mdev.

In imx_media_capture_device_register(), get media device from
v4l2_dev->mdev.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-capture.c| 5 +++--
 drivers/staging/media/imx/imx-media-dev-common.c | 7 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index b77a67bda47c..565d21f169d8 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -732,15 +732,16 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
+   struct v4l2_device *v4l2_dev = sd->v4l2_dev;
struct video_device *vfd = vdev->vfd;
struct vb2_queue *vq = >q;
struct v4l2_subdev_format fmt_src;
int ret;
 
/* get media device */
-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+   priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md);
 
-   vfd->v4l2_dev = sd->v4l2_dev;
+   vfd->v4l2_dev = v4l2_dev;
 
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret) {
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 89dc4ec8dadb..66b505f7e8df 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -260,10 +260,11 @@ static int imx_media_inherit_controls(struct 
imx_media_dev *imxmd,
 static int imx_media_link_notify(struct media_link *link, u32 flags,
 unsigned int notification)
 {
+   struct imx_media_dev *imxmd = container_of(link->graph_obj.mdev,
+  struct imx_media_dev, md);
struct media_entity *source = link->source->entity;
struct imx_media_pad_vdev *pad_vdev;
struct list_head *pad_vdev_list;
-   struct imx_media_dev *imxmd;
struct video_device *vfd;
struct v4l2_subdev *sd;
int pad_idx, ret;
@@ -279,8 +280,6 @@ static int imx_media_link_notify(struct media_link *link, 
u32 flags,
sd = media_entity_to_v4l2_subdev(source);
pad_idx = link->source->index;
 
-   imxmd = dev_get_drvdata(sd->v4l2_dev->dev);
-
pad_vdev_list = to_pad_vdev_list(sd, pad_idx);
if (!pad_vdev_list) {
/* nothing to do if source sd has no pad vdev list */
@@ -384,8 +383,6 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
goto cleanup;
}
 
-   dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
-
INIT_LIST_HEAD(>vdev_list);
 
v4l2_async_notifier_init(>notifier);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v3 6/8] media: staging/imx: Re-organize modules

2019-04-30 Thread Steve Longerbeam
Re-organize modules, and which objects are linked into those modules, so
that:

- imx6-media (renamed from imx-media) is the media driver module for
  imx5/6 only, and has no symbol exports.

- imx6-media-csi (renamed from imx-media-csi) is the subdev driver
  module for imx5/6 CSI. It is now linked direcly with imx-media-fim,
  since only the imx5/6 CSI makes use of the frame interval monitor.

- imx-media-common now only contains common code between imx5/6 and imx7
  media drivers. It contains imx-media-utils, imx-media-of,
  imx-media-dev-common, and imx-media-capture. In order to acheive that,
  some functions common to imx5/6 and imx7 have been moved out of
  imx-media-dev.c and into imx-media-dev-common.c.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/Makefile|  14 +-
 .../staging/media/imx/imx-media-dev-common.c  | 345 +-
 drivers/staging/media/imx/imx-media-dev.c | 340 +
 drivers/staging/media/imx/imx-media-fim.c |   5 -
 drivers/staging/media/imx/imx-media-of.c  |   3 +
 drivers/staging/media/imx/imx-media.h |  16 +-
 drivers/staging/media/imx/imx7-media-csi.c|   4 +-
 7 files changed, 369 insertions(+), 358 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index 86f0c81b6a3b..aa6c4b4ad37e 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,14 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o \
+imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
-imx-media-objs += imx-media-dev-common.o
-imx-media-common-objs := imx-media-utils.o imx-media-fim.o
 
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
+imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
+   imx-media-of.o imx-media-utils.o
+
+imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
+
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
 
-obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
+obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 6cd93419b81d..89dc4ec8dadb 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -8,9 +8,342 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "imx-media.h"
 
-static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx_media_dev, notifier);
+}
+
+/* async subdev bound notifier */
+static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+
+   return 0;
+}
+
+/*
+ * Create the media links for all subdevs that registered.
+ * Called after all async subdevs have bound.
+ */
+static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+{
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+   struct v4l2_subdev *sd;
+
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   switch (sd->grp_id) {
+   case IMX_MEDIA_GRP_ID_IPU_VDIC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
+   /*
+* links have already been created for the
+* sync-registered subdevs.
+*/
+   break;
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
+   case IMX_MEDIA_GRP_ID_CSI:
+   imx_media_create_csi_of_links(imxmd, sd);
+   break;
+   default:
+   /*
+* if this subdev has fwnode links, create media
+* links for them.
+*/
+   imx_media_create_of_links(imxmd, sd);
+   break;
+   }
+   }
+
+   return 0;
+}
+
+/*
+ * adds given video device to given imx-media source pad vdev list.
+ * Continues upstream from the pad entity's sink pads.
+ */
+static int imx_media_add_vdev_to_pad(struct imx_media_dev *imxmd,
+

[PATCH v3 4/8] Revert "media: imx: Set capture compose rectangle in capture_device_set_format"

2019-04-30 Thread Steve Longerbeam
Rvert this commit, as imx_media_capture_device_set_format() will be
removed. The arguments to mx_media_mbus_fmt_to_pix_fmt() and
imx_media_capture_device_set_format() in imx7_csi_set_fmt() are also
reverted.

This reverts commit 5964cbd8692252615370b77eb96764dd70c2f837.

Signed-off-by: Steve Longerbeam 
---
Chnges in v3:
- revert to previous args in imx7_csi_set_fmt().
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 ++--
 drivers/staging/media/imx/imx-media-capture.c | 24 +--
 drivers/staging/media/imx/imx-media-csi.c |  5 ++--
 drivers/staging/media/imx/imx-media-utils.c   | 20 
 drivers/staging/media/imx/imx-media.h |  6 ++---
 drivers/staging/media/imx/imx7-media-csi.c|  5 ++--
 6 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 8242d88dfb82..afaa3a8b15e9 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -910,7 +910,6 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
-   struct v4l2_rect vdev_compose;
int ret = 0;
 
if (sdformat->pad >= PRPENCVF_NUM_PADS)
@@ -952,11 +951,11 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[sdformat->pad] = cc;
 
/* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt, _compose,
+   imx_media_mbus_fmt_to_pix_fmt(_fmt,
  >format_mbus[PRPENCVF_SRC_PAD],
  priv->cc[PRPENCVF_SRC_PAD]);
mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt, _compose);
+   imx_media_capture_device_set_format(vdev, _fmt);
 
return 0;
 out:
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 335084a6b0cd..555f6204660b 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,8 +205,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f,
-struct v4l2_rect *compose)
+struct v4l2_format *f)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -246,8 +245,7 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
}
}
 
-   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, compose,
- _src->format, cc);
+   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
return 0;
 }
@@ -265,7 +263,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
+   return __capture_try_fmt_vid_cap(priv, _src, f);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -273,7 +271,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
-   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -287,14 +284,17 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
+   ret = __capture_try_fmt_vid_cap(priv, _src, f);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose = compose;
+   priv->vdev.compose.left = 0;
+   priv->vdev.compose.top = 0;
+   priv->vdev.compose.width = fmt_src.format.width;
+   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -655,8 +655,7 @@ static struct video_device capture_videodev = {
 };
 
 void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
-const struct v4l2_pix_format *pix,
-const struct v4l2_rect *compose)
+struct v4l2_pix_format *pix)
 {
struct capture_priv *priv = to_capture_priv(vdev);
 
@@ -664,7 +663,6 @@ void imx_media_capture_device_set_format(struct 
imx_media_video_dev *vdev,
priv->vdev.fmt.fmt.pix = *pix;
priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SE

[PATCH v3 3/8] media: staging/imx: Move add_video_device into capture_device_register

2019-04-30 Thread Steve Longerbeam
Move imx_media_add_video_device() into imx_media_capture_device_register().
Also the former has no error conditions to convert to void.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 -
 drivers/staging/media/imx/imx-media-capture.c |  3 +++
 drivers/staging/media/imx/imx-media-csi.c |  7 +--
 drivers/staging/media/imx/imx-media-utils.c   |  9 -
 drivers/staging/media/imx/imx-media.h |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c| 12 +---
 6 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index ddcd87a17c71..8242d88dfb82 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1241,7 +1241,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
@@ -1271,10 +1270,6 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
-   ret = imx_media_add_video_device(ic_priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
ret = prp_init_controls(priv);
if (ret)
goto unreg;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 211ec4df2066..335084a6b0cd 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -780,6 +780,9 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 
vfd->ctrl_handler = >ctrl_hdlr;
 
+   /* add vdev to the video device list */
+   imx_media_add_video_device(priv->md, vdev);
+
return 0;
 unreg:
video_unregister_device(vfd);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index ea3d13103c91..c70fa6b509ae 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1820,13 +1820,8 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
-   ret = imx_media_add_video_device(priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
return 0;
-unreg:
-   imx_media_capture_device_unregister(priv->vdev);
+
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index c52aa59acd05..8a6e57652402 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -767,18 +767,17 @@ imx_media_find_subdev_by_devname(struct imx_media_dev 
*imxmd,
 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
 
 /*
- * Adds a video device to the master video device list. This is called by
- * an async subdev that owns a video device when it is registered.
+ * Adds a video device to the master video device list. This is called
+ * when a video device is registered.
  */
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev)
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev)
 {
mutex_lock(>mutex);
 
list_add_tail(>list, >vdev_list);
 
mutex_unlock(>mutex);
-   return 0;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
 
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index ba2d75bcc4c9..71e20f53ed7b 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -189,8 +189,8 @@ imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
 struct v4l2_subdev *
 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
 const char *devname);
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev);
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev);
 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
 struct media_entity *start_entity);
 struct media_pad *
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 96d01d8af874..f2037aba6e0e 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1126,17 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
 
-   ret = imx_media_capture

[PATCH v3 5/8] media: staging/imx: Remove capture_device_set_format

2019-04-30 Thread Steve Longerbeam
Don't propagate the source pad format to the connected capture device.
It's now the responsibility of userspace to call VIDIOC_S_FMT on the
capture device to ensure the capture format and compose rectangle
are compatible with the connected source. To check this, validate
the capture format with the source before streaming starts.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 16 +
 drivers/staging/media/imx/imx-media-capture.c | 64 +--
 drivers/staging/media/imx/imx-media-csi.c | 16 +
 drivers/staging/media/imx/imx-media.h |  2 -
 drivers/staging/media/imx/imx7-media-csi.c| 17 +
 5 files changed, 50 insertions(+), 65 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index afaa3a8b15e9..63334fd61492 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -906,9 +906,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
   struct v4l2_subdev_format *sdformat)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *cc;
-   struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
 
@@ -945,19 +943,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[PRPENCVF_SRC_PAD] = outcc;
}
 
-   if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
-   goto out;
-
-   priv->cc[sdformat->pad] = cc;
+   if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+   priv->cc[sdformat->pad] = cc;
 
-   /* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt,
- >format_mbus[PRPENCVF_SRC_PAD],
- priv->cc[PRPENCVF_SRC_PAD]);
-   mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt);
-
-   return 0;
 out:
mutex_unlock(>lock);
return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 555f6204660b..b77a67bda47c 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,7 +205,8 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f)
+struct v4l2_format *f,
+struct v4l2_rect *compose)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -247,6 +248,13 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
 
imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
+   if (compose) {
+   compose->left = 0;
+   compose->top = 0;
+   compose->width = fmt_src->format.width;
+   compose->height = fmt_src->format.height;
+   }
+
return 0;
 }
 
@@ -263,7 +271,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f);
+   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -271,6 +279,7 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
+   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -284,17 +293,14 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f);
+   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose.left = 0;
-   priv->vdev.compose.top = 0;
-   priv->vdev.compose.width = fmt_src.format.width;
-   priv->vdev.compose.height = fmt_src.format.height;
+   priv->vdev.compose = compose;
 
return 0;
 }
@@ -524,6 +530,33 @@ static void capture_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(>q_lock, flags);
 }
 
+static int capture_validate_fmt(struct capture_priv *priv)
+{
+   struct v4l2_subdev_format fmt_src;
+   struct v4l2_rect compose;
+   struct v4l2_format f;
+   int ret;
+
+   fmt_src.pad = priv->src_sd_pad;
+  

Re: [PATCH v2 4/8] Revert "media: imx: Set capture compose rectangle in capture_device_set_format"

2019-04-30 Thread Steve Longerbeam
Yes, because the reverted commit was merged before the imx7 support, I 
will fix this for v3.


Steve


On 4/30/19 3:00 PM, Rui Miguel Silva wrote:

Hi Steve,
On Sun 28 Apr 2019 at 20:09, Steve Longerbeam wrote:

Rvert this commit, as imx_media_capture_device_set_format() will be
removed.

This reverts commit 5964cbd8692252615370b77eb96764dd70c2f837.

Signed-off-by: Steve Longerbeam 
---
  drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 ++--
  drivers/staging/media/imx/imx-media-capture.c | 24 +--
  drivers/staging/media/imx/imx-media-csi.c |  5 ++--
  drivers/staging/media/imx/imx-media-utils.c   | 20 
  drivers/staging/media/imx/imx-media.h |  6 ++---
  5 files changed, 23 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 8242d88dfb82..afaa3a8b15e9 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -910,7 +910,6 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
-   struct v4l2_rect vdev_compose;
int ret = 0;
  
  	if (sdformat->pad >= PRPENCVF_NUM_PADS)

@@ -952,11 +951,11 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[sdformat->pad] = cc;
  
  	/* propagate output pad format to capture device */

-   imx_media_mbus_fmt_to_pix_fmt(_fmt, _compose,
+   imx_media_mbus_fmt_to_pix_fmt(_fmt,
  >format_mbus[PRPENCVF_SRC_PAD],
  priv->cc[PRPENCVF_SRC_PAD]);
mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt, _compose);
+   imx_media_capture_device_set_format(vdev, _fmt);
  
  	return 0;

  out:
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 335084a6b0cd..555f6204660b 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,8 +205,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
  
  static int __capture_try_fmt_vid_cap(struct capture_priv *priv,

 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f,
-struct v4l2_rect *compose)
+struct v4l2_format *f)
  {
const struct imx_media_pixfmt *cc, *cc_src;
  
@@ -246,8 +245,7 @@ static int __capture_try_fmt_vid_cap(struct capture_priv *priv,

}
}
  
-	imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, compose,

- _src->format, cc);
+   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
  
  	return 0;

  }
@@ -265,7 +263,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
  
-	return __capture_try_fmt_vid_cap(priv, _src, f, NULL);

+   return __capture_try_fmt_vid_cap(priv, _src, f);
  }
  
  static int capture_s_fmt_vid_cap(struct file *file, void *fh,

@@ -273,7 +271,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
  {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
-   struct v4l2_rect compose;
int ret;
  
  	if (vb2_is_busy(>q)) {

@@ -287,14 +284,17 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
  
-	ret = __capture_try_fmt_vid_cap(priv, _src, f, );

+   ret = __capture_try_fmt_vid_cap(priv, _src, f);
if (ret)
return ret;
  
  	priv->vdev.fmt.fmt.pix = f->fmt.pix;

priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose = compose;
+   priv->vdev.compose.left = 0;
+   priv->vdev.compose.top = 0;
+   priv->vdev.compose.width = fmt_src.format.width;
+   priv->vdev.compose.height = fmt_src.format.height;
  
  	return 0;

  }
@@ -655,8 +655,7 @@ static struct video_device capture_videodev = {
  };
  
  void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,

-const struct v4l2_pix_format *pix,
-const struct v4l2_rect *compose)
+struct v4l2_pix_format *pix)
  {
struct capture_priv *priv = to_capture_priv(vdev);
  
@@ -664,7 +663,6 @@ void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,

priv->vdev.fmt.fmt.pix = *pix;
priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SEL_ANY,
  t

Re: [PATCH v2 1/8] media: staging/imx: Switch to sync registration for IPU subdevs

2019-04-30 Thread Steve Longerbeam

Thanks Rui for catching the bisect problem, I will fix for v3.

Steve


On 4/30/19 2:56 PM, Rui Miguel Silva wrote:

Hi Steve,
On Sun 28 Apr 2019 at 20:09, Steve Longerbeam wrote:

Because the IPU sub-devices VDIC and IC are not present in the
device-tree, platform devices were created for them instead. This
allowed these sub-devices to be added to the media device's async
notifier and registered asynchronously along with the other
sub-devices that do have a device-tree presence (CSI and devices
external to the IPU and SoC).

But that approach isn't really necessary. The IPU sub-devices don't
actually require a backing device (sd->dev is allowed to be NULL).
And that approach can't get around the fact that the IPU sub-devices
are not part of a device hierarchy, which makes it awkward to retrieve
the parent IPU of these devices.

By registering them synchronously, they can be registered from the CSI
async bound notifier, so the init function for them can be given the CSI
subdev, who's dev->parent is the IPU. That is a somewhat cleaner way
to retrieve the parent IPU.

So convert to synchronous registration for the VDIC and IC task
sub-devices, at the time a CSI sub-device is bound. There is no longer
a backing device for them (sd->dev is NULL), but that's ok. Also
set the VDIC/IC sub-device owner as the IPU, so that a reference can
be taken on the IPU module.

Signed-off-by: Steve Longerbeam 

I am trying to bisect when my capture starts to fail to work with
this series, since they are so many changes and reorg that I got
lost on some of them. But... see below.


---
  drivers/staging/media/imx/imx-ic-common.c |  70 ++--
  drivers/staging/media/imx/imx-ic-prp.c|  34 +-
  drivers/staging/media/imx/imx-ic-prpencvf.c   |  70 ++--
  drivers/staging/media/imx/imx-ic.h|   7 +-
  drivers/staging/media/imx/imx-media-capture.c |   7 +-
  drivers/staging/media/imx/imx-media-csi.c |   2 +-
  drivers/staging/media/imx/imx-media-dev.c | 121 +-
  .../staging/media/imx/imx-media-internal-sd.c | 356 --
  drivers/staging/media/imx/imx-media-of.c  |  38 +-
  drivers/staging/media/imx/imx-media-vdic.c|  85 ++---
  drivers/staging/media/imx/imx-media.h |  67 ++--
  drivers/staging/media/imx/imx7-media-csi.c|   3 +-
  12 files changed, 325 insertions(+), 535 deletions(-)

+   dev_dbg(priv->ipu_dev, "%s: link setup %s -> %s",




+   sd->name, remote->entity->name, local->entity->name);
  
  	mutex_lock(>lock);
  
@@ -864,9 +856,6 @@ static int vdic_registered(struct v4l2_subdev *sd)

int i, ret;
u32 code;
  
-	/* get media device */

-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
-
for (i = 0; i < VDIC_NUM_PADS; i++) {
priv->pad[i].flags = (i == VDIC_SRC_PAD_DIRECT) ?
MEDIA_PAD_FL_SOURCE : MEDIA_PAD_FL_SINK;
@@ -938,77 +927,55 @@ static const struct v4l2_subdev_internal_ops 
vdic_internal_ops = {
.unregistered = vdic_unregistered,
  };
  
-static int imx_vdic_probe(struct platform_device *pdev)

+struct v4l2_subdev *imx_media_vdic_register(struct imx_media_dev *imxmd,
+   struct device *ipu_dev,
+   struct ipu_soc *ipu,
+   u32 grp_id)
  {
-   struct imx_media_ipu_internal_sd_pdata *pdata;
+   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct vdic_priv *priv;
int ret;
  
-	priv = devm_kzalloc(>dev, sizeof(*priv), GFP_KERNEL);

+   priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
  
-	platform_set_drvdata(pdev, >sd);

-   priv->dev = >dev;
-
-   pdata = priv->dev->platform_data;
-   priv->ipu_id = pdata->ipu_id;
+   priv->ipu_dev = ipu_dev;
+   priv->ipu = ipu;
+   priv->md = imxmd;
  
  	v4l2_subdev_init(>sd, _subdev_ops);

v4l2_set_subdevdata(>sd, priv);
priv->sd.internal_ops = _internal_ops;
priv->sd.entity.ops = _entity_ops;
priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER;
-   priv->sd.dev = >dev;
-   priv->sd.owner = THIS_MODULE;
+   priv->sd.owner = ipu_dev->driver->owner;
priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE;
-   /* get our group id */
-   priv->sd.grp_id = pdata->grp_id;
-   strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
+   priv->sd.grp_id = grp_id;
+   imx_media_grp_id_to_sd_name(priv->sd.name, sizeof(priv->sd.name),
+   priv->sd.grp_id, ipu_get_num(ipu));
  
  	mutex_init(>lock);
  
-	ret = v4l2_async_register_subdev(>sd);

+   ret = v4l2_device_register_subdev(v4l2_dev, >sd)

[PATCH v2 8/8] media: staging/imx: Don't set driver data for v4l2_dev

2019-04-28 Thread Steve Longerbeam
The media device is already available via multiple methods, there is no
need to set driver data for v4l2_dev to the media device.

In imx_media_link_notify(), get media device from link->graph_obj.mdev.

In imx_media_capture_device_register(), get media device from
v4l2_dev->mdev.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-media-capture.c| 5 +++--
 drivers/staging/media/imx/imx-media-dev-common.c | 7 ++-
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index b77a67bda47c..565d21f169d8 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -732,15 +732,16 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
+   struct v4l2_device *v4l2_dev = sd->v4l2_dev;
struct video_device *vfd = vdev->vfd;
struct vb2_queue *vq = >q;
struct v4l2_subdev_format fmt_src;
int ret;
 
/* get media device */
-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+   priv->md = container_of(v4l2_dev->mdev, struct imx_media_dev, md);
 
-   vfd->v4l2_dev = sd->v4l2_dev;
+   vfd->v4l2_dev = v4l2_dev;
 
ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
if (ret) {
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 89dc4ec8dadb..66b505f7e8df 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -260,10 +260,11 @@ static int imx_media_inherit_controls(struct 
imx_media_dev *imxmd,
 static int imx_media_link_notify(struct media_link *link, u32 flags,
 unsigned int notification)
 {
+   struct imx_media_dev *imxmd = container_of(link->graph_obj.mdev,
+  struct imx_media_dev, md);
struct media_entity *source = link->source->entity;
struct imx_media_pad_vdev *pad_vdev;
struct list_head *pad_vdev_list;
-   struct imx_media_dev *imxmd;
struct video_device *vfd;
struct v4l2_subdev *sd;
int pad_idx, ret;
@@ -279,8 +280,6 @@ static int imx_media_link_notify(struct media_link *link, 
u32 flags,
sd = media_entity_to_v4l2_subdev(source);
pad_idx = link->source->index;
 
-   imxmd = dev_get_drvdata(sd->v4l2_dev->dev);
-
pad_vdev_list = to_pad_vdev_list(sd, pad_idx);
if (!pad_vdev_list) {
/* nothing to do if source sd has no pad vdev list */
@@ -384,8 +383,6 @@ struct imx_media_dev *imx_media_dev_init(struct device *dev,
goto cleanup;
}
 
-   dev_set_drvdata(imxmd->v4l2_dev.dev, imxmd);
-
INIT_LIST_HEAD(>vdev_list);
 
v4l2_async_notifier_init(>notifier);
-- 
2.17.1

___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH v2 5/8] media: staging/imx: Remove capture_device_set_format

2019-04-28 Thread Steve Longerbeam
Don't propagate the source pad format to the connected capture device.
It's now the responsibility of userspace to call VIDIOC_S_FMT on the
capture device to ensure the capture format and compose rectangle
are compatible with the connected source. To check this, validate
the capture format with the source before streaming starts.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   | 16 +
 drivers/staging/media/imx/imx-media-capture.c | 64 +--
 drivers/staging/media/imx/imx-media-csi.c | 16 +
 drivers/staging/media/imx/imx-media.h |  2 -
 drivers/staging/media/imx/imx7-media-csi.c| 18 +-
 5 files changed, 50 insertions(+), 66 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index afaa3a8b15e9..63334fd61492 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -906,9 +906,7 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
   struct v4l2_subdev_format *sdformat)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_media_video_dev *vdev = priv->vdev;
const struct imx_media_pixfmt *cc;
-   struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
 
@@ -945,19 +943,9 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[PRPENCVF_SRC_PAD] = outcc;
}
 
-   if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY)
-   goto out;
-
-   priv->cc[sdformat->pad] = cc;
+   if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+   priv->cc[sdformat->pad] = cc;
 
-   /* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt,
- >format_mbus[PRPENCVF_SRC_PAD],
- priv->cc[PRPENCVF_SRC_PAD]);
-   mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt);
-
-   return 0;
 out:
mutex_unlock(>lock);
return ret;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 555f6204660b..b77a67bda47c 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,7 +205,8 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f)
+struct v4l2_format *f,
+struct v4l2_rect *compose)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -247,6 +248,13 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
 
imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
+   if (compose) {
+   compose->left = 0;
+   compose->top = 0;
+   compose->width = fmt_src->format.width;
+   compose->height = fmt_src->format.height;
+   }
+
return 0;
 }
 
@@ -263,7 +271,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f);
+   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -271,6 +279,7 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
+   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -284,17 +293,14 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f);
+   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose.left = 0;
-   priv->vdev.compose.top = 0;
-   priv->vdev.compose.width = fmt_src.format.width;
-   priv->vdev.compose.height = fmt_src.format.height;
+   priv->vdev.compose = compose;
 
return 0;
 }
@@ -524,6 +530,33 @@ static void capture_buf_queue(struct vb2_buffer *vb)
spin_unlock_irqrestore(>q_lock, flags);
 }
 
+static int capture_validate_fmt(struct capture_priv *priv)
+{
+   struct v4l2_subdev_format fmt_src;
+   struct v4l2_rect compose;
+   struct v4l2_format f;
+   int ret;
+
+   fmt_src.pad = priv->src_sd_pad

[PATCH v2 7/8] media: staging/imx: Improve pipeline searching

2019-04-28 Thread Steve Longerbeam
Export find_pipeline_pad(), renaming to imx_media_pipeline_pad(), and
extend its functionality to allow searching for video devices in the
enabled pipeline in addition to sub-devices.

As part of this:

- Rename imx_media_find_mipi_csi2_channel() to
  imx_media_pipeline_csi2_channel().

- Remove imx_media_find_upstream_pad(), it is redundant now.

- Rename imx_media_find_upstream_subdev() to imx_media_pipeline_subdev()
  with an additional boolean argument for searching upstream or downstream.

- Add imx_media_pipeline_video_device() which is analogous to
  imx_media_pipeline_subdev() but searches for video devices.

- Remove imxmd pointer arg from all of the functions above, it was
  never used in those functions. With that change the i.MX5/6 CSI,
  VDIC, and IC sub-devices no longer require the media_device.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-common.c |   4 +-
 drivers/staging/media/imx/imx-ic-prp.c|   4 +-
 drivers/staging/media/imx/imx-ic.h|   1 -
 drivers/staging/media/imx/imx-media-csi.c |  13 +-
 drivers/staging/media/imx/imx-media-fim.c |   4 -
 .../staging/media/imx/imx-media-internal-sd.c |   5 +-
 drivers/staging/media/imx/imx-media-utils.c   | 128 ++
 drivers/staging/media/imx/imx-media-vdic.c|   5 +-
 drivers/staging/media/imx/imx-media.h |  20 +--
 drivers/staging/media/imx/imx7-media-csi.c|   2 +-
 10 files changed, 93 insertions(+), 93 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index ad0c291db03c..37734984beb4 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -22,12 +22,11 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+struct v4l2_subdev *imx_media_ic_register(struct v4l2_device *v4l2_dev,
  struct device *ipu_dev,
  struct ipu_soc *ipu,
  u32 grp_id)
 {
-   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
@@ -37,7 +36,6 @@ struct v4l2_subdev *imx_media_ic_register(struct 
imx_media_dev *imxmd,
 
priv->ipu_dev = ipu_dev;
priv->ipu = ipu;
-   priv->md = imxmd;
 
/* get our IC task id */
switch (grp_id) {
diff --git a/drivers/staging/media/imx/imx-ic-prp.c 
b/drivers/staging/media/imx/imx-ic-prp.c
index 663db200e594..1432776a33f9 100644
--- a/drivers/staging/media/imx/imx-ic-prp.c
+++ b/drivers/staging/media/imx/imx-ic-prp.c
@@ -302,8 +302,8 @@ static int prp_link_validate(struct v4l2_subdev *sd,
if (ret)
return ret;
 
-   csi = imx_media_find_upstream_subdev(ic_priv->md, _priv->sd.entity,
-IMX_MEDIA_GRP_ID_IPU_CSI);
+   csi = imx_media_pipeline_subdev(_priv->sd.entity,
+   IMX_MEDIA_GRP_ID_IPU_CSI, true);
if (IS_ERR(csi))
csi = NULL;
 
diff --git a/drivers/staging/media/imx/imx-ic.h 
b/drivers/staging/media/imx/imx-ic.h
index 1dcbb37aeada..ff2f66f11982 100644
--- a/drivers/staging/media/imx/imx-ic.h
+++ b/drivers/staging/media/imx/imx-ic.h
@@ -16,7 +16,6 @@
 struct imx_ic_priv {
struct device *ipu_dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
inttask_id;
void   *task_priv;
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 68c2b1a3066a..555904759078 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -60,7 +60,6 @@ struct csi_skip_desc {
 struct csi_priv {
struct device *dev;
struct ipu_soc *ipu;
-   struct imx_media_dev *md;
struct v4l2_subdev sd;
struct media_pad pad[CSI_NUM_PADS];
/* the video device at IDMAC output pad */
@@ -182,8 +181,8 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
 * CSI-2 receiver if it is in the path, otherwise stay
 * with video mux.
 */
-   sd = imx_media_find_upstream_subdev(priv->md, src,
-   IMX_MEDIA_GRP_ID_CSI2);
+   sd = imx_media_pipeline_subdev(src, IMX_MEDIA_GRP_ID_CSI2,
+  true);
if (!IS_ERR(sd))
src = >entity;
}
@@ -197,7 +196,7 @@ static int csi_get_upstream_endpoint(struct csi_priv *priv,
src = >sd.entity;
 
/* get source pad of entity directly upstream from src */
-   pad = imx_media_find_upstream_pad(priv->md, src, 0);
+   pad = imx_m

[PATCH v2 4/8] Revert "media: imx: Set capture compose rectangle in capture_device_set_format"

2019-04-28 Thread Steve Longerbeam
Rvert this commit, as imx_media_capture_device_set_format() will be
removed.

This reverts commit 5964cbd8692252615370b77eb96764dd70c2f837.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 ++--
 drivers/staging/media/imx/imx-media-capture.c | 24 +--
 drivers/staging/media/imx/imx-media-csi.c |  5 ++--
 drivers/staging/media/imx/imx-media-utils.c   | 20 
 drivers/staging/media/imx/imx-media.h |  6 ++---
 5 files changed, 23 insertions(+), 37 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 8242d88dfb82..afaa3a8b15e9 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -910,7 +910,6 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
const struct imx_media_pixfmt *cc;
struct v4l2_pix_format vdev_fmt;
struct v4l2_mbus_framefmt *fmt;
-   struct v4l2_rect vdev_compose;
int ret = 0;
 
if (sdformat->pad >= PRPENCVF_NUM_PADS)
@@ -952,11 +951,11 @@ static int prp_set_fmt(struct v4l2_subdev *sd,
priv->cc[sdformat->pad] = cc;
 
/* propagate output pad format to capture device */
-   imx_media_mbus_fmt_to_pix_fmt(_fmt, _compose,
+   imx_media_mbus_fmt_to_pix_fmt(_fmt,
  >format_mbus[PRPENCVF_SRC_PAD],
  priv->cc[PRPENCVF_SRC_PAD]);
mutex_unlock(>lock);
-   imx_media_capture_device_set_format(vdev, _fmt, _compose);
+   imx_media_capture_device_set_format(vdev, _fmt);
 
return 0;
 out:
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 335084a6b0cd..555f6204660b 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -205,8 +205,7 @@ static int capture_g_fmt_vid_cap(struct file *file, void 
*fh,
 
 static int __capture_try_fmt_vid_cap(struct capture_priv *priv,
 struct v4l2_subdev_format *fmt_src,
-struct v4l2_format *f,
-struct v4l2_rect *compose)
+struct v4l2_format *f)
 {
const struct imx_media_pixfmt *cc, *cc_src;
 
@@ -246,8 +245,7 @@ static int __capture_try_fmt_vid_cap(struct capture_priv 
*priv,
}
}
 
-   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, compose,
- _src->format, cc);
+   imx_media_mbus_fmt_to_pix_fmt(>fmt.pix, _src->format, cc);
 
return 0;
 }
@@ -265,7 +263,7 @@ static int capture_try_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   return __capture_try_fmt_vid_cap(priv, _src, f, NULL);
+   return __capture_try_fmt_vid_cap(priv, _src, f);
 }
 
 static int capture_s_fmt_vid_cap(struct file *file, void *fh,
@@ -273,7 +271,6 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
 {
struct capture_priv *priv = video_drvdata(file);
struct v4l2_subdev_format fmt_src;
-   struct v4l2_rect compose;
int ret;
 
if (vb2_is_busy(>q)) {
@@ -287,14 +284,17 @@ static int capture_s_fmt_vid_cap(struct file *file, void 
*fh,
if (ret)
return ret;
 
-   ret = __capture_try_fmt_vid_cap(priv, _src, f, );
+   ret = __capture_try_fmt_vid_cap(priv, _src, f);
if (ret)
return ret;
 
priv->vdev.fmt.fmt.pix = f->fmt.pix;
priv->vdev.cc = imx_media_find_format(f->fmt.pix.pixelformat,
  CS_SEL_ANY, true);
-   priv->vdev.compose = compose;
+   priv->vdev.compose.left = 0;
+   priv->vdev.compose.top = 0;
+   priv->vdev.compose.width = fmt_src.format.width;
+   priv->vdev.compose.height = fmt_src.format.height;
 
return 0;
 }
@@ -655,8 +655,7 @@ static struct video_device capture_videodev = {
 };
 
 void imx_media_capture_device_set_format(struct imx_media_video_dev *vdev,
-const struct v4l2_pix_format *pix,
-const struct v4l2_rect *compose)
+struct v4l2_pix_format *pix)
 {
struct capture_priv *priv = to_capture_priv(vdev);
 
@@ -664,7 +663,6 @@ void imx_media_capture_device_set_format(struct 
imx_media_video_dev *vdev,
priv->vdev.fmt.fmt.pix = *pix;
priv->vdev.cc = imx_media_find_format(pix->pixelformat, CS_SEL_ANY,
  true);
-   priv->vdev.compose = *compose;
mutex_unlock(>mutex);
 }
 EXPORT_SYMBOL_GPL(imx_media_capture_device_set_format);
@@ -770,8 +768,10 @@ int imx_media_capture_device_

[PATCH v2 2/8] media: staging/imx: Pass device to alloc/free_dma_buf

2019-04-28 Thread Steve Longerbeam
Allocate and free a DMA coherent buffer in imx_media_alloc/free_dma_buf()
from the given device. This allows DMA alloc and free using a device
that is backed by real hardware, which for the imx5/6/7 CSI is the CSI
unit, and for the internal IPU sub-devices, is the parent IPU.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c | 18 +-
 drivers/staging/media/imx/imx-media-csi.c   |  6 +++---
 drivers/staging/media/imx/imx-media-utils.c | 13 ++---
 drivers/staging/media/imx/imx-media.h   |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c  |  4 ++--
 5 files changed, 22 insertions(+), 23 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 069cce512280..ddcd87a17c71 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -464,13 +464,13 @@ static int prp_setup_rotation(struct prp_priv *priv)
incc = priv->cc[PRPENCVF_SINK_PAD];
outcc = vdev->cc;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[0],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[0],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[0], %d\n", ret);
return ret;
}
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >rot_buf[1],
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >rot_buf[1],
  outfmt->sizeimage);
if (ret) {
v4l2_err(_priv->sd, "failed to alloc rot_buf[1], %d\n", ret);
@@ -543,9 +543,9 @@ static int prp_setup_rotation(struct prp_priv *priv)
 unsetup_vb2:
prp_unsetup_vb2_buf(priv, VB2_BUF_STATE_QUEUED);
 free_rot1:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 free_rot0:
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
return ret;
 }
 
@@ -563,8 +563,8 @@ static void prp_unsetup_rotation(struct prp_priv *priv)
 
ipu_ic_disable(priv->ic);
 
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[0]);
-   imx_media_free_dma_buf(ic_priv->md, >rot_buf[1]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[0]);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >rot_buf[1]);
 }
 
 static int prp_setup_norotation(struct prp_priv *priv)
@@ -656,7 +656,7 @@ static int prp_start(struct prp_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(ic_priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(ic_priv->ipu_dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -726,7 +726,7 @@ static int prp_start(struct prp_priv *priv)
 out_unsetup:
prp_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_underrun:
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 out_put_ipu:
prp_put_ipu_resources(priv);
return ret;
@@ -763,7 +763,7 @@ static void prp_stop(struct prp_priv *priv)
 
prp_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(ic_priv->md, >underrun_buf);
+   imx_media_free_dma_buf(ic_priv->ipu_dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeout_timer);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index 93b107eab5f5..ea3d13103c91 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -612,7 +612,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 
outfmt = >fmt.fmt.pix;
 
-   ret = imx_media_alloc_dma_buf(priv->md, >underrun_buf,
+   ret = imx_media_alloc_dma_buf(priv->dev, >underrun_buf,
  outfmt->sizeimage);
if (ret)
goto out_put_ipu;
@@ -666,7 +666,7 @@ static int csi_idmac_start(struct csi_priv *priv)
 out_unsetup:
csi_idmac_unsetup(priv, VB2_BUF_STATE_QUEUED);
 out_free_dma_buf:
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 out_put_ipu:
csi_idmac_put_ipu_resources(priv);
return ret;
@@ -698,7 +698,7 @@ static void csi_idmac_stop(struct csi_priv *priv)
 
csi_idmac_unsetup(priv, VB2_BUF_STATE_ERROR);
 
-   imx_media_free_dma_buf(priv->md, >underrun_buf);
+   imx_media_free_dma_buf(priv->dev, >underrun_buf);
 
/* cancel the EOF timeout timer */
del_timer_sync(>eof_timeou

[PATCH v2 1/8] media: staging/imx: Switch to sync registration for IPU subdevs

2019-04-28 Thread Steve Longerbeam
Because the IPU sub-devices VDIC and IC are not present in the
device-tree, platform devices were created for them instead. This
allowed these sub-devices to be added to the media device's async
notifier and registered asynchronously along with the other
sub-devices that do have a device-tree presence (CSI and devices
external to the IPU and SoC).

But that approach isn't really necessary. The IPU sub-devices don't
actually require a backing device (sd->dev is allowed to be NULL).
And that approach can't get around the fact that the IPU sub-devices
are not part of a device hierarchy, which makes it awkward to retrieve
the parent IPU of these devices.

By registering them synchronously, they can be registered from the CSI
async bound notifier, so the init function for them can be given the CSI
subdev, who's dev->parent is the IPU. That is a somewhat cleaner way
to retrieve the parent IPU.

So convert to synchronous registration for the VDIC and IC task
sub-devices, at the time a CSI sub-device is bound. There is no longer
a backing device for them (sd->dev is NULL), but that's ok. Also
set the VDIC/IC sub-device owner as the IPU, so that a reference can
be taken on the IPU module.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-common.c |  70 ++--
 drivers/staging/media/imx/imx-ic-prp.c|  34 +-
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  70 ++--
 drivers/staging/media/imx/imx-ic.h|   7 +-
 drivers/staging/media/imx/imx-media-capture.c |   7 +-
 drivers/staging/media/imx/imx-media-csi.c |   2 +-
 drivers/staging/media/imx/imx-media-dev.c | 121 +-
 .../staging/media/imx/imx-media-internal-sd.c | 356 --
 drivers/staging/media/imx/imx-media-of.c  |  38 +-
 drivers/staging/media/imx/imx-media-vdic.c|  85 ++---
 drivers/staging/media/imx/imx-media.h |  67 ++--
 drivers/staging/media/imx/imx7-media-csi.c|   3 +-
 12 files changed, 325 insertions(+), 535 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-common.c 
b/drivers/staging/media/imx/imx-ic-common.c
index 1addb0893c57..ad0c291db03c 100644
--- a/drivers/staging/media/imx/imx-ic-common.c
+++ b/drivers/staging/media/imx/imx-ic-common.c
@@ -8,8 +8,6 @@
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
  */
-#include 
-#include 
 #include 
 #include 
 #include "imx-media.h"
@@ -24,23 +22,25 @@ static struct imx_ic_ops *ic_ops[IC_NUM_OPS] = {
[IC_TASK_VIEWFINDER] = _ic_prpencvf_ops,
 };
 
-static int imx_ic_probe(struct platform_device *pdev)
+struct v4l2_subdev *imx_media_ic_register(struct imx_media_dev *imxmd,
+ struct device *ipu_dev,
+ struct ipu_soc *ipu,
+ u32 grp_id)
 {
-   struct imx_media_ipu_internal_sd_pdata *pdata;
+   struct v4l2_device *v4l2_dev = >v4l2_dev;
struct imx_ic_priv *priv;
int ret;
 
-   priv = devm_kzalloc(>dev, sizeof(*priv), GFP_KERNEL);
+   priv = devm_kzalloc(ipu_dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
-   return -ENOMEM;
+   return ERR_PTR(-ENOMEM);
 
-   platform_set_drvdata(pdev, >sd);
-   priv->dev = >dev;
+   priv->ipu_dev = ipu_dev;
+   priv->ipu = ipu;
+   priv->md = imxmd;
 
-   /* get our ipu_id, grp_id and IC task id */
-   pdata = priv->dev->platform_data;
-   priv->ipu_id = pdata->ipu_id;
-   switch (pdata->grp_id) {
+   /* get our IC task id */
+   switch (grp_id) {
case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
priv->task_id = IC_TASK_PRP;
break;
@@ -51,7 +51,7 @@ static int imx_ic_probe(struct platform_device *pdev)
priv->task_id = IC_TASK_VIEWFINDER;
break;
default:
-   return -EINVAL;
+   return ERR_PTR(-EINVAL);
}
 
v4l2_subdev_init(>sd, ic_ops[priv->task_id]->subdev_ops);
@@ -59,55 +59,35 @@ static int imx_ic_probe(struct platform_device *pdev)
priv->sd.internal_ops = ic_ops[priv->task_id]->internal_ops;
priv->sd.entity.ops = ic_ops[priv->task_id]->entity_ops;
priv->sd.entity.function = MEDIA_ENT_F_PROC_VIDEO_SCALER;
-   priv->sd.dev = >dev;
-   priv->sd.owner = THIS_MODULE;
+   priv->sd.owner = ipu_dev->driver->owner;
priv->sd.flags = V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_HAS_EVENTS;
-   priv->sd.grp_id = pdata->grp_id;
-   strscpy(priv->sd.name, pdata->sd_name, sizeof(priv->sd.name));
+   priv->sd.grp_id = grp_id;
+   imx_media_grp_id_to_sd_name(priv->sd.name, sizeof(priv->sd.name),
+   priv->sd.grp_id, ipu_get_num(ipu));
 
ret = ic_ops[priv->task_

[PATCH v2 6/8] media: staging/imx: Re-organize modules

2019-04-28 Thread Steve Longerbeam
Re-organize modules, and which objects are linked into those modules, so
that:

- imx6-media (renamed from imx-media) is the media driver module for
  imx5/6 only, and has no symbol exports. The IPU internal subdevice
  objects now link directly with imx6-media.

- imx6-media-csi (renamed from imx-media-csi) is the subdev driver
  module for imx5/6 CSI. It is now linked direcly with imx-media-fim,
  since only the imx5/6 CSI makes use of the frame interval monitor.

- imx-media-common now only contains common code between imx5/6 and imx7
  media drivers. It contains imx-media-utils, imx-media-of,
  imx-media-dev-common, and imx-media-capture. In order to acheive that,
  some functions common to imx5/6 and imx7 have been moved out of
  imx-media-dev.c and into imx-media-dev-common.c.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/Makefile|  18 +-
 .../staging/media/imx/imx-media-dev-common.c  | 345 +-
 drivers/staging/media/imx/imx-media-dev.c | 340 +
 drivers/staging/media/imx/imx-media-fim.c |   5 -
 drivers/staging/media/imx/imx-media-of.c  |   3 +
 drivers/staging/media/imx/imx-media.h |  16 +-
 drivers/staging/media/imx/imx7-media-csi.c|   4 +-
 7 files changed, 370 insertions(+), 361 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index d2d909a36239..aa6c4b4ad37e 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,16 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
-imx-media-objs += imx-media-dev-common.o
-imx-media-common-objs := imx-media-utils.o imx-media-fim.o
-imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
+imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
+   imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
 
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
+imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
+   imx-media-of.o imx-media-utils.o
+
+imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
+
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
-obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
+obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 6cd93419b81d..89dc4ec8dadb 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -8,9 +8,342 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "imx-media.h"
 
-static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx_media_dev, notifier);
+}
+
+/* async subdev bound notifier */
+static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+
+   return 0;
+}
+
+/*
+ * Create the media links for all subdevs that registered.
+ * Called after all async subdevs have bound.
+ */
+static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+{
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+   struct v4l2_subdev *sd;
+
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   switch (sd->grp_id) {
+   case IMX_MEDIA_GRP_ID_IPU_VDIC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
+   /*
+* links have already been created for the
+* sync-registered subdevs.
+*/
+   break;
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
+   case IMX_MEDIA_GRP_ID_CSI:
+   imx_media_create_csi_of_links(imxmd, sd);
+   break;
+   default:
+   /*
+* if this subdev has fwnode links, create media
+* links for them.
+*/
+   imx_media_create_of_links(imxmd, sd);
+   break;
+   }
+   }
+
+   return 0;
+}
+
+/*
+ * adds given video device to give

[PATCH v2 3/8] media: staging/imx: Move add_video_device into capture_device_register

2019-04-28 Thread Steve Longerbeam
Move imx_media_add_video_device() into imx_media_capture_device_register().
Also the former has no error conditions to convert to void.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/imx-ic-prpencvf.c   |  5 -
 drivers/staging/media/imx/imx-media-capture.c |  3 +++
 drivers/staging/media/imx/imx-media-csi.c |  7 +--
 drivers/staging/media/imx/imx-media-utils.c   |  9 -
 drivers/staging/media/imx/imx-media.h |  4 ++--
 drivers/staging/media/imx/imx7-media-csi.c| 12 +---
 6 files changed, 11 insertions(+), 29 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index ddcd87a17c71..8242d88dfb82 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1241,7 +1241,6 @@ static int prp_s_frame_interval(struct v4l2_subdev *sd,
 static int prp_registered(struct v4l2_subdev *sd)
 {
struct prp_priv *priv = sd_to_priv(sd);
-   struct imx_ic_priv *ic_priv = priv->ic_priv;
int i, ret;
u32 code;
 
@@ -1271,10 +1270,6 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
 
-   ret = imx_media_add_video_device(ic_priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
ret = prp_init_controls(priv);
if (ret)
goto unreg;
diff --git a/drivers/staging/media/imx/imx-media-capture.c 
b/drivers/staging/media/imx/imx-media-capture.c
index 211ec4df2066..335084a6b0cd 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -780,6 +780,9 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
 
vfd->ctrl_handler = >ctrl_hdlr;
 
+   /* add vdev to the video device list */
+   imx_media_add_video_device(priv->md, vdev);
+
return 0;
 unreg:
video_unregister_device(vfd);
diff --git a/drivers/staging/media/imx/imx-media-csi.c 
b/drivers/staging/media/imx/imx-media-csi.c
index ea3d13103c91..c70fa6b509ae 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1820,13 +1820,8 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
 
-   ret = imx_media_add_video_device(priv->md, priv->vdev);
-   if (ret)
-   goto unreg;
-
return 0;
-unreg:
-   imx_media_capture_device_unregister(priv->vdev);
+
 free_fim:
if (priv->fim)
imx_media_fim_free(priv->fim);
diff --git a/drivers/staging/media/imx/imx-media-utils.c 
b/drivers/staging/media/imx/imx-media-utils.c
index c52aa59acd05..8a6e57652402 100644
--- a/drivers/staging/media/imx/imx-media-utils.c
+++ b/drivers/staging/media/imx/imx-media-utils.c
@@ -767,18 +767,17 @@ imx_media_find_subdev_by_devname(struct imx_media_dev 
*imxmd,
 EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname);
 
 /*
- * Adds a video device to the master video device list. This is called by
- * an async subdev that owns a video device when it is registered.
+ * Adds a video device to the master video device list. This is called
+ * when a video device is registered.
  */
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev)
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev)
 {
mutex_lock(>mutex);
 
list_add_tail(>list, >vdev_list);
 
mutex_unlock(>mutex);
-   return 0;
 }
 EXPORT_SYMBOL_GPL(imx_media_add_video_device);
 
diff --git a/drivers/staging/media/imx/imx-media.h 
b/drivers/staging/media/imx/imx-media.h
index ba2d75bcc4c9..71e20f53ed7b 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -189,8 +189,8 @@ imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd,
 struct v4l2_subdev *
 imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd,
 const char *devname);
-int imx_media_add_video_device(struct imx_media_dev *imxmd,
-  struct imx_media_video_dev *vdev);
+void imx_media_add_video_device(struct imx_media_dev *imxmd,
+   struct imx_media_video_dev *vdev);
 int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd,
 struct media_entity *start_entity);
 struct media_pad *
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 96d01d8af874..f2037aba6e0e 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1126,17 +1126,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
 
-   ret = imx_media_capture

Re: [PATCH] media: staging/imx: add media device to capture register

2019-04-28 Thread Steve Longerbeam

Hi Rui,

On second thought, there is no reason to pass the media device to 
imx_media_capture_device_register(), because it is already available via 
v4l2_dev->mdev. I will be posting a patch in v2 of the "Switch to sync 
registration for IPU subdevs" series that fixes this.


Steve


On 4/12/19 9:44 AM, Rui Miguel Silva wrote:

When register the capture media device it is assumed that the device
data is the media device. In the imx6 case is but in the imx7 is not
case. The device data is the csi structure.

Add the explicit argument of the media device that we want to
associate with the capture device.

Reported-by: Laurent Pinchart 
Signed-off-by: Rui Miguel Silva 
---
  drivers/staging/media/imx/imx-ic-prpencvf.c   | 2 +-
  drivers/staging/media/imx/imx-media-capture.c | 6 +++---
  drivers/staging/media/imx/imx-media-csi.c | 2 +-
  drivers/staging/media/imx/imx-media.h | 3 ++-
  drivers/staging/media/imx/imx7-media-csi.c| 2 +-
  5 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/media/imx/imx-ic-prpencvf.c 
b/drivers/staging/media/imx/imx-ic-prpencvf.c
index 5c8e6ad8c025..3ca1422f6154 100644
--- a/drivers/staging/media/imx/imx-ic-prpencvf.c
+++ b/drivers/staging/media/imx/imx-ic-prpencvf.c
@@ -1270,7 +1270,7 @@ static int prp_registered(struct v4l2_subdev *sd)
if (ret)
return ret;
  
-	ret = imx_media_capture_device_register(priv->vdev);

+   ret = imx_media_capture_device_register(priv->md, priv->vdev);
if (ret)
return ret;
  
diff --git a/drivers/staging/media/imx/imx-media-capture.c b/drivers/staging/media/imx/imx-media-capture.c

index 9703c85b19c4..7688238a3396 100644
--- a/drivers/staging/media/imx/imx-media-capture.c
+++ b/drivers/staging/media/imx/imx-media-capture.c
@@ -706,7 +706,8 @@ void imx_media_capture_device_error(struct 
imx_media_video_dev *vdev)
  }
  EXPORT_SYMBOL_GPL(imx_media_capture_device_error);
  
-int imx_media_capture_device_register(struct imx_media_video_dev *vdev)

+int imx_media_capture_device_register(struct imx_media_dev *md,
+ struct imx_media_video_dev *vdev)
  {
struct capture_priv *priv = to_capture_priv(vdev);
struct v4l2_subdev *sd = priv->src_sd;
@@ -715,8 +716,7 @@ int imx_media_capture_device_register(struct 
imx_media_video_dev *vdev)
struct v4l2_subdev_format fmt_src;
int ret;
  
-	/* get media device */

-   priv->md = dev_get_drvdata(sd->v4l2_dev->dev);
+   priv->md = md;
  
  	vfd->v4l2_dev = sd->v4l2_dev;
  
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c

index 3b7517348666..3408ec023d29 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -1806,7 +1806,7 @@ static int csi_registered(struct v4l2_subdev *sd)
if (ret)
goto free_fim;
  
-	ret = imx_media_capture_device_register(priv->vdev);

+   ret = imx_media_capture_device_register(priv->md, priv->vdev);
if (ret)
goto free_fim;
  
diff --git a/drivers/staging/media/imx/imx-media.h b/drivers/staging/media/imx/imx-media.h

index ae964c8d5be1..c3a8512bd10f 100644
--- a/drivers/staging/media/imx/imx-media.h
+++ b/drivers/staging/media/imx/imx-media.h
@@ -271,7 +271,8 @@ int imx_media_of_add_csi(struct imx_media_dev *imxmd,
  struct imx_media_video_dev *
  imx_media_capture_device_init(struct v4l2_subdev *src_sd, int pad);
  void imx_media_capture_device_remove(struct imx_media_video_dev *vdev);
-int imx_media_capture_device_register(struct imx_media_video_dev *vdev);
+int imx_media_capture_device_register(struct imx_media_dev *md,
+  struct imx_media_video_dev *vdev);
  void imx_media_capture_device_unregister(struct imx_media_video_dev *vdev);
  struct imx_media_buffer *
  imx_media_capture_device_next_buf(struct imx_media_video_dev *vdev);
diff --git a/drivers/staging/media/imx/imx7-media-csi.c 
b/drivers/staging/media/imx/imx7-media-csi.c
index 3fba7c27c0ec..a907c5feb3eb 100644
--- a/drivers/staging/media/imx/imx7-media-csi.c
+++ b/drivers/staging/media/imx/imx7-media-csi.c
@@ -1124,7 +1124,7 @@ static int imx7_csi_registered(struct v4l2_subdev *sd)
if (ret < 0)
return ret;
  
-	ret = imx_media_capture_device_register(csi->vdev);

+   ret = imx_media_capture_device_register(csi->imxmd, csi->vdev);
if (ret < 0)
return ret;
  


___
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel


[PATCH 6/6] media: staging/imx: Re-organize modules

2019-04-25 Thread Steve Longerbeam
Re-organize modules, and which objects are linked into those modules, so
that:

- imx6-media (renamed from imx-media) is the media driver module for
  imx5/6 only, and has no symbol exports. The IPU internal subdevice
  objects now link directly with imx6-media.

- imx6-media-csi (renamed from imx-media-csi) is the subdev driver
  module for imx5/6 CSI. It is now linked direcly with imx-media-fim,
  since only the imx5/6 CSI makes use of the frame interval monitor.

- imx-media-common now only contains common code between imx5/6 and imx7
  media drivers. It contains imx-media-utils, imx-media-of,
  imx-media-dev-common, and imx-media-capture. In order to acheive that,
  some functions common to imx5/6 and imx7 have been moved out of
  imx-media-dev.c and into imx-media-dev-common.c.

Signed-off-by: Steve Longerbeam 
---
 drivers/staging/media/imx/Makefile|  18 +-
 .../staging/media/imx/imx-media-dev-common.c  | 345 +-
 drivers/staging/media/imx/imx-media-dev.c | 340 +
 drivers/staging/media/imx/imx-media-fim.c |   5 -
 drivers/staging/media/imx/imx-media-of.c  |   3 +
 drivers/staging/media/imx/imx-media.h |  16 +-
 drivers/staging/media/imx/imx7-media-csi.c|   4 +-
 7 files changed, 370 insertions(+), 361 deletions(-)

diff --git a/drivers/staging/media/imx/Makefile 
b/drivers/staging/media/imx/Makefile
index d2d909a36239..aa6c4b4ad37e 100644
--- a/drivers/staging/media/imx/Makefile
+++ b/drivers/staging/media/imx/Makefile
@@ -1,16 +1,16 @@
 # SPDX-License-Identifier: GPL-2.0
-imx-media-objs := imx-media-dev.o imx-media-internal-sd.o imx-media-of.o
-imx-media-objs += imx-media-dev-common.o
-imx-media-common-objs := imx-media-utils.o imx-media-fim.o
-imx-media-ic-objs := imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o
+imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
+   imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o
 
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media.o
+imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
+   imx-media-of.o imx-media-utils.o
+
+imx6-media-csi-objs := imx-media-csi.o imx-media-fim.o
+
+obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx6-media.o
 obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-common.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-capture.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-vdic.o
-obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx-media-ic.o
 
-obj-$(CONFIG_VIDEO_IMX_CSI) += imx-media-csi.o
+obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-media-csi.o
 obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
 
 obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
diff --git a/drivers/staging/media/imx/imx-media-dev-common.c 
b/drivers/staging/media/imx/imx-media-dev-common.c
index 6cd93419b81d..89dc4ec8dadb 100644
--- a/drivers/staging/media/imx/imx-media-dev-common.c
+++ b/drivers/staging/media/imx/imx-media-dev-common.c
@@ -8,9 +8,342 @@
 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 #include "imx-media.h"
 
-static const struct v4l2_async_notifier_operations imx_media_subdev_ops = {
+static inline struct imx_media_dev *notifier2dev(struct v4l2_async_notifier *n)
+{
+   return container_of(n, struct imx_media_dev, notifier);
+}
+
+/* async subdev bound notifier */
+static int imx_media_subdev_bound(struct v4l2_async_notifier *notifier,
+ struct v4l2_subdev *sd,
+ struct v4l2_async_subdev *asd)
+{
+   v4l2_info(sd->v4l2_dev, "subdev %s bound\n", sd->name);
+
+   return 0;
+}
+
+/*
+ * Create the media links for all subdevs that registered.
+ * Called after all async subdevs have bound.
+ */
+static int imx_media_create_links(struct v4l2_async_notifier *notifier)
+{
+   struct imx_media_dev *imxmd = notifier2dev(notifier);
+   struct v4l2_subdev *sd;
+
+   list_for_each_entry(sd, >v4l2_dev.subdevs, list) {
+   switch (sd->grp_id) {
+   case IMX_MEDIA_GRP_ID_IPU_VDIC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRP:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPENC:
+   case IMX_MEDIA_GRP_ID_IPU_IC_PRPVF:
+   /*
+* links have already been created for the
+* sync-registered subdevs.
+*/
+   break;
+   case IMX_MEDIA_GRP_ID_IPU_CSI0:
+   case IMX_MEDIA_GRP_ID_IPU_CSI1:
+   case IMX_MEDIA_GRP_ID_CSI:
+   imx_media_create_csi_of_links(imxmd, sd);
+   break;
+   default:
+   /*
+* if this subdev has fwnode links, create media
+* links for them.
+*/
+   imx_media_create_of_links(imxmd, sd);
+   break;
+   }
+   }
+
+   return 0;
+}
+
+/*
+ * adds given video device to give

  1   2   3   4   5   6   7   8   >