.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2009 Texas Instruments Inc |
---|
3 | 4 | * Copyright (C) 2014 Lad, Prabhakar <prabhakar.csengg@gmail.com> |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify |
---|
6 | | - * it under the terms of the GNU General Public License as published by |
---|
7 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
8 | | - * (at your option) any later version. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, |
---|
11 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
13 | | - * GNU General Public License for more details. |
---|
14 | 5 | * |
---|
15 | 6 | * TODO : add support for VBI & HBI data service |
---|
16 | 7 | * add static buffer allocation |
---|
.. | .. |
---|
947 | 938 | } |
---|
948 | 939 | |
---|
949 | 940 | /* Fill in the information about format */ |
---|
950 | | - if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) { |
---|
951 | | - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
---|
952 | | - strcpy(fmt->description, "Raw Mode -Bayer Pattern GrRBGb"); |
---|
| 941 | + if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER) |
---|
953 | 942 | fmt->pixelformat = V4L2_PIX_FMT_SBGGR8; |
---|
954 | | - } else { |
---|
955 | | - fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
---|
956 | | - strcpy(fmt->description, "YCbCr4:2:2 Semi-Planar"); |
---|
| 943 | + else |
---|
957 | 944 | fmt->pixelformat = V4L2_PIX_FMT_NV16; |
---|
958 | | - } |
---|
959 | 945 | return 0; |
---|
960 | 946 | } |
---|
961 | 947 | |
---|
.. | .. |
---|
986 | 972 | pixfmt->bytesperline = common->fmt.fmt.pix.width * 2; |
---|
987 | 973 | pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height; |
---|
988 | 974 | } |
---|
989 | | - pixfmt->priv = 0; |
---|
990 | 975 | |
---|
991 | 976 | dev_dbg(vpif_dev, "%s: %d x %d; pitch=%d pixelformat=0x%08x, field=%d, size=%d\n", __func__, |
---|
992 | 977 | pixfmt->width, pixfmt->height, |
---|
.. | .. |
---|
1092 | 1077 | { |
---|
1093 | 1078 | struct vpif_capture_config *config = vpif_dev->platform_data; |
---|
1094 | 1079 | |
---|
1095 | | - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
---|
1096 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
---|
1097 | | - strlcpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); |
---|
| 1080 | + strscpy(cap->driver, VPIF_DRIVER_NAME, sizeof(cap->driver)); |
---|
1098 | 1081 | snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s", |
---|
1099 | 1082 | dev_name(vpif_dev)); |
---|
1100 | | - strlcpy(cap->card, config->card_name, sizeof(cap->card)); |
---|
| 1083 | + strscpy(cap->card, config->card_name, sizeof(cap->card)); |
---|
1101 | 1084 | |
---|
1102 | 1085 | return 0; |
---|
1103 | 1086 | } |
---|
.. | .. |
---|
1252 | 1235 | } else { |
---|
1253 | 1236 | std_info->l5 = std_info->vsize - (bt->vfrontporch - 1); |
---|
1254 | 1237 | } |
---|
1255 | | - strncpy(std_info->name, "Custom timings BT656/1120", VPIF_MAX_NAME); |
---|
| 1238 | + strscpy(std_info->name, "Custom timings BT656/1120", |
---|
| 1239 | + sizeof(std_info->name)); |
---|
1256 | 1240 | std_info->width = bt->width; |
---|
1257 | 1241 | std_info->height = bt->height; |
---|
1258 | 1242 | std_info->frm_fmt = bt->interlaced ? 0 : 1; |
---|
.. | .. |
---|
1382 | 1366 | return err; |
---|
1383 | 1367 | } |
---|
1384 | 1368 | |
---|
| 1369 | +static inline void free_vpif_objs(void) |
---|
| 1370 | +{ |
---|
| 1371 | + int i; |
---|
| 1372 | + |
---|
| 1373 | + for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) |
---|
| 1374 | + kfree(vpif_obj.dev[i]); |
---|
| 1375 | +} |
---|
| 1376 | + |
---|
1385 | 1377 | static int vpif_async_bound(struct v4l2_async_notifier *notifier, |
---|
1386 | 1378 | struct v4l2_subdev *subdev, |
---|
1387 | 1379 | struct v4l2_async_subdev *asd) |
---|
.. | .. |
---|
1463 | 1455 | |
---|
1464 | 1456 | /* Initialize the video_device structure */ |
---|
1465 | 1457 | vdev = &ch->video_dev; |
---|
1466 | | - strlcpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); |
---|
| 1458 | + strscpy(vdev->name, VPIF_DRIVER_NAME, sizeof(vdev->name)); |
---|
1467 | 1459 | vdev->release = video_device_release_empty; |
---|
1468 | 1460 | vdev->fops = &vpif_fops; |
---|
1469 | 1461 | vdev->ioctl_ops = &vpif_ioctl_ops; |
---|
.. | .. |
---|
1471 | 1463 | vdev->vfl_dir = VFL_DIR_RX; |
---|
1472 | 1464 | vdev->queue = q; |
---|
1473 | 1465 | vdev->lock = &common->lock; |
---|
| 1466 | + vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
---|
1474 | 1467 | video_set_drvdata(&ch->video_dev, ch); |
---|
1475 | 1468 | err = video_register_device(vdev, |
---|
1476 | | - VFL_TYPE_GRABBER, (j ? 1 : 0)); |
---|
| 1469 | + VFL_TYPE_VIDEO, (j ? 1 : 0)); |
---|
1477 | 1470 | if (err) |
---|
1478 | 1471 | goto probe_out; |
---|
1479 | 1472 | } |
---|
.. | .. |
---|
1489 | 1482 | /* Unregister video device */ |
---|
1490 | 1483 | video_unregister_device(&ch->video_dev); |
---|
1491 | 1484 | } |
---|
1492 | | - kfree(vpif_obj.sd); |
---|
1493 | | - v4l2_device_unregister(&vpif_obj.v4l2_dev); |
---|
1494 | 1485 | |
---|
1495 | 1486 | return err; |
---|
1496 | 1487 | } |
---|
.. | .. |
---|
1509 | 1500 | vpif_capture_get_pdata(struct platform_device *pdev) |
---|
1510 | 1501 | { |
---|
1511 | 1502 | struct device_node *endpoint = NULL; |
---|
1512 | | - struct v4l2_fwnode_endpoint bus_cfg; |
---|
| 1503 | + struct device_node *rem = NULL; |
---|
1513 | 1504 | struct vpif_capture_config *pdata; |
---|
1514 | 1505 | struct vpif_subdev_info *sdinfo; |
---|
1515 | 1506 | struct vpif_capture_chan_config *chan; |
---|
1516 | 1507 | unsigned int i; |
---|
| 1508 | + |
---|
| 1509 | + v4l2_async_notifier_init(&vpif_obj.notifier); |
---|
1517 | 1510 | |
---|
1518 | 1511 | /* |
---|
1519 | 1512 | * DT boot: OF node from parent device contains |
---|
.. | .. |
---|
1537 | 1530 | return NULL; |
---|
1538 | 1531 | |
---|
1539 | 1532 | for (i = 0; i < VPIF_CAPTURE_NUM_CHANNELS; i++) { |
---|
1540 | | - struct device_node *rem; |
---|
| 1533 | + struct v4l2_fwnode_endpoint bus_cfg = { .bus_type = 0 }; |
---|
1541 | 1534 | unsigned int flags; |
---|
1542 | 1535 | int err; |
---|
1543 | 1536 | |
---|
.. | .. |
---|
1546 | 1539 | if (!endpoint) |
---|
1547 | 1540 | break; |
---|
1548 | 1541 | |
---|
| 1542 | + rem = of_graph_get_remote_port_parent(endpoint); |
---|
| 1543 | + if (!rem) { |
---|
| 1544 | + dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", |
---|
| 1545 | + endpoint); |
---|
| 1546 | + goto done; |
---|
| 1547 | + } |
---|
| 1548 | + |
---|
1549 | 1549 | sdinfo = &pdata->subdev_info[i]; |
---|
1550 | 1550 | chan = &pdata->chan_config[i]; |
---|
1551 | 1551 | chan->inputs = devm_kcalloc(&pdev->dev, |
---|
.. | .. |
---|
1553 | 1553 | sizeof(*chan->inputs), |
---|
1554 | 1554 | GFP_KERNEL); |
---|
1555 | 1555 | if (!chan->inputs) |
---|
1556 | | - return NULL; |
---|
| 1556 | + goto err_cleanup; |
---|
1557 | 1557 | |
---|
1558 | 1558 | chan->input_count++; |
---|
1559 | 1559 | chan->inputs[i].input.type = V4L2_INPUT_TYPE_CAMERA; |
---|
.. | .. |
---|
1564 | 1564 | &bus_cfg); |
---|
1565 | 1565 | if (err) { |
---|
1566 | 1566 | dev_err(&pdev->dev, "Could not parse the endpoint\n"); |
---|
| 1567 | + of_node_put(rem); |
---|
1567 | 1568 | goto done; |
---|
1568 | 1569 | } |
---|
| 1570 | + |
---|
1569 | 1571 | dev_dbg(&pdev->dev, "Endpoint %pOF, bus_width = %d\n", |
---|
1570 | 1572 | endpoint, bus_cfg.bus.parallel.bus_width); |
---|
| 1573 | + |
---|
1571 | 1574 | flags = bus_cfg.bus.parallel.flags; |
---|
1572 | 1575 | |
---|
1573 | 1576 | if (flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) |
---|
.. | .. |
---|
1576 | 1579 | if (flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) |
---|
1577 | 1580 | chan->vpif_if.vd_pol = 1; |
---|
1578 | 1581 | |
---|
1579 | | - rem = of_graph_get_remote_port_parent(endpoint); |
---|
1580 | | - if (!rem) { |
---|
1581 | | - dev_dbg(&pdev->dev, "Remote device at %pOF not found\n", |
---|
1582 | | - endpoint); |
---|
1583 | | - goto done; |
---|
1584 | | - } |
---|
1585 | | - |
---|
1586 | | - dev_dbg(&pdev->dev, "Remote device %s, %pOF found\n", |
---|
1587 | | - rem->name, rem); |
---|
| 1582 | + dev_dbg(&pdev->dev, "Remote device %pOF found\n", rem); |
---|
1588 | 1583 | sdinfo->name = rem->full_name; |
---|
1589 | 1584 | |
---|
1590 | | - pdata->asd[i] = devm_kzalloc(&pdev->dev, |
---|
1591 | | - sizeof(struct v4l2_async_subdev), |
---|
1592 | | - GFP_KERNEL); |
---|
1593 | | - if (!pdata->asd[i]) { |
---|
1594 | | - of_node_put(rem); |
---|
1595 | | - pdata = NULL; |
---|
1596 | | - goto done; |
---|
1597 | | - } |
---|
| 1585 | + pdata->asd[i] = v4l2_async_notifier_add_fwnode_subdev( |
---|
| 1586 | + &vpif_obj.notifier, of_fwnode_handle(rem), |
---|
| 1587 | + sizeof(struct v4l2_async_subdev)); |
---|
| 1588 | + if (IS_ERR(pdata->asd[i])) |
---|
| 1589 | + goto err_cleanup; |
---|
1598 | 1590 | |
---|
1599 | | - pdata->asd[i]->match_type = V4L2_ASYNC_MATCH_FWNODE; |
---|
1600 | | - pdata->asd[i]->match.fwnode = of_fwnode_handle(rem); |
---|
1601 | 1591 | of_node_put(rem); |
---|
1602 | 1592 | } |
---|
1603 | 1593 | |
---|
1604 | 1594 | done: |
---|
1605 | | - if (pdata) { |
---|
1606 | | - pdata->asd_sizes[0] = i; |
---|
1607 | | - pdata->subdev_count = i; |
---|
1608 | | - pdata->card_name = "DA850/OMAP-L138 Video Capture"; |
---|
1609 | | - } |
---|
| 1595 | + of_node_put(endpoint); |
---|
| 1596 | + pdata->asd_sizes[0] = i; |
---|
| 1597 | + pdata->subdev_count = i; |
---|
| 1598 | + pdata->card_name = "DA850/OMAP-L138 Video Capture"; |
---|
1610 | 1599 | |
---|
1611 | 1600 | return pdata; |
---|
| 1601 | + |
---|
| 1602 | +err_cleanup: |
---|
| 1603 | + of_node_put(rem); |
---|
| 1604 | + of_node_put(endpoint); |
---|
| 1605 | + v4l2_async_notifier_cleanup(&vpif_obj.notifier); |
---|
| 1606 | + |
---|
| 1607 | + return NULL; |
---|
1612 | 1608 | } |
---|
1613 | 1609 | |
---|
1614 | 1610 | /** |
---|
.. | .. |
---|
1633 | 1629 | return -EINVAL; |
---|
1634 | 1630 | } |
---|
1635 | 1631 | |
---|
1636 | | - if (!pdev->dev.platform_data) { |
---|
1637 | | - dev_warn(&pdev->dev, "Missing platform data. Giving up.\n"); |
---|
1638 | | - return -EINVAL; |
---|
1639 | | - } |
---|
1640 | | - |
---|
1641 | 1632 | vpif_dev = &pdev->dev; |
---|
1642 | 1633 | |
---|
1643 | 1634 | err = initialize_vpif(); |
---|
1644 | 1635 | if (err) { |
---|
1645 | 1636 | v4l2_err(vpif_dev->driver, "Error initializing vpif\n"); |
---|
1646 | | - return err; |
---|
| 1637 | + goto cleanup; |
---|
1647 | 1638 | } |
---|
1648 | 1639 | |
---|
1649 | 1640 | err = v4l2_device_register(vpif_dev, &vpif_obj.v4l2_dev); |
---|
1650 | 1641 | if (err) { |
---|
1651 | 1642 | v4l2_err(vpif_dev->driver, "Error registering v4l2 device\n"); |
---|
1652 | | - return err; |
---|
| 1643 | + goto vpif_free; |
---|
1653 | 1644 | } |
---|
1654 | 1645 | |
---|
1655 | 1646 | while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) { |
---|
.. | .. |
---|
1696 | 1687 | "registered sub device %s\n", |
---|
1697 | 1688 | subdevdata->name); |
---|
1698 | 1689 | } |
---|
1699 | | - vpif_probe_complete(); |
---|
| 1690 | + err = vpif_probe_complete(); |
---|
| 1691 | + if (err) |
---|
| 1692 | + goto probe_subdev_out; |
---|
1700 | 1693 | } else { |
---|
1701 | | - vpif_obj.notifier.subdevs = vpif_obj.config->asd; |
---|
1702 | | - vpif_obj.notifier.num_subdevs = vpif_obj.config->asd_sizes[0]; |
---|
1703 | 1694 | vpif_obj.notifier.ops = &vpif_async_ops; |
---|
1704 | 1695 | err = v4l2_async_notifier_register(&vpif_obj.v4l2_dev, |
---|
1705 | 1696 | &vpif_obj.notifier); |
---|
.. | .. |
---|
1717 | 1708 | kfree(vpif_obj.sd); |
---|
1718 | 1709 | vpif_unregister: |
---|
1719 | 1710 | v4l2_device_unregister(&vpif_obj.v4l2_dev); |
---|
| 1711 | +vpif_free: |
---|
| 1712 | + free_vpif_objs(); |
---|
| 1713 | +cleanup: |
---|
| 1714 | + v4l2_async_notifier_cleanup(&vpif_obj.notifier); |
---|
1720 | 1715 | |
---|
1721 | 1716 | return err; |
---|
1722 | 1717 | } |
---|
.. | .. |
---|
1732 | 1727 | struct channel_obj *ch; |
---|
1733 | 1728 | int i; |
---|
1734 | 1729 | |
---|
| 1730 | + v4l2_async_notifier_unregister(&vpif_obj.notifier); |
---|
| 1731 | + v4l2_async_notifier_cleanup(&vpif_obj.notifier); |
---|
1735 | 1732 | v4l2_device_unregister(&vpif_obj.v4l2_dev); |
---|
1736 | 1733 | |
---|
1737 | 1734 | kfree(vpif_obj.sd); |
---|