linux/drivers/media/platform/rcar-vin/rcar-core.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Driver for Renesas R-Car VIN
   4 *
   5 * Copyright (C) 2016 Renesas Electronics Corp.
   6 * Copyright (C) 2011-2013 Renesas Solutions Corp.
   7 * Copyright (C) 2013 Cogent Embedded, Inc., <source@cogentembedded.com>
   8 * Copyright (C) 2008 Magnus Damm
   9 *
  10 * Based on the soc-camera rcar_vin driver
  11 */
  12
  13#include <linux/module.h>
  14#include <linux/of.h>
  15#include <linux/of_device.h>
  16#include <linux/of_graph.h>
  17#include <linux/platform_device.h>
  18#include <linux/pm_runtime.h>
  19#include <linux/slab.h>
  20#include <linux/sys_soc.h>
  21
  22#include <media/v4l2-async.h>
  23#include <media/v4l2-fwnode.h>
  24#include <media/v4l2-mc.h>
  25
  26#include "rcar-vin.h"
  27
  28/*
  29 * The companion CSI-2 receiver driver (rcar-csi2) is known
  30 * and we know it has one source pad (pad 0) and four sink
  31 * pads (pad 1-4). So to translate a pad on the remote
  32 * CSI-2 receiver to/from the VIN internal channel number simply
  33 * subtract/add one from the pad/channel number.
  34 */
  35#define rvin_group_csi_pad_to_channel(pad) ((pad) - 1)
  36#define rvin_group_csi_channel_to_pad(channel) ((channel) + 1)
  37
  38/*
  39 * Not all VINs are created equal, master VINs control the
  40 * routing for other VIN's. We can figure out which VIN is
  41 * master by looking at a VINs id.
  42 */
  43#define rvin_group_id_to_master(vin) ((vin) < 4 ? 0 : 4)
  44
  45#define v4l2_dev_to_vin(d)      container_of(d, struct rvin_dev, v4l2_dev)
  46
  47/* -----------------------------------------------------------------------------
  48 * Media Controller link notification
  49 */
  50
  51/* group lock should be held when calling this function. */
  52static int rvin_group_entity_to_csi_id(struct rvin_group *group,
  53                                       struct media_entity *entity)
  54{
  55        struct v4l2_subdev *sd;
  56        unsigned int i;
  57
  58        sd = media_entity_to_v4l2_subdev(entity);
  59
  60        for (i = 0; i < RVIN_CSI_MAX; i++)
  61                if (group->csi[i].subdev == sd)
  62                        return i;
  63
  64        return -ENODEV;
  65}
  66
  67static unsigned int rvin_group_get_mask(struct rvin_dev *vin,
  68                                        enum rvin_csi_id csi_id,
  69                                        unsigned char channel)
  70{
  71        const struct rvin_group_route *route;
  72        unsigned int mask = 0;
  73
  74        for (route = vin->info->routes; route->mask; route++) {
  75                if (route->vin == vin->id &&
  76                    route->csi == csi_id &&
  77                    route->channel == channel) {
  78                        vin_dbg(vin,
  79                                "Adding route: vin: %d csi: %d channel: %d\n",
  80                                route->vin, route->csi, route->channel);
  81                        mask |= route->mask;
  82                }
  83        }
  84
  85        return mask;
  86}
  87
  88/*
  89 * Link setup for the links between a VIN and a CSI-2 receiver is a bit
  90 * complex. The reason for this is that the register controlling routing
  91 * is not present in each VIN instance. There are special VINs which
  92 * control routing for themselves and other VINs. There are not many
  93 * different possible links combinations that can be enabled at the same
  94 * time, therefor all already enabled links which are controlled by a
  95 * master VIN need to be taken into account when making the decision
  96 * if a new link can be enabled or not.
  97 *
  98 * 1. Find out which VIN the link the user tries to enable is connected to.
  99 * 2. Lookup which master VIN controls the links for this VIN.
 100 * 3. Start with a bitmask with all bits set.
 101 * 4. For each previously enabled link from the master VIN bitwise AND its
 102 *    route mask (see documentation for mask in struct rvin_group_route)
 103 *    with the bitmask.
 104 * 5. Bitwise AND the mask for the link the user tries to enable to the bitmask.
 105 * 6. If the bitmask is not empty at this point the new link can be enabled
 106 *    while keeping all previous links enabled. Update the CHSEL value of the
 107 *    master VIN and inform the user that the link could be enabled.
 108 *
 109 * Please note that no link can be enabled if any VIN in the group is
 110 * currently open.
 111 */
 112static int rvin_group_link_notify(struct media_link *link, u32 flags,
 113                                  unsigned int notification)
 114{
 115        struct rvin_group *group = container_of(link->graph_obj.mdev,
 116                                                struct rvin_group, mdev);
 117        unsigned int master_id, channel, mask_new, i;
 118        unsigned int mask = ~0;
 119        struct media_entity *entity;
 120        struct video_device *vdev;
 121        struct media_pad *csi_pad;
 122        struct rvin_dev *vin = NULL;
 123        int csi_id, ret;
 124
 125        ret = v4l2_pipeline_link_notify(link, flags, notification);
 126        if (ret)
 127                return ret;
 128
 129        /* Only care about link enablement for VIN nodes. */
 130        if (!(flags & MEDIA_LNK_FL_ENABLED) ||
 131            !is_media_entity_v4l2_video_device(link->sink->entity))
 132                return 0;
 133
 134        /*
 135         * Don't allow link changes if any entity in the graph is
 136         * streaming, modifying the CHSEL register fields can disrupt
 137         * running streams.
 138         */
 139        media_device_for_each_entity(entity, &group->mdev)
 140                if (entity->stream_count)
 141                        return -EBUSY;
 142
 143        mutex_lock(&group->lock);
 144
 145        /* Find the master VIN that controls the routes. */
 146        vdev = media_entity_to_video_device(link->sink->entity);
 147        vin = container_of(vdev, struct rvin_dev, vdev);
 148        master_id = rvin_group_id_to_master(vin->id);
 149
 150        if (WARN_ON(!group->vin[master_id])) {
 151                ret = -ENODEV;
 152                goto out;
 153        }
 154
 155        /* Build a mask for already enabled links. */
 156        for (i = master_id; i < master_id + 4; i++) {
 157                if (!group->vin[i])
 158                        continue;
 159
 160                /* Get remote CSI-2, if any. */
 161                csi_pad = media_entity_remote_pad(
 162                                &group->vin[i]->vdev.entity.pads[0]);
 163                if (!csi_pad)
 164                        continue;
 165
 166                csi_id = rvin_group_entity_to_csi_id(group, csi_pad->entity);
 167                channel = rvin_group_csi_pad_to_channel(csi_pad->index);
 168
 169                mask &= rvin_group_get_mask(group->vin[i], csi_id, channel);
 170        }
 171
 172        /* Add the new link to the existing mask and check if it works. */
 173        csi_id = rvin_group_entity_to_csi_id(group, link->source->entity);
 174
 175        if (csi_id == -ENODEV) {
 176                struct v4l2_subdev *sd;
 177
 178                /*
 179                 * Make sure the source entity subdevice is registered as
 180                 * a parallel input of one of the enabled VINs if it is not
 181                 * one of the CSI-2 subdevices.
 182                 *
 183                 * No hardware configuration required for parallel inputs,
 184                 * we can return here.
 185                 */
 186                sd = media_entity_to_v4l2_subdev(link->source->entity);
 187                for (i = 0; i < RCAR_VIN_NUM; i++) {
 188                        if (group->vin[i] && group->vin[i]->parallel &&
 189                            group->vin[i]->parallel->subdev == sd) {
 190                                group->vin[i]->is_csi = false;
 191                                ret = 0;
 192                                goto out;
 193                        }
 194                }
 195
 196                vin_err(vin, "Subdevice %s not registered to any VIN\n",
 197                        link->source->entity->name);
 198                ret = -ENODEV;
 199                goto out;
 200        }
 201
 202        channel = rvin_group_csi_pad_to_channel(link->source->index);
 203        mask_new = mask & rvin_group_get_mask(vin, csi_id, channel);
 204        vin_dbg(vin, "Try link change mask: 0x%x new: 0x%x\n", mask, mask_new);
 205
 206        if (!mask_new) {
 207                ret = -EMLINK;
 208                goto out;
 209        }
 210
 211        /* New valid CHSEL found, set the new value. */
 212        ret = rvin_set_channel_routing(group->vin[master_id], __ffs(mask_new));
 213        if (ret)
 214                goto out;
 215
 216        vin->is_csi = true;
 217
 218out:
 219        mutex_unlock(&group->lock);
 220
 221        return ret;
 222}
 223
 224static const struct media_device_ops rvin_media_ops = {
 225        .link_notify = rvin_group_link_notify,
 226};
 227
 228/* -----------------------------------------------------------------------------
 229 * Gen3 CSI2 Group Allocator
 230 */
 231
 232/* FIXME:  This should if we find a system that supports more
 233 * than one group for the whole system be replaced with a linked
 234 * list of groups. And eventually all of this should be replaced
 235 * with a global device allocator API.
 236 *
 237 * But for now this works as on all supported systems there will
 238 * be only one group for all instances.
 239 */
 240
 241static DEFINE_MUTEX(rvin_group_lock);
 242static struct rvin_group *rvin_group_data;
 243
 244static void rvin_group_cleanup(struct rvin_group *group)
 245{
 246        media_device_unregister(&group->mdev);
 247        media_device_cleanup(&group->mdev);
 248        mutex_destroy(&group->lock);
 249}
 250
 251static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
 252{
 253        struct media_device *mdev = &group->mdev;
 254        const struct of_device_id *match;
 255        struct device_node *np;
 256        int ret;
 257
 258        mutex_init(&group->lock);
 259
 260        /* Count number of VINs in the system */
 261        group->count = 0;
 262        for_each_matching_node(np, vin->dev->driver->of_match_table)
 263                if (of_device_is_available(np))
 264                        group->count++;
 265
 266        vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
 267
 268        mdev->dev = vin->dev;
 269        mdev->ops = &rvin_media_ops;
 270
 271        match = of_match_node(vin->dev->driver->of_match_table,
 272                              vin->dev->of_node);
 273
 274        strscpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
 275        strscpy(mdev->model, match->compatible, sizeof(mdev->model));
 276        snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
 277                 dev_name(mdev->dev));
 278
 279        media_device_init(mdev);
 280
 281        ret = media_device_register(&group->mdev);
 282        if (ret)
 283                rvin_group_cleanup(group);
 284
 285        return ret;
 286}
 287
 288static void rvin_group_release(struct kref *kref)
 289{
 290        struct rvin_group *group =
 291                container_of(kref, struct rvin_group, refcount);
 292
 293        mutex_lock(&rvin_group_lock);
 294
 295        rvin_group_data = NULL;
 296
 297        rvin_group_cleanup(group);
 298
 299        kfree(group);
 300
 301        mutex_unlock(&rvin_group_lock);
 302}
 303
 304static int rvin_group_get(struct rvin_dev *vin)
 305{
 306        struct rvin_group *group;
 307        u32 id;
 308        int ret;
 309
 310        /* Make sure VIN id is present and sane */
 311        ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id);
 312        if (ret) {
 313                vin_err(vin, "%pOF: No renesas,id property found\n",
 314                        vin->dev->of_node);
 315                return -EINVAL;
 316        }
 317
 318        if (id >= RCAR_VIN_NUM) {
 319                vin_err(vin, "%pOF: Invalid renesas,id '%u'\n",
 320                        vin->dev->of_node, id);
 321                return -EINVAL;
 322        }
 323
 324        /* Join or create a VIN group */
 325        mutex_lock(&rvin_group_lock);
 326        if (rvin_group_data) {
 327                group = rvin_group_data;
 328                kref_get(&group->refcount);
 329        } else {
 330                group = kzalloc(sizeof(*group), GFP_KERNEL);
 331                if (!group) {
 332                        ret = -ENOMEM;
 333                        goto err_group;
 334                }
 335
 336                ret = rvin_group_init(group, vin);
 337                if (ret) {
 338                        kfree(group);
 339                        vin_err(vin, "Failed to initialize group\n");
 340                        goto err_group;
 341                }
 342
 343                kref_init(&group->refcount);
 344
 345                rvin_group_data = group;
 346        }
 347        mutex_unlock(&rvin_group_lock);
 348
 349        /* Add VIN to group */
 350        mutex_lock(&group->lock);
 351
 352        if (group->vin[id]) {
 353                vin_err(vin, "Duplicate renesas,id property value %u\n", id);
 354                mutex_unlock(&group->lock);
 355                kref_put(&group->refcount, rvin_group_release);
 356                return -EINVAL;
 357        }
 358
 359        group->vin[id] = vin;
 360
 361        vin->id = id;
 362        vin->group = group;
 363        vin->v4l2_dev.mdev = &group->mdev;
 364
 365        mutex_unlock(&group->lock);
 366
 367        return 0;
 368err_group:
 369        mutex_unlock(&rvin_group_lock);
 370        return ret;
 371}
 372
 373static void rvin_group_put(struct rvin_dev *vin)
 374{
 375        struct rvin_group *group = vin->group;
 376
 377        mutex_lock(&group->lock);
 378
 379        vin->group = NULL;
 380        vin->v4l2_dev.mdev = NULL;
 381
 382        if (WARN_ON(group->vin[vin->id] != vin))
 383                goto out;
 384
 385        group->vin[vin->id] = NULL;
 386out:
 387        mutex_unlock(&group->lock);
 388
 389        kref_put(&group->refcount, rvin_group_release);
 390}
 391
 392/* -----------------------------------------------------------------------------
 393 * Controls
 394 */
 395
 396static int rvin_s_ctrl(struct v4l2_ctrl *ctrl)
 397{
 398        struct rvin_dev *vin =
 399                container_of(ctrl->handler, struct rvin_dev, ctrl_handler);
 400
 401        switch (ctrl->id) {
 402        case V4L2_CID_ALPHA_COMPONENT:
 403                rvin_set_alpha(vin, ctrl->val);
 404                break;
 405        }
 406
 407        return 0;
 408}
 409
 410static const struct v4l2_ctrl_ops rvin_ctrl_ops = {
 411        .s_ctrl = rvin_s_ctrl,
 412};
 413
 414/* -----------------------------------------------------------------------------
 415 * Async notifier
 416 */
 417
 418static int rvin_find_pad(struct v4l2_subdev *sd, int direction)
 419{
 420        unsigned int pad;
 421
 422        if (sd->entity.num_pads <= 1)
 423                return 0;
 424
 425        for (pad = 0; pad < sd->entity.num_pads; pad++)
 426                if (sd->entity.pads[pad].flags & direction)
 427                        return pad;
 428
 429        return -EINVAL;
 430}
 431
 432/* -----------------------------------------------------------------------------
 433 * Parallel async notifier
 434 */
 435
 436/* The vin lock should be held when calling the subdevice attach and detach */
 437static int rvin_parallel_subdevice_attach(struct rvin_dev *vin,
 438                                          struct v4l2_subdev *subdev)
 439{
 440        struct v4l2_subdev_mbus_code_enum code = {
 441                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
 442        };
 443        int ret;
 444
 445        /* Find source and sink pad of remote subdevice */
 446        ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
 447        if (ret < 0)
 448                return ret;
 449        vin->parallel->source_pad = ret;
 450
 451        ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
 452        vin->parallel->sink_pad = ret < 0 ? 0 : ret;
 453
 454        if (vin->info->use_mc) {
 455                vin->parallel->subdev = subdev;
 456                return 0;
 457        }
 458
 459        /* Find compatible subdevices mbus format */
 460        vin->mbus_code = 0;
 461        code.index = 0;
 462        code.pad = vin->parallel->source_pad;
 463        while (!vin->mbus_code &&
 464               !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
 465                code.index++;
 466                switch (code.code) {
 467                case MEDIA_BUS_FMT_YUYV8_1X16:
 468                case MEDIA_BUS_FMT_UYVY8_1X16:
 469                case MEDIA_BUS_FMT_UYVY8_2X8:
 470                case MEDIA_BUS_FMT_UYVY10_2X10:
 471                case MEDIA_BUS_FMT_RGB888_1X24:
 472                        vin->mbus_code = code.code;
 473                        vin_dbg(vin, "Found media bus format for %s: %d\n",
 474                                subdev->name, vin->mbus_code);
 475                        break;
 476                default:
 477                        break;
 478                }
 479        }
 480
 481        if (!vin->mbus_code) {
 482                vin_err(vin, "Unsupported media bus format for %s\n",
 483                        subdev->name);
 484                return -EINVAL;
 485        }
 486
 487        /* Read tvnorms */
 488        ret = v4l2_subdev_call(subdev, video, g_tvnorms, &vin->vdev.tvnorms);
 489        if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 490                return ret;
 491
 492        /* Read standard */
 493        vin->std = V4L2_STD_UNKNOWN;
 494        ret = v4l2_subdev_call(subdev, video, g_std, &vin->std);
 495        if (ret < 0 && ret != -ENOIOCTLCMD)
 496                return ret;
 497
 498        /* Add the controls */
 499        ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
 500        if (ret < 0)
 501                return ret;
 502
 503        v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
 504                          V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
 505
 506        if (vin->ctrl_handler.error) {
 507                ret = vin->ctrl_handler.error;
 508                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 509                return ret;
 510        }
 511
 512        ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler,
 513                                    NULL, true);
 514        if (ret < 0) {
 515                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 516                return ret;
 517        }
 518
 519        vin->vdev.ctrl_handler = &vin->ctrl_handler;
 520
 521        vin->parallel->subdev = subdev;
 522
 523        return 0;
 524}
 525
 526static void rvin_parallel_subdevice_detach(struct rvin_dev *vin)
 527{
 528        rvin_v4l2_unregister(vin);
 529        vin->parallel->subdev = NULL;
 530
 531        if (!vin->info->use_mc) {
 532                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 533                vin->vdev.ctrl_handler = NULL;
 534        }
 535}
 536
 537static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier)
 538{
 539        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 540        struct media_entity *source;
 541        struct media_entity *sink;
 542        int ret;
 543
 544        ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
 545        if (ret < 0) {
 546                vin_err(vin, "Failed to register subdev nodes\n");
 547                return ret;
 548        }
 549
 550        if (!video_is_registered(&vin->vdev)) {
 551                ret = rvin_v4l2_register(vin);
 552                if (ret < 0)
 553                        return ret;
 554        }
 555
 556        if (!vin->info->use_mc)
 557                return 0;
 558
 559        /* If we're running with media-controller, link the subdevs. */
 560        source = &vin->parallel->subdev->entity;
 561        sink = &vin->vdev.entity;
 562
 563        ret = media_create_pad_link(source, vin->parallel->source_pad,
 564                                    sink, vin->parallel->sink_pad, 0);
 565        if (ret)
 566                vin_err(vin, "Error adding link from %s to %s: %d\n",
 567                        source->name, sink->name, ret);
 568
 569        return ret;
 570}
 571
 572static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier,
 573                                        struct v4l2_subdev *subdev,
 574                                        struct v4l2_async_subdev *asd)
 575{
 576        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 577
 578        vin_dbg(vin, "unbind parallel subdev %s\n", subdev->name);
 579
 580        mutex_lock(&vin->lock);
 581        rvin_parallel_subdevice_detach(vin);
 582        mutex_unlock(&vin->lock);
 583}
 584
 585static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier,
 586                                      struct v4l2_subdev *subdev,
 587                                      struct v4l2_async_subdev *asd)
 588{
 589        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 590        int ret;
 591
 592        mutex_lock(&vin->lock);
 593        ret = rvin_parallel_subdevice_attach(vin, subdev);
 594        mutex_unlock(&vin->lock);
 595        if (ret)
 596                return ret;
 597
 598        v4l2_set_subdev_hostdata(subdev, vin);
 599
 600        vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n",
 601                subdev->name, vin->parallel->source_pad,
 602                vin->parallel->sink_pad);
 603
 604        return 0;
 605}
 606
 607static const struct v4l2_async_notifier_operations rvin_parallel_notify_ops = {
 608        .bound = rvin_parallel_notify_bound,
 609        .unbind = rvin_parallel_notify_unbind,
 610        .complete = rvin_parallel_notify_complete,
 611};
 612
 613static int rvin_parallel_parse_v4l2(struct device *dev,
 614                                    struct v4l2_fwnode_endpoint *vep,
 615                                    struct v4l2_async_subdev *asd)
 616{
 617        struct rvin_dev *vin = dev_get_drvdata(dev);
 618        struct rvin_parallel_entity *rvpe =
 619                container_of(asd, struct rvin_parallel_entity, asd);
 620
 621        if (vep->base.port || vep->base.id)
 622                return -ENOTCONN;
 623
 624        vin->parallel = rvpe;
 625        vin->parallel->mbus_type = vep->bus_type;
 626
 627        switch (vin->parallel->mbus_type) {
 628        case V4L2_MBUS_PARALLEL:
 629                vin_dbg(vin, "Found PARALLEL media bus\n");
 630                vin->parallel->mbus_flags = vep->bus.parallel.flags;
 631                break;
 632        case V4L2_MBUS_BT656:
 633                vin_dbg(vin, "Found BT656 media bus\n");
 634                vin->parallel->mbus_flags = 0;
 635                break;
 636        default:
 637                vin_err(vin, "Unknown media bus type\n");
 638                return -EINVAL;
 639        }
 640
 641        return 0;
 642}
 643
 644static int rvin_parallel_init(struct rvin_dev *vin)
 645{
 646        int ret;
 647
 648        v4l2_async_notifier_init(&vin->notifier);
 649
 650        ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
 651                vin->dev, &vin->notifier, sizeof(struct rvin_parallel_entity),
 652                0, rvin_parallel_parse_v4l2);
 653        if (ret)
 654                return ret;
 655
 656        /* If using mc, it's fine not to have any input registered. */
 657        if (!vin->parallel)
 658                return vin->info->use_mc ? 0 : -ENODEV;
 659
 660        vin_dbg(vin, "Found parallel subdevice %pOF\n",
 661                to_of_node(vin->parallel->asd.match.fwnode));
 662
 663        vin->notifier.ops = &rvin_parallel_notify_ops;
 664        ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
 665        if (ret < 0) {
 666                vin_err(vin, "Notifier registration failed\n");
 667                v4l2_async_notifier_cleanup(&vin->notifier);
 668                return ret;
 669        }
 670
 671        return 0;
 672}
 673
 674/* -----------------------------------------------------------------------------
 675 * Group async notifier
 676 */
 677
 678static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
 679{
 680        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 681        const struct rvin_group_route *route;
 682        unsigned int i;
 683        int ret;
 684
 685        ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
 686        if (ret) {
 687                vin_err(vin, "Failed to register subdev nodes\n");
 688                return ret;
 689        }
 690
 691        /* Register all video nodes for the group. */
 692        for (i = 0; i < RCAR_VIN_NUM; i++) {
 693                if (vin->group->vin[i] &&
 694                    !video_is_registered(&vin->group->vin[i]->vdev)) {
 695                        ret = rvin_v4l2_register(vin->group->vin[i]);
 696                        if (ret)
 697                                return ret;
 698                }
 699        }
 700
 701        /* Create all media device links between VINs and CSI-2's. */
 702        mutex_lock(&vin->group->lock);
 703        for (route = vin->info->routes; route->mask; route++) {
 704                struct media_pad *source_pad, *sink_pad;
 705                struct media_entity *source, *sink;
 706                unsigned int source_idx;
 707
 708                /* Check that VIN is part of the group. */
 709                if (!vin->group->vin[route->vin])
 710                        continue;
 711
 712                /* Check that VIN' master is part of the group. */
 713                if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
 714                        continue;
 715
 716                /* Check that CSI-2 is part of the group. */
 717                if (!vin->group->csi[route->csi].subdev)
 718                        continue;
 719
 720                source = &vin->group->csi[route->csi].subdev->entity;
 721                source_idx = rvin_group_csi_channel_to_pad(route->channel);
 722                source_pad = &source->pads[source_idx];
 723
 724                sink = &vin->group->vin[route->vin]->vdev.entity;
 725                sink_pad = &sink->pads[0];
 726
 727                /* Skip if link already exists. */
 728                if (media_entity_find_link(source_pad, sink_pad))
 729                        continue;
 730
 731                ret = media_create_pad_link(source, source_idx, sink, 0, 0);
 732                if (ret) {
 733                        vin_err(vin, "Error adding link from %s to %s\n",
 734                                source->name, sink->name);
 735                        break;
 736                }
 737        }
 738        mutex_unlock(&vin->group->lock);
 739
 740        return ret;
 741}
 742
 743static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
 744                                     struct v4l2_subdev *subdev,
 745                                     struct v4l2_async_subdev *asd)
 746{
 747        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 748        unsigned int i;
 749
 750        for (i = 0; i < RCAR_VIN_NUM; i++)
 751                if (vin->group->vin[i])
 752                        rvin_v4l2_unregister(vin->group->vin[i]);
 753
 754        mutex_lock(&vin->group->lock);
 755
 756        for (i = 0; i < RVIN_CSI_MAX; i++) {
 757                if (vin->group->csi[i].fwnode != asd->match.fwnode)
 758                        continue;
 759                vin->group->csi[i].subdev = NULL;
 760                vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
 761                break;
 762        }
 763
 764        mutex_unlock(&vin->group->lock);
 765}
 766
 767static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
 768                                   struct v4l2_subdev *subdev,
 769                                   struct v4l2_async_subdev *asd)
 770{
 771        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 772        unsigned int i;
 773
 774        mutex_lock(&vin->group->lock);
 775
 776        for (i = 0; i < RVIN_CSI_MAX; i++) {
 777                if (vin->group->csi[i].fwnode != asd->match.fwnode)
 778                        continue;
 779                vin->group->csi[i].subdev = subdev;
 780                vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
 781                break;
 782        }
 783
 784        mutex_unlock(&vin->group->lock);
 785
 786        return 0;
 787}
 788
 789static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
 790        .bound = rvin_group_notify_bound,
 791        .unbind = rvin_group_notify_unbind,
 792        .complete = rvin_group_notify_complete,
 793};
 794
 795static int rvin_mc_parse_of_endpoint(struct device *dev,
 796                                     struct v4l2_fwnode_endpoint *vep,
 797                                     struct v4l2_async_subdev *asd)
 798{
 799        struct rvin_dev *vin = dev_get_drvdata(dev);
 800        int ret = 0;
 801
 802        if (vep->base.port != 1 || vep->base.id >= RVIN_CSI_MAX)
 803                return -EINVAL;
 804
 805        if (!of_device_is_available(to_of_node(asd->match.fwnode))) {
 806                vin_dbg(vin, "OF device %pOF disabled, ignoring\n",
 807                        to_of_node(asd->match.fwnode));
 808                return -ENOTCONN;
 809        }
 810
 811        mutex_lock(&vin->group->lock);
 812
 813        if (vin->group->csi[vep->base.id].fwnode) {
 814                vin_dbg(vin, "OF device %pOF already handled\n",
 815                        to_of_node(asd->match.fwnode));
 816                ret = -ENOTCONN;
 817                goto out;
 818        }
 819
 820        vin->group->csi[vep->base.id].fwnode = asd->match.fwnode;
 821
 822        vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
 823                to_of_node(asd->match.fwnode), vep->base.id);
 824out:
 825        mutex_unlock(&vin->group->lock);
 826
 827        return ret;
 828}
 829
 830static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
 831{
 832        unsigned int count = 0, vin_mask = 0;
 833        unsigned int i;
 834        int ret;
 835
 836        mutex_lock(&vin->group->lock);
 837
 838        /* If not all VIN's are registered don't register the notifier. */
 839        for (i = 0; i < RCAR_VIN_NUM; i++) {
 840                if (vin->group->vin[i]) {
 841                        count++;
 842                        vin_mask |= BIT(i);
 843                }
 844        }
 845
 846        if (vin->group->count != count) {
 847                mutex_unlock(&vin->group->lock);
 848                return 0;
 849        }
 850
 851        mutex_unlock(&vin->group->lock);
 852
 853        v4l2_async_notifier_init(&vin->group->notifier);
 854
 855        /*
 856         * Have all VIN's look for CSI-2 subdevices. Some subdevices will
 857         * overlap but the parser function can handle it, so each subdevice
 858         * will only be registered once with the group notifier.
 859         */
 860        for (i = 0; i < RCAR_VIN_NUM; i++) {
 861                if (!(vin_mask & BIT(i)))
 862                        continue;
 863
 864                ret = v4l2_async_notifier_parse_fwnode_endpoints_by_port(
 865                                vin->group->vin[i]->dev, &vin->group->notifier,
 866                                sizeof(struct v4l2_async_subdev), 1,
 867                                rvin_mc_parse_of_endpoint);
 868                if (ret)
 869                        return ret;
 870        }
 871
 872        if (list_empty(&vin->group->notifier.asd_list))
 873                return 0;
 874
 875        vin->group->notifier.ops = &rvin_group_notify_ops;
 876        ret = v4l2_async_notifier_register(&vin->v4l2_dev,
 877                                           &vin->group->notifier);
 878        if (ret < 0) {
 879                vin_err(vin, "Notifier registration failed\n");
 880                v4l2_async_notifier_cleanup(&vin->group->notifier);
 881                return ret;
 882        }
 883
 884        return 0;
 885}
 886
 887static int rvin_mc_init(struct rvin_dev *vin)
 888{
 889        int ret;
 890
 891        vin->pad.flags = MEDIA_PAD_FL_SINK;
 892        ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
 893        if (ret)
 894                return ret;
 895
 896        ret = rvin_group_get(vin);
 897        if (ret)
 898                return ret;
 899
 900        ret = rvin_mc_parse_of_graph(vin);
 901        if (ret)
 902                rvin_group_put(vin);
 903
 904        ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1);
 905        if (ret < 0)
 906                return ret;
 907
 908        v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
 909                          V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
 910
 911        if (vin->ctrl_handler.error) {
 912                ret = vin->ctrl_handler.error;
 913                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 914                return ret;
 915        }
 916
 917        vin->vdev.ctrl_handler = &vin->ctrl_handler;
 918
 919        return ret;
 920}
 921
 922/* -----------------------------------------------------------------------------
 923 * Platform Device Driver
 924 */
 925
 926static const struct rvin_info rcar_info_h1 = {
 927        .model = RCAR_H1,
 928        .use_mc = false,
 929        .max_width = 2048,
 930        .max_height = 2048,
 931};
 932
 933static const struct rvin_info rcar_info_m1 = {
 934        .model = RCAR_M1,
 935        .use_mc = false,
 936        .max_width = 2048,
 937        .max_height = 2048,
 938};
 939
 940static const struct rvin_info rcar_info_gen2 = {
 941        .model = RCAR_GEN2,
 942        .use_mc = false,
 943        .max_width = 2048,
 944        .max_height = 2048,
 945};
 946
 947static const struct rvin_group_route rcar_info_r8a7795_routes[] = {
 948        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
 949        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
 950        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
 951        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
 952        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
 953        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
 954        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
 955        { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
 956        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
 957        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
 958        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
 959        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
 960        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
 961        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
 962        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
 963        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
 964        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
 965        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
 966        { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
 967        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
 968        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
 969        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
 970        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
 971        { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
 972        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
 973        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
 974        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
 975        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
 976        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
 977        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
 978        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
 979        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
 980        { /* Sentinel */ }
 981};
 982
 983static const struct rvin_info rcar_info_r8a7795 = {
 984        .model = RCAR_GEN3,
 985        .use_mc = true,
 986        .nv12 = true,
 987        .max_width = 4096,
 988        .max_height = 4096,
 989        .routes = rcar_info_r8a7795_routes,
 990};
 991
 992static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
 993        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
 994        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
 995        { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) },
 996        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
 997        { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) },
 998        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
 999        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1000        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1001        { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = BIT(5) },
1002        { .csi = RVIN_CSI21, .channel = 0, .vin = 2, .mask = BIT(0) },
1003        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1004        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1005        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1006        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1007        { .csi = RVIN_CSI21, .channel = 2, .vin = 2, .mask = BIT(5) },
1008        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1009        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1010        { .csi = RVIN_CSI21, .channel = 1, .vin = 3, .mask = BIT(2) },
1011        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1012        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1013        { .csi = RVIN_CSI21, .channel = 3, .vin = 3, .mask = BIT(5) },
1014        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1015        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1016        { .csi = RVIN_CSI21, .channel = 0, .vin = 4, .mask = BIT(2) | BIT(5) },
1017        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1018        { .csi = RVIN_CSI21, .channel = 0, .vin = 5, .mask = BIT(1) },
1019        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1020        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(3) },
1021        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1022        { .csi = RVIN_CSI21, .channel = 1, .vin = 5, .mask = BIT(5) },
1023        { .csi = RVIN_CSI21, .channel = 0, .vin = 6, .mask = BIT(0) },
1024        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1025        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1026        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1027        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1028        { .csi = RVIN_CSI21, .channel = 2, .vin = 6, .mask = BIT(5) },
1029        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1030        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1031        { .csi = RVIN_CSI21, .channel = 1, .vin = 7, .mask = BIT(2) },
1032        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1033        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1034        { .csi = RVIN_CSI21, .channel = 3, .vin = 7, .mask = BIT(5) },
1035        { /* Sentinel */ }
1036};
1037
1038static const struct rvin_info rcar_info_r8a7795es1 = {
1039        .model = RCAR_GEN3,
1040        .use_mc = true,
1041        .max_width = 4096,
1042        .max_height = 4096,
1043        .routes = rcar_info_r8a7795es1_routes,
1044};
1045
1046static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
1047        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1048        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1049        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1050        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1051        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1052        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1053        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1054        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1055        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1056        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1057        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1058        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1059        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1060        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1061        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1062        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1063        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1064        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1065        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) },
1066        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1067        { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1068        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1069        { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1070        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1071        { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1072        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1073        { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1074        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1075        { /* Sentinel */ }
1076};
1077
1078static const struct rvin_info rcar_info_r8a7796 = {
1079        .model = RCAR_GEN3,
1080        .use_mc = true,
1081        .nv12 = true,
1082        .max_width = 4096,
1083        .max_height = 4096,
1084        .routes = rcar_info_r8a7796_routes,
1085};
1086
1087static const struct rvin_group_route rcar_info_r8a77965_routes[] = {
1088        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1089        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1090        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1091        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1092        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1093        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1094        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1095        { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
1096        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1097        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1098        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1099        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1100        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1101        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
1102        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1103        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1104        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1105        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1106        { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1107        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1108        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1109        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1110        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1111        { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1112        { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1113        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1114        { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1115        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1116        { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1117        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1118        { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1119        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1120        { /* Sentinel */ }
1121};
1122
1123static const struct rvin_info rcar_info_r8a77965 = {
1124        .model = RCAR_GEN3,
1125        .use_mc = true,
1126        .nv12 = true,
1127        .max_width = 4096,
1128        .max_height = 4096,
1129        .routes = rcar_info_r8a77965_routes,
1130};
1131
1132static const struct rvin_group_route rcar_info_r8a77970_routes[] = {
1133        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1134        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1135        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1136        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1137        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1138        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1139        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1140        { /* Sentinel */ }
1141};
1142
1143static const struct rvin_info rcar_info_r8a77970 = {
1144        .model = RCAR_GEN3,
1145        .use_mc = true,
1146        .max_width = 4096,
1147        .max_height = 4096,
1148        .routes = rcar_info_r8a77970_routes,
1149};
1150
1151static const struct rvin_group_route rcar_info_r8a77980_routes[] = {
1152        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1153        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1154        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1155        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1156        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1157        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1158        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1159        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1160        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1161        { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
1162        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1163        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1164        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1165        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1166        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1167        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1168        { /* Sentinel */ }
1169};
1170
1171static const struct rvin_info rcar_info_r8a77980 = {
1172        .model = RCAR_GEN3,
1173        .use_mc = true,
1174        .nv12 = true,
1175        .max_width = 4096,
1176        .max_height = 4096,
1177        .routes = rcar_info_r8a77980_routes,
1178};
1179
1180static const struct rvin_group_route rcar_info_r8a77990_routes[] = {
1181        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1182        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1183        { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1184        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1185        { /* Sentinel */ }
1186};
1187
1188static const struct rvin_info rcar_info_r8a77990 = {
1189        .model = RCAR_GEN3,
1190        .use_mc = true,
1191        .nv12 = true,
1192        .max_width = 4096,
1193        .max_height = 4096,
1194        .routes = rcar_info_r8a77990_routes,
1195};
1196
1197static const struct rvin_group_route rcar_info_r8a77995_routes[] = {
1198        { /* Sentinel */ }
1199};
1200
1201static const struct rvin_info rcar_info_r8a77995 = {
1202        .model = RCAR_GEN3,
1203        .use_mc = true,
1204        .nv12 = true,
1205        .max_width = 4096,
1206        .max_height = 4096,
1207        .routes = rcar_info_r8a77995_routes,
1208};
1209
1210static const struct of_device_id rvin_of_id_table[] = {
1211        {
1212                .compatible = "renesas,vin-r8a774a1",
1213                .data = &rcar_info_r8a7796,
1214        },
1215        {
1216                .compatible = "renesas,vin-r8a774b1",
1217                .data = &rcar_info_r8a77965,
1218        },
1219        {
1220                .compatible = "renesas,vin-r8a774c0",
1221                .data = &rcar_info_r8a77990,
1222        },
1223        {
1224                .compatible = "renesas,vin-r8a7778",
1225                .data = &rcar_info_m1,
1226        },
1227        {
1228                .compatible = "renesas,vin-r8a7779",
1229                .data = &rcar_info_h1,
1230        },
1231        {
1232                .compatible = "renesas,vin-r8a7790",
1233                .data = &rcar_info_gen2,
1234        },
1235        {
1236                .compatible = "renesas,vin-r8a7791",
1237                .data = &rcar_info_gen2,
1238        },
1239        {
1240                .compatible = "renesas,vin-r8a7793",
1241                .data = &rcar_info_gen2,
1242        },
1243        {
1244                .compatible = "renesas,vin-r8a7794",
1245                .data = &rcar_info_gen2,
1246        },
1247        {
1248                .compatible = "renesas,rcar-gen2-vin",
1249                .data = &rcar_info_gen2,
1250        },
1251        {
1252                .compatible = "renesas,vin-r8a7795",
1253                .data = &rcar_info_r8a7795,
1254        },
1255        {
1256                .compatible = "renesas,vin-r8a7796",
1257                .data = &rcar_info_r8a7796,
1258        },
1259        {
1260                .compatible = "renesas,vin-r8a77965",
1261                .data = &rcar_info_r8a77965,
1262        },
1263        {
1264                .compatible = "renesas,vin-r8a77970",
1265                .data = &rcar_info_r8a77970,
1266        },
1267        {
1268                .compatible = "renesas,vin-r8a77980",
1269                .data = &rcar_info_r8a77980,
1270        },
1271        {
1272                .compatible = "renesas,vin-r8a77990",
1273                .data = &rcar_info_r8a77990,
1274        },
1275        {
1276                .compatible = "renesas,vin-r8a77995",
1277                .data = &rcar_info_r8a77995,
1278        },
1279        { /* Sentinel */ },
1280};
1281MODULE_DEVICE_TABLE(of, rvin_of_id_table);
1282
1283static const struct soc_device_attribute r8a7795es1[] = {
1284        {
1285                .soc_id = "r8a7795", .revision = "ES1.*",
1286                .data = &rcar_info_r8a7795es1,
1287        },
1288        { /* Sentinel */ }
1289};
1290
1291static int rcar_vin_probe(struct platform_device *pdev)
1292{
1293        const struct soc_device_attribute *attr;
1294        struct rvin_dev *vin;
1295        int irq, ret;
1296
1297        vin = devm_kzalloc(&pdev->dev, sizeof(*vin), GFP_KERNEL);
1298        if (!vin)
1299                return -ENOMEM;
1300
1301        vin->dev = &pdev->dev;
1302        vin->info = of_device_get_match_data(&pdev->dev);
1303        vin->alpha = 0xff;
1304
1305        /*
1306         * Special care is needed on r8a7795 ES1.x since it
1307         * uses different routing than r8a7795 ES2.0.
1308         */
1309        attr = soc_device_match(r8a7795es1);
1310        if (attr)
1311                vin->info = attr->data;
1312
1313        vin->base = devm_platform_ioremap_resource(pdev, 0);
1314        if (IS_ERR(vin->base))
1315                return PTR_ERR(vin->base);
1316
1317        irq = platform_get_irq(pdev, 0);
1318        if (irq < 0)
1319                return irq;
1320
1321        ret = rvin_dma_register(vin, irq);
1322        if (ret)
1323                return ret;
1324
1325        platform_set_drvdata(pdev, vin);
1326
1327        if (vin->info->use_mc) {
1328                ret = rvin_mc_init(vin);
1329                if (ret)
1330                        goto error_dma_unregister;
1331        }
1332
1333        ret = rvin_parallel_init(vin);
1334        if (ret)
1335                goto error_group_unregister;
1336
1337        pm_suspend_ignore_children(&pdev->dev, true);
1338        pm_runtime_enable(&pdev->dev);
1339
1340        return 0;
1341
1342error_group_unregister:
1343        v4l2_ctrl_handler_free(&vin->ctrl_handler);
1344
1345        if (vin->info->use_mc) {
1346                mutex_lock(&vin->group->lock);
1347                if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
1348                        v4l2_async_notifier_unregister(&vin->group->notifier);
1349                        v4l2_async_notifier_cleanup(&vin->group->notifier);
1350                }
1351                mutex_unlock(&vin->group->lock);
1352                rvin_group_put(vin);
1353        }
1354
1355error_dma_unregister:
1356        rvin_dma_unregister(vin);
1357
1358        return ret;
1359}
1360
1361static int rcar_vin_remove(struct platform_device *pdev)
1362{
1363        struct rvin_dev *vin = platform_get_drvdata(pdev);
1364
1365        pm_runtime_disable(&pdev->dev);
1366
1367        rvin_v4l2_unregister(vin);
1368
1369        v4l2_async_notifier_unregister(&vin->notifier);
1370        v4l2_async_notifier_cleanup(&vin->notifier);
1371
1372        if (vin->info->use_mc) {
1373                mutex_lock(&vin->group->lock);
1374                if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
1375                        v4l2_async_notifier_unregister(&vin->group->notifier);
1376                        v4l2_async_notifier_cleanup(&vin->group->notifier);
1377                }
1378                mutex_unlock(&vin->group->lock);
1379                rvin_group_put(vin);
1380        }
1381
1382        v4l2_ctrl_handler_free(&vin->ctrl_handler);
1383
1384        rvin_dma_unregister(vin);
1385
1386        return 0;
1387}
1388
1389static struct platform_driver rcar_vin_driver = {
1390        .driver = {
1391                .name = "rcar-vin",
1392                .of_match_table = rvin_of_id_table,
1393        },
1394        .probe = rcar_vin_probe,
1395        .remove = rcar_vin_remove,
1396};
1397
1398module_platform_driver(rcar_vin_driver);
1399
1400MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");
1401MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
1402MODULE_LICENSE("GPL");
1403