On 11/11/17 01:38, 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
Reviewed-by: Hans Verkuil
Regards,
Hans
> ---
> drivers/media/platform/rcar-vin/rcar-core.c | 205
>
> 1 file changed, 205 insertions(+)
>
> diff --git a/drivers/media/platform/rcar-vin/rcar-core.c
> b/drivers/media/platform/rcar-vin/rcar-core.c
> index 78a9766eb7114959..79b0334d8c563328 100644
> --- a/drivers/media/platform/rcar-vin/rcar-core.c
> +++ b/drivers/media/platform/rcar-vin/rcar-core.c
> @@ -27,6 +27,209 @@
>
> #include "rcar-vin.h"
>
> +/*
> -
> + * Media Controller link notification
> + */
> +
> +static unsigned int rvin_group_csi_pad_to_chan(unsigned int pad)
> +{
> + /*
> + * The companion CSI-2 receiver driver (rcar-csi2) is known
> + * and we know it have one source pad (pad 0) and four sink
> + * pads (pad 1-4). So to translate a pad on the remote
> + * CSI-2 receiver to the VIN internal channel number simply
> + * subtract one from the pad number.
> + */
> + return pad - 1;
> +}
> +
> +/* group lock should be held when calling this function */
> +static int rvin_group_entity_to_vin_num(struct rvin_group *group,
> + struct media_entity *entity)
> +{
> + struct video_device *vdev;
> + int i;
> +
> + if (!is_media_entity_v4l2_video_device(entity))
> + return -ENODEV;
> +
> + vdev = media_entity_to_video_device(entity);
> +
> + for (i = 0; i < RCAR_VIN_NUM; i++) {
> + if (!group->vin[i])
> + continue;
> +
> + if (&group->vin[i]->vdev == vdev)
> + return i;
> + }
> +
> + return -ENODEV;
> +}
> +
> +/* group lock should be held when calling this function */
> +static int rvin_group_entity_to_csi_num(struct rvin_group *group,
> + struct media_entity *entity)
> +{
> + struct v4l2_subdev *sd;
> + int i;
> +
> + if (!is_media_entity_v4l2_subdev(entity))
> + return -ENODEV;
> +
> + 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;
> +}
> +
> +/* group lock should be held when calling this function */
> +static void __rvin_group_build_link_list(struct rvin_group *group,
> + struct rvin_group_chsel *map,
> + int start, int len)
> +{
> + struct media_pad *vin_pad, *remote_pad;
> + unsigned int n;
> +
> + for (n = 0; n < len; n++) {
> + map[n].csi = -1;
> + map[n].chan = -1;
> +
> + if (!group->vin[start + n])
> + continue;
> +
> + vin_pad = &group->vin[start + n]->vdev.entity.pads[0];
> +
> + remote_pad = media_entity_remote_pad(vin_pad);
> + if (!remote_pad)
> + continue;
> +
> + map[n].csi =
> + rvin_group_entity_to_csi_num(group, remote_pad->entity);
> + map[n].chan = rvin_group_csi_pad_to_chan(remote_pad->index);
> + }
> +}
> +
> +/* group lock should be held when calling this function */
> +static int __rvin_group_try_get_chsel(struct rvin_group *group,
> + struct rvin_group_chsel *map,
> + int start, int len)
> +{
> + const struct rvin_group_chsel *sel;
> + unsigned int i, n;
> + int chsel;
> +
> + for (i = 0; i < group->vin[start]->info->num_chsels; i++) {
> + chsel = i;
> + for (n = 0; n < len; n++) {
> +
> + /* If the link is not active it's OK */
> + if (map[n].csi == -1)
> + continue;
> +
> +