File Index
Files and directories
Sign in
FILE

rcar-core.c

File preview with syntax highlighting.

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