Most hardware doesn't support re-mapping of the CSI-2 lanes. Especially sensor drivers have a default number of lanes. Instead of requiring the caller (the driver) to provide such a unit mapping, provide one if no mapping is configured. Signed-off-by: Sakari Ailus <sakari.ailus@xxxxxxxxxxxxxxx> --- drivers/media/v4l2-core/v4l2-fwnode.c | 60 +++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/drivers/media/v4l2-core/v4l2-fwnode.c b/drivers/media/v4l2-core/v4l2-fwnode.c index 282595c90818..0ddf05bb589a 100644 --- a/drivers/media/v4l2-core/v4l2-fwnode.c +++ b/drivers/media/v4l2-core/v4l2-fwnode.c @@ -47,20 +47,35 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, enum v4l2_fwnode_bus_type bus_type) { struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2; - bool have_clk_lane = false, have_lane_polarities = false; + bool have_clk_lane = false, have_data_lanes = false, + have_lane_polarities = false; unsigned int flags = 0, lanes_used = 0; u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES]; + u32 clock_lane = 0; unsigned int num_data_lanes = 0; + bool use_default_lane_mapping = false; unsigned int i; u32 v; int rval; if (bus_type == V4L2_FWNODE_BUS_TYPE_CSI2_DPHY) { + use_default_lane_mapping = true; + num_data_lanes = min_t(u32, bus->num_data_lanes, V4L2_FWNODE_CSI2_MAX_DATA_LANES); - for (i = 0; i < num_data_lanes; i++) + clock_lane = bus->clock_lane; + if (clock_lane) + use_default_lane_mapping = false; + + for (i = 0; i < num_data_lanes; i++) { array[i] = bus->data_lanes[i]; + if (array[i]) + use_default_lane_mapping = false; + } + + if (use_default_lane_mapping) + pr_debug("using default lane mapping\n"); } rval = fwnode_property_read_u32_array(fwnode, "data-lanes", NULL, 0); @@ -70,15 +85,21 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, fwnode_property_read_u32_array(fwnode, "data-lanes", array, num_data_lanes); + + have_data_lanes = true; } for (i = 0; i < num_data_lanes; i++) { - if (lanes_used & BIT(array[i])) - pr_warn("duplicated lane %u in data-lanes\n", - array[i]); + if (lanes_used & BIT(array[i])) { + if (have_data_lanes || !use_default_lane_mapping) + pr_warn("duplicated lane %u in data-lanes, using defaults\n", + array[i]); + use_default_lane_mapping = true; + } lanes_used |= BIT(array[i]); - pr_debug("lane %u position %u\n", i, array[i]); + if (have_data_lanes) + pr_debug("lane %u position %u\n", i, array[i]); } rval = fwnode_property_read_u32_array(fwnode, "lane-polarities", NULL, @@ -94,13 +115,16 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, } if (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) { - if (lanes_used & BIT(v)) - pr_warn("duplicated lane %u in clock-lanes\n", v); - lanes_used |= BIT(v); - - bus->clock_lane = v; - have_clk_lane = true; + clock_lane = v; pr_debug("clock lane position %u\n", v); + have_clk_lane = true; + } + + if (lanes_used & BIT(clock_lane)) { + if (have_clk_lane || !use_default_lane_mapping) + pr_warn("duplicated lane %u in clock-lanes, using defaults\n", + v); + use_default_lane_mapping = true; } if (fwnode_property_present(fwnode, "clock-noncontinuous")) { @@ -115,8 +139,16 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, bus->flags = flags; vep->bus_type = V4L2_MBUS_CSI2_DPHY; bus->num_data_lanes = num_data_lanes; - for (i = 0; i < num_data_lanes; i++) - bus->data_lanes[i] = array[i]; + + if (use_default_lane_mapping) { + bus->clock_lane = 0; + for (i = 0; i < num_data_lanes; i++) + bus->data_lanes[i] = 1 + i; + } else { + bus->clock_lane = clock_lane; + for (i = 0; i < num_data_lanes; i++) + bus->data_lanes[i] = array[i]; + } if (have_lane_polarities) { fwnode_property_read_u32_array(fwnode, -- 2.11.0