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] &&
 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_cleanup(&group->mdev);
 247        mutex_destroy(&group->lock);
 248}
 249
 250static int rvin_group_init(struct rvin_group *group, struct rvin_dev *vin)
 251{
 252        struct media_device *mdev = &group->mdev;
 253        const struct of_device_id *match;
 254        struct device_node *np;
 255
 256        mutex_init(&group->lock);
 257
 258        /* Count number of VINs in the system */
 259        group->count = 0;
 260        for_each_matching_node(np, vin->dev->driver->of_match_table)
 261                if (of_device_is_available(np))
 262                        group->count++;
 263
 264        vin_dbg(vin, "found %u enabled VIN's in DT", group->count);
 265
 266        mdev->dev = vin->dev;
 267        mdev->ops = &rvin_media_ops;
 268
 269        match = of_match_node(vin->dev->driver->of_match_table,
 270                              vin->dev->of_node);
 271
 272        strscpy(mdev->driver_name, KBUILD_MODNAME, sizeof(mdev->driver_name));
 273        strscpy(mdev->model, match->compatible, sizeof(mdev->model));
 274        snprintf(mdev->bus_info, sizeof(mdev->bus_info), "platform:%s",
 275                 dev_name(mdev->dev));
 276
 277        media_device_init(mdev);
 278
 279        return 0;
 280}
 281
 282static void rvin_group_release(struct kref *kref)
 283{
 284        struct rvin_group *group =
 285                container_of(kref, struct rvin_group, refcount);
 286
 287        mutex_lock(&rvin_group_lock);
 288
 289        rvin_group_data = NULL;
 290
 291        rvin_group_cleanup(group);
 292
 293        kfree(group);
 294
 295        mutex_unlock(&rvin_group_lock);
 296}
 297
 298static int rvin_group_get(struct rvin_dev *vin)
 299{
 300        struct rvin_group *group;
 301        u32 id;
 302        int ret;
 303
 304        /* Make sure VIN id is present and sane */
 305        ret = of_property_read_u32(vin->dev->of_node, "renesas,id", &id);
 306        if (ret) {
 307                vin_err(vin, "%pOF: No renesas,id property found\n",
 308                        vin->dev->of_node);
 309                return -EINVAL;
 310        }
 311
 312        if (id >= RCAR_VIN_NUM) {
 313                vin_err(vin, "%pOF: Invalid renesas,id '%u'\n",
 314                        vin->dev->of_node, id);
 315                return -EINVAL;
 316        }
 317
 318        /* Join or create a VIN group */
 319        mutex_lock(&rvin_group_lock);
 320        if (rvin_group_data) {
 321                group = rvin_group_data;
 322                kref_get(&group->refcount);
 323        } else {
 324                group = kzalloc(sizeof(*group), GFP_KERNEL);
 325                if (!group) {
 326                        ret = -ENOMEM;
 327                        goto err_group;
 328                }
 329
 330                ret = rvin_group_init(group, vin);
 331                if (ret) {
 332                        kfree(group);
 333                        vin_err(vin, "Failed to initialize group\n");
 334                        goto err_group;
 335                }
 336
 337                kref_init(&group->refcount);
 338
 339                rvin_group_data = group;
 340        }
 341        mutex_unlock(&rvin_group_lock);
 342
 343        /* Add VIN to group */
 344        mutex_lock(&group->lock);
 345
 346        if (group->vin[id]) {
 347                vin_err(vin, "Duplicate renesas,id property value %u\n", id);
 348                mutex_unlock(&group->lock);
 349                kref_put(&group->refcount, rvin_group_release);
 350                return -EINVAL;
 351        }
 352
 353        group->vin[id] = vin;
 354
 355        vin->id = id;
 356        vin->group = group;
 357        vin->v4l2_dev.mdev = &group->mdev;
 358
 359        mutex_unlock(&group->lock);
 360
 361        return 0;
 362err_group:
 363        mutex_unlock(&rvin_group_lock);
 364        return ret;
 365}
 366
 367static void rvin_group_put(struct rvin_dev *vin)
 368{
 369        struct rvin_group *group = vin->group;
 370
 371        mutex_lock(&group->lock);
 372
 373        vin->group = NULL;
 374        vin->v4l2_dev.mdev = NULL;
 375
 376        if (WARN_ON(group->vin[vin->id] != vin))
 377                goto out;
 378
 379        group->vin[vin->id] = NULL;
 380out:
 381        mutex_unlock(&group->lock);
 382
 383        kref_put(&group->refcount, rvin_group_release);
 384}
 385
 386/* -----------------------------------------------------------------------------
 387 * Controls
 388 */
 389
 390static int rvin_s_ctrl(struct v4l2_ctrl *ctrl)
 391{
 392        struct rvin_dev *vin =
 393                container_of(ctrl->handler, struct rvin_dev, ctrl_handler);
 394
 395        switch (ctrl->id) {
 396        case V4L2_CID_ALPHA_COMPONENT:
 397                rvin_set_alpha(vin, ctrl->val);
 398                break;
 399        }
 400
 401        return 0;
 402}
 403
 404static const struct v4l2_ctrl_ops rvin_ctrl_ops = {
 405        .s_ctrl = rvin_s_ctrl,
 406};
 407
 408/* -----------------------------------------------------------------------------
 409 * Async notifier
 410 */
 411
 412static int rvin_find_pad(struct v4l2_subdev *sd, int direction)
 413{
 414        unsigned int pad;
 415
 416        if (sd->entity.num_pads <= 1)
 417                return 0;
 418
 419        for (pad = 0; pad < sd->entity.num_pads; pad++)
 420                if (sd->entity.pads[pad].flags & direction)
 421                        return pad;
 422
 423        return -EINVAL;
 424}
 425
 426/* -----------------------------------------------------------------------------
 427 * Parallel async notifier
 428 */
 429
 430/* The vin lock should be held when calling the subdevice attach and detach */
 431static int rvin_parallel_subdevice_attach(struct rvin_dev *vin,
 432                                          struct v4l2_subdev *subdev)
 433{
 434        struct v4l2_subdev_mbus_code_enum code = {
 435                .which = V4L2_SUBDEV_FORMAT_ACTIVE,
 436        };
 437        int ret;
 438
 439        /* Find source and sink pad of remote subdevice */
 440        ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SOURCE);
 441        if (ret < 0)
 442                return ret;
 443        vin->parallel.source_pad = ret;
 444
 445        ret = rvin_find_pad(subdev, MEDIA_PAD_FL_SINK);
 446        vin->parallel.sink_pad = ret < 0 ? 0 : ret;
 447
 448        if (vin->info->use_mc) {
 449                vin->parallel.subdev = subdev;
 450                return 0;
 451        }
 452
 453        /* Find compatible subdevices mbus format */
 454        vin->mbus_code = 0;
 455        code.index = 0;
 456        code.pad = vin->parallel.source_pad;
 457        while (!vin->mbus_code &&
 458               !v4l2_subdev_call(subdev, pad, enum_mbus_code, NULL, &code)) {
 459                code.index++;
 460                switch (code.code) {
 461                case MEDIA_BUS_FMT_YUYV8_1X16:
 462                case MEDIA_BUS_FMT_UYVY8_1X16:
 463                case MEDIA_BUS_FMT_UYVY8_2X8:
 464                case MEDIA_BUS_FMT_UYVY10_2X10:
 465                case MEDIA_BUS_FMT_RGB888_1X24:
 466                        vin->mbus_code = code.code;
 467                        vin_dbg(vin, "Found media bus format for %s: %d\n",
 468                                subdev->name, vin->mbus_code);
 469                        break;
 470                default:
 471                        break;
 472                }
 473        }
 474
 475        if (!vin->mbus_code) {
 476                vin_err(vin, "Unsupported media bus format for %s\n",
 477                        subdev->name);
 478                return -EINVAL;
 479        }
 480
 481        /* Read tvnorms */
 482        ret = v4l2_subdev_call(subdev, video, g_tvnorms, &vin->vdev.tvnorms);
 483        if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
 484                return ret;
 485
 486        /* Read standard */
 487        vin->std = V4L2_STD_UNKNOWN;
 488        ret = v4l2_subdev_call(subdev, video, g_std, &vin->std);
 489        if (ret < 0 && ret != -ENOIOCTLCMD)
 490                return ret;
 491
 492        /* Add the controls */
 493        ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 16);
 494        if (ret < 0)
 495                return ret;
 496
 497        v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
 498                          V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
 499
 500        if (vin->ctrl_handler.error) {
 501                ret = vin->ctrl_handler.error;
 502                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 503                return ret;
 504        }
 505
 506        ret = v4l2_ctrl_add_handler(&vin->ctrl_handler, subdev->ctrl_handler,
 507                                    NULL, true);
 508        if (ret < 0) {
 509                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 510                return ret;
 511        }
 512
 513        vin->vdev.ctrl_handler = &vin->ctrl_handler;
 514
 515        vin->parallel.subdev = subdev;
 516
 517        return 0;
 518}
 519
 520static void rvin_parallel_subdevice_detach(struct rvin_dev *vin)
 521{
 522        rvin_v4l2_unregister(vin);
 523        vin->parallel.subdev = NULL;
 524
 525        if (!vin->info->use_mc) {
 526                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 527                vin->vdev.ctrl_handler = NULL;
 528        }
 529}
 530
 531static int rvin_parallel_notify_complete(struct v4l2_async_notifier *notifier)
 532{
 533        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 534        struct media_entity *source;
 535        struct media_entity *sink;
 536        int ret;
 537
 538        ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
 539        if (ret < 0) {
 540                vin_err(vin, "Failed to register subdev nodes\n");
 541                return ret;
 542        }
 543
 544        if (!video_is_registered(&vin->vdev)) {
 545                ret = rvin_v4l2_register(vin);
 546                if (ret < 0)
 547                        return ret;
 548        }
 549
 550        if (!vin->info->use_mc)
 551                return 0;
 552
 553        /* If we're running with media-controller, link the subdevs. */
 554        source = &vin->parallel.subdev->entity;
 555        sink = &vin->vdev.entity;
 556
 557        ret = media_create_pad_link(source, vin->parallel.source_pad,
 558                                    sink, vin->parallel.sink_pad, 0);
 559        if (ret)
 560                vin_err(vin, "Error adding link from %s to %s: %d\n",
 561                        source->name, sink->name, ret);
 562
 563        return ret;
 564}
 565
 566static void rvin_parallel_notify_unbind(struct v4l2_async_notifier *notifier,
 567                                        struct v4l2_subdev *subdev,
 568                                        struct v4l2_async_subdev *asd)
 569{
 570        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 571
 572        vin_dbg(vin, "unbind parallel subdev %s\n", subdev->name);
 573
 574        mutex_lock(&vin->lock);
 575        rvin_parallel_subdevice_detach(vin);
 576        mutex_unlock(&vin->lock);
 577}
 578
 579static int rvin_parallel_notify_bound(struct v4l2_async_notifier *notifier,
 580                                      struct v4l2_subdev *subdev,
 581                                      struct v4l2_async_subdev *asd)
 582{
 583        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 584        int ret;
 585
 586        mutex_lock(&vin->lock);
 587        ret = rvin_parallel_subdevice_attach(vin, subdev);
 588        mutex_unlock(&vin->lock);
 589        if (ret)
 590                return ret;
 591
 592        v4l2_set_subdev_hostdata(subdev, vin);
 593
 594        vin_dbg(vin, "bound subdev %s source pad: %u sink pad: %u\n",
 595                subdev->name, vin->parallel.source_pad,
 596                vin->parallel.sink_pad);
 597
 598        return 0;
 599}
 600
 601static const struct v4l2_async_notifier_operations rvin_parallel_notify_ops = {
 602        .bound = rvin_parallel_notify_bound,
 603        .unbind = rvin_parallel_notify_unbind,
 604        .complete = rvin_parallel_notify_complete,
 605};
 606
 607static int rvin_parallel_parse_of(struct rvin_dev *vin)
 608{
 609        struct fwnode_handle *ep, *fwnode;
 610        struct v4l2_fwnode_endpoint vep = {
 611                .bus_type = V4L2_MBUS_UNKNOWN,
 612        };
 613        struct v4l2_async_subdev *asd;
 614        int ret;
 615
 616        ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 0, 0, 0);
 617        if (!ep)
 618                return 0;
 619
 620        fwnode = fwnode_graph_get_remote_endpoint(ep);
 621        ret = v4l2_fwnode_endpoint_parse(ep, &vep);
 622        fwnode_handle_put(ep);
 623        if (ret) {
 624                vin_err(vin, "Failed to parse %pOF\n", to_of_node(fwnode));
 625                ret = -EINVAL;
 626                goto out;
 627        }
 628
 629        switch (vep.bus_type) {
 630        case V4L2_MBUS_PARALLEL:
 631        case V4L2_MBUS_BT656:
 632                vin_dbg(vin, "Found %s media bus\n",
 633                        vep.bus_type == V4L2_MBUS_PARALLEL ?
 634                        "PARALLEL" : "BT656");
 635                vin->parallel.mbus_type = vep.bus_type;
 636                vin->parallel.bus = vep.bus.parallel;
 637                break;
 638        default:
 639                vin_err(vin, "Unknown media bus type\n");
 640                ret = -EINVAL;
 641                goto out;
 642        }
 643
 644        asd = v4l2_async_notifier_add_fwnode_subdev(&vin->notifier, fwnode,
 645                                                    struct v4l2_async_subdev);
 646        if (IS_ERR(asd)) {
 647                ret = PTR_ERR(asd);
 648                goto out;
 649        }
 650
 651        vin->parallel.asd = asd;
 652
 653        vin_dbg(vin, "Add parallel OF device %pOF\n", to_of_node(fwnode));
 654out:
 655        fwnode_handle_put(fwnode);
 656
 657        return ret;
 658}
 659
 660static int rvin_parallel_init(struct rvin_dev *vin)
 661{
 662        int ret;
 663
 664        v4l2_async_notifier_init(&vin->notifier);
 665
 666        ret = rvin_parallel_parse_of(vin);
 667        if (ret)
 668                return ret;
 669
 670        /* If using mc, it's fine not to have any input registered. */
 671        if (!vin->parallel.asd)
 672                return vin->info->use_mc ? 0 : -ENODEV;
 673
 674        vin_dbg(vin, "Found parallel subdevice %pOF\n",
 675                to_of_node(vin->parallel.asd->match.fwnode));
 676
 677        vin->notifier.ops = &rvin_parallel_notify_ops;
 678        ret = v4l2_async_notifier_register(&vin->v4l2_dev, &vin->notifier);
 679        if (ret < 0) {
 680                vin_err(vin, "Notifier registration failed\n");
 681                v4l2_async_notifier_cleanup(&vin->notifier);
 682                return ret;
 683        }
 684
 685        return 0;
 686}
 687
 688/* -----------------------------------------------------------------------------
 689 * Group async notifier
 690 */
 691
 692static int rvin_group_notify_complete(struct v4l2_async_notifier *notifier)
 693{
 694        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 695        const struct rvin_group_route *route;
 696        unsigned int i;
 697        int ret;
 698
 699        ret = media_device_register(&vin->group->mdev);
 700        if (ret)
 701                return ret;
 702
 703        ret = v4l2_device_register_subdev_nodes(&vin->v4l2_dev);
 704        if (ret) {
 705                vin_err(vin, "Failed to register subdev nodes\n");
 706                return ret;
 707        }
 708
 709        /* Register all video nodes for the group. */
 710        for (i = 0; i < RCAR_VIN_NUM; i++) {
 711                if (vin->group->vin[i] &&
 712                    !video_is_registered(&vin->group->vin[i]->vdev)) {
 713                        ret = rvin_v4l2_register(vin->group->vin[i]);
 714                        if (ret)
 715                                return ret;
 716                }
 717        }
 718
 719        /* Create all media device links between VINs and CSI-2's. */
 720        mutex_lock(&vin->group->lock);
 721        for (route = vin->info->routes; route->mask; route++) {
 722                struct media_pad *source_pad, *sink_pad;
 723                struct media_entity *source, *sink;
 724                unsigned int source_idx;
 725
 726                /* Check that VIN is part of the group. */
 727                if (!vin->group->vin[route->vin])
 728                        continue;
 729
 730                /* Check that VIN' master is part of the group. */
 731                if (!vin->group->vin[rvin_group_id_to_master(route->vin)])
 732                        continue;
 733
 734                /* Check that CSI-2 is part of the group. */
 735                if (!vin->group->csi[route->csi].subdev)
 736                        continue;
 737
 738                source = &vin->group->csi[route->csi].subdev->entity;
 739                source_idx = rvin_group_csi_channel_to_pad(route->channel);
 740                source_pad = &source->pads[source_idx];
 741
 742                sink = &vin->group->vin[route->vin]->vdev.entity;
 743                sink_pad = &sink->pads[0];
 744
 745                /* Skip if link already exists. */
 746                if (media_entity_find_link(source_pad, sink_pad))
 747                        continue;
 748
 749                ret = media_create_pad_link(source, source_idx, sink, 0, 0);
 750                if (ret) {
 751                        vin_err(vin, "Error adding link from %s to %s\n",
 752                                source->name, sink->name);
 753                        break;
 754                }
 755        }
 756        mutex_unlock(&vin->group->lock);
 757
 758        return ret;
 759}
 760
 761static void rvin_group_notify_unbind(struct v4l2_async_notifier *notifier,
 762                                     struct v4l2_subdev *subdev,
 763                                     struct v4l2_async_subdev *asd)
 764{
 765        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 766        unsigned int i;
 767
 768        for (i = 0; i < RCAR_VIN_NUM; i++)
 769                if (vin->group->vin[i])
 770                        rvin_v4l2_unregister(vin->group->vin[i]);
 771
 772        mutex_lock(&vin->group->lock);
 773
 774        for (i = 0; i < RVIN_CSI_MAX; i++) {
 775                if (vin->group->csi[i].asd != asd)
 776                        continue;
 777                vin->group->csi[i].subdev = NULL;
 778                vin_dbg(vin, "Unbind CSI-2 %s from slot %u\n", subdev->name, i);
 779                break;
 780        }
 781
 782        mutex_unlock(&vin->group->lock);
 783
 784        media_device_unregister(&vin->group->mdev);
 785}
 786
 787static int rvin_group_notify_bound(struct v4l2_async_notifier *notifier,
 788                                   struct v4l2_subdev *subdev,
 789                                   struct v4l2_async_subdev *asd)
 790{
 791        struct rvin_dev *vin = v4l2_dev_to_vin(notifier->v4l2_dev);
 792        unsigned int i;
 793
 794        mutex_lock(&vin->group->lock);
 795
 796        for (i = 0; i < RVIN_CSI_MAX; i++) {
 797                if (vin->group->csi[i].asd != asd)
 798                        continue;
 799                vin->group->csi[i].subdev = subdev;
 800                vin_dbg(vin, "Bound CSI-2 %s to slot %u\n", subdev->name, i);
 801                break;
 802        }
 803
 804        mutex_unlock(&vin->group->lock);
 805
 806        return 0;
 807}
 808
 809static const struct v4l2_async_notifier_operations rvin_group_notify_ops = {
 810        .bound = rvin_group_notify_bound,
 811        .unbind = rvin_group_notify_unbind,
 812        .complete = rvin_group_notify_complete,
 813};
 814
 815static int rvin_mc_parse_of(struct rvin_dev *vin, unsigned int id)
 816{
 817        struct fwnode_handle *ep, *fwnode;
 818        struct v4l2_fwnode_endpoint vep = {
 819                .bus_type = V4L2_MBUS_CSI2_DPHY,
 820        };
 821        struct v4l2_async_subdev *asd;
 822        int ret;
 823
 824        ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(vin->dev), 1, id, 0);
 825        if (!ep)
 826                return 0;
 827
 828        fwnode = fwnode_graph_get_remote_endpoint(ep);
 829        ret = v4l2_fwnode_endpoint_parse(ep, &vep);
 830        fwnode_handle_put(ep);
 831        if (ret) {
 832                vin_err(vin, "Failed to parse %pOF\n", to_of_node(fwnode));
 833                ret = -EINVAL;
 834                goto out;
 835        }
 836
 837        if (!of_device_is_available(to_of_node(fwnode))) {
 838                vin_dbg(vin, "OF device %pOF disabled, ignoring\n",
 839                        to_of_node(fwnode));
 840                ret = -ENOTCONN;
 841                goto out;
 842        }
 843
 844        asd = v4l2_async_notifier_add_fwnode_subdev(&vin->group->notifier,
 845                                                    fwnode,
 846                                                    struct v4l2_async_subdev);
 847        if (IS_ERR(asd)) {
 848                ret = PTR_ERR(asd);
 849                goto out;
 850        }
 851
 852        vin->group->csi[vep.base.id].asd = asd;
 853
 854        vin_dbg(vin, "Add group OF device %pOF to slot %u\n",
 855                to_of_node(fwnode), vep.base.id);
 856out:
 857        fwnode_handle_put(fwnode);
 858
 859        return ret;
 860}
 861
 862static int rvin_mc_parse_of_graph(struct rvin_dev *vin)
 863{
 864        unsigned int count = 0, vin_mask = 0;
 865        unsigned int i, id;
 866        int ret;
 867
 868        mutex_lock(&vin->group->lock);
 869
 870        /* If not all VIN's are registered don't register the notifier. */
 871        for (i = 0; i < RCAR_VIN_NUM; i++) {
 872                if (vin->group->vin[i]) {
 873                        count++;
 874                        vin_mask |= BIT(i);
 875                }
 876        }
 877
 878        if (vin->group->count != count) {
 879                mutex_unlock(&vin->group->lock);
 880                return 0;
 881        }
 882
 883        mutex_unlock(&vin->group->lock);
 884
 885        v4l2_async_notifier_init(&vin->group->notifier);
 886
 887        /*
 888         * Have all VIN's look for CSI-2 subdevices. Some subdevices will
 889         * overlap but the parser function can handle it, so each subdevice
 890         * will only be registered once with the group notifier.
 891         */
 892        for (i = 0; i < RCAR_VIN_NUM; i++) {
 893                if (!(vin_mask & BIT(i)))
 894                        continue;
 895
 896                for (id = 0; id < RVIN_CSI_MAX; id++) {
 897                        if (vin->group->csi[id].asd)
 898                                continue;
 899
 900                        ret = rvin_mc_parse_of(vin->group->vin[i], id);
 901                        if (ret)
 902                                return ret;
 903                }
 904        }
 905
 906        if (list_empty(&vin->group->notifier.asd_list))
 907                return 0;
 908
 909        vin->group->notifier.ops = &rvin_group_notify_ops;
 910        ret = v4l2_async_notifier_register(&vin->v4l2_dev,
 911                                           &vin->group->notifier);
 912        if (ret < 0) {
 913                vin_err(vin, "Notifier registration failed\n");
 914                v4l2_async_notifier_cleanup(&vin->group->notifier);
 915                return ret;
 916        }
 917
 918        return 0;
 919}
 920
 921static int rvin_mc_init(struct rvin_dev *vin)
 922{
 923        int ret;
 924
 925        vin->pad.flags = MEDIA_PAD_FL_SINK;
 926        ret = media_entity_pads_init(&vin->vdev.entity, 1, &vin->pad);
 927        if (ret)
 928                return ret;
 929
 930        ret = rvin_group_get(vin);
 931        if (ret)
 932                return ret;
 933
 934        ret = rvin_mc_parse_of_graph(vin);
 935        if (ret)
 936                rvin_group_put(vin);
 937
 938        ret = v4l2_ctrl_handler_init(&vin->ctrl_handler, 1);
 939        if (ret < 0)
 940                return ret;
 941
 942        v4l2_ctrl_new_std(&vin->ctrl_handler, &rvin_ctrl_ops,
 943                          V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 255);
 944
 945        if (vin->ctrl_handler.error) {
 946                ret = vin->ctrl_handler.error;
 947                v4l2_ctrl_handler_free(&vin->ctrl_handler);
 948                return ret;
 949        }
 950
 951        vin->vdev.ctrl_handler = &vin->ctrl_handler;
 952
 953        return ret;
 954}
 955
 956/* -----------------------------------------------------------------------------
 957 * Suspend / Resume
 958 */
 959
 960static int __maybe_unused rvin_suspend(struct device *dev)
 961{
 962        struct rvin_dev *vin = dev_get_drvdata(dev);
 963
 964        if (vin->state != RUNNING)
 965                return 0;
 966
 967        rvin_stop_streaming(vin);
 968
 969        vin->state = SUSPENDED;
 970
 971        return 0;
 972}
 973
 974static int __maybe_unused rvin_resume(struct device *dev)
 975{
 976        struct rvin_dev *vin = dev_get_drvdata(dev);
 977
 978        if (vin->state != SUSPENDED)
 979                return 0;
 980
 981        /*
 982         * Restore group master CHSEL setting.
 983         *
 984         * This needs to be done by every VIN resuming not only the master
 985         * as we don't know if and in which order the master VINs will
 986         * be resumed.
 987         */
 988        if (vin->info->use_mc) {
 989                unsigned int master_id = rvin_group_id_to_master(vin->id);
 990                struct rvin_dev *master = vin->group->vin[master_id];
 991                int ret;
 992
 993                if (WARN_ON(!master))
 994                        return -ENODEV;
 995
 996                ret = rvin_set_channel_routing(master, master->chsel);
 997                if (ret)
 998                        return ret;
 999        }
1000
1001        return rvin_start_streaming(vin);
1002}
1003
1004/* -----------------------------------------------------------------------------
1005 * Platform Device Driver
1006 */
1007
1008static const struct rvin_info rcar_info_h1 = {
1009        .model = RCAR_H1,
1010        .use_mc = false,
1011        .max_width = 2048,
1012        .max_height = 2048,
1013};
1014
1015static const struct rvin_info rcar_info_m1 = {
1016        .model = RCAR_M1,
1017        .use_mc = false,
1018        .max_width = 2048,
1019        .max_height = 2048,
1020};
1021
1022static const struct rvin_info rcar_info_gen2 = {
1023        .model = RCAR_GEN2,
1024        .use_mc = false,
1025        .max_width = 2048,
1026        .max_height = 2048,
1027};
1028
1029static const struct rvin_group_route rcar_info_r8a774e1_routes[] = {
1030        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1031        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1032        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1033        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1034        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1035        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1036        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1037        { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
1038        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1039        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1040        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1041        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1042        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1043        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
1044        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1045        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1046        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1047        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1048        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1049        { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1050        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1051        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1052        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1053        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1054        { /* Sentinel */ }
1055};
1056
1057static const struct rvin_info rcar_info_r8a774e1 = {
1058        .model = RCAR_GEN3,
1059        .use_mc = true,
1060        .max_width = 4096,
1061        .max_height = 4096,
1062        .routes = rcar_info_r8a774e1_routes,
1063};
1064
1065static const struct rvin_group_route rcar_info_r8a7795_routes[] = {
1066        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1067        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1068        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1069        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1070        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1071        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1072        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1073        { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
1074        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1075        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1076        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1077        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1078        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1079        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
1080        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1081        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1082        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1083        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1084        { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
1085        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1086        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1087        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1088        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1089        { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1090        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1091        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1092        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1093        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1094        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1095        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1096        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1097        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1098        { /* Sentinel */ }
1099};
1100
1101static const struct rvin_info rcar_info_r8a7795 = {
1102        .model = RCAR_GEN3,
1103        .use_mc = true,
1104        .nv12 = true,
1105        .max_width = 4096,
1106        .max_height = 4096,
1107        .routes = rcar_info_r8a7795_routes,
1108};
1109
1110static const struct rvin_group_route rcar_info_r8a7795es1_routes[] = {
1111        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1112        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1113        { .csi = RVIN_CSI21, .channel = 0, .vin = 0, .mask = BIT(2) | BIT(5) },
1114        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1115        { .csi = RVIN_CSI21, .channel = 0, .vin = 1, .mask = BIT(1) },
1116        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1117        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1118        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1119        { .csi = RVIN_CSI21, .channel = 1, .vin = 1, .mask = BIT(5) },
1120        { .csi = RVIN_CSI21, .channel = 0, .vin = 2, .mask = BIT(0) },
1121        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1122        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1123        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1124        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1125        { .csi = RVIN_CSI21, .channel = 2, .vin = 2, .mask = BIT(5) },
1126        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1127        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1128        { .csi = RVIN_CSI21, .channel = 1, .vin = 3, .mask = BIT(2) },
1129        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1130        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1131        { .csi = RVIN_CSI21, .channel = 3, .vin = 3, .mask = BIT(5) },
1132        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1133        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1134        { .csi = RVIN_CSI21, .channel = 0, .vin = 4, .mask = BIT(2) | BIT(5) },
1135        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1136        { .csi = RVIN_CSI21, .channel = 0, .vin = 5, .mask = BIT(1) },
1137        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1138        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(3) },
1139        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1140        { .csi = RVIN_CSI21, .channel = 1, .vin = 5, .mask = BIT(5) },
1141        { .csi = RVIN_CSI21, .channel = 0, .vin = 6, .mask = BIT(0) },
1142        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1143        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1144        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1145        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1146        { .csi = RVIN_CSI21, .channel = 2, .vin = 6, .mask = BIT(5) },
1147        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1148        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1149        { .csi = RVIN_CSI21, .channel = 1, .vin = 7, .mask = BIT(2) },
1150        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1151        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1152        { .csi = RVIN_CSI21, .channel = 3, .vin = 7, .mask = BIT(5) },
1153        { /* Sentinel */ }
1154};
1155
1156static const struct rvin_info rcar_info_r8a7795es1 = {
1157        .model = RCAR_GEN3,
1158        .use_mc = true,
1159        .max_width = 4096,
1160        .max_height = 4096,
1161        .routes = rcar_info_r8a7795es1_routes,
1162};
1163
1164static const struct rvin_group_route rcar_info_r8a7796_routes[] = {
1165        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1166        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1167        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1168        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1169        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1170        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1171        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1172        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1173        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1174        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1175        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1176        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) },
1177        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1178        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1179        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1180        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1181        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1182        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1183        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(3) },
1184        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1185        { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1186        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1187        { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1188        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1189        { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1190        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) },
1191        { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1192        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1193        { /* Sentinel */ }
1194};
1195
1196static const struct rvin_info rcar_info_r8a7796 = {
1197        .model = RCAR_GEN3,
1198        .use_mc = true,
1199        .nv12 = true,
1200        .max_width = 4096,
1201        .max_height = 4096,
1202        .routes = rcar_info_r8a7796_routes,
1203};
1204
1205static const struct rvin_group_route rcar_info_r8a77965_routes[] = {
1206        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1207        { .csi = RVIN_CSI20, .channel = 0, .vin = 0, .mask = BIT(1) | BIT(4) },
1208        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1209        { .csi = RVIN_CSI20, .channel = 0, .vin = 1, .mask = BIT(0) },
1210        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1211        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1212        { .csi = RVIN_CSI20, .channel = 1, .vin = 1, .mask = BIT(4) },
1213        { .csi = RVIN_CSI20, .channel = 1, .vin = 2, .mask = BIT(0) },
1214        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1215        { .csi = RVIN_CSI20, .channel = 0, .vin = 2, .mask = BIT(2) },
1216        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1217        { .csi = RVIN_CSI20, .channel = 2, .vin = 2, .mask = BIT(4) },
1218        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1219        { .csi = RVIN_CSI20, .channel = 1, .vin = 3, .mask = BIT(1) | BIT(2) },
1220        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1221        { .csi = RVIN_CSI20, .channel = 3, .vin = 3, .mask = BIT(4) },
1222        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1223        { .csi = RVIN_CSI20, .channel = 0, .vin = 4, .mask = BIT(1) | BIT(4) },
1224        { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1225        { .csi = RVIN_CSI20, .channel = 0, .vin = 5, .mask = BIT(0) },
1226        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1227        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1228        { .csi = RVIN_CSI20, .channel = 1, .vin = 5, .mask = BIT(4) },
1229        { .csi = RVIN_CSI20, .channel = 1, .vin = 6, .mask = BIT(0) },
1230        { .csi = RVIN_CSI40, .channel = 0, .vin = 6, .mask = BIT(1) },
1231        { .csi = RVIN_CSI20, .channel = 0, .vin = 6, .mask = BIT(2) },
1232        { .csi = RVIN_CSI40, .channel = 2, .vin = 6, .mask = BIT(3) },
1233        { .csi = RVIN_CSI20, .channel = 2, .vin = 6, .mask = BIT(4) },
1234        { .csi = RVIN_CSI40, .channel = 1, .vin = 7, .mask = BIT(0) },
1235        { .csi = RVIN_CSI20, .channel = 1, .vin = 7, .mask = BIT(1) | BIT(2) },
1236        { .csi = RVIN_CSI40, .channel = 3, .vin = 7, .mask = BIT(3) },
1237        { .csi = RVIN_CSI20, .channel = 3, .vin = 7, .mask = BIT(4) },
1238        { /* Sentinel */ }
1239};
1240
1241static const struct rvin_info rcar_info_r8a77965 = {
1242        .model = RCAR_GEN3,
1243        .use_mc = true,
1244        .nv12 = true,
1245        .max_width = 4096,
1246        .max_height = 4096,
1247        .routes = rcar_info_r8a77965_routes,
1248};
1249
1250static const struct rvin_group_route rcar_info_r8a77970_routes[] = {
1251        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1252        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1253        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(3) },
1254        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1255        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1256        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1257        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1258        { /* Sentinel */ }
1259};
1260
1261static const struct rvin_info rcar_info_r8a77970 = {
1262        .model = RCAR_GEN3,
1263        .use_mc = true,
1264        .max_width = 4096,
1265        .max_height = 4096,
1266        .routes = rcar_info_r8a77970_routes,
1267};
1268
1269static const struct rvin_group_route rcar_info_r8a77980_routes[] = {
1270        { .csi = RVIN_CSI40, .channel = 0, .vin = 0, .mask = BIT(0) | BIT(3) },
1271        { .csi = RVIN_CSI40, .channel = 1, .vin = 0, .mask = BIT(2) },
1272        { .csi = RVIN_CSI40, .channel = 0, .vin = 1, .mask = BIT(2) },
1273        { .csi = RVIN_CSI40, .channel = 1, .vin = 1, .mask = BIT(1) | BIT(3) },
1274        { .csi = RVIN_CSI40, .channel = 0, .vin = 2, .mask = BIT(1) },
1275        { .csi = RVIN_CSI40, .channel = 2, .vin = 2, .mask = BIT(3) },
1276        { .csi = RVIN_CSI40, .channel = 1, .vin = 3, .mask = BIT(0) },
1277        { .csi = RVIN_CSI40, .channel = 3, .vin = 3, .mask = BIT(3) },
1278        { .csi = RVIN_CSI41, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1279        { .csi = RVIN_CSI41, .channel = 1, .vin = 4, .mask = BIT(2) },
1280        { .csi = RVIN_CSI41, .channel = 0, .vin = 5, .mask = BIT(2) },
1281        { .csi = RVIN_CSI41, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1282        { .csi = RVIN_CSI41, .channel = 0, .vin = 6, .mask = BIT(1) },
1283        { .csi = RVIN_CSI41, .channel = 2, .vin = 6, .mask = BIT(3) },
1284        { .csi = RVIN_CSI41, .channel = 1, .vin = 7, .mask = BIT(0) },
1285        { .csi = RVIN_CSI41, .channel = 3, .vin = 7, .mask = BIT(3) },
1286        { /* Sentinel */ }
1287};
1288
1289static const struct rvin_info rcar_info_r8a77980 = {
1290        .model = RCAR_GEN3,
1291        .use_mc = true,
1292        .nv12 = true,
1293        .max_width = 4096,
1294        .max_height = 4096,
1295        .routes = rcar_info_r8a77980_routes,
1296};
1297
1298static const struct rvin_group_route rcar_info_r8a77990_routes[] = {
1299        { .csi = RVIN_CSI40, .channel = 0, .vin = 4, .mask = BIT(0) | BIT(3) },
1300        { .csi = RVIN_CSI40, .channel = 0, .vin = 5, .mask = BIT(2) },
1301        { .csi = RVIN_CSI40, .channel = 1, .vin = 4, .mask = BIT(2) },
1302        { .csi = RVIN_CSI40, .channel = 1, .vin = 5, .mask = BIT(1) | BIT(3) },
1303        { /* Sentinel */ }
1304};
1305
1306static const struct rvin_info rcar_info_r8a77990 = {
1307        .model = RCAR_GEN3,
1308        .use_mc = true,
1309        .nv12 = true,
1310        .max_width = 4096,
1311        .max_height = 4096,
1312        .routes = rcar_info_r8a77990_routes,
1313};
1314
1315static const struct rvin_group_route rcar_info_r8a77995_routes[] = {
1316        { /* Sentinel */ }
1317};
1318
1319static const struct rvin_info rcar_info_r8a77995 = {
1320        .model = RCAR_GEN3,
1321        .use_mc = true,
1322        .nv12 = true,
1323        .max_width = 4096,
1324        .max_height = 4096,
1325        .routes = rcar_info_r8a77995_routes,
1326};
1327
1328static const struct of_device_id rvin_of_id_table[] = {
1329        {
1330                .compatible = "renesas,vin-r8a774a1",
1331                .data = &rcar_info_r8a7796,
1332        },
1333        {
1334                .compatible = "renesas,vin-r8a774b1",
1335                .data = &rcar_info_r8a77965,
1336        },
1337        {
1338                .compatible = "renesas,vin-r8a774c0",
1339                .data = &rcar_info_r8a77990,
1340        },
1341        {
1342                .compatible = "renesas,vin-r8a774e1",
1343                .data = &rcar_info_r8a774e1,
1344        },
1345        {
1346                .compatible = "renesas,vin-r8a7778",
1347                .data = &rcar_info_m1,
1348        },
1349        {
1350                .compatible = "renesas,vin-r8a7779",
1351                .data = &rcar_info_h1,
1352        },
1353        {
1354                .compatible = "renesas,rcar-gen2-vin",
1355                .data = &rcar_info_gen2,
1356        },
1357        {
1358                .compatible = "renesas,vin-r8a7795",
1359                .data = &rcar_info_r8a7795,
1360        },
1361        {
1362                .compatible = "renesas,vin-r8a7796",
1363                .data = &rcar_info_r8a7796,
1364        },
1365        {
1366                .compatible = "renesas,vin-r8a77961",
1367                .data = &rcar_info_r8a7796,
1368        },
1369        {
1370                .compatible = "renesas,vin-r8a77965",
1371                .data = &rcar_info_r8a77965,
1372        },
1373        {
1374                .compatible = "renesas,vin-r8a77970",
1375                .data = &rcar_info_r8a77970,
1376        },
1377        {
1378                .compatible = "renesas,vin-r8a77980",
1379                .data = &rcar_info_r8a77980,
1380        },
1381        {
1382                .compatible = "renesas,vin-r8a77990",
1383                .data = &rcar_info_r8a77990,
1384        },
1385        {
1386                .compatible = "renesas,vin-r8a77995",
1387                .data = &rcar_info_r8a77995,
1388        },
1389        { /* Sentinel */ },
1390};
1391MODULE_DEVICE_TABLE(of, rvin_of_id_table);
1392
1393static const struct soc_device_attribute r8a7795es1[] = {
1394        {
1395                .soc_id = "r8a7795", .revision = "ES1.*",
1396                .data = &rcar_info_r8a7795es1,
1397        },
1398        { /* Sentinel */ }
1399};
1400
1401static int rcar_vin_probe(struct platform_device *pdev)
1402{
1403        const struct soc_device_attribute *attr;
1404        struct rvin_dev *vin;
1405        int irq, ret;
1406
1407        vin = devm_kzalloc(&pdev->dev, sizeof(*vin), GFP_KERNEL);
1408        if (!vin)
1409                return -ENOMEM;
1410
1411        vin->dev = &pdev->dev;
1412        vin->info = of_device_get_match_data(&pdev->dev);
1413        vin->alpha = 0xff;
1414
1415        /*
1416         * Special care is needed on r8a7795 ES1.x since it
1417         * uses different routing than r8a7795 ES2.0.
1418         */
1419        attr = soc_device_match(r8a7795es1);
1420        if (attr)
1421                vin->info = attr->data;
1422
1423        vin->base = devm_platform_ioremap_resource(pdev, 0);
1424        if (IS_ERR(vin->base))
1425                return PTR_ERR(vin->base);
1426
1427        irq = platform_get_irq(pdev, 0);
1428        if (irq < 0)
1429                return irq;
1430
1431        ret = rvin_dma_register(vin, irq);
1432        if (ret)
1433                return ret;
1434
1435        platform_set_drvdata(pdev, vin);
1436
1437        if (vin->info->use_mc) {
1438                ret = rvin_mc_init(vin);
1439                if (ret)
1440                        goto error_dma_unregister;
1441        }
1442
1443        ret = rvin_parallel_init(vin);
1444        if (ret)
1445                goto error_group_unregister;
1446
1447        pm_suspend_ignore_children(&pdev->dev, true);
1448        pm_runtime_enable(&pdev->dev);
1449
1450        return 0;
1451
1452error_group_unregister:
1453        v4l2_ctrl_handler_free(&vin->ctrl_handler);
1454
1455        if (vin->info->use_mc) {
1456                mutex_lock(&vin->group->lock);
1457                if (&vin->v4l2_dev == vin->group->notifier.v4l2_dev) {
1458                        v4l2_async_notifier_unregister(&vin->group->notifier);
1459                        v4l2_async_notifier_cleanup(&vin->group->notifier);
1460                }
1461                mutex_unlock(&vin->group->lock);
1462                rvin_group_put(vin);
1463        }
1464
1465error_dma_unregister:
1466        rvin_dma_unregister(vin);
1467
1468        return ret;
1469}
1470
1471static int rcar_vin_remove(struct platform_device *pdev)
1472{
1473        struct rvin_dev *vin = platform_get_drvdata(pdev);
1474
1475        pm_runtime_disable(&pdev->dev);
1476
1477        rvin_v4l2_unregister(vin);
1478
1479        v4l2_async_notifier_unregister(&vin->notifier);
1480        v4l2_async_notifier_cleanup(&vin->notifier);
1481
1482        if (vin->info->use_mc) {
1483                v4l2_async_notifier_unregister(&vin->group->notifier);
1484                v4l2_async_notifier_cleanup(&vin->group->notifier);
1485                rvin_group_put(vin);
1486        }
1487
1488        v4l2_ctrl_handler_free(&vin->ctrl_handler);
1489
1490        rvin_dma_unregister(vin);
1491
1492        return 0;
1493}
1494
1495static SIMPLE_DEV_PM_OPS(rvin_pm_ops, rvin_suspend, rvin_resume);
1496
1497static struct platform_driver rcar_vin_driver = {
1498        .driver = {
1499                .name = "rcar-vin",
1500                .pm = &rvin_pm_ops,
1501                .of_match_table = rvin_of_id_table,
1502        },
1503        .probe = rcar_vin_probe,
1504        .remove = rcar_vin_remove,
1505};
1506
1507module_platform_driver(rcar_vin_driver);
1508
1509MODULE_AUTHOR("Niklas Söderlund <niklas.soderlund@ragnatech.se>");
1510MODULE_DESCRIPTION("Renesas R-Car VIN camera host driver");
1511MODULE_LICENSE("GPL");
1512