From bf3cfaa712e5c396f5fe3b2b2a2ca5dd901de23d Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Thu, 14 Dec 2017 20:04:39 -0500 Subject: media: staging/imx: get CSI bus type from nearest upstream entity The imx-media driver currently supports a device tree graph of limited complexity. This patch is a first step in allowing imx-media to work with more general OF graphs. The CSI subdevice assumes the originating upstream subdevice (the "sensor") is connected directly to either the CSI mux or the MIPI CSI-2 receiver. But for more complex graphs, the sensor can be distant, with possible bridge entities in between. Thus the sensor's bus type could be quite different from what is entering the CSI. For example a distant sensor could have a parallel interface, but the stream entering the i.MX is MIPI CSI-2. To remove this assumption, get the entering bus config from the entity that is directly upstream from either the CSI mux, or the CSI-2 receiver. If the CSI-2 receiver is not in the enabled pipeline, the bus type to the CSI is parallel, otherwise the CSI is receiving MIPI CSI-2. Note that we can't use the direct upstream source connected to CSI (which is either the CSI mux or the CSI-2 receiver) to determine bus type. The bus entering the CSI from the CSI-2 receiver is a 32-bit parallel bus containing the demultiplexed MIPI CSI-2 virtual channels. But the CSI and its IDMAC channels must be configured based on whether it is receiving data from the CSI-2 receiver or from the CSI mux's parallel interface pins. The function csi_get_upstream_endpoint() is used to find this endpoint. It makes use of a new utility function imx_media_find_upstream_pad(), that if given a grp_id of 0, will return the closest upstream pad from start_entity. With these changes, imx_media_find_sensor() is no longer used and is removed. As a result there is also no longer a need to identify any sensor or set the sensor subdev's group id as a method to search for it. So IMX_MEDIA_GRP_ID_SENSOR is removed. Also the video-mux group id IMX_MEDIA_GRP_ID_VIDMUX was never used so that is removed as well. The remaining IMX_MEDIA_GRP_ID_* definitions are entities internal to the i.MX. Another use of imx_media_find_sensor() in the CSI was to call the sensor's g_skip_frames op to determine if a delay was needed before enabling the CSI at stream on. If necessary this will have to be re-addressed at a later time. Signed-off-by: Steve Longerbeam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-utils.c | 63 +++++++++++++++-------------- 1 file changed, 32 insertions(+), 31 deletions(-) (limited to 'drivers/staging/media/imx/imx-media-utils.c') diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 59523872a886..51d7e184e8d7 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -730,10 +730,11 @@ out: EXPORT_SYMBOL_GPL(imx_media_add_video_device); /* - * Search upstream or downstream for a subdevice in the current pipeline + * Search upstream/downstream for a subdevice in the current pipeline * with given grp_id, starting from start_entity. Returns the subdev's - * source/sink pad that it was reached from. Must be called with - * mdev->graph_mutex held. + * source/sink pad that it was reached from. If grp_id is zero, just + * returns the nearest source/sink pad to start_entity. Must be called + * with mdev->graph_mutex held. */ static struct media_pad * find_pipeline_pad(struct imx_media_dev *imxmd, @@ -756,11 +757,16 @@ find_pipeline_pad(struct imx_media_dev *imxmd, if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) continue; - sd = media_entity_to_v4l2_subdev(pad->entity); - if (sd->grp_id & grp_id) - return pad; + if (grp_id != 0) { + sd = media_entity_to_v4l2_subdev(pad->entity); + if (sd->grp_id & grp_id) + return pad; - return find_pipeline_pad(imxmd, pad->entity, grp_id, upstream); + return find_pipeline_pad(imxmd, pad->entity, + grp_id, upstream); + } else { + return pad; + } } return NULL; @@ -789,7 +795,6 @@ find_upstream_subdev(struct imx_media_dev *imxmd, return pad ? media_entity_to_v4l2_subdev(pad->entity) : NULL; } - /* * Find the upstream mipi-csi2 virtual channel reached from the given * start entity in the current pipeline. @@ -813,6 +818,25 @@ int imx_media_find_mipi_csi2_channel(struct imx_media_dev *imxmd, } EXPORT_SYMBOL_GPL(imx_media_find_mipi_csi2_channel); +/* + * Find a source pad reached upstream from the given start entity in + * the current pipeline. Must be called with mdev->graph_mutex held. + */ +struct media_pad * +imx_media_find_upstream_pad(struct imx_media_dev *imxmd, + struct media_entity *start_entity, + u32 grp_id) +{ + struct media_pad *pad; + + pad = find_pipeline_pad(imxmd, start_entity, grp_id, true); + if (!pad) + return ERR_PTR(-ENODEV); + + return pad; +} +EXPORT_SYMBOL_GPL(imx_media_find_upstream_pad); + /* * Find a subdev reached upstream from the given start entity in * the current pipeline. @@ -833,29 +857,6 @@ imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, } EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev); -struct imx_media_subdev * -__imx_media_find_sensor(struct imx_media_dev *imxmd, - struct media_entity *start_entity) -{ - return imx_media_find_upstream_subdev(imxmd, start_entity, - IMX_MEDIA_GRP_ID_SENSOR); -} -EXPORT_SYMBOL_GPL(__imx_media_find_sensor); - -struct imx_media_subdev * -imx_media_find_sensor(struct imx_media_dev *imxmd, - struct media_entity *start_entity) -{ - struct imx_media_subdev *sensor; - - mutex_lock(&imxmd->md.graph_mutex); - sensor = __imx_media_find_sensor(imxmd, start_entity); - mutex_unlock(&imxmd->md.graph_mutex); - - return sensor; -} -EXPORT_SYMBOL_GPL(imx_media_find_sensor); - /* * Turn current pipeline streaming on/off starting from entity. */ -- cgit From 9f6a0c59eba91c116f6cd7a487f4929faa07a7f8 Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Thu, 14 Dec 2017 20:04:44 -0500 Subject: media: staging/imx: remove static subdev arrays For more complex OF graphs, there will be more async subdevices registered. Remove the static subdev[IMX_MEDIA_MAX_SUBDEVS] array, so that imx-media places no limits on the number of async subdevs that can be added and registered. There were two uses for 'struct imx_media_subdev'. First was to act as the async subdev list to be passed to v4l2_async_notifier_register(). Second was to aid in inheriting subdev controls to the capture devices, and this is done by creating a list of capture devices that can be reached from a subdev's source pad. So 'struct imx_media_subdev' also contained a static array of 'struct imx_media_pad' for placing the capture device lists at each pad. 'struct imx_media_subdev' has been completely removed. Instead, at async completion, allocate an array of 'struct imx_media_pad' and attach it to the subdev's host_priv pointer, in order to support subdev controls inheritance. Likewise, remove static async_ptrs[IMX_MEDIA_MAX_SUBDEVS] array. Instead, allocate a 'struct imx_media_async_subdev' when forming the async list, and add it to an asd_list list_head in imx_media_add_async_subdev(). At async completion, allocate the asd pointer list and pull the asd's off asd_list for v4l2_async_notifier_register(). Signed-off-by: Steve Longerbeam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-utils.c | 43 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 23 deletions(-) (limited to 'drivers/staging/media/imx/imx-media-utils.c') diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index 51d7e184e8d7..e143a88d3317 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -668,38 +668,35 @@ 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); -struct imx_media_subdev * -imx_media_find_subdev_by_sd(struct imx_media_dev *imxmd, - struct v4l2_subdev *sd) +struct v4l2_subdev * +imx_media_find_subdev_by_fwnode(struct imx_media_dev *imxmd, + struct fwnode_handle *fwnode) { - struct imx_media_subdev *imxsd; - int i; + struct v4l2_subdev *sd; - for (i = 0; i < imxmd->num_subdevs; i++) { - imxsd = &imxmd->subdev[i]; - if (sd == imxsd->sd) - return imxsd; + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { + if (sd->fwnode == fwnode) + return sd; } - return ERR_PTR(-ENODEV); + return NULL; } -EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_sd); +EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_fwnode); -struct imx_media_subdev * -imx_media_find_subdev_by_id(struct imx_media_dev *imxmd, u32 grp_id) +struct v4l2_subdev * +imx_media_find_subdev_by_devname(struct imx_media_dev *imxmd, + const char *devname) { - struct imx_media_subdev *imxsd; - int i; + struct v4l2_subdev *sd; - for (i = 0; i < imxmd->num_subdevs; i++) { - imxsd = &imxmd->subdev[i]; - if (imxsd->sd && imxsd->sd->grp_id == grp_id) - return imxsd; + list_for_each_entry(sd, &imxmd->v4l2_dev.subdevs, list) { + if (!strcmp(devname, dev_name(sd->dev))) + return sd; } - return ERR_PTR(-ENODEV); + return NULL; } -EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_id); +EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname); /* * Adds a video device to the master video device list. This is called by @@ -842,7 +839,7 @@ EXPORT_SYMBOL_GPL(imx_media_find_upstream_pad); * the current pipeline. * Must be called with mdev->graph_mutex held. */ -struct imx_media_subdev * +struct v4l2_subdev * imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, struct media_entity *start_entity, u32 grp_id) @@ -853,7 +850,7 @@ imx_media_find_upstream_subdev(struct imx_media_dev *imxmd, if (!sd) return ERR_PTR(-ENODEV); - return imx_media_find_subdev_by_sd(imxmd, sd); + return sd; } EXPORT_SYMBOL_GPL(imx_media_find_upstream_subdev); -- cgit From bd9d208a04e0db4f66255c24ff37e49069d274ee Mon Sep 17 00:00:00 2001 From: Steve Longerbeam Date: Thu, 14 Dec 2017 20:04:45 -0500 Subject: media: staging/imx: convert static vdev lists to list_head Although not technically necessary because imx-media has only a maximum of 8 video devices, and once setup the video device lists are static, in anticipation of moving control ineritance to v4l2-core, make the vdev lists more generic by converting to dynamic list_head's. After doing that, 'struct imx_media_pad' is now just a list_head of video devices reachable from a pad. Allocate an array of list_head's, one list_head for each pad, and attach that array to sd->host_priv. An entry in the pad lists is of type 'struct imx_media_pad_vdev', and points to a video device from the master list. Signed-off-by: Steve Longerbeam Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/staging/media/imx/imx-media-utils.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/staging/media/imx/imx-media-utils.c') diff --git a/drivers/staging/media/imx/imx-media-utils.c b/drivers/staging/media/imx/imx-media-utils.c index e143a88d3317..13dafa77a2eb 100644 --- a/drivers/staging/media/imx/imx-media-utils.c +++ b/drivers/staging/media/imx/imx-media-utils.c @@ -705,24 +705,12 @@ EXPORT_SYMBOL_GPL(imx_media_find_subdev_by_devname); int imx_media_add_video_device(struct imx_media_dev *imxmd, struct imx_media_video_dev *vdev) { - int vdev_idx, ret = 0; - mutex_lock(&imxmd->mutex); - vdev_idx = imxmd->num_vdevs; - if (vdev_idx >= IMX_MEDIA_MAX_VDEVS) { - dev_err(imxmd->md.dev, - "%s: too many video devices! can't add %s\n", - __func__, vdev->vfd->name); - ret = -ENOSPC; - goto out; - } + list_add_tail(&vdev->list, &imxmd->vdev_list); - imxmd->vdev[vdev_idx] = vdev; - imxmd->num_vdevs++; -out: mutex_unlock(&imxmd->mutex); - return ret; + return 0; } EXPORT_SYMBOL_GPL(imx_media_add_video_device); -- cgit