| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * V4L2 Driver for PXA camera host |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2006, Sascha Hauer, Pengutronix |
|---|
| 5 | 6 | * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de> |
|---|
| 6 | 7 | * Copyright (C) 2016, Robert Jarzmik <robert.jarzmik@free.fr> |
|---|
| 7 | | - * |
|---|
| 8 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 9 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 10 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 11 | | - * (at your option) any later version. |
|---|
| 12 | 8 | */ |
|---|
| 13 | 9 | |
|---|
| 14 | 10 | #include <linux/init.h> |
|---|
| .. | .. |
|---|
| 68 | 64 | #define CIBR1 0x0030 |
|---|
| 69 | 65 | #define CIBR2 0x0038 |
|---|
| 70 | 66 | |
|---|
| 71 | | -#define CICR0_DMAEN (1 << 31) /* DMA request enable */ |
|---|
| 67 | +#define CICR0_DMAEN (1UL << 31) /* DMA request enable */ |
|---|
| 72 | 68 | #define CICR0_PAR_EN (1 << 30) /* Parity enable */ |
|---|
| 73 | 69 | #define CICR0_SL_CAP_EN (1 << 29) /* Capture enable for slave mode */ |
|---|
| 74 | 70 | #define CICR0_ENB (1 << 28) /* Camera interface enable */ |
|---|
| .. | .. |
|---|
| 85 | 81 | #define CICR0_EOFM (1 << 1) /* End-of-frame mask */ |
|---|
| 86 | 82 | #define CICR0_FOM (1 << 0) /* FIFO-overrun mask */ |
|---|
| 87 | 83 | |
|---|
| 88 | | -#define CICR1_TBIT (1 << 31) /* Transparency bit */ |
|---|
| 84 | +#define CICR1_TBIT (1UL << 31) /* Transparency bit */ |
|---|
| 89 | 85 | #define CICR1_RGBT_CONV (0x3 << 29) /* RGBT conversion mask */ |
|---|
| 90 | 86 | #define CICR1_PPL (0x7ff << 15) /* Pixels per line mask */ |
|---|
| 91 | 87 | #define CICR1_RGB_CONV (0x7 << 12) /* RGB conversion mask */ |
|---|
| .. | .. |
|---|
| 609 | 605 | return pxa_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt)); |
|---|
| 610 | 606 | } |
|---|
| 611 | 607 | |
|---|
| 612 | | -static unsigned int pxa_mbus_config_compatible(const struct v4l2_mbus_config *cfg, |
|---|
| 613 | | - unsigned int flags) |
|---|
| 614 | | -{ |
|---|
| 615 | | - unsigned long common_flags; |
|---|
| 616 | | - bool hsync = true, vsync = true, pclk, data, mode; |
|---|
| 617 | | - bool mipi_lanes, mipi_clock; |
|---|
| 618 | | - |
|---|
| 619 | | - common_flags = cfg->flags & flags; |
|---|
| 620 | | - |
|---|
| 621 | | - switch (cfg->type) { |
|---|
| 622 | | - case V4L2_MBUS_PARALLEL: |
|---|
| 623 | | - hsync = common_flags & (V4L2_MBUS_HSYNC_ACTIVE_HIGH | |
|---|
| 624 | | - V4L2_MBUS_HSYNC_ACTIVE_LOW); |
|---|
| 625 | | - vsync = common_flags & (V4L2_MBUS_VSYNC_ACTIVE_HIGH | |
|---|
| 626 | | - V4L2_MBUS_VSYNC_ACTIVE_LOW); |
|---|
| 627 | | - /* fall through */ |
|---|
| 628 | | - case V4L2_MBUS_BT656: |
|---|
| 629 | | - pclk = common_flags & (V4L2_MBUS_PCLK_SAMPLE_RISING | |
|---|
| 630 | | - V4L2_MBUS_PCLK_SAMPLE_FALLING); |
|---|
| 631 | | - data = common_flags & (V4L2_MBUS_DATA_ACTIVE_HIGH | |
|---|
| 632 | | - V4L2_MBUS_DATA_ACTIVE_LOW); |
|---|
| 633 | | - mode = common_flags & (V4L2_MBUS_MASTER | V4L2_MBUS_SLAVE); |
|---|
| 634 | | - return (!hsync || !vsync || !pclk || !data || !mode) ? |
|---|
| 635 | | - 0 : common_flags; |
|---|
| 636 | | - case V4L2_MBUS_CSI2: |
|---|
| 637 | | - mipi_lanes = common_flags & V4L2_MBUS_CSI2_LANES; |
|---|
| 638 | | - mipi_clock = common_flags & (V4L2_MBUS_CSI2_NONCONTINUOUS_CLOCK | |
|---|
| 639 | | - V4L2_MBUS_CSI2_CONTINUOUS_CLOCK); |
|---|
| 640 | | - return (!mipi_lanes || !mipi_clock) ? 0 : common_flags; |
|---|
| 641 | | - default: |
|---|
| 642 | | - WARN_ON(1); |
|---|
| 643 | | - return -EINVAL; |
|---|
| 644 | | - } |
|---|
| 645 | | - return 0; |
|---|
| 646 | | -} |
|---|
| 647 | | - |
|---|
| 648 | 608 | /** |
|---|
| 649 | 609 | * struct pxa_camera_format_xlate - match between host and sensor formats |
|---|
| 650 | 610 | * @code: code of a sensor provided format |
|---|
| .. | .. |
|---|
| 697 | 657 | struct v4l2_pix_format current_pix; |
|---|
| 698 | 658 | |
|---|
| 699 | 659 | struct v4l2_async_subdev asd; |
|---|
| 700 | | - struct v4l2_async_subdev *asds[1]; |
|---|
| 701 | 660 | |
|---|
| 702 | 661 | /* |
|---|
| 703 | 662 | * PXA27x is only supposed to handle one camera on its Quick Capture |
|---|
| .. | .. |
|---|
| 1021 | 980 | * - a videobuffer is queued on the pcdev->capture list |
|---|
| 1022 | 981 | * |
|---|
| 1023 | 982 | * Please check the "DMA hot chaining timeslice issue" in |
|---|
| 1024 | | - * Documentation/media/v4l-drivers/pxa_camera.rst |
|---|
| 983 | + * Documentation/driver-api/media/drivers/pxa_camera.rst |
|---|
| 1025 | 984 | * |
|---|
| 1026 | 985 | * Context: should only be called within the dma irq handler |
|---|
| 1027 | 986 | */ |
|---|
| .. | .. |
|---|
| 1191 | 1150 | clk_disable_unprepare(pcdev->clk); |
|---|
| 1192 | 1151 | } |
|---|
| 1193 | 1152 | |
|---|
| 1194 | | -static void pxa_camera_eof(unsigned long arg) |
|---|
| 1153 | +static void pxa_camera_eof(struct tasklet_struct *t) |
|---|
| 1195 | 1154 | { |
|---|
| 1196 | | - struct pxa_camera_dev *pcdev = (struct pxa_camera_dev *)arg; |
|---|
| 1155 | + struct pxa_camera_dev *pcdev = from_tasklet(pcdev, t, task_eof); |
|---|
| 1197 | 1156 | unsigned long cifr; |
|---|
| 1198 | 1157 | struct pxa_buffer *buf; |
|---|
| 1199 | 1158 | |
|---|
| .. | .. |
|---|
| 1234 | 1193 | } |
|---|
| 1235 | 1194 | |
|---|
| 1236 | 1195 | return IRQ_HANDLED; |
|---|
| 1237 | | -} |
|---|
| 1238 | | - |
|---|
| 1239 | | -static int test_platform_param(struct pxa_camera_dev *pcdev, |
|---|
| 1240 | | - unsigned char buswidth, unsigned long *flags) |
|---|
| 1241 | | -{ |
|---|
| 1242 | | - /* |
|---|
| 1243 | | - * Platform specified synchronization and pixel clock polarities are |
|---|
| 1244 | | - * only a recommendation and are only used during probing. The PXA270 |
|---|
| 1245 | | - * quick capture interface supports both. |
|---|
| 1246 | | - */ |
|---|
| 1247 | | - *flags = (pcdev->platform_flags & PXA_CAMERA_MASTER ? |
|---|
| 1248 | | - V4L2_MBUS_MASTER : V4L2_MBUS_SLAVE) | |
|---|
| 1249 | | - V4L2_MBUS_HSYNC_ACTIVE_HIGH | |
|---|
| 1250 | | - V4L2_MBUS_HSYNC_ACTIVE_LOW | |
|---|
| 1251 | | - V4L2_MBUS_VSYNC_ACTIVE_HIGH | |
|---|
| 1252 | | - V4L2_MBUS_VSYNC_ACTIVE_LOW | |
|---|
| 1253 | | - V4L2_MBUS_DATA_ACTIVE_HIGH | |
|---|
| 1254 | | - V4L2_MBUS_PCLK_SAMPLE_RISING | |
|---|
| 1255 | | - V4L2_MBUS_PCLK_SAMPLE_FALLING; |
|---|
| 1256 | | - |
|---|
| 1257 | | - /* If requested data width is supported by the platform, use it */ |
|---|
| 1258 | | - if ((1 << (buswidth - 1)) & pcdev->width_flags) |
|---|
| 1259 | | - return 0; |
|---|
| 1260 | | - |
|---|
| 1261 | | - return -EINVAL; |
|---|
| 1262 | 1196 | } |
|---|
| 1263 | 1197 | |
|---|
| 1264 | 1198 | static void pxa_camera_setup_cicr(struct pxa_camera_dev *pcdev, |
|---|
| .. | .. |
|---|
| 1393 | 1327 | break; |
|---|
| 1394 | 1328 | default: |
|---|
| 1395 | 1329 | return -EINVAL; |
|---|
| 1396 | | - }; |
|---|
| 1330 | + } |
|---|
| 1397 | 1331 | buf->nb_planes = nb_channels; |
|---|
| 1398 | 1332 | |
|---|
| 1399 | 1333 | ret = sg_split(sgt->sgl, sgt->nents, 0, nb_channels, |
|---|
| .. | .. |
|---|
| 1443 | 1377 | |
|---|
| 1444 | 1378 | /* |
|---|
| 1445 | 1379 | * Please check the DMA prepared buffer structure in : |
|---|
| 1446 | | - * Documentation/media/v4l-drivers/pxa_camera.rst |
|---|
| 1380 | + * Documentation/driver-api/media/drivers/pxa_camera.rst |
|---|
| 1447 | 1381 | * Please check also in pxa_camera_check_link_miss() to understand why DMA chain |
|---|
| 1448 | 1382 | * modification while DMA chain is running will work anyway. |
|---|
| 1449 | 1383 | */ |
|---|
| .. | .. |
|---|
| 1606 | 1540 | */ |
|---|
| 1607 | 1541 | static int pxa_camera_set_bus_param(struct pxa_camera_dev *pcdev) |
|---|
| 1608 | 1542 | { |
|---|
| 1543 | + unsigned int bus_width = pcdev->current_fmt->host_fmt->bits_per_sample; |
|---|
| 1609 | 1544 | struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
|---|
| 1610 | 1545 | u32 pixfmt = pcdev->current_fmt->host_fmt->fourcc; |
|---|
| 1611 | | - unsigned long bus_flags, common_flags; |
|---|
| 1546 | + int mbus_config; |
|---|
| 1612 | 1547 | int ret; |
|---|
| 1613 | 1548 | |
|---|
| 1614 | | - ret = test_platform_param(pcdev, |
|---|
| 1615 | | - pcdev->current_fmt->host_fmt->bits_per_sample, |
|---|
| 1616 | | - &bus_flags); |
|---|
| 1617 | | - if (ret < 0) |
|---|
| 1618 | | - return ret; |
|---|
| 1619 | | - |
|---|
| 1620 | | - ret = sensor_call(pcdev, video, g_mbus_config, &cfg); |
|---|
| 1621 | | - if (!ret) { |
|---|
| 1622 | | - common_flags = pxa_mbus_config_compatible(&cfg, |
|---|
| 1623 | | - bus_flags); |
|---|
| 1624 | | - if (!common_flags) { |
|---|
| 1625 | | - dev_warn(pcdev_to_dev(pcdev), |
|---|
| 1626 | | - "Flags incompatible: camera 0x%x, host 0x%lx\n", |
|---|
| 1627 | | - cfg.flags, bus_flags); |
|---|
| 1628 | | - return -EINVAL; |
|---|
| 1629 | | - } |
|---|
| 1630 | | - } else if (ret != -ENOIOCTLCMD) { |
|---|
| 1631 | | - return ret; |
|---|
| 1632 | | - } else { |
|---|
| 1633 | | - common_flags = bus_flags; |
|---|
| 1549 | + if (!((1 << (bus_width - 1)) & pcdev->width_flags)) { |
|---|
| 1550 | + dev_err(pcdev_to_dev(pcdev), "Unsupported bus width %u", |
|---|
| 1551 | + bus_width); |
|---|
| 1552 | + return -EINVAL; |
|---|
| 1634 | 1553 | } |
|---|
| 1635 | 1554 | |
|---|
| 1636 | 1555 | pcdev->channels = 1; |
|---|
| 1637 | 1556 | |
|---|
| 1638 | | - /* Make choises, based on platform preferences */ |
|---|
| 1639 | | - if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) && |
|---|
| 1640 | | - (common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) { |
|---|
| 1641 | | - if (pcdev->platform_flags & PXA_CAMERA_HSP) |
|---|
| 1642 | | - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH; |
|---|
| 1643 | | - else |
|---|
| 1644 | | - common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW; |
|---|
| 1645 | | - } |
|---|
| 1557 | + /* Make choices, based on platform preferences */ |
|---|
| 1558 | + mbus_config = 0; |
|---|
| 1559 | + if (pcdev->platform_flags & PXA_CAMERA_MASTER) |
|---|
| 1560 | + mbus_config |= V4L2_MBUS_MASTER; |
|---|
| 1561 | + else |
|---|
| 1562 | + mbus_config |= V4L2_MBUS_SLAVE; |
|---|
| 1646 | 1563 | |
|---|
| 1647 | | - if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) && |
|---|
| 1648 | | - (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) { |
|---|
| 1649 | | - if (pcdev->platform_flags & PXA_CAMERA_VSP) |
|---|
| 1650 | | - common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH; |
|---|
| 1651 | | - else |
|---|
| 1652 | | - common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW; |
|---|
| 1653 | | - } |
|---|
| 1564 | + if (pcdev->platform_flags & PXA_CAMERA_HSP) |
|---|
| 1565 | + mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_HIGH; |
|---|
| 1566 | + else |
|---|
| 1567 | + mbus_config |= V4L2_MBUS_HSYNC_ACTIVE_LOW; |
|---|
| 1654 | 1568 | |
|---|
| 1655 | | - if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) && |
|---|
| 1656 | | - (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) { |
|---|
| 1657 | | - if (pcdev->platform_flags & PXA_CAMERA_PCP) |
|---|
| 1658 | | - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING; |
|---|
| 1659 | | - else |
|---|
| 1660 | | - common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING; |
|---|
| 1661 | | - } |
|---|
| 1569 | + if (pcdev->platform_flags & PXA_CAMERA_VSP) |
|---|
| 1570 | + mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_HIGH; |
|---|
| 1571 | + else |
|---|
| 1572 | + mbus_config |= V4L2_MBUS_VSYNC_ACTIVE_LOW; |
|---|
| 1662 | 1573 | |
|---|
| 1663 | | - cfg.flags = common_flags; |
|---|
| 1664 | | - ret = sensor_call(pcdev, video, s_mbus_config, &cfg); |
|---|
| 1574 | + if (pcdev->platform_flags & PXA_CAMERA_PCP) |
|---|
| 1575 | + mbus_config |= V4L2_MBUS_PCLK_SAMPLE_RISING; |
|---|
| 1576 | + else |
|---|
| 1577 | + mbus_config |= V4L2_MBUS_PCLK_SAMPLE_FALLING; |
|---|
| 1578 | + mbus_config |= V4L2_MBUS_DATA_ACTIVE_HIGH; |
|---|
| 1579 | + |
|---|
| 1580 | + cfg.flags = mbus_config; |
|---|
| 1581 | + ret = sensor_call(pcdev, pad, set_mbus_config, 0, &cfg); |
|---|
| 1665 | 1582 | if (ret < 0 && ret != -ENOIOCTLCMD) { |
|---|
| 1666 | | - dev_dbg(pcdev_to_dev(pcdev), |
|---|
| 1667 | | - "camera s_mbus_config(0x%lx) returned %d\n", |
|---|
| 1668 | | - common_flags, ret); |
|---|
| 1583 | + dev_err(pcdev_to_dev(pcdev), |
|---|
| 1584 | + "Failed to call set_mbus_config: %d\n", ret); |
|---|
| 1669 | 1585 | return ret; |
|---|
| 1670 | 1586 | } |
|---|
| 1671 | 1587 | |
|---|
| 1672 | | - pxa_camera_setup_cicr(pcdev, common_flags, pixfmt); |
|---|
| 1673 | | - |
|---|
| 1674 | | - return 0; |
|---|
| 1675 | | -} |
|---|
| 1676 | | - |
|---|
| 1677 | | -static int pxa_camera_try_bus_param(struct pxa_camera_dev *pcdev, |
|---|
| 1678 | | - unsigned char buswidth) |
|---|
| 1679 | | -{ |
|---|
| 1680 | | - struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,}; |
|---|
| 1681 | | - unsigned long bus_flags, common_flags; |
|---|
| 1682 | | - int ret = test_platform_param(pcdev, buswidth, &bus_flags); |
|---|
| 1683 | | - |
|---|
| 1684 | | - if (ret < 0) |
|---|
| 1685 | | - return ret; |
|---|
| 1686 | | - |
|---|
| 1687 | | - ret = sensor_call(pcdev, video, g_mbus_config, &cfg); |
|---|
| 1688 | | - if (!ret) { |
|---|
| 1689 | | - common_flags = pxa_mbus_config_compatible(&cfg, |
|---|
| 1690 | | - bus_flags); |
|---|
| 1691 | | - if (!common_flags) { |
|---|
| 1692 | | - dev_warn(pcdev_to_dev(pcdev), |
|---|
| 1693 | | - "Flags incompatible: camera 0x%x, host 0x%lx\n", |
|---|
| 1694 | | - cfg.flags, bus_flags); |
|---|
| 1588 | + /* |
|---|
| 1589 | + * If the requested media bus configuration has not been fully applied |
|---|
| 1590 | + * make sure it is supported by the platform. |
|---|
| 1591 | + * |
|---|
| 1592 | + * PXA does not support V4L2_MBUS_DATA_ACTIVE_LOW and the bus mastering |
|---|
| 1593 | + * roles should match. |
|---|
| 1594 | + */ |
|---|
| 1595 | + if (cfg.flags != mbus_config) { |
|---|
| 1596 | + unsigned int pxa_mbus_role = mbus_config & (V4L2_MBUS_MASTER | |
|---|
| 1597 | + V4L2_MBUS_SLAVE); |
|---|
| 1598 | + if (pxa_mbus_role != (cfg.flags & (V4L2_MBUS_MASTER | |
|---|
| 1599 | + V4L2_MBUS_SLAVE))) { |
|---|
| 1600 | + dev_err(pcdev_to_dev(pcdev), |
|---|
| 1601 | + "Unsupported mbus configuration: bus mastering\n"); |
|---|
| 1695 | 1602 | return -EINVAL; |
|---|
| 1696 | 1603 | } |
|---|
| 1697 | | - } else if (ret == -ENOIOCTLCMD) { |
|---|
| 1698 | | - ret = 0; |
|---|
| 1604 | + |
|---|
| 1605 | + if (cfg.flags & V4L2_MBUS_DATA_ACTIVE_LOW) { |
|---|
| 1606 | + dev_err(pcdev_to_dev(pcdev), |
|---|
| 1607 | + "Unsupported mbus configuration: DATA_ACTIVE_LOW\n"); |
|---|
| 1608 | + return -EINVAL; |
|---|
| 1609 | + } |
|---|
| 1699 | 1610 | } |
|---|
| 1700 | 1611 | |
|---|
| 1701 | | - return ret; |
|---|
| 1612 | + pxa_camera_setup_cicr(pcdev, cfg.flags, pixfmt); |
|---|
| 1613 | + |
|---|
| 1614 | + return 0; |
|---|
| 1702 | 1615 | } |
|---|
| 1703 | 1616 | |
|---|
| 1704 | 1617 | static const struct pxa_mbus_pixelfmt pxa_camera_formats[] = { |
|---|
| .. | .. |
|---|
| 1745 | 1658 | "Invalid format code #%u: %d\n", idx, code.code); |
|---|
| 1746 | 1659 | return 0; |
|---|
| 1747 | 1660 | } |
|---|
| 1748 | | - |
|---|
| 1749 | | - /* This also checks support for the requested bits-per-sample */ |
|---|
| 1750 | | - ret = pxa_camera_try_bus_param(pcdev, fmt->bits_per_sample); |
|---|
| 1751 | | - if (ret < 0) |
|---|
| 1752 | | - return 0; |
|---|
| 1753 | 1661 | |
|---|
| 1754 | 1662 | switch (code.code) { |
|---|
| 1755 | 1663 | case MEDIA_BUS_FMT_UYVY8_2X8: |
|---|
| .. | .. |
|---|
| 1997 | 1905 | static int pxac_vidioc_querycap(struct file *file, void *priv, |
|---|
| 1998 | 1906 | struct v4l2_capability *cap) |
|---|
| 1999 | 1907 | { |
|---|
| 2000 | | - strlcpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info)); |
|---|
| 2001 | | - strlcpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver)); |
|---|
| 2002 | | - strlcpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); |
|---|
| 2003 | | - cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING; |
|---|
| 2004 | | - cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS; |
|---|
| 2005 | | - |
|---|
| 1908 | + strscpy(cap->bus_info, "platform:pxa-camera", sizeof(cap->bus_info)); |
|---|
| 1909 | + strscpy(cap->driver, PXA_CAM_DRV_NAME, sizeof(cap->driver)); |
|---|
| 1910 | + strscpy(cap->card, pxa_cam_driver_description, sizeof(cap->card)); |
|---|
| 2006 | 1911 | return 0; |
|---|
| 2007 | 1912 | } |
|---|
| 2008 | 1913 | |
|---|
| .. | .. |
|---|
| 2013 | 1918 | return -EINVAL; |
|---|
| 2014 | 1919 | |
|---|
| 2015 | 1920 | i->type = V4L2_INPUT_TYPE_CAMERA; |
|---|
| 2016 | | - strlcpy(i->name, "Camera", sizeof(i->name)); |
|---|
| 1921 | + strscpy(i->name, "Camera", sizeof(i->name)); |
|---|
| 2017 | 1922 | |
|---|
| 2018 | 1923 | return 0; |
|---|
| 2019 | 1924 | } |
|---|
| .. | .. |
|---|
| 2202 | 2107 | if (err) |
|---|
| 2203 | 2108 | goto out_sensor_poweroff; |
|---|
| 2204 | 2109 | |
|---|
| 2205 | | - err = video_register_device(&pcdev->vdev, VFL_TYPE_GRABBER, -1); |
|---|
| 2110 | + err = video_register_device(&pcdev->vdev, VFL_TYPE_VIDEO, -1); |
|---|
| 2206 | 2111 | if (err) { |
|---|
| 2207 | 2112 | v4l2_err(v4l2_dev, "register video device failed: %d\n", err); |
|---|
| 2208 | 2113 | pcdev->sensor = NULL; |
|---|
| .. | .. |
|---|
| 2302 | 2207 | { |
|---|
| 2303 | 2208 | u32 mclk_rate; |
|---|
| 2304 | 2209 | struct device_node *remote, *np = dev->of_node; |
|---|
| 2305 | | - struct v4l2_fwnode_endpoint ep; |
|---|
| 2210 | + struct v4l2_fwnode_endpoint ep = { .bus_type = 0 }; |
|---|
| 2306 | 2211 | int err = of_property_read_u32(np, "clock-frequency", |
|---|
| 2307 | 2212 | &mclk_rate); |
|---|
| 2308 | 2213 | if (!err) { |
|---|
| .. | .. |
|---|
| 2354 | 2259 | pcdev->platform_flags |= PXA_CAMERA_PCLK_EN; |
|---|
| 2355 | 2260 | |
|---|
| 2356 | 2261 | asd->match_type = V4L2_ASYNC_MATCH_FWNODE; |
|---|
| 2357 | | - remote = of_graph_get_remote_port(np); |
|---|
| 2358 | | - if (remote) { |
|---|
| 2262 | + remote = of_graph_get_remote_port_parent(np); |
|---|
| 2263 | + if (remote) |
|---|
| 2359 | 2264 | asd->match.fwnode = of_fwnode_handle(remote); |
|---|
| 2360 | | - of_node_put(remote); |
|---|
| 2361 | | - } else { |
|---|
| 2265 | + else |
|---|
| 2362 | 2266 | dev_notice(dev, "no remote for %pOF\n", np); |
|---|
| 2363 | | - } |
|---|
| 2364 | 2267 | |
|---|
| 2365 | 2268 | out: |
|---|
| 2366 | 2269 | of_node_put(np); |
|---|
| .. | .. |
|---|
| 2400 | 2303 | pcdev->res = res; |
|---|
| 2401 | 2304 | |
|---|
| 2402 | 2305 | pcdev->pdata = pdev->dev.platform_data; |
|---|
| 2403 | | - if (pdev->dev.of_node && !pcdev->pdata) { |
|---|
| 2404 | | - err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd); |
|---|
| 2405 | | - } else { |
|---|
| 2306 | + if (pcdev->pdata) { |
|---|
| 2406 | 2307 | pcdev->platform_flags = pcdev->pdata->flags; |
|---|
| 2407 | 2308 | pcdev->mclk = pcdev->pdata->mclk_10khz * 10000; |
|---|
| 2408 | 2309 | pcdev->asd.match_type = V4L2_ASYNC_MATCH_I2C; |
|---|
| 2409 | 2310 | pcdev->asd.match.i2c.adapter_id = |
|---|
| 2410 | 2311 | pcdev->pdata->sensor_i2c_adapter_id; |
|---|
| 2411 | 2312 | pcdev->asd.match.i2c.address = pcdev->pdata->sensor_i2c_address; |
|---|
| 2313 | + } else if (pdev->dev.of_node) { |
|---|
| 2314 | + err = pxa_camera_pdata_from_dt(&pdev->dev, pcdev, &pcdev->asd); |
|---|
| 2315 | + } else { |
|---|
| 2316 | + return -ENODEV; |
|---|
| 2412 | 2317 | } |
|---|
| 2413 | 2318 | if (err < 0) |
|---|
| 2414 | 2319 | return err; |
|---|
| .. | .. |
|---|
| 2451 | 2356 | pcdev->base = base; |
|---|
| 2452 | 2357 | |
|---|
| 2453 | 2358 | /* request dma */ |
|---|
| 2454 | | - pcdev->dma_chans[0] = dma_request_slave_channel(&pdev->dev, "CI_Y"); |
|---|
| 2455 | | - if (!pcdev->dma_chans[0]) { |
|---|
| 2359 | + pcdev->dma_chans[0] = dma_request_chan(&pdev->dev, "CI_Y"); |
|---|
| 2360 | + if (IS_ERR(pcdev->dma_chans[0])) { |
|---|
| 2456 | 2361 | dev_err(&pdev->dev, "Can't request DMA for Y\n"); |
|---|
| 2457 | | - return -ENODEV; |
|---|
| 2362 | + return PTR_ERR(pcdev->dma_chans[0]); |
|---|
| 2458 | 2363 | } |
|---|
| 2459 | 2364 | |
|---|
| 2460 | | - pcdev->dma_chans[1] = dma_request_slave_channel(&pdev->dev, "CI_U"); |
|---|
| 2461 | | - if (!pcdev->dma_chans[1]) { |
|---|
| 2462 | | - dev_err(&pdev->dev, "Can't request DMA for Y\n"); |
|---|
| 2463 | | - err = -ENODEV; |
|---|
| 2365 | + pcdev->dma_chans[1] = dma_request_chan(&pdev->dev, "CI_U"); |
|---|
| 2366 | + if (IS_ERR(pcdev->dma_chans[1])) { |
|---|
| 2367 | + dev_err(&pdev->dev, "Can't request DMA for U\n"); |
|---|
| 2368 | + err = PTR_ERR(pcdev->dma_chans[1]); |
|---|
| 2464 | 2369 | goto exit_free_dma_y; |
|---|
| 2465 | 2370 | } |
|---|
| 2466 | 2371 | |
|---|
| 2467 | | - pcdev->dma_chans[2] = dma_request_slave_channel(&pdev->dev, "CI_V"); |
|---|
| 2468 | | - if (!pcdev->dma_chans[2]) { |
|---|
| 2372 | + pcdev->dma_chans[2] = dma_request_chan(&pdev->dev, "CI_V"); |
|---|
| 2373 | + if (IS_ERR(pcdev->dma_chans[2])) { |
|---|
| 2469 | 2374 | dev_err(&pdev->dev, "Can't request DMA for V\n"); |
|---|
| 2470 | | - err = -ENODEV; |
|---|
| 2375 | + err = PTR_ERR(pcdev->dma_chans[2]); |
|---|
| 2471 | 2376 | goto exit_free_dma_u; |
|---|
| 2472 | 2377 | } |
|---|
| 2473 | 2378 | |
|---|
| .. | .. |
|---|
| 2489 | 2394 | goto exit_free_dma; |
|---|
| 2490 | 2395 | } |
|---|
| 2491 | 2396 | |
|---|
| 2492 | | - tasklet_init(&pcdev->task_eof, pxa_camera_eof, (unsigned long)pcdev); |
|---|
| 2397 | + tasklet_setup(&pcdev->task_eof, pxa_camera_eof); |
|---|
| 2493 | 2398 | |
|---|
| 2494 | 2399 | pxa_camera_activate(pcdev); |
|---|
| 2495 | 2400 | |
|---|
| .. | .. |
|---|
| 2498 | 2403 | if (err) |
|---|
| 2499 | 2404 | goto exit_deactivate; |
|---|
| 2500 | 2405 | |
|---|
| 2501 | | - pcdev->asds[0] = &pcdev->asd; |
|---|
| 2502 | | - pcdev->notifier.subdevs = pcdev->asds; |
|---|
| 2503 | | - pcdev->notifier.num_subdevs = 1; |
|---|
| 2406 | + v4l2_async_notifier_init(&pcdev->notifier); |
|---|
| 2407 | + |
|---|
| 2408 | + err = v4l2_async_notifier_add_subdev(&pcdev->notifier, &pcdev->asd); |
|---|
| 2409 | + if (err) { |
|---|
| 2410 | + fwnode_handle_put(pcdev->asd.match.fwnode); |
|---|
| 2411 | + goto exit_free_v4l2dev; |
|---|
| 2412 | + } |
|---|
| 2413 | + |
|---|
| 2504 | 2414 | pcdev->notifier.ops = &pxa_camera_sensor_ops; |
|---|
| 2505 | 2415 | |
|---|
| 2506 | 2416 | if (!of_have_populated_dt()) |
|---|
| .. | .. |
|---|
| 2508 | 2418 | |
|---|
| 2509 | 2419 | err = pxa_camera_init_videobuf2(pcdev); |
|---|
| 2510 | 2420 | if (err) |
|---|
| 2511 | | - goto exit_free_v4l2dev; |
|---|
| 2421 | + goto exit_notifier_cleanup; |
|---|
| 2512 | 2422 | |
|---|
| 2513 | | - if (pcdev->mclk) { |
|---|
| 2514 | | - v4l2_clk_name_i2c(clk_name, sizeof(clk_name), |
|---|
| 2515 | | - pcdev->asd.match.i2c.adapter_id, |
|---|
| 2516 | | - pcdev->asd.match.i2c.address); |
|---|
| 2423 | + v4l2_clk_name_i2c(clk_name, sizeof(clk_name), |
|---|
| 2424 | + pcdev->asd.match.i2c.adapter_id, |
|---|
| 2425 | + pcdev->asd.match.i2c.address); |
|---|
| 2517 | 2426 | |
|---|
| 2518 | | - pcdev->mclk_clk = v4l2_clk_register(&pxa_camera_mclk_ops, |
|---|
| 2519 | | - clk_name, NULL); |
|---|
| 2520 | | - if (IS_ERR(pcdev->mclk_clk)) { |
|---|
| 2521 | | - err = PTR_ERR(pcdev->mclk_clk); |
|---|
| 2522 | | - goto exit_free_v4l2dev; |
|---|
| 2523 | | - } |
|---|
| 2427 | + pcdev->mclk_clk = v4l2_clk_register(&pxa_camera_mclk_ops, clk_name, NULL); |
|---|
| 2428 | + if (IS_ERR(pcdev->mclk_clk)) { |
|---|
| 2429 | + err = PTR_ERR(pcdev->mclk_clk); |
|---|
| 2430 | + goto exit_notifier_cleanup; |
|---|
| 2524 | 2431 | } |
|---|
| 2525 | 2432 | |
|---|
| 2526 | 2433 | err = v4l2_async_notifier_register(&pcdev->v4l2_dev, &pcdev->notifier); |
|---|
| .. | .. |
|---|
| 2530 | 2437 | return 0; |
|---|
| 2531 | 2438 | exit_free_clk: |
|---|
| 2532 | 2439 | v4l2_clk_unregister(pcdev->mclk_clk); |
|---|
| 2440 | +exit_notifier_cleanup: |
|---|
| 2441 | + v4l2_async_notifier_cleanup(&pcdev->notifier); |
|---|
| 2533 | 2442 | exit_free_v4l2dev: |
|---|
| 2534 | 2443 | v4l2_device_unregister(&pcdev->v4l2_dev); |
|---|
| 2535 | 2444 | exit_deactivate: |
|---|
| 2536 | 2445 | pxa_camera_deactivate(pcdev); |
|---|
| 2446 | + tasklet_kill(&pcdev->task_eof); |
|---|
| 2537 | 2447 | exit_free_dma: |
|---|
| 2538 | 2448 | dma_release_channel(pcdev->dma_chans[2]); |
|---|
| 2539 | 2449 | exit_free_dma_u: |
|---|
| .. | .. |
|---|
| 2548 | 2458 | struct pxa_camera_dev *pcdev = dev_get_drvdata(&pdev->dev); |
|---|
| 2549 | 2459 | |
|---|
| 2550 | 2460 | pxa_camera_deactivate(pcdev); |
|---|
| 2461 | + tasklet_kill(&pcdev->task_eof); |
|---|
| 2551 | 2462 | dma_release_channel(pcdev->dma_chans[0]); |
|---|
| 2552 | 2463 | dma_release_channel(pcdev->dma_chans[1]); |
|---|
| 2553 | 2464 | dma_release_channel(pcdev->dma_chans[2]); |
|---|
| 2554 | 2465 | |
|---|
| 2555 | 2466 | v4l2_async_notifier_unregister(&pcdev->notifier); |
|---|
| 2467 | + v4l2_async_notifier_cleanup(&pcdev->notifier); |
|---|
| 2556 | 2468 | |
|---|
| 2557 | 2469 | if (pcdev->mclk_clk) { |
|---|
| 2558 | 2470 | v4l2_clk_unregister(pcdev->mclk_clk); |
|---|
| .. | .. |
|---|
| 2589 | 2501 | |
|---|
| 2590 | 2502 | module_platform_driver(pxa_camera_driver); |
|---|
| 2591 | 2503 | |
|---|
| 2592 | | -MODULE_DESCRIPTION("PXA27x SoC Camera Host driver"); |
|---|
| 2504 | +MODULE_DESCRIPTION("PXA27x Camera Driver"); |
|---|
| 2593 | 2505 | MODULE_AUTHOR("Guennadi Liakhovetski <kernel@pengutronix.de>"); |
|---|
| 2594 | 2506 | MODULE_LICENSE("GPL"); |
|---|
| 2595 | 2507 | MODULE_VERSION(PXA_CAM_VERSION); |
|---|