Hi Niklas,
Thank you for the patch.
On Monday, 29 January 2018 18:34:31 EET Niklas Söderlund wrote:
> Add the ability to process media device link change request. Link
> enabling is a bit complicated on Gen3, whether or not it's possible to
> enable a link depends on what other links already are enabled. On Gen3
> the 8 VINs are split into two subgroup's (VIN0-3 and VIN4-7) and from a
> routing perspective these two groups are independent of each other.
> Each subgroup's routing is controlled by the subgroup VIN master
> instance (VIN0 and VIN4).
>
> There are a limited number of possible route setups available for each
> subgroup and the configuration of each setup is dictated by the
> hardware. On H3 for example there are 6 possible route setups for each
> subgroup to choose from.
>
> This leads to the media device link notification code being rather large
> since it will find the best routing configuration to try and accommodate
> as many links as possible. When it's not possible to enable a new link
> due to hardware constrains the link_notifier callback will return
> -EMLINK.
>
> Signed-off-by: Niklas Söderlund
> ---
> drivers/media/platform/rcar-vin/rcar-core.c | 129 +
> 1 file changed, 129 insertions(+)
>
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c index
> f08277a0dc11f477..7ceff0de40078580 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -24,6 +24,7 @@
>
> #include
> #include
> +#include
>
> #include "rcar-vin.h"
>
> @@ -44,6 +45,133 @@
> */
> #define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
>
> +/*
> + * Media Controller link notification
> + */
> +
> +/* group lock should be held when calling this function */
> +static int rvin_group_entity_to_csi_id(struct rvin_group *group,
> + struct media_entity *entity)
> +{
> + struct v4l2_subdev *sd;
> + int i;
unsigned int.
> +
> + if (!is_media_entity_v4l2_subdev(entity))
> + return -ENODEV;
Can this happen ?
> + sd = media_entity_to_v4l2_subdev(entity);
> +
> + for (i = 0; i < RVIN_CSI_MAX; i++)
> + if (group->csi[i].subdev == sd)
> + return i;
> +
> + return -ENODEV;
> +}
> +
> +static unsigned int rvin_group_get_mask(struct rvin_dev *vin,
> + enum rvin_csi_id csi_id,
> + unsigned char chan)
> +{
> + const struct rvin_group_route *route;
> + unsigned int mask = 0;
> +
> + for (route = vin->info->routes; route->mask; route++) {
Please document the fact that the array needs to be terminated by an empty
element in the kerneldoc for vin->info->routes.
> + if (route->vin == vin->id &&
> + route->csi == csi_id &&
> + route->chan == chan) {
> + vin_dbg(vin, "Adding route: vin: %d csi: %d chan: %d\n",
> + route->vin, route->csi, route->chan);
> + mask |= route->mask;
> + }
> + }
> +
> + return mask;
> +}
> +
> +static int rvin_group_link_notify(struct media_link *link, u32 flags,
> + unsigned int notification)
> +{
> + struct rvin_group *group = container_of(link->graph_obj.mdev,
> + struct rvin_group, mdev);
> + unsigned int i, master_id, chan, mask_new, mask = ~0;
I'm sure you could spare a few more lines :-)
> + struct media_entity *entity;
> + struct video_device *vdev;
> + struct media_pad *csi_pad;
> + struct rvin_dev *vin = NULL;
> + int csi_id, ret;
> +
> + ret = v4l2_pipeline_link_notify(link, flags, notification);
> + if (ret)
> + return ret;
> +
> + /* Only care about link enablement for VIN nodes */
> + if (!(flags & MEDIA_LNK_FL_ENABLED) ||
> + !is_media_entity_v4l2_video_device(link->sink->entity))
> + return 0;
> +
> + /* If any entity are in use don't allow link changes */
s/are/is/
> + media_device_for_each_entity(entity, >mdev)
> + if (entity->use_count)
> + return -EBUSY;
> +
> + mutex_lock(>lock);
> +
> + /* Find VIN and its master for which the link */
The words make sense individually. Maybe you could try a different order ? :-)
> + entity = link->sink->entity;
> + vdev = media_entity_to_video_device(entity);
You can combine those two lines and remove the entity variable.
> + for (i = 0; i < RCAR_VIN_NUM; i++) {
> + if (group->vin[i] && >vin[i]->vdev == vdev) {
> + vin = group->vin[i];
> + master_id = rvin_group_id_to_master(vin->id);
> +