.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * isp.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
36 | 37 | * Thara Gopinath <thara@ti.com> |
---|
37 | 38 | * Toni Leinonen <toni.leinonen@nokia.com> |
---|
38 | 39 | * Troy Laramy <t-laramy@ti.com> |
---|
39 | | - * |
---|
40 | | - * This program is free software; you can redistribute it and/or modify |
---|
41 | | - * it under the terms of the GNU General Public License version 2 as |
---|
42 | | - * published by the Free Software Foundation. |
---|
43 | 40 | */ |
---|
44 | | - |
---|
45 | | -#include <asm/cacheflush.h> |
---|
46 | 41 | |
---|
47 | 42 | #include <linux/clk.h> |
---|
48 | 43 | #include <linux/clkdev.h> |
---|
.. | .. |
---|
147 | 142 | * readback the same register, in this case the revision register. |
---|
148 | 143 | * |
---|
149 | 144 | * See this link for reference: |
---|
150 | | - * http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html |
---|
| 145 | + * https://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html |
---|
151 | 146 | */ |
---|
152 | 147 | void omap3isp_flush(struct isp_device *isp) |
---|
153 | 148 | { |
---|
.. | .. |
---|
813 | 808 | |
---|
814 | 809 | ret = v4l2_subdev_call(subdev, video, s_stream, 0); |
---|
815 | 810 | |
---|
| 811 | + /* Stop at the first external sub-device. */ |
---|
| 812 | + if (subdev->dev != isp->dev) |
---|
| 813 | + break; |
---|
| 814 | + |
---|
816 | 815 | if (subdev == &isp->isp_res.subdev) |
---|
817 | 816 | ret |= isp_pipeline_wait(isp, isp_pipeline_wait_resizer); |
---|
818 | 817 | else if (subdev == &isp->isp_prev.subdev) |
---|
.. | .. |
---|
840 | 839 | &subdev->entity); |
---|
841 | 840 | failure = -ETIMEDOUT; |
---|
842 | 841 | } |
---|
843 | | - |
---|
844 | | - /* Stop at the first external sub-device. */ |
---|
845 | | - if (subdev->dev != isp->dev) |
---|
846 | | - break; |
---|
847 | 842 | } |
---|
848 | 843 | |
---|
849 | 844 | return failure; |
---|
.. | .. |
---|
1525 | 1520 | * |
---|
1526 | 1521 | * To solve this problem power management support is split into prepare/complete |
---|
1527 | 1522 | * and suspend/resume operations. The pipelines are stopped in prepare() and the |
---|
1528 | | - * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in |
---|
| 1523 | + * ISP clocks get disabled in suspend(). Similarly, the clocks are re-enabled in |
---|
1529 | 1524 | * resume(), and the the pipelines are restarted in complete(). |
---|
1530 | 1525 | * |
---|
1531 | 1526 | * TODO: PM dependencies between the ISP and sensors are not modelled explicitly |
---|
.. | .. |
---|
1686 | 1681 | int ret; |
---|
1687 | 1682 | |
---|
1688 | 1683 | isp->media_dev.dev = isp->dev; |
---|
1689 | | - strlcpy(isp->media_dev.model, "TI OMAP3 ISP", |
---|
| 1684 | + strscpy(isp->media_dev.model, "TI OMAP3 ISP", |
---|
1690 | 1685 | sizeof(isp->media_dev.model)); |
---|
1691 | 1686 | isp->media_dev.hw_revision = isp->revision; |
---|
1692 | 1687 | isp->media_dev.ops = &isp_media_ops; |
---|
.. | .. |
---|
2014 | 2009 | media_entity_enum_cleanup(&isp->crashed); |
---|
2015 | 2010 | v4l2_async_notifier_cleanup(&isp->notifier); |
---|
2016 | 2011 | |
---|
| 2012 | + kfree(isp); |
---|
| 2013 | + |
---|
2017 | 2014 | return 0; |
---|
2018 | 2015 | } |
---|
2019 | 2016 | |
---|
.. | .. |
---|
2022 | 2019 | ISP_OF_PHY_CSIPHY1, |
---|
2023 | 2020 | ISP_OF_PHY_CSIPHY2, |
---|
2024 | 2021 | }; |
---|
2025 | | - |
---|
2026 | | -static int isp_fwnode_parse(struct device *dev, |
---|
2027 | | - struct v4l2_fwnode_endpoint *vep, |
---|
2028 | | - struct v4l2_async_subdev *asd) |
---|
2029 | | -{ |
---|
2030 | | - struct isp_async_subdev *isd = |
---|
2031 | | - container_of(asd, struct isp_async_subdev, asd); |
---|
2032 | | - struct isp_bus_cfg *buscfg = &isd->bus; |
---|
2033 | | - bool csi1 = false; |
---|
2034 | | - unsigned int i; |
---|
2035 | | - |
---|
2036 | | - dev_dbg(dev, "parsing endpoint %pOF, interface %u\n", |
---|
2037 | | - to_of_node(vep->base.local_fwnode), vep->base.port); |
---|
2038 | | - |
---|
2039 | | - switch (vep->base.port) { |
---|
2040 | | - case ISP_OF_PHY_PARALLEL: |
---|
2041 | | - buscfg->interface = ISP_INTERFACE_PARALLEL; |
---|
2042 | | - buscfg->bus.parallel.data_lane_shift = |
---|
2043 | | - vep->bus.parallel.data_shift; |
---|
2044 | | - buscfg->bus.parallel.clk_pol = |
---|
2045 | | - !!(vep->bus.parallel.flags |
---|
2046 | | - & V4L2_MBUS_PCLK_SAMPLE_FALLING); |
---|
2047 | | - buscfg->bus.parallel.hs_pol = |
---|
2048 | | - !!(vep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); |
---|
2049 | | - buscfg->bus.parallel.vs_pol = |
---|
2050 | | - !!(vep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); |
---|
2051 | | - buscfg->bus.parallel.fld_pol = |
---|
2052 | | - !!(vep->bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); |
---|
2053 | | - buscfg->bus.parallel.data_pol = |
---|
2054 | | - !!(vep->bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); |
---|
2055 | | - buscfg->bus.parallel.bt656 = vep->bus_type == V4L2_MBUS_BT656; |
---|
2056 | | - break; |
---|
2057 | | - |
---|
2058 | | - case ISP_OF_PHY_CSIPHY1: |
---|
2059 | | - case ISP_OF_PHY_CSIPHY2: |
---|
2060 | | - switch (vep->bus_type) { |
---|
2061 | | - case V4L2_MBUS_CCP2: |
---|
2062 | | - case V4L2_MBUS_CSI1: |
---|
2063 | | - dev_dbg(dev, "CSI-1/CCP-2 configuration\n"); |
---|
2064 | | - csi1 = true; |
---|
2065 | | - break; |
---|
2066 | | - case V4L2_MBUS_CSI2: |
---|
2067 | | - dev_dbg(dev, "CSI-2 configuration\n"); |
---|
2068 | | - csi1 = false; |
---|
2069 | | - break; |
---|
2070 | | - default: |
---|
2071 | | - dev_err(dev, "unsupported bus type %u\n", |
---|
2072 | | - vep->bus_type); |
---|
2073 | | - return -EINVAL; |
---|
2074 | | - } |
---|
2075 | | - |
---|
2076 | | - switch (vep->base.port) { |
---|
2077 | | - case ISP_OF_PHY_CSIPHY1: |
---|
2078 | | - if (csi1) |
---|
2079 | | - buscfg->interface = ISP_INTERFACE_CCP2B_PHY1; |
---|
2080 | | - else |
---|
2081 | | - buscfg->interface = ISP_INTERFACE_CSI2C_PHY1; |
---|
2082 | | - break; |
---|
2083 | | - case ISP_OF_PHY_CSIPHY2: |
---|
2084 | | - if (csi1) |
---|
2085 | | - buscfg->interface = ISP_INTERFACE_CCP2B_PHY2; |
---|
2086 | | - else |
---|
2087 | | - buscfg->interface = ISP_INTERFACE_CSI2A_PHY2; |
---|
2088 | | - break; |
---|
2089 | | - } |
---|
2090 | | - if (csi1) { |
---|
2091 | | - buscfg->bus.ccp2.lanecfg.clk.pos = |
---|
2092 | | - vep->bus.mipi_csi1.clock_lane; |
---|
2093 | | - buscfg->bus.ccp2.lanecfg.clk.pol = |
---|
2094 | | - vep->bus.mipi_csi1.lane_polarity[0]; |
---|
2095 | | - dev_dbg(dev, "clock lane polarity %u, pos %u\n", |
---|
2096 | | - buscfg->bus.ccp2.lanecfg.clk.pol, |
---|
2097 | | - buscfg->bus.ccp2.lanecfg.clk.pos); |
---|
2098 | | - |
---|
2099 | | - buscfg->bus.ccp2.lanecfg.data[0].pos = |
---|
2100 | | - vep->bus.mipi_csi1.data_lane; |
---|
2101 | | - buscfg->bus.ccp2.lanecfg.data[0].pol = |
---|
2102 | | - vep->bus.mipi_csi1.lane_polarity[1]; |
---|
2103 | | - |
---|
2104 | | - dev_dbg(dev, "data lane polarity %u, pos %u\n", |
---|
2105 | | - buscfg->bus.ccp2.lanecfg.data[0].pol, |
---|
2106 | | - buscfg->bus.ccp2.lanecfg.data[0].pos); |
---|
2107 | | - |
---|
2108 | | - buscfg->bus.ccp2.strobe_clk_pol = |
---|
2109 | | - vep->bus.mipi_csi1.clock_inv; |
---|
2110 | | - buscfg->bus.ccp2.phy_layer = vep->bus.mipi_csi1.strobe; |
---|
2111 | | - buscfg->bus.ccp2.ccp2_mode = |
---|
2112 | | - vep->bus_type == V4L2_MBUS_CCP2; |
---|
2113 | | - buscfg->bus.ccp2.vp_clk_pol = 1; |
---|
2114 | | - |
---|
2115 | | - buscfg->bus.ccp2.crc = 1; |
---|
2116 | | - } else { |
---|
2117 | | - buscfg->bus.csi2.lanecfg.clk.pos = |
---|
2118 | | - vep->bus.mipi_csi2.clock_lane; |
---|
2119 | | - buscfg->bus.csi2.lanecfg.clk.pol = |
---|
2120 | | - vep->bus.mipi_csi2.lane_polarities[0]; |
---|
2121 | | - dev_dbg(dev, "clock lane polarity %u, pos %u\n", |
---|
2122 | | - buscfg->bus.csi2.lanecfg.clk.pol, |
---|
2123 | | - buscfg->bus.csi2.lanecfg.clk.pos); |
---|
2124 | | - |
---|
2125 | | - buscfg->bus.csi2.num_data_lanes = |
---|
2126 | | - vep->bus.mipi_csi2.num_data_lanes; |
---|
2127 | | - |
---|
2128 | | - for (i = 0; i < buscfg->bus.csi2.num_data_lanes; i++) { |
---|
2129 | | - buscfg->bus.csi2.lanecfg.data[i].pos = |
---|
2130 | | - vep->bus.mipi_csi2.data_lanes[i]; |
---|
2131 | | - buscfg->bus.csi2.lanecfg.data[i].pol = |
---|
2132 | | - vep->bus.mipi_csi2.lane_polarities[i + 1]; |
---|
2133 | | - dev_dbg(dev, |
---|
2134 | | - "data lane %u polarity %u, pos %u\n", i, |
---|
2135 | | - buscfg->bus.csi2.lanecfg.data[i].pol, |
---|
2136 | | - buscfg->bus.csi2.lanecfg.data[i].pos); |
---|
2137 | | - } |
---|
2138 | | - /* |
---|
2139 | | - * FIXME: now we assume the CRC is always there. |
---|
2140 | | - * Implement a way to obtain this information from the |
---|
2141 | | - * sensor. Frame descriptors, perhaps? |
---|
2142 | | - */ |
---|
2143 | | - buscfg->bus.csi2.crc = 1; |
---|
2144 | | - } |
---|
2145 | | - break; |
---|
2146 | | - |
---|
2147 | | - default: |
---|
2148 | | - dev_warn(dev, "%pOF: invalid interface %u\n", |
---|
2149 | | - to_of_node(vep->base.local_fwnode), vep->base.port); |
---|
2150 | | - return -EINVAL; |
---|
2151 | | - } |
---|
2152 | | - |
---|
2153 | | - return 0; |
---|
2154 | | -} |
---|
2155 | 2022 | |
---|
2156 | 2023 | static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async) |
---|
2157 | 2024 | { |
---|
.. | .. |
---|
2182 | 2049 | return media_device_register(&isp->media_dev); |
---|
2183 | 2050 | } |
---|
2184 | 2051 | |
---|
| 2052 | +static void isp_parse_of_parallel_endpoint(struct device *dev, |
---|
| 2053 | + struct v4l2_fwnode_endpoint *vep, |
---|
| 2054 | + struct isp_bus_cfg *buscfg) |
---|
| 2055 | +{ |
---|
| 2056 | + buscfg->interface = ISP_INTERFACE_PARALLEL; |
---|
| 2057 | + buscfg->bus.parallel.data_lane_shift = vep->bus.parallel.data_shift; |
---|
| 2058 | + buscfg->bus.parallel.clk_pol = |
---|
| 2059 | + !!(vep->bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING); |
---|
| 2060 | + buscfg->bus.parallel.hs_pol = |
---|
| 2061 | + !!(vep->bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW); |
---|
| 2062 | + buscfg->bus.parallel.vs_pol = |
---|
| 2063 | + !!(vep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW); |
---|
| 2064 | + buscfg->bus.parallel.fld_pol = |
---|
| 2065 | + !!(vep->bus.parallel.flags & V4L2_MBUS_FIELD_EVEN_LOW); |
---|
| 2066 | + buscfg->bus.parallel.data_pol = |
---|
| 2067 | + !!(vep->bus.parallel.flags & V4L2_MBUS_DATA_ACTIVE_LOW); |
---|
| 2068 | + buscfg->bus.parallel.bt656 = vep->bus_type == V4L2_MBUS_BT656; |
---|
| 2069 | +} |
---|
| 2070 | + |
---|
| 2071 | +static void isp_parse_of_csi2_endpoint(struct device *dev, |
---|
| 2072 | + struct v4l2_fwnode_endpoint *vep, |
---|
| 2073 | + struct isp_bus_cfg *buscfg) |
---|
| 2074 | +{ |
---|
| 2075 | + unsigned int i; |
---|
| 2076 | + |
---|
| 2077 | + buscfg->bus.csi2.lanecfg.clk.pos = vep->bus.mipi_csi2.clock_lane; |
---|
| 2078 | + buscfg->bus.csi2.lanecfg.clk.pol = |
---|
| 2079 | + vep->bus.mipi_csi2.lane_polarities[0]; |
---|
| 2080 | + dev_dbg(dev, "clock lane polarity %u, pos %u\n", |
---|
| 2081 | + buscfg->bus.csi2.lanecfg.clk.pol, |
---|
| 2082 | + buscfg->bus.csi2.lanecfg.clk.pos); |
---|
| 2083 | + |
---|
| 2084 | + buscfg->bus.csi2.num_data_lanes = vep->bus.mipi_csi2.num_data_lanes; |
---|
| 2085 | + |
---|
| 2086 | + for (i = 0; i < buscfg->bus.csi2.num_data_lanes; i++) { |
---|
| 2087 | + buscfg->bus.csi2.lanecfg.data[i].pos = |
---|
| 2088 | + vep->bus.mipi_csi2.data_lanes[i]; |
---|
| 2089 | + buscfg->bus.csi2.lanecfg.data[i].pol = |
---|
| 2090 | + vep->bus.mipi_csi2.lane_polarities[i + 1]; |
---|
| 2091 | + dev_dbg(dev, |
---|
| 2092 | + "data lane %u polarity %u, pos %u\n", i, |
---|
| 2093 | + buscfg->bus.csi2.lanecfg.data[i].pol, |
---|
| 2094 | + buscfg->bus.csi2.lanecfg.data[i].pos); |
---|
| 2095 | + } |
---|
| 2096 | + /* |
---|
| 2097 | + * FIXME: now we assume the CRC is always there. Implement a way to |
---|
| 2098 | + * obtain this information from the sensor. Frame descriptors, perhaps? |
---|
| 2099 | + */ |
---|
| 2100 | + buscfg->bus.csi2.crc = 1; |
---|
| 2101 | +} |
---|
| 2102 | + |
---|
| 2103 | +static void isp_parse_of_csi1_endpoint(struct device *dev, |
---|
| 2104 | + struct v4l2_fwnode_endpoint *vep, |
---|
| 2105 | + struct isp_bus_cfg *buscfg) |
---|
| 2106 | +{ |
---|
| 2107 | + buscfg->bus.ccp2.lanecfg.clk.pos = vep->bus.mipi_csi1.clock_lane; |
---|
| 2108 | + buscfg->bus.ccp2.lanecfg.clk.pol = vep->bus.mipi_csi1.lane_polarity[0]; |
---|
| 2109 | + dev_dbg(dev, "clock lane polarity %u, pos %u\n", |
---|
| 2110 | + buscfg->bus.ccp2.lanecfg.clk.pol, |
---|
| 2111 | + buscfg->bus.ccp2.lanecfg.clk.pos); |
---|
| 2112 | + |
---|
| 2113 | + buscfg->bus.ccp2.lanecfg.data[0].pos = vep->bus.mipi_csi1.data_lane; |
---|
| 2114 | + buscfg->bus.ccp2.lanecfg.data[0].pol = |
---|
| 2115 | + vep->bus.mipi_csi1.lane_polarity[1]; |
---|
| 2116 | + |
---|
| 2117 | + dev_dbg(dev, "data lane polarity %u, pos %u\n", |
---|
| 2118 | + buscfg->bus.ccp2.lanecfg.data[0].pol, |
---|
| 2119 | + buscfg->bus.ccp2.lanecfg.data[0].pos); |
---|
| 2120 | + |
---|
| 2121 | + buscfg->bus.ccp2.strobe_clk_pol = vep->bus.mipi_csi1.clock_inv; |
---|
| 2122 | + buscfg->bus.ccp2.phy_layer = vep->bus.mipi_csi1.strobe; |
---|
| 2123 | + buscfg->bus.ccp2.ccp2_mode = vep->bus_type == V4L2_MBUS_CCP2; |
---|
| 2124 | + buscfg->bus.ccp2.vp_clk_pol = 1; |
---|
| 2125 | + |
---|
| 2126 | + buscfg->bus.ccp2.crc = 1; |
---|
| 2127 | +} |
---|
| 2128 | + |
---|
| 2129 | +static struct { |
---|
| 2130 | + u32 phy; |
---|
| 2131 | + u32 csi2_if; |
---|
| 2132 | + u32 csi1_if; |
---|
| 2133 | +} isp_bus_interfaces[2] = { |
---|
| 2134 | + { ISP_OF_PHY_CSIPHY1, |
---|
| 2135 | + ISP_INTERFACE_CSI2C_PHY1, ISP_INTERFACE_CCP2B_PHY1 }, |
---|
| 2136 | + { ISP_OF_PHY_CSIPHY2, |
---|
| 2137 | + ISP_INTERFACE_CSI2A_PHY2, ISP_INTERFACE_CCP2B_PHY2 }, |
---|
| 2138 | +}; |
---|
| 2139 | + |
---|
| 2140 | +static int isp_parse_of_endpoints(struct isp_device *isp) |
---|
| 2141 | +{ |
---|
| 2142 | + struct fwnode_handle *ep; |
---|
| 2143 | + struct isp_async_subdev *isd = NULL; |
---|
| 2144 | + struct v4l2_async_subdev *asd; |
---|
| 2145 | + unsigned int i; |
---|
| 2146 | + |
---|
| 2147 | + ep = fwnode_graph_get_endpoint_by_id( |
---|
| 2148 | + dev_fwnode(isp->dev), ISP_OF_PHY_PARALLEL, 0, |
---|
| 2149 | + FWNODE_GRAPH_ENDPOINT_NEXT); |
---|
| 2150 | + |
---|
| 2151 | + if (ep) { |
---|
| 2152 | + struct v4l2_fwnode_endpoint vep = { |
---|
| 2153 | + .bus_type = V4L2_MBUS_PARALLEL |
---|
| 2154 | + }; |
---|
| 2155 | + int ret; |
---|
| 2156 | + |
---|
| 2157 | + dev_dbg(isp->dev, "parsing parallel interface\n"); |
---|
| 2158 | + |
---|
| 2159 | + ret = v4l2_fwnode_endpoint_parse(ep, &vep); |
---|
| 2160 | + |
---|
| 2161 | + if (!ret) { |
---|
| 2162 | + asd = v4l2_async_notifier_add_fwnode_remote_subdev( |
---|
| 2163 | + &isp->notifier, ep, sizeof(*isd)); |
---|
| 2164 | + if (!IS_ERR(asd)) { |
---|
| 2165 | + isd = container_of(asd, struct isp_async_subdev, asd); |
---|
| 2166 | + isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus); |
---|
| 2167 | + } |
---|
| 2168 | + } |
---|
| 2169 | + |
---|
| 2170 | + fwnode_handle_put(ep); |
---|
| 2171 | + } |
---|
| 2172 | + |
---|
| 2173 | + for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) { |
---|
| 2174 | + struct v4l2_fwnode_endpoint vep = { |
---|
| 2175 | + .bus_type = V4L2_MBUS_CSI2_DPHY |
---|
| 2176 | + }; |
---|
| 2177 | + int ret; |
---|
| 2178 | + |
---|
| 2179 | + ep = fwnode_graph_get_endpoint_by_id( |
---|
| 2180 | + dev_fwnode(isp->dev), isp_bus_interfaces[i].phy, 0, |
---|
| 2181 | + FWNODE_GRAPH_ENDPOINT_NEXT); |
---|
| 2182 | + |
---|
| 2183 | + if (!ep) |
---|
| 2184 | + continue; |
---|
| 2185 | + |
---|
| 2186 | + dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i, |
---|
| 2187 | + to_of_node(ep)); |
---|
| 2188 | + |
---|
| 2189 | + ret = v4l2_fwnode_endpoint_parse(ep, &vep); |
---|
| 2190 | + if (ret == -ENXIO) { |
---|
| 2191 | + vep = (struct v4l2_fwnode_endpoint) |
---|
| 2192 | + { .bus_type = V4L2_MBUS_CSI1 }; |
---|
| 2193 | + ret = v4l2_fwnode_endpoint_parse(ep, &vep); |
---|
| 2194 | + |
---|
| 2195 | + if (ret == -ENXIO) { |
---|
| 2196 | + vep = (struct v4l2_fwnode_endpoint) |
---|
| 2197 | + { .bus_type = V4L2_MBUS_CCP2 }; |
---|
| 2198 | + ret = v4l2_fwnode_endpoint_parse(ep, &vep); |
---|
| 2199 | + } |
---|
| 2200 | + } |
---|
| 2201 | + |
---|
| 2202 | + if (!ret) { |
---|
| 2203 | + asd = v4l2_async_notifier_add_fwnode_remote_subdev( |
---|
| 2204 | + &isp->notifier, ep, sizeof(*isd)); |
---|
| 2205 | + |
---|
| 2206 | + if (!IS_ERR(asd)) { |
---|
| 2207 | + isd = container_of(asd, struct isp_async_subdev, asd); |
---|
| 2208 | + |
---|
| 2209 | + switch (vep.bus_type) { |
---|
| 2210 | + case V4L2_MBUS_CSI2_DPHY: |
---|
| 2211 | + isd->bus.interface = |
---|
| 2212 | + isp_bus_interfaces[i].csi2_if; |
---|
| 2213 | + isp_parse_of_csi2_endpoint(isp->dev, &vep, &isd->bus); |
---|
| 2214 | + break; |
---|
| 2215 | + case V4L2_MBUS_CSI1: |
---|
| 2216 | + case V4L2_MBUS_CCP2: |
---|
| 2217 | + isd->bus.interface = |
---|
| 2218 | + isp_bus_interfaces[i].csi1_if; |
---|
| 2219 | + isp_parse_of_csi1_endpoint(isp->dev, &vep, |
---|
| 2220 | + &isd->bus); |
---|
| 2221 | + break; |
---|
| 2222 | + default: |
---|
| 2223 | + break; |
---|
| 2224 | + } |
---|
| 2225 | + } |
---|
| 2226 | + } |
---|
| 2227 | + |
---|
| 2228 | + fwnode_handle_put(ep); |
---|
| 2229 | + } |
---|
| 2230 | + |
---|
| 2231 | + return 0; |
---|
| 2232 | +} |
---|
| 2233 | + |
---|
2185 | 2234 | static const struct v4l2_async_notifier_operations isp_subdev_notifier_ops = { |
---|
2186 | 2235 | .complete = isp_subdev_notifier_complete, |
---|
2187 | 2236 | }; |
---|
.. | .. |
---|
2204 | 2253 | int ret; |
---|
2205 | 2254 | int i, m; |
---|
2206 | 2255 | |
---|
2207 | | - isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); |
---|
| 2256 | + isp = kzalloc(sizeof(*isp), GFP_KERNEL); |
---|
2208 | 2257 | if (!isp) { |
---|
2209 | 2258 | dev_err(&pdev->dev, "could not allocate memory\n"); |
---|
2210 | 2259 | return -ENOMEM; |
---|
.. | .. |
---|
2213 | 2262 | ret = fwnode_property_read_u32(of_fwnode_handle(pdev->dev.of_node), |
---|
2214 | 2263 | "ti,phy-type", &isp->phy_type); |
---|
2215 | 2264 | if (ret) |
---|
2216 | | - return ret; |
---|
| 2265 | + goto error_release_isp; |
---|
2217 | 2266 | |
---|
2218 | 2267 | isp->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, |
---|
2219 | 2268 | "syscon"); |
---|
2220 | | - if (IS_ERR(isp->syscon)) |
---|
2221 | | - return PTR_ERR(isp->syscon); |
---|
| 2269 | + if (IS_ERR(isp->syscon)) { |
---|
| 2270 | + ret = PTR_ERR(isp->syscon); |
---|
| 2271 | + goto error_release_isp; |
---|
| 2272 | + } |
---|
2222 | 2273 | |
---|
2223 | 2274 | ret = of_property_read_u32_index(pdev->dev.of_node, |
---|
2224 | 2275 | "syscon", 1, &isp->syscon_offset); |
---|
2225 | 2276 | if (ret) |
---|
2226 | | - return ret; |
---|
| 2277 | + goto error_release_isp; |
---|
2227 | 2278 | |
---|
2228 | 2279 | isp->autoidle = autoidle; |
---|
2229 | 2280 | |
---|
2230 | 2281 | mutex_init(&isp->isp_mutex); |
---|
2231 | 2282 | spin_lock_init(&isp->stat_lock); |
---|
| 2283 | + v4l2_async_notifier_init(&isp->notifier); |
---|
| 2284 | + isp->dev = &pdev->dev; |
---|
2232 | 2285 | |
---|
2233 | | - ret = v4l2_async_notifier_parse_fwnode_endpoints( |
---|
2234 | | - &pdev->dev, &isp->notifier, sizeof(struct isp_async_subdev), |
---|
2235 | | - isp_fwnode_parse); |
---|
| 2286 | + ret = isp_parse_of_endpoints(isp); |
---|
2236 | 2287 | if (ret < 0) |
---|
2237 | 2288 | goto error; |
---|
2238 | 2289 | |
---|
2239 | | - isp->dev = &pdev->dev; |
---|
2240 | 2290 | isp->ref_count = 0; |
---|
2241 | 2291 | |
---|
2242 | 2292 | ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32)); |
---|
.. | .. |
---|
2247 | 2297 | |
---|
2248 | 2298 | /* Regulators */ |
---|
2249 | 2299 | isp->isp_csiphy1.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy1"); |
---|
| 2300 | + if (IS_ERR(isp->isp_csiphy1.vdd)) { |
---|
| 2301 | + ret = PTR_ERR(isp->isp_csiphy1.vdd); |
---|
| 2302 | + goto error; |
---|
| 2303 | + } |
---|
| 2304 | + |
---|
2250 | 2305 | isp->isp_csiphy2.vdd = devm_regulator_get(&pdev->dev, "vdd-csiphy2"); |
---|
| 2306 | + if (IS_ERR(isp->isp_csiphy2.vdd)) { |
---|
| 2307 | + ret = PTR_ERR(isp->isp_csiphy2.vdd); |
---|
| 2308 | + goto error; |
---|
| 2309 | + } |
---|
2251 | 2310 | |
---|
2252 | 2311 | /* Clocks |
---|
2253 | 2312 | * |
---|
.. | .. |
---|
2332 | 2391 | /* Interrupt */ |
---|
2333 | 2392 | ret = platform_get_irq(pdev, 0); |
---|
2334 | 2393 | if (ret <= 0) { |
---|
2335 | | - dev_err(isp->dev, "No IRQ resource\n"); |
---|
2336 | 2394 | ret = -ENODEV; |
---|
2337 | 2395 | goto error_iommu; |
---|
2338 | 2396 | } |
---|
.. | .. |
---|
2381 | 2439 | error: |
---|
2382 | 2440 | v4l2_async_notifier_cleanup(&isp->notifier); |
---|
2383 | 2441 | mutex_destroy(&isp->isp_mutex); |
---|
| 2442 | +error_release_isp: |
---|
| 2443 | + kfree(isp); |
---|
2384 | 2444 | |
---|
2385 | 2445 | return ret; |
---|
2386 | 2446 | } |
---|
.. | .. |
---|
2392 | 2452 | .complete = isp_pm_complete, |
---|
2393 | 2453 | }; |
---|
2394 | 2454 | |
---|
2395 | | -static struct platform_device_id omap3isp_id_table[] = { |
---|
| 2455 | +static const struct platform_device_id omap3isp_id_table[] = { |
---|
2396 | 2456 | { "omap3isp", 0 }, |
---|
2397 | 2457 | { }, |
---|
2398 | 2458 | }; |
---|