forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/media/platform/omap3isp/isp.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * isp.c
34 *
....@@ -36,13 +37,7 @@
3637 * Thara Gopinath <thara@ti.com>
3738 * Toni Leinonen <toni.leinonen@nokia.com>
3839 * 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.
4340 */
44
-
45
-#include <asm/cacheflush.h>
4641
4742 #include <linux/clk.h>
4843 #include <linux/clkdev.h>
....@@ -147,7 +142,7 @@
147142 * readback the same register, in this case the revision register.
148143 *
149144 * 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
151146 */
152147 void omap3isp_flush(struct isp_device *isp)
153148 {
....@@ -813,6 +808,10 @@
813808
814809 ret = v4l2_subdev_call(subdev, video, s_stream, 0);
815810
811
+ /* Stop at the first external sub-device. */
812
+ if (subdev->dev != isp->dev)
813
+ break;
814
+
816815 if (subdev == &isp->isp_res.subdev)
817816 ret |= isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
818817 else if (subdev == &isp->isp_prev.subdev)
....@@ -840,10 +839,6 @@
840839 &subdev->entity);
841840 failure = -ETIMEDOUT;
842841 }
843
-
844
- /* Stop at the first external sub-device. */
845
- if (subdev->dev != isp->dev)
846
- break;
847842 }
848843
849844 return failure;
....@@ -1525,7 +1520,7 @@
15251520 *
15261521 * To solve this problem power management support is split into prepare/complete
15271522 * 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
15291524 * resume(), and the the pipelines are restarted in complete().
15301525 *
15311526 * TODO: PM dependencies between the ISP and sensors are not modelled explicitly
....@@ -1686,7 +1681,7 @@
16861681 int ret;
16871682
16881683 isp->media_dev.dev = isp->dev;
1689
- strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
1684
+ strscpy(isp->media_dev.model, "TI OMAP3 ISP",
16901685 sizeof(isp->media_dev.model));
16911686 isp->media_dev.hw_revision = isp->revision;
16921687 isp->media_dev.ops = &isp_media_ops;
....@@ -2014,6 +2009,8 @@
20142009 media_entity_enum_cleanup(&isp->crashed);
20152010 v4l2_async_notifier_cleanup(&isp->notifier);
20162011
2012
+ kfree(isp);
2013
+
20172014 return 0;
20182015 }
20192016
....@@ -2022,136 +2019,6 @@
20222019 ISP_OF_PHY_CSIPHY1,
20232020 ISP_OF_PHY_CSIPHY2,
20242021 };
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
-}
21552022
21562023 static int isp_subdev_notifier_complete(struct v4l2_async_notifier *async)
21572024 {
....@@ -2182,6 +2049,188 @@
21822049 return media_device_register(&isp->media_dev);
21832050 }
21842051
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
+
21852234 static const struct v4l2_async_notifier_operations isp_subdev_notifier_ops = {
21862235 .complete = isp_subdev_notifier_complete,
21872236 };
....@@ -2204,7 +2253,7 @@
22042253 int ret;
22052254 int i, m;
22062255
2207
- isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL);
2256
+ isp = kzalloc(sizeof(*isp), GFP_KERNEL);
22082257 if (!isp) {
22092258 dev_err(&pdev->dev, "could not allocate memory\n");
22102259 return -ENOMEM;
....@@ -2213,30 +2262,31 @@
22132262 ret = fwnode_property_read_u32(of_fwnode_handle(pdev->dev.of_node),
22142263 "ti,phy-type", &isp->phy_type);
22152264 if (ret)
2216
- return ret;
2265
+ goto error_release_isp;
22172266
22182267 isp->syscon = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
22192268 "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
+ }
22222273
22232274 ret = of_property_read_u32_index(pdev->dev.of_node,
22242275 "syscon", 1, &isp->syscon_offset);
22252276 if (ret)
2226
- return ret;
2277
+ goto error_release_isp;
22272278
22282279 isp->autoidle = autoidle;
22292280
22302281 mutex_init(&isp->isp_mutex);
22312282 spin_lock_init(&isp->stat_lock);
2283
+ v4l2_async_notifier_init(&isp->notifier);
2284
+ isp->dev = &pdev->dev;
22322285
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);
22362287 if (ret < 0)
22372288 goto error;
22382289
2239
- isp->dev = &pdev->dev;
22402290 isp->ref_count = 0;
22412291
22422292 ret = dma_coerce_mask_and_coherent(isp->dev, DMA_BIT_MASK(32));
....@@ -2247,7 +2297,16 @@
22472297
22482298 /* Regulators */
22492299 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
+
22502305 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
+ }
22512310
22522311 /* Clocks
22532312 *
....@@ -2332,7 +2391,6 @@
23322391 /* Interrupt */
23332392 ret = platform_get_irq(pdev, 0);
23342393 if (ret <= 0) {
2335
- dev_err(isp->dev, "No IRQ resource\n");
23362394 ret = -ENODEV;
23372395 goto error_iommu;
23382396 }
....@@ -2381,6 +2439,8 @@
23812439 error:
23822440 v4l2_async_notifier_cleanup(&isp->notifier);
23832441 mutex_destroy(&isp->isp_mutex);
2442
+error_release_isp:
2443
+ kfree(isp);
23842444
23852445 return ret;
23862446 }
....@@ -2392,7 +2452,7 @@
23922452 .complete = isp_pm_complete,
23932453 };
23942454
2395
-static struct platform_device_id omap3isp_id_table[] = {
2455
+static const struct platform_device_id omap3isp_id_table[] = {
23962456 { "omap3isp", 0 },
23972457 { },
23982458 };