| .. | .. |
|---|
| 189 | 189 | |
|---|
| 190 | 190 | /* async subdev notification helpers */ |
|---|
| 191 | 191 | struct v4l2_async_notifier notifier; |
|---|
| 192 | | - /* pointers to "struct ceu_subdevice -> asd" */ |
|---|
| 193 | | - struct v4l2_async_subdev **asds; |
|---|
| 194 | 192 | |
|---|
| 195 | 193 | /* vb2 queue, capture buffer list and active buffer pointer */ |
|---|
| 196 | 194 | struct vb2_queue vb2_vq; |
|---|
| .. | .. |
|---|
| 407 | 405 | /* Non-swapped planar image capture mode. */ |
|---|
| 408 | 406 | case V4L2_PIX_FMT_NV16: |
|---|
| 409 | 407 | cdocr |= CEU_CDOCR_NO_DOWSAMPLE; |
|---|
| 410 | | - /* fall-through */ |
|---|
| 408 | + fallthrough; |
|---|
| 411 | 409 | case V4L2_PIX_FMT_NV12: |
|---|
| 412 | 410 | if (mbus_fmt->swapped) |
|---|
| 413 | 411 | camcr = mbus_fmt->fmt_order_swap; |
|---|
| .. | .. |
|---|
| 421 | 419 | /* Swapped planar image capture mode. */ |
|---|
| 422 | 420 | case V4L2_PIX_FMT_NV61: |
|---|
| 423 | 421 | cdocr |= CEU_CDOCR_NO_DOWSAMPLE; |
|---|
| 424 | | - /* fall-through */ |
|---|
| 422 | + fallthrough; |
|---|
| 425 | 423 | case V4L2_PIX_FMT_NV21: |
|---|
| 426 | 424 | if (mbus_fmt->swapped) |
|---|
| 427 | 425 | camcr = mbus_fmt->fmt_order; |
|---|
| .. | .. |
|---|
| 1137 | 1135 | { |
|---|
| 1138 | 1136 | struct ceu_device *ceudev = video_drvdata(file); |
|---|
| 1139 | 1137 | |
|---|
| 1140 | | - strlcpy(cap->card, "Renesas CEU", sizeof(cap->card)); |
|---|
| 1141 | | - strlcpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); |
|---|
| 1138 | + strscpy(cap->card, "Renesas CEU", sizeof(cap->card)); |
|---|
| 1139 | + strscpy(cap->driver, DRIVER_NAME, sizeof(cap->driver)); |
|---|
| 1142 | 1140 | snprintf(cap->bus_info, sizeof(cap->bus_info), |
|---|
| 1143 | 1141 | "platform:renesas-ceu-%s", dev_name(ceudev->dev)); |
|---|
| 1144 | 1142 | |
|---|
| .. | .. |
|---|
| 1341 | 1339 | static const struct v4l2_ioctl_ops ceu_ioctl_ops = { |
|---|
| 1342 | 1340 | .vidioc_querycap = ceu_querycap, |
|---|
| 1343 | 1341 | |
|---|
| 1344 | | - .vidioc_enum_fmt_vid_cap_mplane = ceu_enum_fmt_vid_cap, |
|---|
| 1342 | + .vidioc_enum_fmt_vid_cap = ceu_enum_fmt_vid_cap, |
|---|
| 1345 | 1343 | .vidioc_try_fmt_vid_cap_mplane = ceu_try_fmt_vid_cap, |
|---|
| 1346 | 1344 | .vidioc_s_fmt_vid_cap_mplane = ceu_s_fmt_vid_cap, |
|---|
| 1347 | 1345 | .vidioc_g_fmt_vid_cap_mplane = ceu_g_fmt_vid_cap, |
|---|
| .. | .. |
|---|
| 1440 | 1438 | return ret; |
|---|
| 1441 | 1439 | |
|---|
| 1442 | 1440 | /* Register the video device. */ |
|---|
| 1443 | | - strlcpy(vdev->name, DRIVER_NAME, sizeof(vdev->name)); |
|---|
| 1441 | + strscpy(vdev->name, DRIVER_NAME, sizeof(vdev->name)); |
|---|
| 1444 | 1442 | vdev->v4l2_dev = v4l2_dev; |
|---|
| 1445 | 1443 | vdev->lock = &ceudev->mlock; |
|---|
| 1446 | 1444 | vdev->queue = &ceudev->vb2_vq; |
|---|
| .. | .. |
|---|
| 1452 | 1450 | V4L2_CAP_STREAMING; |
|---|
| 1453 | 1451 | video_set_drvdata(vdev, ceudev); |
|---|
| 1454 | 1452 | |
|---|
| 1455 | | - ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 1453 | + ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 1456 | 1454 | if (ret < 0) { |
|---|
| 1457 | 1455 | v4l2_err(vdev->v4l2_dev, |
|---|
| 1458 | 1456 | "video_register_device failed: %d\n", ret); |
|---|
| .. | .. |
|---|
| 1482 | 1480 | if (!ceudev->subdevs) |
|---|
| 1483 | 1481 | return -ENOMEM; |
|---|
| 1484 | 1482 | |
|---|
| 1485 | | - /* |
|---|
| 1486 | | - * Reserve memory for 'n_sd' pointers to async_subdevices. |
|---|
| 1487 | | - * ceudev->asds members will point to &ceu_subdev.asd |
|---|
| 1488 | | - */ |
|---|
| 1489 | | - ceudev->asds = devm_kcalloc(ceudev->dev, n_sd, |
|---|
| 1490 | | - sizeof(*ceudev->asds), GFP_KERNEL); |
|---|
| 1491 | | - if (!ceudev->asds) |
|---|
| 1492 | | - return -ENOMEM; |
|---|
| 1493 | | - |
|---|
| 1494 | 1483 | ceudev->sd = NULL; |
|---|
| 1495 | 1484 | ceudev->sd_index = 0; |
|---|
| 1496 | 1485 | ceudev->num_sd = 0; |
|---|
| .. | .. |
|---|
| 1518 | 1507 | return ret; |
|---|
| 1519 | 1508 | |
|---|
| 1520 | 1509 | for (i = 0; i < pdata->num_subdevs; i++) { |
|---|
| 1510 | + |
|---|
| 1521 | 1511 | /* Setup the ceu subdevice and the async subdevice. */ |
|---|
| 1522 | 1512 | async_sd = &pdata->subdevs[i]; |
|---|
| 1523 | 1513 | ceu_sd = &ceudev->subdevs[i]; |
|---|
| .. | .. |
|---|
| 1529 | 1519 | ceu_sd->asd.match.i2c.adapter_id = async_sd->i2c_adapter_id; |
|---|
| 1530 | 1520 | ceu_sd->asd.match.i2c.address = async_sd->i2c_address; |
|---|
| 1531 | 1521 | |
|---|
| 1532 | | - ceudev->asds[i] = &ceu_sd->asd; |
|---|
| 1522 | + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, |
|---|
| 1523 | + &ceu_sd->asd); |
|---|
| 1524 | + if (ret) { |
|---|
| 1525 | + v4l2_async_notifier_cleanup(&ceudev->notifier); |
|---|
| 1526 | + return ret; |
|---|
| 1527 | + } |
|---|
| 1533 | 1528 | } |
|---|
| 1534 | 1529 | |
|---|
| 1535 | 1530 | return pdata->num_subdevs; |
|---|
| .. | .. |
|---|
| 1541 | 1536 | static int ceu_parse_dt(struct ceu_device *ceudev) |
|---|
| 1542 | 1537 | { |
|---|
| 1543 | 1538 | struct device_node *of = ceudev->dev->of_node; |
|---|
| 1544 | | - struct v4l2_fwnode_endpoint fw_ep; |
|---|
| 1539 | + struct device_node *ep, *remote; |
|---|
| 1545 | 1540 | struct ceu_subdev *ceu_sd; |
|---|
| 1546 | | - struct device_node *ep; |
|---|
| 1547 | 1541 | unsigned int i; |
|---|
| 1548 | 1542 | int num_ep; |
|---|
| 1549 | 1543 | int ret; |
|---|
| .. | .. |
|---|
| 1557 | 1551 | return ret; |
|---|
| 1558 | 1552 | |
|---|
| 1559 | 1553 | for (i = 0; i < num_ep; i++) { |
|---|
| 1554 | + struct v4l2_fwnode_endpoint fw_ep = { |
|---|
| 1555 | + .bus_type = V4L2_MBUS_PARALLEL, |
|---|
| 1556 | + .bus = { |
|---|
| 1557 | + .parallel = { |
|---|
| 1558 | + .flags = V4L2_MBUS_HSYNC_ACTIVE_HIGH | |
|---|
| 1559 | + V4L2_MBUS_VSYNC_ACTIVE_HIGH, |
|---|
| 1560 | + .bus_width = 8, |
|---|
| 1561 | + }, |
|---|
| 1562 | + }, |
|---|
| 1563 | + }; |
|---|
| 1564 | + |
|---|
| 1560 | 1565 | ep = of_graph_get_endpoint_by_regs(of, 0, i); |
|---|
| 1561 | 1566 | if (!ep) { |
|---|
| 1562 | 1567 | dev_err(ceudev->dev, |
|---|
| 1563 | 1568 | "No subdevice connected on endpoint %u.\n", i); |
|---|
| 1564 | 1569 | ret = -ENODEV; |
|---|
| 1565 | | - goto error_put_node; |
|---|
| 1570 | + goto error_cleanup; |
|---|
| 1566 | 1571 | } |
|---|
| 1567 | 1572 | |
|---|
| 1568 | 1573 | ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &fw_ep); |
|---|
| 1569 | 1574 | if (ret) { |
|---|
| 1570 | 1575 | dev_err(ceudev->dev, |
|---|
| 1571 | | - "Unable to parse endpoint #%u.\n", i); |
|---|
| 1572 | | - goto error_put_node; |
|---|
| 1573 | | - } |
|---|
| 1574 | | - |
|---|
| 1575 | | - if (fw_ep.bus_type != V4L2_MBUS_PARALLEL) { |
|---|
| 1576 | | - dev_err(ceudev->dev, |
|---|
| 1577 | | - "Only parallel input supported.\n"); |
|---|
| 1578 | | - ret = -EINVAL; |
|---|
| 1579 | | - goto error_put_node; |
|---|
| 1576 | + "Unable to parse endpoint #%u: %d.\n", i, ret); |
|---|
| 1577 | + goto error_cleanup; |
|---|
| 1580 | 1578 | } |
|---|
| 1581 | 1579 | |
|---|
| 1582 | 1580 | /* Setup the ceu subdevice and the async subdevice. */ |
|---|
| 1583 | 1581 | ceu_sd = &ceudev->subdevs[i]; |
|---|
| 1584 | 1582 | INIT_LIST_HEAD(&ceu_sd->asd.list); |
|---|
| 1585 | 1583 | |
|---|
| 1584 | + remote = of_graph_get_remote_port_parent(ep); |
|---|
| 1586 | 1585 | ceu_sd->mbus_flags = fw_ep.bus.parallel.flags; |
|---|
| 1587 | 1586 | ceu_sd->asd.match_type = V4L2_ASYNC_MATCH_FWNODE; |
|---|
| 1588 | | - ceu_sd->asd.match.fwnode = |
|---|
| 1589 | | - fwnode_graph_get_remote_port_parent( |
|---|
| 1590 | | - of_fwnode_handle(ep)); |
|---|
| 1587 | + ceu_sd->asd.match.fwnode = of_fwnode_handle(remote); |
|---|
| 1591 | 1588 | |
|---|
| 1592 | | - ceudev->asds[i] = &ceu_sd->asd; |
|---|
| 1589 | + ret = v4l2_async_notifier_add_subdev(&ceudev->notifier, |
|---|
| 1590 | + &ceu_sd->asd); |
|---|
| 1591 | + if (ret) { |
|---|
| 1592 | + of_node_put(remote); |
|---|
| 1593 | + goto error_cleanup; |
|---|
| 1594 | + } |
|---|
| 1595 | + |
|---|
| 1593 | 1596 | of_node_put(ep); |
|---|
| 1594 | 1597 | } |
|---|
| 1595 | 1598 | |
|---|
| 1596 | 1599 | return num_ep; |
|---|
| 1597 | 1600 | |
|---|
| 1598 | | -error_put_node: |
|---|
| 1601 | +error_cleanup: |
|---|
| 1602 | + v4l2_async_notifier_cleanup(&ceudev->notifier); |
|---|
| 1599 | 1603 | of_node_put(ep); |
|---|
| 1600 | 1604 | return ret; |
|---|
| 1601 | 1605 | } |
|---|
| .. | .. |
|---|
| 1655 | 1659 | } |
|---|
| 1656 | 1660 | |
|---|
| 1657 | 1661 | ret = platform_get_irq(pdev, 0); |
|---|
| 1658 | | - if (ret < 0) { |
|---|
| 1659 | | - dev_err(dev, "Failed to get irq: %d\n", ret); |
|---|
| 1662 | + if (ret < 0) |
|---|
| 1660 | 1663 | goto error_free_ceudev; |
|---|
| 1661 | | - } |
|---|
| 1662 | 1664 | irq = ret; |
|---|
| 1663 | 1665 | |
|---|
| 1664 | 1666 | ret = devm_request_irq(dev, irq, ceu_irq, |
|---|
| .. | .. |
|---|
| 1673 | 1675 | ret = v4l2_device_register(dev, &ceudev->v4l2_dev); |
|---|
| 1674 | 1676 | if (ret) |
|---|
| 1675 | 1677 | goto error_pm_disable; |
|---|
| 1678 | + |
|---|
| 1679 | + v4l2_async_notifier_init(&ceudev->notifier); |
|---|
| 1676 | 1680 | |
|---|
| 1677 | 1681 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) { |
|---|
| 1678 | 1682 | ceu_data = of_match_device(ceu_of_match, dev)->data; |
|---|
| .. | .. |
|---|
| 1693 | 1697 | ceudev->irq_mask = ceu_data->irq_mask; |
|---|
| 1694 | 1698 | |
|---|
| 1695 | 1699 | ceudev->notifier.v4l2_dev = &ceudev->v4l2_dev; |
|---|
| 1696 | | - ceudev->notifier.subdevs = ceudev->asds; |
|---|
| 1697 | | - ceudev->notifier.num_subdevs = num_subdevs; |
|---|
| 1698 | 1700 | ceudev->notifier.ops = &ceu_notify_ops; |
|---|
| 1699 | 1701 | ret = v4l2_async_notifier_register(&ceudev->v4l2_dev, |
|---|
| 1700 | 1702 | &ceudev->notifier); |
|---|
| 1701 | 1703 | if (ret) |
|---|
| 1702 | | - goto error_v4l2_unregister; |
|---|
| 1704 | + goto error_cleanup; |
|---|
| 1703 | 1705 | |
|---|
| 1704 | 1706 | dev_info(dev, "Renesas Capture Engine Unit %s\n", dev_name(dev)); |
|---|
| 1705 | 1707 | |
|---|
| 1706 | 1708 | return 0; |
|---|
| 1707 | 1709 | |
|---|
| 1710 | +error_cleanup: |
|---|
| 1711 | + v4l2_async_notifier_cleanup(&ceudev->notifier); |
|---|
| 1708 | 1712 | error_v4l2_unregister: |
|---|
| 1709 | 1713 | v4l2_device_unregister(&ceudev->v4l2_dev); |
|---|
| 1710 | 1714 | error_pm_disable: |
|---|
| .. | .. |
|---|
| 1723 | 1727 | |
|---|
| 1724 | 1728 | v4l2_async_notifier_unregister(&ceudev->notifier); |
|---|
| 1725 | 1729 | |
|---|
| 1730 | + v4l2_async_notifier_cleanup(&ceudev->notifier); |
|---|
| 1731 | + |
|---|
| 1726 | 1732 | v4l2_device_unregister(&ceudev->v4l2_dev); |
|---|
| 1727 | 1733 | |
|---|
| 1728 | 1734 | video_unregister_device(&ceudev->vdev); |
|---|