drivers/intel/mipi_camera: Add ACPI device type selection
Refactor the MIPI camera driver to support two ACPI device generation modes via a Kconfig choice: 1. Windows/Linux mode (MIPI_ACPI_TYPE_WINDOWS_LINUX): Generates a single ACPI device for the camera sensor and any associated VCM or NVM devices on the same I2C bus. The IPU ACPI device is attached to the iGPU, not standalone. This is the preferred method for Windows and mainline Linux. 2. ChromeOS mode (MIPI_ACPI_TYPE_CHROMEOS): Generates separate ACPI devices for each camera component (sensor, CIO2, VCM, NVM). The IPU ACPI device is generated separately from the iGPU. This maintains compatibility with the existing ChromeOS-style setup. The implementation uses runtime conditionals to select between the two modes. Common helper functions are shared between modes, while device- specific logic is conditional based on the selected ACPI type. The default selection is MIPI_ACPI_TYPE_CHROMEOS for ChromeOS builds and MIPI_ACPI_TYPE_WINDOWS_LINUX otherwise. Change-Id: I0bc4894aff04d6b296011e85d790d624890da055 Signed-off-by: Matt DeVillier <matt.devillier@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/90522 Reviewed-by: Felix Singer <service+coreboot-gerrit@felixsinger.de> Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Alicja Michalska <ahplka19@gmail.com>
This commit is contained in:
parent
1532eb60ee
commit
ae0d232402
2 changed files with 101 additions and 23 deletions
|
|
@ -8,8 +8,36 @@ config DRIVERS_INTEL_MIPI_CAMERA
|
|||
MIPI CSI I2C camera SSDT generator. Generates SSDB and PWDB
|
||||
structures which are used by the Intel kernel drivers.
|
||||
|
||||
if DRIVERS_INTEL_MIPI_CAMERA
|
||||
|
||||
config DRIVERS_INTEL_MIPI_SUPPORTS_PRE_PRODUCTION_SOC
|
||||
def_bool n
|
||||
help
|
||||
Use this config to provide information to IPU kernel driver
|
||||
if pre-production or production signed IPU FW needs to be loaded.
|
||||
|
||||
choice
|
||||
prompt "MIPI camera ACPI type"
|
||||
default MIPI_ACPI_TYPE_CHROMEOS if CHROMEOS
|
||||
default MIPI_ACPI_TYPE_WINDOWS_LINUX
|
||||
help
|
||||
Select the ACPI device type to generate for the MIPI camera.
|
||||
|
||||
config MIPI_ACPI_TYPE_WINDOWS_LINUX
|
||||
bool "Windows / Linux"
|
||||
help
|
||||
Generates a single ACPI device for the camera sensor and any
|
||||
associated VCM or NVM devices on the same I2C bus, instead of
|
||||
separate ACPI devices for each camera related device. The IPU
|
||||
ACPI device is attached to the iGPU, not standalone. This is
|
||||
the preferred method for Windows and mainline Linux.
|
||||
|
||||
config MIPI_ACPI_TYPE_CHROMEOS
|
||||
bool "Chrome OS"
|
||||
help
|
||||
Generates separate ACPI devices for each camera related device.
|
||||
The IPU ACPI device is generated separately from the iGPU.
|
||||
This is the preferred method for ChromeOS.
|
||||
|
||||
endchoice
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -513,27 +513,44 @@ static void camera_fill_ssdb_defaults(struct drivers_intel_mipi_camera_config *c
|
|||
}
|
||||
|
||||
/*
|
||||
* Adds settings for a camera sensor device (typically at "\_SB.PCI0.I2Cx.CAMy"). The drivers
|
||||
* for Linux tends to expect the camera sensor device and any related nvram / vcm devices to be
|
||||
* separate ACPI devices, while the drivers for Windows want all of these to be grouped
|
||||
* together in the camera sensor ACPI device. This implementation tries to satisfy both,
|
||||
* though the unfortunate tradeoff is that the same I2C address for nvram and vcm is advertised
|
||||
* by multiple devices in ACPI (via "_CRS"). The Windows driver can use the "_DSM" method to
|
||||
* disambiguate the I2C resources in the camera sensor ACPI device. Drivers for Windows
|
||||
* typically query "SSDB" for configuration information (represented as a binary blob dump of
|
||||
* struct), while Linux drivers typically consult individual parameters in "_DSD".
|
||||
* Adds settings for a camera sensor device (typically at "\_SB.PCI0.I2Cx.CAMy").
|
||||
*
|
||||
* Single ACPI device mode: The drivers for Windows and Linux want the sensor and any associated
|
||||
* VCM or NVM devices to be grouped together in the camera sensor ACPI device. The OS driver
|
||||
* uses the "_DSM" method to disambiguate the I2C resources in the camera sensor ACPI device.
|
||||
* Drivers typically query "SSDB" for configuration information (represented as a binary blob
|
||||
* dump of struct).
|
||||
*
|
||||
* Multi ACPI device mode: The drivers for ChromeOS expect the camera sensor device and any
|
||||
* related nvram / vcm devices to be separate ACPI devices.
|
||||
*
|
||||
* The tree of tables in "_DSD" is analogous to what's used for the "CIO2" device. The _DSD
|
||||
* specifies a child table for the sensor's port (e.g., PRT0 for "port0"--this implementation
|
||||
* assumes a camera only has 1 port). The PRT0 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 EP00 table). The EP00 table primarily describes the # of lanes
|
||||
* in "data-lines", a list of frequencies in "list-frequencies", and specifies the name of the
|
||||
* in "data-lanes", a list of frequencies in "list-frequencies", and specifies the name of the
|
||||
* other side in "remote-endpoint" (typically "\_SB.PCI0.CIO2").
|
||||
*/
|
||||
static void camera_fill_sensor(const struct device *dev)
|
||||
{
|
||||
struct drivers_intel_mipi_camera_config *config = dev->chip_info;
|
||||
|
||||
camera_generate_pld(dev);
|
||||
|
||||
camera_fill_ssdb_defaults(config);
|
||||
|
||||
/* _DSM */
|
||||
camera_generate_dsm(dev);
|
||||
|
||||
if (CONFIG(MIPI_ACPI_TYPE_WINDOWS_LINUX)) {
|
||||
acpigen_write_method_serialized("SSDB", 0);
|
||||
acpigen_write_return_byte_buffer((uint8_t *)&config->ssdb, sizeof(config->ssdb));
|
||||
acpigen_pop_len(); /* Method */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Multi-device mode: add _DSD with endpoint information */
|
||||
struct acpi_dp *ep00 = NULL;
|
||||
struct acpi_dp *prt0 = NULL;
|
||||
struct acpi_dp *dsd = NULL;
|
||||
|
|
@ -543,13 +560,6 @@ static void camera_fill_sensor(const struct device *dev)
|
|||
const char *remote_name;
|
||||
struct device *cio2 = pcidev_on_root(CIO2_PCI_DEV, CIO2_PCI_FN);
|
||||
|
||||
camera_generate_pld(dev);
|
||||
|
||||
camera_fill_ssdb_defaults(config);
|
||||
|
||||
/* _DSM */
|
||||
camera_generate_dsm(dev);
|
||||
|
||||
ep00 = acpi_dp_new_table("EP00");
|
||||
acpi_dp_add_integer(ep00, "endpoint", DEFAULT_ENDPOINT);
|
||||
acpi_dp_add_integer(ep00, "clock-lanes", 0);
|
||||
|
|
@ -1035,7 +1045,10 @@ static void write_i2c_camera_device(const struct device *dev, const char *scope)
|
|||
acpigen_write_name_integer("_ADR", 0);
|
||||
|
||||
acpigen_write_name_integer("_UID", config->acpi_uid);
|
||||
acpigen_write_name_string("_DDN", config->chip_name);
|
||||
if (CONFIG(MIPI_ACPI_TYPE_WINDOWS_LINUX))
|
||||
acpigen_write_name_string("_DDN", config->sensor_name);
|
||||
else
|
||||
acpigen_write_name_string("_DDN", config->chip_name);
|
||||
acpigen_write_STA(acpi_device_status(dev));
|
||||
acpigen_write_method("_DSC", 0);
|
||||
acpigen_write_return_integer(config->max_dstate_for_probe);
|
||||
|
|
@ -1071,11 +1084,12 @@ static void write_camera_device_common(const struct device *dev)
|
|||
{
|
||||
struct drivers_intel_mipi_camera_config *config = dev->chip_info;
|
||||
|
||||
/* Mark it as Camera related device */
|
||||
if (config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_IMGU ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_VCM) {
|
||||
/* Mark it as Camera related device (multi-device mode only) */
|
||||
if (CONFIG(MIPI_ACPI_TYPE_CHROMEOS) &&
|
||||
(config->device_type == INTEL_ACPI_CAMERA_CIO2 ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_IMGU ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_SENSOR ||
|
||||
config->device_type == INTEL_ACPI_CAMERA_VCM)) {
|
||||
acpigen_write_name_integer("CAMD", config->device_type);
|
||||
}
|
||||
|
||||
|
|
@ -1114,6 +1128,36 @@ static void camera_fill_ssdt(const struct device *dev)
|
|||
const char *scope = NULL;
|
||||
const struct device *pdev = dev->upstream->dev;
|
||||
|
||||
if (CONFIG(MIPI_ACPI_TYPE_WINDOWS_LINUX)) {
|
||||
/* Only generate SSDT for an i2c-attached sensor device */
|
||||
if (dev->path.type != DEVICE_PATH_I2C || config->device_type != INTEL_ACPI_CAMERA_SENSOR)
|
||||
return;
|
||||
|
||||
scope = acpi_device_scope(dev);
|
||||
if (!scope) {
|
||||
printk(BIOS_ERR, "Failed to get scope for device %s\n", dev_path(dev));
|
||||
return;
|
||||
}
|
||||
|
||||
acpigen_write_scope(scope);
|
||||
|
||||
if (config->has_power_resource && pdev && pdev->enabled) {
|
||||
add_guarded_operations(config, &config->on_seq);
|
||||
add_guarded_operations(config, &config->off_seq);
|
||||
}
|
||||
|
||||
write_i2c_camera_device(dev, scope);
|
||||
write_camera_device_common(dev);
|
||||
|
||||
acpigen_pop_len(); /* Device */
|
||||
acpigen_pop_len(); /* Scope */
|
||||
|
||||
printk(BIOS_INFO, "%s: %s at I2C 0x%02x\n", acpi_device_path(dev),
|
||||
dev->chip_ops->name, dev->path.i2c.device);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Multi-device mode */
|
||||
if (config->has_power_resource) {
|
||||
if (!pdev || !pdev->enabled)
|
||||
return;
|
||||
|
|
@ -1175,6 +1219,12 @@ static const char *camera_acpi_name(const struct device *dev)
|
|||
if (config->acpi_name)
|
||||
return config->acpi_name;
|
||||
|
||||
if (CONFIG(MIPI_ACPI_TYPE_WINDOWS_LINUX)) {
|
||||
snprintf(name, sizeof(name), "CAM%1u", config->acpi_uid);
|
||||
return name;
|
||||
}
|
||||
|
||||
/* Multi-device mode */
|
||||
switch (config->device_type) {
|
||||
case INTEL_ACPI_CAMERA_CIO2:
|
||||
return "CIO2";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue