Hello Matt Delco,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/42470
to review the following change.
Change subject: drivers/intel/mipi_camera: SSDT changes to handle CIO2 device ......................................................................
drivers/intel/mipi_camera: SSDT changes to handle CIO2 device
This change updates mipi_camera driver to handle CIO2 device type.
Change-Id: I521740524bc1c4da3d8593f011a033542e4a872c Signed-off-by: Sugnan Prabhu S sugnan.prabhu.s@intel.com --- M src/drivers/intel/mipi_camera/camera.c M src/drivers/intel/mipi_camera/chip.h 2 files changed, 113 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/42470/1
diff --git a/src/drivers/intel/mipi_camera/camera.c b/src/drivers/intel/mipi_camera/camera.c index ddafccf..bcce7a6 100644 --- a/src/drivers/intel/mipi_camera/camera.c +++ b/src/drivers/intel/mipi_camera/camera.c @@ -10,9 +10,83 @@ #include <device/pci_def.h> #include "chip.h"
+#define CIO2_PCI_DEV 0x14 +#define CIO2_PCI_FN 0x3 #define SENSOR_NAME_UUID "822ace8f-2814-4174-a56b-5f029fe079ee" #define SENSOR_TYPE_UUID "26257549-9271-4ca4-bb43-c4899d5a4881"
+/* + * This implementation assumes there is only 1 endpoint at each end of every data port. It also + * assumes there are no clock lanes. It also assumes that any VCM or NVM for a CAM is on the + * same I2C bus as the CAM. + */ + +/* + * Adds settings for a CIO2 device (typically at "_SB.PCI0.CIO2"). A _DSD is added that + * specifies a child table for each port (e.g., PRT0 for "port0" and PRT1 for "port1"). Each + * PRTx table specifies a table for each endpoint (though only 1 endpoint is supported by this + * implementation so the table only has an "endpoint0" that points to a EPx0 table). The EPx0 + * table primarily describes the # of lanes in "data-lines" and specifies the name of the other + * side in "remote-endpoint" (the name is usually of the form "_SB.PCI0.I2Cx.CAM0" for the + * first port/cam and "_SB.PCI0.I2Cx.CAM1" if there's a second port/cam). + */ +static void camera_fill_cio2(const struct device *dev) +{ + struct drivers_intel_mipi_camera_config *config = dev->chip_info; + struct acpi_dp *dsd = acpi_dp_new_table("_DSD"); + char *ep_table_name[MAX_PORT_ENTRIES] = {NULL}; + char *port_table_name[MAX_PORT_ENTRIES] = {NULL}; + char *port_name[MAX_PORT_ENTRIES] = {NULL}; + unsigned int i, j; + char name[BUS_PATH_MAX]; + struct acpi_dp *ep_table = NULL; + struct acpi_dp *port_table = NULL; + struct acpi_dp *remote = NULL; + struct acpi_dp *lanes = NULL; + + for (i = 0; i < config->cio2_num_ports && i < MAX_PORT_ENTRIES; ++i) { + snprintf(name, sizeof(name), "EP%u0", i); + ep_table_name[i] = strdup(name); + ep_table = acpi_dp_new_table(ep_table_name[i]); + acpi_dp_add_integer(ep_table, "endpoint", 0); + acpi_dp_add_integer(ep_table, "clock-lanes", 0); + + if (config->cio2_lanes_used[i] > 0) { + lanes = acpi_dp_new_table("data-lanes"); + + for (j = 1; j <= config->cio2_lanes_used[i]; ++j) + acpi_dp_add_integer(lanes, NULL, j); + acpi_dp_add_array(ep_table, lanes); + } + + if (config->cio2_lane_endpoint[i]) { + remote = acpi_dp_new_table("remote-endpoint"); + acpi_dp_add_reference(remote, NULL, config->cio2_lane_endpoint[i]); + acpi_dp_add_integer(remote, NULL, 0); + acpi_dp_add_integer(remote, NULL, 0); + acpi_dp_add_array(ep_table, remote); + } + + snprintf(name, sizeof(name), "PRT%u", i); + port_table_name[i] = strdup(name); + port_table = acpi_dp_new_table(port_table_name[i]); + acpi_dp_add_integer(port_table, "port", config->cio2_prt[i]); + acpi_dp_add_child(port_table, "endpoint0", ep_table); + + snprintf(name, sizeof(name), "port%u", i); + port_name[i] = strdup(name); + acpi_dp_add_child(dsd, port_name[i], port_table); + } + + acpi_dp_write(dsd); + + for (i = 0; i < config->cio2_num_ports; ++i) { + free(ep_table_name[i]); + free(port_table_name[i]); + free(port_name[i]); + } +} + static void apply_pld_defaults(struct drivers_intel_mipi_camera_config *config) { if (!config->pld.ignore_color) @@ -142,6 +216,11 @@
static void camera_fill_sensor_defaults(struct drivers_intel_mipi_camera_config *config) { + struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN); + struct drivers_intel_mipi_camera_config *cio2_config; + if (!config->ssdb.bdf_value) + config->ssdb.bdf_value = PCI_DEVFN(CIO2_PCI_DEV, CIO2_PCI_FN); + if (!config->ssdb.platform) config->ssdb.platform = PLATFORM_SKC;
@@ -156,6 +235,31 @@
if (!config->ssdb.mclk_speed) config->ssdb.mclk_speed = CLK_FREQ_19_2MHZ; + + if (!config->ssdb.lanes_used) { + cio2_config = cio2 ? cio2->chip_info : NULL; + + if (!cio2_config) { + printk(BIOS_ERR, "Failed to get CIO2 config\n"); + } else if (cio2_config->device_type != INTEL_ACPI_CAMERA_CIO2) { + printk(BIOS_ERR, "Device type isn't CIO2: %u\n", + (u32)cio2_config->device_type); + } else if (config->ssdb.link_used >= cio2_config->cio2_num_ports) { + printk(BIOS_ERR, "%u exceeds CIO2's %u links\n", + (u32)config->ssdb.link_used, + (u32)cio2_config->cio2_num_ports); + } else { + config->ssdb.lanes_used = + cio2_config->cio2_lanes_used[config->ssdb.link_used]; + } + } + + if (!config->remote_name) { + if (cio2) + config->remote_name = acpi_device_path(cio2); + else + config->remote_name = "\_SB.PCI0.CIO2"; + } }
/* @@ -409,6 +513,9 @@ }
switch (config->device_type) { + case INTEL_ACPI_CAMERA_CIO2: + camera_fill_cio2(dev); + break; case INTEL_ACPI_CAMERA_SENSOR: camera_fill_sensor(dev); break; diff --git a/src/drivers/intel/mipi_camera/chip.h b/src/drivers/intel/mipi_camera/chip.h index 95a3ebb..82223c1 100644 --- a/src/drivers/intel/mipi_camera/chip.h +++ b/src/drivers/intel/mipi_camera/chip.h @@ -127,6 +127,12 @@ const char *chip_name; unsigned int acpi_uid;
+ /* Settings specific to CIO2 device */ + uint32_t cio2_num_ports; + uint32_t cio2_lanes_used[MAX_PORT_ENTRIES]; + const char *cio2_lane_endpoint[MAX_PORT_ENTRIES]; + uint32_t cio2_prt[MAX_PORT_ENTRIES]; + /* Settings specific to camera sensor */ bool disable_ssdb_defaults;