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