root/drivers/media/platform/rcar-vin/rcar-core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rvin_group_entity_to_csi_id
  2. rvin_group_get_mask
  3. rvin_group_link_notify
  4. rvin_group_cleanup
  5. rvin_group_init
  6. rvin_group_release
  7. rvin_group_get
  8. rvin_group_put
  9. rvin_s_ctrl
  10. rvin_find_pad
  11. rvin_parallel_subdevice_attach
  12. rvin_parallel_subdevice_detach
  13. rvin_parallel_notify_complete
  14. rvin_parallel_notify_unbind
  15. rvin_parallel_notify_bound
  16. rvin_parallel_parse_v4l2
  17. rvin_parallel_init
  18. rvin_group_notify_complete
  19. rvin_group_notify_unbind
  20. rvin_group_notify_bound
  21. rvin_mc_parse_of_endpoint
  22. rvin_mc_parse_of_graph
  23. rvin_mc_init
  24. rcar_vin_probe
  25. rcar_vin_remove

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

/* [<][>][^][v][top][bottom][index][help] */