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