1 /* 2 * Xilinx Video IP Composite Device 3 * 4 * Copyright (C) 2013-2015 Ideas on Board 5 * Copyright (C) 2013-2015 Xilinx, Inc. 6 * 7 * Contacts: Hyun Kwon <hyun.kwon@xilinx.com> 8 * Laurent Pinchart <laurent.pinchart@ideasonboard.com> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15 #include <linux/list.h> 16 #include <linux/module.h> 17 #include <linux/of.h> 18 #include <linux/of_graph.h> 19 #include <linux/platform_device.h> 20 #include <linux/slab.h> 21 22 #include <media/v4l2-async.h> 23 #include <media/v4l2-common.h> 24 #include <media/v4l2-device.h> 25 #include <media/v4l2-fwnode.h> 26 27 #include "xilinx-dma.h" 28 #include "xilinx-vipp.h" 29 30 #define XVIPP_DMA_S2MM 0 31 #define XVIPP_DMA_MM2S 1 32 33 /** 34 * struct xvip_graph_entity - Entity in the video graph 35 * @list: list entry in a graph entities list 36 * @node: the entity's DT node 37 * @entity: media entity, from the corresponding V4L2 subdev 38 * @asd: subdev asynchronous registration information 39 * @subdev: V4L2 subdev 40 */ 41 struct xvip_graph_entity { 42 struct list_head list; 43 struct device_node *node; 44 struct media_entity *entity; 45 46 struct v4l2_async_subdev asd; 47 struct v4l2_subdev *subdev; 48 }; 49 50 /* ----------------------------------------------------------------------------- 51 * Graph Management 52 */ 53 54 static struct xvip_graph_entity * 55 xvip_graph_find_entity(struct xvip_composite_device *xdev, 56 const struct device_node *node) 57 { 58 struct xvip_graph_entity *entity; 59 60 list_for_each_entry(entity, &xdev->entities, list) { 61 if (entity->node == node) 62 return entity; 63 } 64 65 return NULL; 66 } 67 68 static int xvip_graph_build_one(struct xvip_composite_device *xdev, 69 struct xvip_graph_entity *entity) 70 { 71 u32 link_flags = MEDIA_LNK_FL_ENABLED; 72 struct media_entity *local = entity->entity; 73 struct media_entity *remote; 74 struct media_pad *local_pad; 75 struct media_pad *remote_pad; 76 struct xvip_graph_entity *ent; 77 struct v4l2_fwnode_link link; 78 struct device_node *ep = NULL; 79 struct device_node *next; 80 int ret = 0; 81 82 dev_dbg(xdev->dev, "creating links for entity %s\n", local->name); 83 84 while (1) { 85 /* Get the next endpoint and parse its link. */ 86 next = of_graph_get_next_endpoint(entity->node, ep); 87 if (next == NULL) 88 break; 89 90 of_node_put(ep); 91 ep = next; 92 93 dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep); 94 95 ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); 96 if (ret < 0) { 97 dev_err(xdev->dev, "failed to parse link for %pOF\n", 98 ep); 99 continue; 100 } 101 102 /* Skip sink ports, they will be processed from the other end of 103 * the link. 104 */ 105 if (link.local_port >= local->num_pads) { 106 dev_err(xdev->dev, "invalid port number %u for %pOF\n", 107 link.local_port, 108 to_of_node(link.local_node)); 109 v4l2_fwnode_put_link(&link); 110 ret = -EINVAL; 111 break; 112 } 113 114 local_pad = &local->pads[link.local_port]; 115 116 if (local_pad->flags & MEDIA_PAD_FL_SINK) { 117 dev_dbg(xdev->dev, "skipping sink port %pOF:%u\n", 118 to_of_node(link.local_node), 119 link.local_port); 120 v4l2_fwnode_put_link(&link); 121 continue; 122 } 123 124 /* Skip DMA engines, they will be processed separately. */ 125 if (link.remote_node == of_fwnode_handle(xdev->dev->of_node)) { 126 dev_dbg(xdev->dev, "skipping DMA port %pOF:%u\n", 127 to_of_node(link.local_node), 128 link.local_port); 129 v4l2_fwnode_put_link(&link); 130 continue; 131 } 132 133 /* Find the remote entity. */ 134 ent = xvip_graph_find_entity(xdev, 135 to_of_node(link.remote_node)); 136 if (ent == NULL) { 137 dev_err(xdev->dev, "no entity found for %pOF\n", 138 to_of_node(link.remote_node)); 139 v4l2_fwnode_put_link(&link); 140 ret = -ENODEV; 141 break; 142 } 143 144 remote = ent->entity; 145 146 if (link.remote_port >= remote->num_pads) { 147 dev_err(xdev->dev, "invalid port number %u on %pOF\n", 148 link.remote_port, to_of_node(link.remote_node)); 149 v4l2_fwnode_put_link(&link); 150 ret = -EINVAL; 151 break; 152 } 153 154 remote_pad = &remote->pads[link.remote_port]; 155 156 v4l2_fwnode_put_link(&link); 157 158 /* Create the media link. */ 159 dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", 160 local->name, local_pad->index, 161 remote->name, remote_pad->index); 162 163 ret = media_create_pad_link(local, local_pad->index, 164 remote, remote_pad->index, 165 link_flags); 166 if (ret < 0) { 167 dev_err(xdev->dev, 168 "failed to create %s:%u -> %s:%u link\n", 169 local->name, local_pad->index, 170 remote->name, remote_pad->index); 171 break; 172 } 173 } 174 175 of_node_put(ep); 176 return ret; 177 } 178 179 static struct xvip_dma * 180 xvip_graph_find_dma(struct xvip_composite_device *xdev, unsigned int port) 181 { 182 struct xvip_dma *dma; 183 184 list_for_each_entry(dma, &xdev->dmas, list) { 185 if (dma->port == port) 186 return dma; 187 } 188 189 return NULL; 190 } 191 192 static int xvip_graph_build_dma(struct xvip_composite_device *xdev) 193 { 194 u32 link_flags = MEDIA_LNK_FL_ENABLED; 195 struct device_node *node = xdev->dev->of_node; 196 struct media_entity *source; 197 struct media_entity *sink; 198 struct media_pad *source_pad; 199 struct media_pad *sink_pad; 200 struct xvip_graph_entity *ent; 201 struct v4l2_fwnode_link link; 202 struct device_node *ep = NULL; 203 struct device_node *next; 204 struct xvip_dma *dma; 205 int ret = 0; 206 207 dev_dbg(xdev->dev, "creating links for DMA engines\n"); 208 209 while (1) { 210 /* Get the next endpoint and parse its link. */ 211 next = of_graph_get_next_endpoint(node, ep); 212 if (next == NULL) 213 break; 214 215 of_node_put(ep); 216 ep = next; 217 218 dev_dbg(xdev->dev, "processing endpoint %pOF\n", ep); 219 220 ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); 221 if (ret < 0) { 222 dev_err(xdev->dev, "failed to parse link for %pOF\n", 223 ep); 224 continue; 225 } 226 227 /* Find the DMA engine. */ 228 dma = xvip_graph_find_dma(xdev, link.local_port); 229 if (dma == NULL) { 230 dev_err(xdev->dev, "no DMA engine found for port %u\n", 231 link.local_port); 232 v4l2_fwnode_put_link(&link); 233 ret = -EINVAL; 234 break; 235 } 236 237 dev_dbg(xdev->dev, "creating link for DMA engine %s\n", 238 dma->video.name); 239 240 /* Find the remote entity. */ 241 ent = xvip_graph_find_entity(xdev, 242 to_of_node(link.remote_node)); 243 if (ent == NULL) { 244 dev_err(xdev->dev, "no entity found for %pOF\n", 245 to_of_node(link.remote_node)); 246 v4l2_fwnode_put_link(&link); 247 ret = -ENODEV; 248 break; 249 } 250 251 if (link.remote_port >= ent->entity->num_pads) { 252 dev_err(xdev->dev, "invalid port number %u on %pOF\n", 253 link.remote_port, 254 to_of_node(link.remote_node)); 255 v4l2_fwnode_put_link(&link); 256 ret = -EINVAL; 257 break; 258 } 259 260 if (dma->pad.flags & MEDIA_PAD_FL_SOURCE) { 261 source = &dma->video.entity; 262 source_pad = &dma->pad; 263 sink = ent->entity; 264 sink_pad = &sink->pads[link.remote_port]; 265 } else { 266 source = ent->entity; 267 source_pad = &source->pads[link.remote_port]; 268 sink = &dma->video.entity; 269 sink_pad = &dma->pad; 270 } 271 272 v4l2_fwnode_put_link(&link); 273 274 /* Create the media link. */ 275 dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", 276 source->name, source_pad->index, 277 sink->name, sink_pad->index); 278 279 ret = media_create_pad_link(source, source_pad->index, 280 sink, sink_pad->index, 281 link_flags); 282 if (ret < 0) { 283 dev_err(xdev->dev, 284 "failed to create %s:%u -> %s:%u link\n", 285 source->name, source_pad->index, 286 sink->name, sink_pad->index); 287 break; 288 } 289 } 290 291 of_node_put(ep); 292 return ret; 293 } 294 295 static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) 296 { 297 struct xvip_composite_device *xdev = 298 container_of(notifier, struct xvip_composite_device, notifier); 299 struct xvip_graph_entity *entity; 300 int ret; 301 302 dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); 303 304 /* Create links for every entity. */ 305 list_for_each_entry(entity, &xdev->entities, list) { 306 ret = xvip_graph_build_one(xdev, entity); 307 if (ret < 0) 308 return ret; 309 } 310 311 /* Create links for DMA channels. */ 312 ret = xvip_graph_build_dma(xdev); 313 if (ret < 0) 314 return ret; 315 316 ret = v4l2_device_register_subdev_nodes(&xdev->v4l2_dev); 317 if (ret < 0) 318 dev_err(xdev->dev, "failed to register subdev nodes\n"); 319 320 return media_device_register(&xdev->media_dev); 321 } 322 323 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, 324 struct v4l2_subdev *subdev, 325 struct v4l2_async_subdev *asd) 326 { 327 struct xvip_composite_device *xdev = 328 container_of(notifier, struct xvip_composite_device, notifier); 329 struct xvip_graph_entity *entity; 330 331 /* Locate the entity corresponding to the bound subdev and store the 332 * subdev pointer. 333 */ 334 list_for_each_entry(entity, &xdev->entities, list) { 335 if (entity->node != subdev->dev->of_node) 336 continue; 337 338 if (entity->subdev) { 339 dev_err(xdev->dev, "duplicate subdev for node %pOF\n", 340 entity->node); 341 return -EINVAL; 342 } 343 344 dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name); 345 entity->entity = &subdev->entity; 346 entity->subdev = subdev; 347 return 0; 348 } 349 350 dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name); 351 return -EINVAL; 352 } 353 354 static int xvip_graph_parse_one(struct xvip_composite_device *xdev, 355 struct device_node *node) 356 { 357 struct xvip_graph_entity *entity; 358 struct device_node *remote; 359 struct device_node *ep = NULL; 360 int ret = 0; 361 362 dev_dbg(xdev->dev, "parsing node %pOF\n", node); 363 364 while (1) { 365 ep = of_graph_get_next_endpoint(node, ep); 366 if (ep == NULL) 367 break; 368 369 dev_dbg(xdev->dev, "handling endpoint %pOF\n", ep); 370 371 remote = of_graph_get_remote_port_parent(ep); 372 if (remote == NULL) { 373 ret = -EINVAL; 374 break; 375 } 376 377 /* Skip entities that we have already processed. */ 378 if (remote == xdev->dev->of_node || 379 xvip_graph_find_entity(xdev, remote)) { 380 of_node_put(remote); 381 continue; 382 } 383 384 entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL); 385 if (entity == NULL) { 386 of_node_put(remote); 387 ret = -ENOMEM; 388 break; 389 } 390 391 entity->node = remote; 392 entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 393 entity->asd.match.fwnode.fwnode = of_fwnode_handle(remote); 394 list_add_tail(&entity->list, &xdev->entities); 395 xdev->num_subdevs++; 396 } 397 398 of_node_put(ep); 399 return ret; 400 } 401 402 static int xvip_graph_parse(struct xvip_composite_device *xdev) 403 { 404 struct xvip_graph_entity *entity; 405 int ret; 406 407 /* 408 * Walk the links to parse the full graph. Start by parsing the 409 * composite node and then parse entities in turn. The list_for_each 410 * loop will handle entities added at the end of the list while walking 411 * the links. 412 */ 413 ret = xvip_graph_parse_one(xdev, xdev->dev->of_node); 414 if (ret < 0) 415 return 0; 416 417 list_for_each_entry(entity, &xdev->entities, list) { 418 ret = xvip_graph_parse_one(xdev, entity->node); 419 if (ret < 0) 420 break; 421 } 422 423 return ret; 424 } 425 426 static int xvip_graph_dma_init_one(struct xvip_composite_device *xdev, 427 struct device_node *node) 428 { 429 struct xvip_dma *dma; 430 enum v4l2_buf_type type; 431 const char *direction; 432 unsigned int index; 433 int ret; 434 435 ret = of_property_read_string(node, "direction", &direction); 436 if (ret < 0) 437 return ret; 438 439 if (strcmp(direction, "input") == 0) 440 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 441 else if (strcmp(direction, "output") == 0) 442 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 443 else 444 return -EINVAL; 445 446 of_property_read_u32(node, "reg", &index); 447 448 dma = devm_kzalloc(xdev->dev, sizeof(*dma), GFP_KERNEL); 449 if (dma == NULL) 450 return -ENOMEM; 451 452 ret = xvip_dma_init(xdev, dma, type, index); 453 if (ret < 0) { 454 dev_err(xdev->dev, "%pOF initialization failed\n", node); 455 return ret; 456 } 457 458 list_add_tail(&dma->list, &xdev->dmas); 459 460 xdev->v4l2_caps |= type == V4L2_BUF_TYPE_VIDEO_CAPTURE 461 ? V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_VIDEO_OUTPUT; 462 463 return 0; 464 } 465 466 static int xvip_graph_dma_init(struct xvip_composite_device *xdev) 467 { 468 struct device_node *ports; 469 struct device_node *port; 470 int ret; 471 472 ports = of_get_child_by_name(xdev->dev->of_node, "ports"); 473 if (ports == NULL) { 474 dev_err(xdev->dev, "ports node not present\n"); 475 return -EINVAL; 476 } 477 478 for_each_child_of_node(ports, port) { 479 ret = xvip_graph_dma_init_one(xdev, port); 480 if (ret < 0) { 481 of_node_put(port); 482 return ret; 483 } 484 } 485 486 return 0; 487 } 488 489 static void xvip_graph_cleanup(struct xvip_composite_device *xdev) 490 { 491 struct xvip_graph_entity *entityp; 492 struct xvip_graph_entity *entity; 493 struct xvip_dma *dmap; 494 struct xvip_dma *dma; 495 496 v4l2_async_notifier_unregister(&xdev->notifier); 497 498 list_for_each_entry_safe(entity, entityp, &xdev->entities, list) { 499 of_node_put(entity->node); 500 list_del(&entity->list); 501 } 502 503 list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) { 504 xvip_dma_cleanup(dma); 505 list_del(&dma->list); 506 } 507 } 508 509 static int xvip_graph_init(struct xvip_composite_device *xdev) 510 { 511 struct xvip_graph_entity *entity; 512 struct v4l2_async_subdev **subdevs = NULL; 513 unsigned int num_subdevs; 514 unsigned int i; 515 int ret; 516 517 /* Init the DMA channels. */ 518 ret = xvip_graph_dma_init(xdev); 519 if (ret < 0) { 520 dev_err(xdev->dev, "DMA initialization failed\n"); 521 goto done; 522 } 523 524 /* Parse the graph to extract a list of subdevice DT nodes. */ 525 ret = xvip_graph_parse(xdev); 526 if (ret < 0) { 527 dev_err(xdev->dev, "graph parsing failed\n"); 528 goto done; 529 } 530 531 if (!xdev->num_subdevs) { 532 dev_err(xdev->dev, "no subdev found in graph\n"); 533 goto done; 534 } 535 536 /* Register the subdevices notifier. */ 537 num_subdevs = xdev->num_subdevs; 538 subdevs = devm_kzalloc(xdev->dev, sizeof(*subdevs) * num_subdevs, 539 GFP_KERNEL); 540 if (subdevs == NULL) { 541 ret = -ENOMEM; 542 goto done; 543 } 544 545 i = 0; 546 list_for_each_entry(entity, &xdev->entities, list) 547 subdevs[i++] = &entity->asd; 548 549 xdev->notifier.subdevs = subdevs; 550 xdev->notifier.num_subdevs = num_subdevs; 551 xdev->notifier.bound = xvip_graph_notify_bound; 552 xdev->notifier.complete = xvip_graph_notify_complete; 553 554 ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier); 555 if (ret < 0) { 556 dev_err(xdev->dev, "notifier registration failed\n"); 557 goto done; 558 } 559 560 ret = 0; 561 562 done: 563 if (ret < 0) 564 xvip_graph_cleanup(xdev); 565 566 return ret; 567 } 568 569 /* ----------------------------------------------------------------------------- 570 * Media Controller and V4L2 571 */ 572 573 static void xvip_composite_v4l2_cleanup(struct xvip_composite_device *xdev) 574 { 575 v4l2_device_unregister(&xdev->v4l2_dev); 576 media_device_unregister(&xdev->media_dev); 577 media_device_cleanup(&xdev->media_dev); 578 } 579 580 static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) 581 { 582 int ret; 583 584 xdev->media_dev.dev = xdev->dev; 585 strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device", 586 sizeof(xdev->media_dev.model)); 587 xdev->media_dev.hw_revision = 0; 588 589 media_device_init(&xdev->media_dev); 590 591 xdev->v4l2_dev.mdev = &xdev->media_dev; 592 ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev); 593 if (ret < 0) { 594 dev_err(xdev->dev, "V4L2 device registration failed (%d)\n", 595 ret); 596 media_device_cleanup(&xdev->media_dev); 597 return ret; 598 } 599 600 return 0; 601 } 602 603 /* ----------------------------------------------------------------------------- 604 * Platform Device Driver 605 */ 606 607 static int xvip_composite_probe(struct platform_device *pdev) 608 { 609 struct xvip_composite_device *xdev; 610 int ret; 611 612 xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); 613 if (!xdev) 614 return -ENOMEM; 615 616 xdev->dev = &pdev->dev; 617 INIT_LIST_HEAD(&xdev->entities); 618 INIT_LIST_HEAD(&xdev->dmas); 619 620 ret = xvip_composite_v4l2_init(xdev); 621 if (ret < 0) 622 return ret; 623 624 ret = xvip_graph_init(xdev); 625 if (ret < 0) 626 goto error; 627 628 platform_set_drvdata(pdev, xdev); 629 630 dev_info(xdev->dev, "device registered\n"); 631 632 return 0; 633 634 error: 635 xvip_composite_v4l2_cleanup(xdev); 636 return ret; 637 } 638 639 static int xvip_composite_remove(struct platform_device *pdev) 640 { 641 struct xvip_composite_device *xdev = platform_get_drvdata(pdev); 642 643 xvip_graph_cleanup(xdev); 644 xvip_composite_v4l2_cleanup(xdev); 645 646 return 0; 647 } 648 649 static const struct of_device_id xvip_composite_of_id_table[] = { 650 { .compatible = "xlnx,video" }, 651 { } 652 }; 653 MODULE_DEVICE_TABLE(of, xvip_composite_of_id_table); 654 655 static struct platform_driver xvip_composite_driver = { 656 .driver = { 657 .name = "xilinx-video", 658 .of_match_table = xvip_composite_of_id_table, 659 }, 660 .probe = xvip_composite_probe, 661 .remove = xvip_composite_remove, 662 }; 663 664 module_platform_driver(xvip_composite_driver); 665 666 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 667 MODULE_DESCRIPTION("Xilinx Video IP Composite Driver"); 668 MODULE_LICENSE("GPL v2"); 669