diff options
Diffstat (limited to 'drivers/media/pci/intel/ipu3/cio2-bridge.c')
| -rw-r--r-- | drivers/media/pci/intel/ipu3/cio2-bridge.c | 60 | 
1 files changed, 56 insertions, 4 deletions
| diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c index 30d29b96a339..67c467d3c81f 100644 --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c @@ -29,6 +29,7 @@ static const struct cio2_sensor_config cio2_supported_sensors[] = {  static const struct cio2_property_names prop_names = {  	.clock_frequency = "clock-frequency",  	.rotation = "rotation", +	.orientation = "orientation",  	.bus_type = "bus-type",  	.data_lanes = "data-lanes",  	.remote_endpoint = "remote-endpoint", @@ -72,11 +73,51 @@ out_free_buff:  	return ret;  } +static u32 cio2_bridge_parse_rotation(struct cio2_sensor *sensor) +{ +	switch (sensor->ssdb.degree) { +	case CIO2_SENSOR_ROTATION_NORMAL: +		return 0; +	case CIO2_SENSOR_ROTATION_INVERTED: +		return 180; +	default: +		dev_warn(&sensor->adev->dev, +			 "Unknown rotation %d. Assume 0 degree rotation\n", +			 sensor->ssdb.degree); +		return 0; +	} +} + +static enum v4l2_fwnode_orientation cio2_bridge_parse_orientation(struct cio2_sensor *sensor) +{ +	switch (sensor->pld->panel) { +	case ACPI_PLD_PANEL_FRONT: +		return V4L2_FWNODE_ORIENTATION_FRONT; +	case ACPI_PLD_PANEL_BACK: +		return V4L2_FWNODE_ORIENTATION_BACK; +	case ACPI_PLD_PANEL_TOP: +	case ACPI_PLD_PANEL_LEFT: +	case ACPI_PLD_PANEL_RIGHT: +	case ACPI_PLD_PANEL_UNKNOWN: +		return V4L2_FWNODE_ORIENTATION_EXTERNAL; +	default: +		dev_warn(&sensor->adev->dev, "Unknown _PLD panel value %d\n", +			 sensor->pld->panel); +		return V4L2_FWNODE_ORIENTATION_EXTERNAL; +	} +} +  static void cio2_bridge_create_fwnode_properties(  	struct cio2_sensor *sensor,  	struct cio2_bridge *bridge,  	const struct cio2_sensor_config *cfg)  { +	u32 rotation; +	enum v4l2_fwnode_orientation orientation; + +	rotation = cio2_bridge_parse_rotation(sensor); +	orientation = cio2_bridge_parse_orientation(sensor); +  	sensor->prop_names = prop_names;  	sensor->local_ref[0] = SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_CIO2_ENDPOINT]); @@ -85,9 +126,12 @@ static void cio2_bridge_create_fwnode_properties(  	sensor->dev_properties[0] = PROPERTY_ENTRY_U32(  					sensor->prop_names.clock_frequency,  					sensor->ssdb.mclkspeed); -	sensor->dev_properties[1] = PROPERTY_ENTRY_U8( +	sensor->dev_properties[1] = PROPERTY_ENTRY_U32(  					sensor->prop_names.rotation, -					sensor->ssdb.degree); +					rotation); +	sensor->dev_properties[2] = PROPERTY_ENTRY_U32( +					sensor->prop_names.orientation, +					orientation);  	sensor->ep_properties[0] = PROPERTY_ENTRY_U32(  					sensor->prop_names.bus_type, @@ -159,6 +203,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)  	for (i = 0; i < bridge->n_sensors; i++) {  		sensor = &bridge->sensors[i];  		software_node_unregister_nodes(sensor->swnodes); +		ACPI_FREE(sensor->pld);  		acpi_dev_put(sensor->adev);  	}  } @@ -170,6 +215,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,  	struct fwnode_handle *fwnode;  	struct cio2_sensor *sensor;  	struct acpi_device *adev; +	acpi_status status;  	int ret;  	for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) { @@ -191,11 +237,15 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,  		if (ret)  			goto err_put_adev; +		status = acpi_get_physical_device_location(adev->handle, &sensor->pld); +		if (ACPI_FAILURE(status)) +			goto err_put_adev; +  		if (sensor->ssdb.lanes > CIO2_MAX_LANES) {  			dev_err(&adev->dev,  				"Number of lanes in SSDB is invalid\n");  			ret = -EINVAL; -			goto err_put_adev; +			goto err_free_pld;  		}  		cio2_bridge_create_fwnode_properties(sensor, bridge, cfg); @@ -203,7 +253,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,  		ret = software_node_register_nodes(sensor->swnodes);  		if (ret) -			goto err_put_adev; +			goto err_free_pld;  		fwnode = software_node_fwnode(&sensor->swnodes[  						      SWNODE_SENSOR_HID]); @@ -225,6 +275,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,  err_free_swnodes:  	software_node_unregister_nodes(sensor->swnodes); +err_free_pld: +	ACPI_FREE(sensor->pld);  err_put_adev:  	acpi_dev_put(adev);  	return ret; | 
