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