Commit b4357d21 authored by Sakari Ailus's avatar Sakari Ailus Committed by Mauro Carvalho Chehab

media: v4l: fwnode: Support default CSI-2 lane mapping for drivers

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: default avatarSakari Ailus <sakari.ailus@linux.intel.com>
Tested-by: default avatarSteve Longerbeam <steve_longerbeam@mentor.com>
Tested-by: default avatarJacopo Mondi <jacopo+renesas@jmondi.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab+samsung@kernel.org>
parent c2475aeb
...@@ -47,20 +47,35 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, ...@@ -47,20 +47,35 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
enum v4l2_fwnode_bus_type bus_type) enum v4l2_fwnode_bus_type bus_type)
{ {
struct v4l2_fwnode_bus_mipi_csi2 *bus = &vep->bus.mipi_csi2; 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; unsigned int flags = 0, lanes_used = 0;
u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES]; u32 array[1 + V4L2_FWNODE_CSI2_MAX_DATA_LANES];
u32 clock_lane = 0;
unsigned int num_data_lanes = 0; unsigned int num_data_lanes = 0;
bool use_default_lane_mapping = false;
unsigned int i; unsigned int i;
u32 v; u32 v;
int rval; int rval;
if (bus_type == V4L2_FWNODE_BUS_TYPE_CSI2_DPHY) { if (bus_type == V4L2_FWNODE_BUS_TYPE_CSI2_DPHY) {
use_default_lane_mapping = true;
num_data_lanes = min_t(u32, bus->num_data_lanes, num_data_lanes = min_t(u32, bus->num_data_lanes,
V4L2_FWNODE_CSI2_MAX_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]; 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); 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, ...@@ -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, fwnode_property_read_u32_array(fwnode, "data-lanes", array,
num_data_lanes); num_data_lanes);
have_data_lanes = true;
} }
for (i = 0; i < num_data_lanes; i++) { for (i = 0; i < num_data_lanes; i++) {
if (lanes_used & BIT(array[i])) if (lanes_used & BIT(array[i])) {
pr_warn("duplicated lane %u in data-lanes\n", if (have_data_lanes || !use_default_lane_mapping)
array[i]); pr_warn("duplicated lane %u in data-lanes, using defaults\n",
array[i]);
use_default_lane_mapping = true;
}
lanes_used |= BIT(array[i]); 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, 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, ...@@ -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 (!fwnode_property_read_u32(fwnode, "clock-lanes", &v)) {
if (lanes_used & BIT(v)) clock_lane = v;
pr_warn("duplicated lane %u in clock-lanes\n", v);
lanes_used |= BIT(v);
bus->clock_lane = v;
have_clk_lane = true;
pr_debug("clock lane position %u\n", 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")) { if (fwnode_property_present(fwnode, "clock-noncontinuous")) {
...@@ -115,8 +139,16 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode, ...@@ -115,8 +139,16 @@ static int v4l2_fwnode_endpoint_parse_csi2_bus(struct fwnode_handle *fwnode,
bus->flags = flags; bus->flags = flags;
vep->bus_type = V4L2_MBUS_CSI2_DPHY; vep->bus_type = V4L2_MBUS_CSI2_DPHY;
bus->num_data_lanes = num_data_lanes; 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) { if (have_lane_polarities) {
fwnode_property_read_u32_array(fwnode, fwnode_property_read_u32_array(fwnode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment