forked from mirrors/linux
		
	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: Sakari Ailus <sakari.ailus@linux.intel.com> Tested-by: Steve Longerbeam <steve_longerbeam@mentor.com> Tested-by: Jacopo Mondi <jacopo+renesas@jmondi.org> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
		
							parent
							
								
									c2475aeb12
								
							
						
					
					
						commit
						b4357d21d6
					
				
					 1 changed files with 46 additions and 14 deletions
				
			
		| 
						 | 
					@ -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,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		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,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	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,
 | 
				
			||||||
		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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue