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 %s\n", ep->full_name); 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 %s\n", 98 ep->full_name); 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 %s\n", 107 link.local_port, 108 to_of_node(link.local_node)->full_name); 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 %s:%u\n", 118 to_of_node(link.local_node)->full_name, 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 %s:%u\n", 127 to_of_node(link.local_node)->full_name, 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 %s\n", 138 to_of_node(link.remote_node)->full_name); 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 %s\n", 148 link.remote_port, 149 to_of_node(link.remote_node)->full_name); 150 v4l2_fwnode_put_link(&link); 151 ret = -EINVAL; 152 break; 153 } 154 155 remote_pad = &remote->pads[link.remote_port]; 156 157 v4l2_fwnode_put_link(&link); 158 159 /* Create the media link. */ 160 dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", 161 local->name, local_pad->index, 162 remote->name, remote_pad->index); 163 164 ret = media_create_pad_link(local, local_pad->index, 165 remote, remote_pad->index, 166 link_flags); 167 if (ret < 0) { 168 dev_err(xdev->dev, 169 "failed to create %s:%u -> %s:%u link\n", 170 local->name, local_pad->index, 171 remote->name, remote_pad->index); 172 break; 173 } 174 } 175 176 of_node_put(ep); 177 return ret; 178 } 179 180 static struct xvip_dma * 181 xvip_graph_find_dma(struct xvip_composite_device *xdev, unsigned int port) 182 { 183 struct xvip_dma *dma; 184 185 list_for_each_entry(dma, &xdev->dmas, list) { 186 if (dma->port == port) 187 return dma; 188 } 189 190 return NULL; 191 } 192 193 static int xvip_graph_build_dma(struct xvip_composite_device *xdev) 194 { 195 u32 link_flags = MEDIA_LNK_FL_ENABLED; 196 struct device_node *node = xdev->dev->of_node; 197 struct media_entity *source; 198 struct media_entity *sink; 199 struct media_pad *source_pad; 200 struct media_pad *sink_pad; 201 struct xvip_graph_entity *ent; 202 struct v4l2_fwnode_link link; 203 struct device_node *ep = NULL; 204 struct device_node *next; 205 struct xvip_dma *dma; 206 int ret = 0; 207 208 dev_dbg(xdev->dev, "creating links for DMA engines\n"); 209 210 while (1) { 211 /* Get the next endpoint and parse its link. */ 212 next = of_graph_get_next_endpoint(node, ep); 213 if (next == NULL) 214 break; 215 216 of_node_put(ep); 217 ep = next; 218 219 dev_dbg(xdev->dev, "processing endpoint %s\n", ep->full_name); 220 221 ret = v4l2_fwnode_parse_link(of_fwnode_handle(ep), &link); 222 if (ret < 0) { 223 dev_err(xdev->dev, "failed to parse link for %s\n", 224 ep->full_name); 225 continue; 226 } 227 228 /* Find the DMA engine. */ 229 dma = xvip_graph_find_dma(xdev, link.local_port); 230 if (dma == NULL) { 231 dev_err(xdev->dev, "no DMA engine found for port %u\n", 232 link.local_port); 233 v4l2_fwnode_put_link(&link); 234 ret = -EINVAL; 235 break; 236 } 237 238 dev_dbg(xdev->dev, "creating link for DMA engine %s\n", 239 dma->video.name); 240 241 /* Find the remote entity. */ 242 ent = xvip_graph_find_entity(xdev, 243 to_of_node(link.remote_node)); 244 if (ent == NULL) { 245 dev_err(xdev->dev, "no entity found for %s\n", 246 to_of_node(link.remote_node)->full_name); 247 v4l2_fwnode_put_link(&link); 248 ret = -ENODEV; 249 break; 250 } 251 252 if (link.remote_port >= ent->entity->num_pads) { 253 dev_err(xdev->dev, "invalid port number %u on %s\n", 254 link.remote_port, 255 to_of_node(link.remote_node)->full_name); 256 v4l2_fwnode_put_link(&link); 257 ret = -EINVAL; 258 break; 259 } 260 261 if (dma->pad.flags & MEDIA_PAD_FL_SOURCE) { 262 source = &dma->video.entity; 263 source_pad = &dma->pad; 264 sink = ent->entity; 265 sink_pad = &sink->pads[link.remote_port]; 266 } else { 267 source = ent->entity; 268 source_pad = &source->pads[link.remote_port]; 269 sink = &dma->video.entity; 270 sink_pad = &dma->pad; 271 } 272 273 v4l2_fwnode_put_link(&link); 274 275 /* Create the media link. */ 276 dev_dbg(xdev->dev, "creating %s:%u -> %s:%u link\n", 277 source->name, source_pad->index, 278 sink->name, sink_pad->index); 279 280 ret = media_create_pad_link(source, source_pad->index, 281 sink, sink_pad->index, 282 link_flags); 283 if (ret < 0) { 284 dev_err(xdev->dev, 285 "failed to create %s:%u -> %s:%u link\n", 286 source->name, source_pad->index, 287 sink->name, sink_pad->index); 288 break; 289 } 290 } 291 292 of_node_put(ep); 293 return ret; 294 } 295 296 static int xvip_graph_notify_complete(struct v4l2_async_notifier *notifier) 297 { 298 struct xvip_composite_device *xdev = 299 container_of(notifier, struct xvip_composite_device, notifier); 300 struct xvip_graph_entity *entity; 301 int ret; 302 303 dev_dbg(xdev->dev, "notify complete, all subdevs registered\n"); 304 305 /* Create links for every entity. */ 306 list_for_each_entry(entity, &xdev->entities, list) { 307 ret = xvip_graph_build_one(xdev, entity); 308 if (ret < 0) 309 return ret; 310 } 311 312 /* Create links for DMA channels. */ 313 ret = xvip_graph_build_dma(xdev); 314 if (ret < 0) 315 return ret; 316 317 ret = v4l2_device_register_subdev_nodes(&xdev->v4l2_dev); 318 if (ret < 0) 319 dev_err(xdev->dev, "failed to register subdev nodes\n"); 320 321 return media_device_register(&xdev->media_dev); 322 } 323 324 static int xvip_graph_notify_bound(struct v4l2_async_notifier *notifier, 325 struct v4l2_subdev *subdev, 326 struct v4l2_async_subdev *asd) 327 { 328 struct xvip_composite_device *xdev = 329 container_of(notifier, struct xvip_composite_device, notifier); 330 struct xvip_graph_entity *entity; 331 332 /* Locate the entity corresponding to the bound subdev and store the 333 * subdev pointer. 334 */ 335 list_for_each_entry(entity, &xdev->entities, list) { 336 if (entity->node != subdev->dev->of_node) 337 continue; 338 339 if (entity->subdev) { 340 dev_err(xdev->dev, "duplicate subdev for node %s\n", 341 entity->node->full_name); 342 return -EINVAL; 343 } 344 345 dev_dbg(xdev->dev, "subdev %s bound\n", subdev->name); 346 entity->entity = &subdev->entity; 347 entity->subdev = subdev; 348 return 0; 349 } 350 351 dev_err(xdev->dev, "no entity for subdev %s\n", subdev->name); 352 return -EINVAL; 353 } 354 355 static int xvip_graph_parse_one(struct xvip_composite_device *xdev, 356 struct device_node *node) 357 { 358 struct xvip_graph_entity *entity; 359 struct device_node *remote; 360 struct device_node *ep = NULL; 361 int ret = 0; 362 363 dev_dbg(xdev->dev, "parsing node %s\n", node->full_name); 364 365 while (1) { 366 ep = of_graph_get_next_endpoint(node, ep); 367 if (ep == NULL) 368 break; 369 370 dev_dbg(xdev->dev, "handling endpoint %s\n", ep->full_name); 371 372 remote = of_graph_get_remote_port_parent(ep); 373 if (remote == NULL) { 374 ret = -EINVAL; 375 break; 376 } 377 378 /* Skip entities that we have already processed. */ 379 if (remote == xdev->dev->of_node || 380 xvip_graph_find_entity(xdev, remote)) { 381 of_node_put(remote); 382 continue; 383 } 384 385 entity = devm_kzalloc(xdev->dev, sizeof(*entity), GFP_KERNEL); 386 if (entity == NULL) { 387 of_node_put(remote); 388 ret = -ENOMEM; 389 break; 390 } 391 392 entity->node = remote; 393 entity->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; 394 entity->asd.match.fwnode.fwnode = of_fwnode_handle(remote); 395 list_add_tail(&entity->list, &xdev->entities); 396 xdev->num_subdevs++; 397 } 398 399 of_node_put(ep); 400 return ret; 401 } 402 403 static int xvip_graph_parse(struct xvip_composite_device *xdev) 404 { 405 struct xvip_graph_entity *entity; 406 int ret; 407 408 /* 409 * Walk the links to parse the full graph. Start by parsing the 410 * composite node and then parse entities in turn. The list_for_each 411 * loop will handle entities added at the end of the list while walking 412 * the links. 413 */ 414 ret = xvip_graph_parse_one(xdev, xdev->dev->of_node); 415 if (ret < 0) 416 return 0; 417 418 list_for_each_entry(entity, &xdev->entities, list) { 419 ret = xvip_graph_parse_one(xdev, entity->node); 420 if (ret < 0) 421 break; 422 } 423 424 return ret; 425 } 426 427 static int xvip_graph_dma_init_one(struct xvip_composite_device *xdev, 428 struct device_node *node) 429 { 430 struct xvip_dma *dma; 431 enum v4l2_buf_type type; 432 const char *direction; 433 unsigned int index; 434 int ret; 435 436 ret = of_property_read_string(node, "direction", &direction); 437 if (ret < 0) 438 return ret; 439 440 if (strcmp(direction, "input") == 0) 441 type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 442 else if (strcmp(direction, "output") == 0) 443 type = V4L2_BUF_TYPE_VIDEO_OUTPUT; 444 else 445 return -EINVAL; 446 447 of_property_read_u32(node, "reg", &index); 448 449 dma = devm_kzalloc(xdev->dev, sizeof(*dma), GFP_KERNEL); 450 if (dma == NULL) 451 return -ENOMEM; 452 453 ret = xvip_dma_init(xdev, dma, type, index); 454 if (ret < 0) { 455 dev_err(xdev->dev, "%s initialization failed\n", 456 node->full_name); 457 return ret; 458 } 459 460 list_add_tail(&dma->list, &xdev->dmas); 461 462 xdev->v4l2_caps |= type == V4L2_BUF_TYPE_VIDEO_CAPTURE 463 ? V4L2_CAP_VIDEO_CAPTURE : V4L2_CAP_VIDEO_OUTPUT; 464 465 return 0; 466 } 467 468 static int xvip_graph_dma_init(struct xvip_composite_device *xdev) 469 { 470 struct device_node *ports; 471 struct device_node *port; 472 int ret; 473 474 ports = of_get_child_by_name(xdev->dev->of_node, "ports"); 475 if (ports == NULL) { 476 dev_err(xdev->dev, "ports node not present\n"); 477 return -EINVAL; 478 } 479 480 for_each_child_of_node(ports, port) { 481 ret = xvip_graph_dma_init_one(xdev, port); 482 if (ret < 0) { 483 of_node_put(port); 484 return ret; 485 } 486 } 487 488 return 0; 489 } 490 491 static void xvip_graph_cleanup(struct xvip_composite_device *xdev) 492 { 493 struct xvip_graph_entity *entityp; 494 struct xvip_graph_entity *entity; 495 struct xvip_dma *dmap; 496 struct xvip_dma *dma; 497 498 v4l2_async_notifier_unregister(&xdev->notifier); 499 500 list_for_each_entry_safe(entity, entityp, &xdev->entities, list) { 501 of_node_put(entity->node); 502 list_del(&entity->list); 503 } 504 505 list_for_each_entry_safe(dma, dmap, &xdev->dmas, list) { 506 xvip_dma_cleanup(dma); 507 list_del(&dma->list); 508 } 509 } 510 511 static int xvip_graph_init(struct xvip_composite_device *xdev) 512 { 513 struct xvip_graph_entity *entity; 514 struct v4l2_async_subdev **subdevs = NULL; 515 unsigned int num_subdevs; 516 unsigned int i; 517 int ret; 518 519 /* Init the DMA channels. */ 520 ret = xvip_graph_dma_init(xdev); 521 if (ret < 0) { 522 dev_err(xdev->dev, "DMA initialization failed\n"); 523 goto done; 524 } 525 526 /* Parse the graph to extract a list of subdevice DT nodes. */ 527 ret = xvip_graph_parse(xdev); 528 if (ret < 0) { 529 dev_err(xdev->dev, "graph parsing failed\n"); 530 goto done; 531 } 532 533 if (!xdev->num_subdevs) { 534 dev_err(xdev->dev, "no subdev found in graph\n"); 535 goto done; 536 } 537 538 /* Register the subdevices notifier. */ 539 num_subdevs = xdev->num_subdevs; 540 subdevs = devm_kzalloc(xdev->dev, sizeof(*subdevs) * num_subdevs, 541 GFP_KERNEL); 542 if (subdevs == NULL) { 543 ret = -ENOMEM; 544 goto done; 545 } 546 547 i = 0; 548 list_for_each_entry(entity, &xdev->entities, list) 549 subdevs[i++] = &entity->asd; 550 551 xdev->notifier.subdevs = subdevs; 552 xdev->notifier.num_subdevs = num_subdevs; 553 xdev->notifier.bound = xvip_graph_notify_bound; 554 xdev->notifier.complete = xvip_graph_notify_complete; 555 556 ret = v4l2_async_notifier_register(&xdev->v4l2_dev, &xdev->notifier); 557 if (ret < 0) { 558 dev_err(xdev->dev, "notifier registration failed\n"); 559 goto done; 560 } 561 562 ret = 0; 563 564 done: 565 if (ret < 0) 566 xvip_graph_cleanup(xdev); 567 568 return ret; 569 } 570 571 /* ----------------------------------------------------------------------------- 572 * Media Controller and V4L2 573 */ 574 575 static void xvip_composite_v4l2_cleanup(struct xvip_composite_device *xdev) 576 { 577 v4l2_device_unregister(&xdev->v4l2_dev); 578 media_device_unregister(&xdev->media_dev); 579 media_device_cleanup(&xdev->media_dev); 580 } 581 582 static int xvip_composite_v4l2_init(struct xvip_composite_device *xdev) 583 { 584 int ret; 585 586 xdev->media_dev.dev = xdev->dev; 587 strlcpy(xdev->media_dev.model, "Xilinx Video Composite Device", 588 sizeof(xdev->media_dev.model)); 589 xdev->media_dev.hw_revision = 0; 590 591 media_device_init(&xdev->media_dev); 592 593 xdev->v4l2_dev.mdev = &xdev->media_dev; 594 ret = v4l2_device_register(xdev->dev, &xdev->v4l2_dev); 595 if (ret < 0) { 596 dev_err(xdev->dev, "V4L2 device registration failed (%d)\n", 597 ret); 598 media_device_cleanup(&xdev->media_dev); 599 return ret; 600 } 601 602 return 0; 603 } 604 605 /* ----------------------------------------------------------------------------- 606 * Platform Device Driver 607 */ 608 609 static int xvip_composite_probe(struct platform_device *pdev) 610 { 611 struct xvip_composite_device *xdev; 612 int ret; 613 614 xdev = devm_kzalloc(&pdev->dev, sizeof(*xdev), GFP_KERNEL); 615 if (!xdev) 616 return -ENOMEM; 617 618 xdev->dev = &pdev->dev; 619 INIT_LIST_HEAD(&xdev->entities); 620 INIT_LIST_HEAD(&xdev->dmas); 621 622 ret = xvip_composite_v4l2_init(xdev); 623 if (ret < 0) 624 return ret; 625 626 ret = xvip_graph_init(xdev); 627 if (ret < 0) 628 goto error; 629 630 platform_set_drvdata(pdev, xdev); 631 632 dev_info(xdev->dev, "device registered\n"); 633 634 return 0; 635 636 error: 637 xvip_composite_v4l2_cleanup(xdev); 638 return ret; 639 } 640 641 static int xvip_composite_remove(struct platform_device *pdev) 642 { 643 struct xvip_composite_device *xdev = platform_get_drvdata(pdev); 644 645 xvip_graph_cleanup(xdev); 646 xvip_composite_v4l2_cleanup(xdev); 647 648 return 0; 649 } 650 651 static const struct of_device_id xvip_composite_of_id_table[] = { 652 { .compatible = "xlnx,video" }, 653 { } 654 }; 655 MODULE_DEVICE_TABLE(of, xvip_composite_of_id_table); 656 657 static struct platform_driver xvip_composite_driver = { 658 .driver = { 659 .name = "xilinx-video", 660 .of_match_table = xvip_composite_of_id_table, 661 }, 662 .probe = xvip_composite_probe, 663 .remove = xvip_composite_remove, 664 }; 665 666 module_platform_driver(xvip_composite_driver); 667 668 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>"); 669 MODULE_DESCRIPTION("Xilinx Video IP Composite Driver"); 670 MODULE_LICENSE("GPL v2"); 671