diff mbox series

[28/30,SRU,Jammy] UBUNTU: SAUCE: mei_vsc: distinguish platform with different camera sensor

Message ID 20220117151928.954829-29-vicamo.yang@canonical.com
State New
Headers show
Series Support Intel IPU6 MIPI camera on Alder Lake platforms | expand

Commit Message

You-Sheng Yang Jan. 17, 2022, 3:19 p.m. UTC
From: Ye Xiang <xiang.ye@intel.com>

BugLink: https://bugs.launchpad.net/bugs/1955383

Distinguish platform with different camera sensor by
camera model name from acpi. Then we could download
different FW to VSC according to the camera model.

Signed-off-by: Ye Xiang <xiang.ye@intel.com>
(cherry picked from commit 85cac41780cd4a1f5d84bd7e64aa9b1036cf877e github.com/intel/ivsc-driver)
Signed-off-by: You-Sheng Yang <vicamo.yang@canonical.com>
---
 drivers/misc/mei/hw-vsc.c  | 35 +++++++++++------
 drivers/misc/mei/hw-vsc.h  |  7 ++--
 drivers/misc/mei/spi-vsc.c | 77 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 104 insertions(+), 15 deletions(-)
diff mbox series

Patch

diff --git a/drivers/misc/mei/hw-vsc.c b/drivers/misc/mei/hw-vsc.c
index d9a22de48532..818d03b0d5dc 100644
--- a/drivers/misc/mei/hw-vsc.c
+++ b/drivers/misc/mei/hw-vsc.c
@@ -339,16 +339,17 @@  static int vsc_reset(struct mei_device *dev)
 	return 0;
 }
 
-static char *fw_name[][3] = {
+/* %s is sensor name, need to be get and format in runtime */
+static char *fw_name_template[][3] = {
 	{
 		"vsc/soc_a1/ivsc_fw_a1.bin",
-		"vsc/soc_a1/ivsc_pkg_ovti01as_0_a1.bin",
-		"vsc/soc_a1/ivsc_skucfg_ovti01as_0_1_a1.bin",
+		"vsc/soc_a1/ivsc_pkg_%s_0_a1.bin",
+		"vsc/soc_a1/ivsc_skucfg_%s_0_1_a1.bin",
 	},
 	{
 		"vsc/soc_a1_prod/ivsc_fw_a1_prod.bin",
-		"vsc/soc_a1_prod/ivsc_pkg_ovti01as_0_a1_prod.bin",
-		"vsc/soc_a1_prod/ivsc_skucfg_ovti01as_0_1_a1_prod.bin",
+		"vsc/soc_a1_prod/ivsc_pkg_%s_0_a1_prod.bin",
+		"vsc/soc_a1_prod/ivsc_skucfg_%s_0_1_a1_prod.bin",
 	},
 };
 
@@ -452,13 +453,25 @@  static int check_silicon(struct mei_device *dev)
 		hw->fw.key_src == SI_STRAP_KEY_SRC_DEBUG ? "" : "-prod");
 	if (hw->fw.sub_ver == SI_SUBSTEPPING_VERSION_1) {
 		if (hw->fw.key_src == SI_STRAP_KEY_SRC_DEBUG) {
-			hw->fw.fw_file_name = fw_name[0][0];
-			hw->fw.sensor_file_name = fw_name[0][1];
-			hw->fw.sku_cnf_file_name = fw_name[0][2];
+			snprintf(hw->fw.fw_file_name,
+				 sizeof(hw->fw.fw_file_name),
+				 fw_name_template[0][0]);
+			snprintf(hw->fw.sensor_file_name,
+				 sizeof(hw->fw.sensor_file_name),
+				 fw_name_template[0][1], hw->cam_sensor_name);
+			snprintf(hw->fw.sku_cnf_file_name,
+				 sizeof(hw->fw.sku_cnf_file_name),
+				 fw_name_template[0][2], hw->cam_sensor_name);
 		} else {
-			hw->fw.fw_file_name = fw_name[1][0];
-			hw->fw.sensor_file_name = fw_name[1][1];
-			hw->fw.sku_cnf_file_name = fw_name[1][2];
+			snprintf(hw->fw.fw_file_name,
+				 sizeof(hw->fw.fw_file_name),
+				 fw_name_template[1][0]);
+			snprintf(hw->fw.sensor_file_name,
+				 sizeof(hw->fw.sensor_file_name),
+				 fw_name_template[1][1], hw->cam_sensor_name);
+			snprintf(hw->fw.sku_cnf_file_name,
+				 sizeof(hw->fw.sku_cnf_file_name),
+				 fw_name_template[1][2], hw->cam_sensor_name);
 		}
 	}
 
diff --git a/drivers/misc/mei/hw-vsc.h b/drivers/misc/mei/hw-vsc.h
index 228edb77fab3..0bdc879e5ca4 100644
--- a/drivers/misc/mei/hw-vsc.h
+++ b/drivers/misc/mei/hw-vsc.h
@@ -332,11 +332,11 @@  struct vsc_boot_fw {
 	u8 rx_buf[FW_SPI_PKG_SIZE];
 
 	/* FirmwareBootFile */
-	char *fw_file_name;
+	char fw_file_name[256];
 	/* PkgBootFile */
-	char *sensor_file_name;
+	char sensor_file_name[256];
 	/* SkuConfigBootFile */
-	char *sku_cnf_file_name;
+	char sku_cnf_file_name[256];
 
 	u32 fw_option;
 	u32 fw_cnt;
@@ -370,6 +370,7 @@  struct mei_vsc_hw {
 	atomic_t lock_cnt;
 	int write_lock_cnt;
 	wait_queue_head_t xfer_wait;
+	char cam_sensor_name[32];
 };
 
 #define to_vsc_hw(dev) ((struct mei_vsc_hw *)((dev)->hw))
diff --git a/drivers/misc/mei/spi-vsc.c b/drivers/misc/mei/spi-vsc.c
index a39329b0b1a8..f759006179af 100644
--- a/drivers/misc/mei/spi-vsc.c
+++ b/drivers/misc/mei/spi-vsc.c
@@ -17,7 +17,12 @@ 
 #include "hw-vsc.h"
 #include "mei_dev.h"
 
-/* gpio resources*/
+#define CVFD_ACPI_ID_TGL "INTC1059"
+#define CVFD_ACPI_ID_ADL "INTC1095"
+#define LINK_NUMBER (1)
+#define METHOD_NAME_SID "SID"
+
+/* gpio resources */
 static const struct acpi_gpio_params wakeuphost_gpio = { 0, 0, false };
 static const struct acpi_gpio_params wakeuphostint_gpio = { 1, 0, false };
 static const struct acpi_gpio_params resetfw_gpio = { 2, 0, false };
@@ -30,6 +35,72 @@  static const struct acpi_gpio_mapping mei_vsc_acpi_gpios[] = {
 	{}
 };
 
+static struct acpi_device *find_cvfd_child_adev(struct acpi_device *parent)
+{
+	struct acpi_device *adev;
+
+	if (!parent)
+		return NULL;
+
+	list_for_each_entry (adev, &parent->children, node) {
+		if (!strcmp(CVFD_ACPI_ID_TGL, acpi_device_hid(adev)) ||
+		    !strcmp(CVFD_ACPI_ID_ADL, acpi_device_hid(adev)))
+			return adev;
+	}
+
+	return NULL;
+}
+
+static int get_sensor_name(struct mei_device *dev)
+{
+	struct mei_vsc_hw *hw = to_vsc_hw(dev);
+	struct spi_device *spi = hw->spi;
+	struct acpi_device *adev;
+	union acpi_object obj = { .type = ACPI_TYPE_INTEGER };
+	union acpi_object *ret_obj;
+	struct acpi_object_list arg_list = {
+		.count = 1,
+		.pointer = &obj,
+	};
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_status status;
+	char *c;
+
+	adev = find_cvfd_child_adev(ACPI_COMPANION(&spi->dev));
+	if (!adev) {
+		dev_err(&spi->dev, "ACPI not found CVFD device\n");
+		return -ENODEV;
+	}
+
+	obj.integer.value = LINK_NUMBER;
+	status = acpi_evaluate_object(adev->handle, METHOD_NAME_SID, &arg_list,
+				      &buffer);
+	if (ACPI_FAILURE(status)) {
+		dev_err(&spi->dev, "can't evaluate SID method: %d\n", status);
+		return -ENODEV;
+	}
+
+	ret_obj = buffer.pointer;
+	dev_dbg(&spi->dev, "SID status %d %lld %d - %d %s %d\n", status,
+		buffer.length, ret_obj->type, ret_obj->string.length,
+		ret_obj->string.pointer,
+		acpi_has_method(adev->handle, METHOD_NAME_SID));
+
+	if (ret_obj->string.length > sizeof(hw->cam_sensor_name)) {
+		ACPI_FREE(buffer.pointer);
+		return -EINVAL;
+	}
+	memcpy(hw->cam_sensor_name, ret_obj->string.pointer,
+	       ret_obj->string.length);
+
+	/* camera sensor name are all in lower case */
+	for (c = hw->cam_sensor_name; *c != '\0'; c++)
+		*c = tolower(*c);
+
+	ACPI_FREE(buffer.pointer);
+	return 0;
+}
+
 static int mei_vsc_probe(struct spi_device *spi)
 {
 	struct mei_vsc_hw *hw;
@@ -46,6 +117,10 @@  static int mei_vsc_probe(struct spi_device *spi)
 	hw->spi = spi;
 	spi_set_drvdata(spi, dev);
 
+	ret = get_sensor_name(dev);
+	if (ret)
+		return ret;
+
 	ret = devm_acpi_dev_add_driver_gpios(&spi->dev, mei_vsc_acpi_gpios);
 	if (ret) {
 		dev_err(&spi->dev, "%s: fail to add gpio\n", __func__);