mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	More ACPI updates for 5.16-rc1
- Add support for new ACPI device configuration object called _DSC
    to allow certain devices to be probed without changing their power
    states, document it and make two drivers use it (Sakari Ailus,
    Rajmohan Mani).
 
  - Fix device wakeup power reference counting broken recently by
    mistake (Rafael Wysocki).
 
  - Drop unused symbol and macros depending on it from acgcc.h (Rafael
    Wysocki).
 
  - Add HP ZHAN 66 Pro to the "no EC wakeup" quirk list (Binbin Zhou).
 
  - Add Xiaomi Mi Pad 2 to the backlight quirk list and drop an unused
    piece of data from all of the list entries (Hans de Goede).
 
  - Fix register read accesses handling in the Intel PMIC operation
    region driver (Hans de Goede).
 
  - Clean up static variables initialization in the EC driver
    (wangzhitong).
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmGL01cSHHJqd0Byand5
 c29ja2kubmV0AAoJEILEb/54YlRxF0YQAKXlCWrebWXwkDDqnSXZOqk7/aL+QZ9x
 Di1snFSqrpzgnSgZTuEjpUWLCFZ6hdpEyIH9X12PYo3o9SI3TkfGWpoA4XWEU6v7
 CRpFWIXGHznFWFx3IHoyuUgfDMT2bLxdSrYQrC1lw0icvZHOyk72zNH7oVp0tsXq
 QwfxQDozJKypgSnNxbL+KsabG/DhK8Vyf4HjE6K1pTZ9fpsf0q9CnRGWWgdiaqdE
 B5iFxVIA46J1+izE2C9aN+bEJ43HThgVrvv9V+WOMLJKLJoHwEikZaDRBzvR1ofZ
 dm2f7J5/TDhJQSrlRYftMtNkYrw4Fcey+1xeGE1lTrmw0GM+/pvOs8THfj+TaUp9
 0dmJCsHTndEby6PpQqCqTdfTRYsCIbhp8xRK3Q9qZcrYVNXcOrrifzmqY9bUDh2G
 IXHzPao6sfv4E9yWypuZ7VO4UR5alzxTQfnB5K+cCju2vMqz6Zkk1tr32xJLlsw/
 vd6w3q3Bataa1xGZEBbgSYvgSkKEJwFOeU9R+Rvcn1QWgXQuoPufOssz28KSH3oQ
 0mj/nHMJdRdlSDqADzyRUgoaxv7KUmRYRxbTUMiM+aWnDCu/OD7jWNq24sTNi9xC
 c7WMWHYC+0t5YxsyHo1MRfz8Q12zE1qWJFjBqMO23IZuBO3M1p3YSjl+z6NkUMj6
 95M4WeJK2cBb
 =k8+T
 -----END PGP SIGNATURE-----
Merge tag 'acpi-5.16-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm
Pull more ACPI updates from Rafael Wysocki:
 "These add support for a new ACPI device configuration object called
  _DSC, fix some issues including one recent regression, add two new
  items to quirk lists and clean up assorted pieces of code.
  Specifics:
   - Add support for new ACPI device configuration object called _DSC
     ("Deepest State for Configuration") to allow certain devices to be
     probed without changing their power states, document it and make
     two drivers use it (Sakari Ailus, Rajmohan Mani).
   - Fix device wakeup power reference counting broken recently by
     mistake (Rafael Wysocki).
   - Drop unused symbol and macros depending on it from acgcc.h (Rafael
     Wysocki).
   - Add HP ZHAN 66 Pro to the "no EC wakeup" quirk list (Binbin Zhou).
   - Add Xiaomi Mi Pad 2 to the backlight quirk list and drop an unused
     piece of data from all of the list entries (Hans de Goede).
   - Fix register read accesses handling in the Intel PMIC operation
     region driver (Hans de Goede).
   - Clean up static variables initialization in the EC driver
     (wangzhitong)"
* tag 'acpi-5.16-rc1-2' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  Documentation: ACPI: Fix non-D0 probe _DSC object example
  ACPI: Drop ACPI_USE_BUILTIN_STDARG ifdef from acgcc.h
  ACPI: PM: Fix device wakeup power reference counting error
  ACPI: video: use platform backlight driver on Xiaomi Mi Pad 2
  ACPI: video: Drop dmi_system_id.ident settings from video_detect_dmi_table[]
  ACPI: PMIC: Fix intel_pmic_regs_handler() read accesses
  ACPI: EC: Remove initialization of static variables to false
  ACPI: EC: Use ec_no_wakeup on HP ZHAN 66 Pro
  at24: Support probing while in non-zero ACPI D state
  media: i2c: imx319: Support device probe in non-zero ACPI D state
  ACPI: Add a convenience function to tell a device is in D0 state
  Documentation: ACPI: Document _DSC object usage for enum power state
  i2c: Allow an ACPI driver to manage the device's power state during probe
  ACPI: scan: Obtain device's desired enumeration power state
			
			
This commit is contained in:
		
						commit
						285fc3db0a
					
				
					 16 changed files with 302 additions and 130 deletions
				
			
		| 
						 | 
				
			
			@ -26,5 +26,6 @@ ACPI Support
 | 
			
		|||
   acpi-lid
 | 
			
		||||
   lpit
 | 
			
		||||
   video_extension
 | 
			
		||||
   non-d0-probe
 | 
			
		||||
   extcon-intel-int3496
 | 
			
		||||
   intel-pmc-mux
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										78
									
								
								Documentation/firmware-guide/acpi/non-d0-probe.rst
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Documentation/firmware-guide/acpi/non-d0-probe.rst
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,78 @@
 | 
			
		|||
.. SPDX-License-Identifier: GPL-2.0
 | 
			
		||||
 | 
			
		||||
========================================
 | 
			
		||||
Probing devices in other D states than 0
 | 
			
		||||
========================================
 | 
			
		||||
 | 
			
		||||
Introduction
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
In some cases it may be preferred to leave certain devices powered off for the
 | 
			
		||||
entire system bootup if powering on these devices has adverse side effects,
 | 
			
		||||
beyond just powering on the said device.
 | 
			
		||||
 | 
			
		||||
How it works
 | 
			
		||||
============
 | 
			
		||||
 | 
			
		||||
The _DSC (Device State for Configuration) object that evaluates to an integer
 | 
			
		||||
may be used to tell Linux the highest allowed D state for a device during
 | 
			
		||||
probe. The support for _DSC requires support from the kernel bus type if the
 | 
			
		||||
bus driver normally sets the device in D0 state for probe.
 | 
			
		||||
 | 
			
		||||
The downside of using _DSC is that as the device is not powered on, even if
 | 
			
		||||
there's a problem with the device, the driver likely probes just fine but the
 | 
			
		||||
first user will find out the device doesn't work, instead of a failure at probe
 | 
			
		||||
time. This feature should thus be used sparingly.
 | 
			
		||||
 | 
			
		||||
I²C
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
If an I²C driver indicates its support for this by setting the
 | 
			
		||||
I2C_DRV_ACPI_WAIVE_D0_PROBE flag in struct i2c_driver.flags field and the
 | 
			
		||||
_DSC object evaluates to integer higher than the D state of the device,
 | 
			
		||||
the device will not be powered on (put in D0 state) for probe.
 | 
			
		||||
 | 
			
		||||
D states
 | 
			
		||||
--------
 | 
			
		||||
 | 
			
		||||
The D states and thus also the allowed values for _DSC are listed below. Refer
 | 
			
		||||
to [1] for more information on device power states.
 | 
			
		||||
 | 
			
		||||
.. code-block:: text
 | 
			
		||||
 | 
			
		||||
	Number	State	Description
 | 
			
		||||
	0	D0	Device fully powered on
 | 
			
		||||
	1	D1
 | 
			
		||||
	2	D2
 | 
			
		||||
	3	D3hot
 | 
			
		||||
	4	D3cold	Off
 | 
			
		||||
 | 
			
		||||
References
 | 
			
		||||
==========
 | 
			
		||||
 | 
			
		||||
[1] https://uefi.org/specifications/ACPI/6.4/02_Definition_of_Terms/Definition_of_Terms.html#device-power-state-definitions
 | 
			
		||||
 | 
			
		||||
Example
 | 
			
		||||
=======
 | 
			
		||||
 | 
			
		||||
An ASL example describing an ACPI device using _DSC object to tell Operating
 | 
			
		||||
System the device should remain powered off during probe looks like this. Some
 | 
			
		||||
objects not relevant from the example point of view have been omitted.
 | 
			
		||||
 | 
			
		||||
.. code-block:: text
 | 
			
		||||
 | 
			
		||||
	Device (CAM0)
 | 
			
		||||
	{
 | 
			
		||||
		Name (_HID, "SONY319A")
 | 
			
		||||
		Name (_UID, Zero)
 | 
			
		||||
		Name (_CRS, ResourceTemplate ()
 | 
			
		||||
		{
 | 
			
		||||
			I2cSerialBus(0x0020, ControllerInitiated, 0x00061A80,
 | 
			
		||||
				     AddressingMode7Bit, "\\_SB.PCI0.I2C0",
 | 
			
		||||
				     0x00, ResourceConsumer)
 | 
			
		||||
		})
 | 
			
		||||
		Method (_DSC, 0, NotSerialized)
 | 
			
		||||
		{
 | 
			
		||||
			Return (0x4)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -1400,4 +1400,30 @@ bool acpi_storage_d3(struct device *dev)
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(acpi_storage_d3);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * acpi_dev_state_d0 - Tell if the device is in D0 power state
 | 
			
		||||
 * @dev: Physical device the ACPI power state of which to check
 | 
			
		||||
 *
 | 
			
		||||
 * On a system without ACPI, return true. On a system with ACPI, return true if
 | 
			
		||||
 * the current ACPI power state of the device is D0, or false otherwise.
 | 
			
		||||
 *
 | 
			
		||||
 * Note that the power state of a device is not well-defined after it has been
 | 
			
		||||
 * passed to acpi_device_set_power() and before that function returns, so it is
 | 
			
		||||
 * not valid to ask for the ACPI power state of the device in that time frame.
 | 
			
		||||
 *
 | 
			
		||||
 * This function is intended to be used in a driver's probe or remove
 | 
			
		||||
 * function. See Documentation/firmware-guide/acpi/low-power-probe.rst for
 | 
			
		||||
 * more information.
 | 
			
		||||
 */
 | 
			
		||||
bool acpi_dev_state_d0(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct acpi_device *adev = ACPI_COMPANION(dev);
 | 
			
		||||
 | 
			
		||||
	if (!adev)
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
	return adev->power.state == ACPI_STATE_D0;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(acpi_dev_state_d0);
 | 
			
		||||
 | 
			
		||||
#endif /* CONFIG_PM */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -133,7 +133,7 @@ static unsigned int ec_storm_threshold  __read_mostly = 8;
 | 
			
		|||
module_param(ec_storm_threshold, uint, 0644);
 | 
			
		||||
MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm");
 | 
			
		||||
 | 
			
		||||
static bool ec_freeze_events __read_mostly = false;
 | 
			
		||||
static bool ec_freeze_events __read_mostly;
 | 
			
		||||
module_param(ec_freeze_events, bool, 0644);
 | 
			
		||||
MODULE_PARM_DESC(ec_freeze_events, "Disabling event handling during suspend/resume");
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +177,7 @@ struct acpi_ec *first_ec;
 | 
			
		|||
EXPORT_SYMBOL(first_ec);
 | 
			
		||||
 | 
			
		||||
static struct acpi_ec *boot_ec;
 | 
			
		||||
static bool boot_ec_is_ecdt = false;
 | 
			
		||||
static bool boot_ec_is_ecdt;
 | 
			
		||||
static struct workqueue_struct *ec_wq;
 | 
			
		||||
static struct workqueue_struct *ec_query_wq;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2152,6 +2152,13 @@ static const struct dmi_system_id acpi_ec_no_wakeup[] = {
 | 
			
		|||
			DMI_MATCH(DMI_PRODUCT_FAMILY, "ThinkPad X1 Yoga 3rd"),
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
		.ident = "HP ZHAN 66 Pro",
 | 
			
		||||
		.matches = {
 | 
			
		||||
			DMI_MATCH(DMI_SYS_VENDOR, "HP"),
 | 
			
		||||
			DMI_MATCH(DMI_PRODUCT_FAMILY, "103C_5336AN HP ZHAN 66 Pro"),
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{ },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -211,8 +211,9 @@ static acpi_status intel_pmic_regs_handler(u32 function,
 | 
			
		|||
		void *handler_context, void *region_context)
 | 
			
		||||
{
 | 
			
		||||
	struct intel_pmic_opregion *opregion = region_context;
 | 
			
		||||
	int result = 0;
 | 
			
		||||
	int result = -EINVAL;
 | 
			
		||||
 | 
			
		||||
	if (function == ACPI_WRITE) {
 | 
			
		||||
		switch (address) {
 | 
			
		||||
		case 0:
 | 
			
		||||
			return AE_OK;
 | 
			
		||||
| 
						 | 
				
			
			@ -232,10 +233,14 @@ static acpi_status intel_pmic_regs_handler(u32 function,
 | 
			
		|||
			} else {
 | 
			
		||||
				result = regmap_read(opregion->regmap, opregion->ctx.addr,
 | 
			
		||||
						     &opregion->ctx.val);
 | 
			
		||||
			if (result == 0)
 | 
			
		||||
				*value64 = opregion->ctx.val;
 | 
			
		||||
			}
 | 
			
		||||
		memset(&opregion->ctx, 0x00, sizeof(opregion->ctx));
 | 
			
		||||
			opregion->ctx.addr = 0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (function == ACPI_READ && address == 3) {
 | 
			
		||||
		*value64 = opregion->ctx.val;
 | 
			
		||||
		return AE_OK;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (result < 0) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -757,13 +757,11 @@ int acpi_disable_wakeup_device_power(struct acpi_device *dev)
 | 
			
		|||
 | 
			
		||||
	mutex_lock(&acpi_device_lock);
 | 
			
		||||
 | 
			
		||||
	if (dev->wakeup.prepare_count > 1) {
 | 
			
		||||
		dev->wakeup.prepare_count--;
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Do nothing if wakeup power has not been enabled for this device. */
 | 
			
		||||
	if (!dev->wakeup.prepare_count)
 | 
			
		||||
	if (dev->wakeup.prepare_count <= 0)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	if (--dev->wakeup.prepare_count > 0)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
	err = acpi_device_sleep_wake(dev, 0, 0, 0);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1017,6 +1017,7 @@ static void acpi_bus_init_power_state(struct acpi_device *device, int state)
 | 
			
		|||
 | 
			
		||||
static void acpi_bus_get_power_flags(struct acpi_device *device)
 | 
			
		||||
{
 | 
			
		||||
	unsigned long long dsc = ACPI_STATE_D0;
 | 
			
		||||
	u32 i;
 | 
			
		||||
 | 
			
		||||
	/* Presence of _PS0|_PR0 indicates 'power manageable' */
 | 
			
		||||
| 
						 | 
				
			
			@ -1038,6 +1039,9 @@ static void acpi_bus_get_power_flags(struct acpi_device *device)
 | 
			
		|||
	if (acpi_has_method(device->handle, "_DSW"))
 | 
			
		||||
		device->power.flags.dsw_present = 1;
 | 
			
		||||
 | 
			
		||||
	acpi_evaluate_integer(device->handle, "_DSC", NULL, &dsc);
 | 
			
		||||
	device->power.state_for_enumeration = dsc;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Enumerate supported power management states
 | 
			
		||||
	 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -115,7 +115,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	 */
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_vendor,
 | 
			
		||||
	 .ident = "X360",
 | 
			
		||||
	 /* X360 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +124,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_vendor,
 | 
			
		||||
	.ident = "Asus UL30VT",
 | 
			
		||||
	/* Asus UL30VT */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "UL30VT"),
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +132,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_vendor,
 | 
			
		||||
	.ident = "Asus UL30A",
 | 
			
		||||
	/* Asus UL30A */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "UL30A"),
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_vendor,
 | 
			
		||||
	.ident = "GIGABYTE GB-BXBT-2807",
 | 
			
		||||
	/* GIGABYTE GB-BXBT-2807 */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "GB-BXBT-2807"),
 | 
			
		||||
| 
						 | 
				
			
			@ -148,12 +148,20 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_vendor,
 | 
			
		||||
	.ident = "Sony VPCEH3U1E",
 | 
			
		||||
	/* Sony VPCEH3U1E */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "VPCEH3U1E"),
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_vendor,
 | 
			
		||||
	/* Xiaomi Mi Pad 2 */
 | 
			
		||||
	.matches = {
 | 
			
		||||
			DMI_MATCH(DMI_SYS_VENDOR, "Xiaomi Inc"),
 | 
			
		||||
			DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"),
 | 
			
		||||
		},
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * These models have a working acpi_video backlight control, and using
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +172,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	 */
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "ThinkPad T420",
 | 
			
		||||
	 /* ThinkPad T420 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T420"),
 | 
			
		||||
| 
						 | 
				
			
			@ -172,7 +180,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "ThinkPad T520",
 | 
			
		||||
	 /* ThinkPad T520 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T520"),
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +188,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "ThinkPad X201s",
 | 
			
		||||
	 /* ThinkPad X201s */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201s"),
 | 
			
		||||
| 
						 | 
				
			
			@ -188,7 +196,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "ThinkPad X201T",
 | 
			
		||||
	 /* ThinkPad X201T */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201T"),
 | 
			
		||||
| 
						 | 
				
			
			@ -199,7 +207,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugs.freedesktop.org/show_bug.cgi?id=81515 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "HP ENVY 15 Notebook",
 | 
			
		||||
	 /* HP ENVY 15 Notebook */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY 15 Notebook PC"),
 | 
			
		||||
| 
						 | 
				
			
			@ -207,7 +215,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 870Z5E/880Z5E/680Z5E",
 | 
			
		||||
	 /* SAMSUNG 870Z5E/880Z5E/680Z5E */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "870Z5E/880Z5E/680Z5E"),
 | 
			
		||||
| 
						 | 
				
			
			@ -215,7 +223,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V",
 | 
			
		||||
	 /* SAMSUNG 370R4E/370R4V/370R5E/3570RE/370R5V */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME,
 | 
			
		||||
| 
						 | 
				
			
			@ -225,7 +233,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1186097 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 3570R/370R/470R/450R/510R/4450RV",
 | 
			
		||||
	 /* SAMSUNG 3570R/370R/470R/450R/510R/4450RV */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME,
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +243,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1557060 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 670Z5E",
 | 
			
		||||
	 /* SAMSUNG 670Z5E */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "670Z5E"),
 | 
			
		||||
| 
						 | 
				
			
			@ -244,7 +252,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1094948 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 730U3E/740U3E",
 | 
			
		||||
	 /* SAMSUNG 730U3E/740U3E */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
 | 
			
		||||
| 
						 | 
				
			
			@ -253,7 +261,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D",
 | 
			
		||||
	 /* SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME,
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +271,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1272633 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "Dell XPS14 L421X",
 | 
			
		||||
	 /* Dell XPS14 L421X */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"),
 | 
			
		||||
| 
						 | 
				
			
			@ -272,7 +280,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "Dell XPS15 L521X",
 | 
			
		||||
	 /* Dell XPS15 L521X */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "XPS L521X"),
 | 
			
		||||
| 
						 | 
				
			
			@ -281,7 +289,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.kernel.org/show_bug.cgi?id=108971 */
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "SAMSUNG 530U4E/540U4E",
 | 
			
		||||
	 /* SAMSUNG 530U4E/540U4E */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "530U4E/540U4E"),
 | 
			
		||||
| 
						 | 
				
			
			@ -290,7 +298,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	/* https://bugs.launchpad.net/bugs/1894667 */
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_video,
 | 
			
		||||
	 .ident = "HP 635 Notebook",
 | 
			
		||||
	 /* HP 635 Notebook */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "HP 635 Notebook PC"),
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +309,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1201530 */
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Lenovo Ideapad S405",
 | 
			
		||||
	 /* Lenovo Ideapad S405 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_BOARD_NAME, "Lenovo IdeaPad S405"),
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +318,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1187004 */
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Lenovo Ideapad Z570",
 | 
			
		||||
	 /* Lenovo Ideapad Z570 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "102434U"),
 | 
			
		||||
| 
						 | 
				
			
			@ -318,7 +326,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Lenovo E41-25",
 | 
			
		||||
	 /* Lenovo E41-25 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "81FS"),
 | 
			
		||||
| 
						 | 
				
			
			@ -326,7 +334,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Lenovo E41-45",
 | 
			
		||||
	 /* Lenovo E41-45 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "82BK"),
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +343,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1217249 */
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Apple MacBook Pro 12,1",
 | 
			
		||||
	 /* Apple MacBook Pro 12,1 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro12,1"),
 | 
			
		||||
| 
						 | 
				
			
			@ -343,7 +351,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Dell Vostro V131",
 | 
			
		||||
	 /* Dell Vostro V131 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"),
 | 
			
		||||
| 
						 | 
				
			
			@ -352,7 +360,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.redhat.com/show_bug.cgi?id=1123661 */
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Dell XPS 17 L702X",
 | 
			
		||||
	 /* Dell XPS 17 L702X */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "Dell System XPS L702X"),
 | 
			
		||||
| 
						 | 
				
			
			@ -360,7 +368,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Dell Precision 7510",
 | 
			
		||||
	 /* Dell Precision 7510 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "Precision 7510"),
 | 
			
		||||
| 
						 | 
				
			
			@ -368,7 +376,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Acer Aspire 5738z",
 | 
			
		||||
	 /* Acer Aspire 5738z */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5738"),
 | 
			
		||||
| 
						 | 
				
			
			@ -378,7 +386,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	{
 | 
			
		||||
	 /* https://bugzilla.kernel.org/show_bug.cgi?id=207835 */
 | 
			
		||||
	 .callback = video_detect_force_native,
 | 
			
		||||
	 .ident = "Acer TravelMate 5735Z",
 | 
			
		||||
	 /* Acer TravelMate 5735Z */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 5735Z"),
 | 
			
		||||
| 
						 | 
				
			
			@ -387,7 +395,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_native,
 | 
			
		||||
	.ident = "ASUSTeK COMPUTER INC. GA401",
 | 
			
		||||
	/* ASUSTeK COMPUTER INC. GA401 */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "GA401"),
 | 
			
		||||
| 
						 | 
				
			
			@ -395,7 +403,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_native,
 | 
			
		||||
	.ident = "ASUSTeK COMPUTER INC. GA502",
 | 
			
		||||
	/* ASUSTeK COMPUTER INC. GA502 */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "GA502"),
 | 
			
		||||
| 
						 | 
				
			
			@ -403,7 +411,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	.callback = video_detect_force_native,
 | 
			
		||||
	.ident = "ASUSTeK COMPUTER INC. GA503",
 | 
			
		||||
	/* ASUSTeK COMPUTER INC. GA503 */
 | 
			
		||||
	.matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "GA503"),
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +424,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	 */
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_none,
 | 
			
		||||
	 .ident = "Dell OptiPlex 9020M",
 | 
			
		||||
	 /* Dell OptiPlex 9020M */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 9020M"),
 | 
			
		||||
| 
						 | 
				
			
			@ -424,7 +432,7 @@ static const struct dmi_system_id video_detect_dmi_table[] = {
 | 
			
		|||
	},
 | 
			
		||||
	{
 | 
			
		||||
	 .callback = video_detect_force_none,
 | 
			
		||||
	 .ident = "MSI MS-7721",
 | 
			
		||||
	 /* MSI MS-7721 */
 | 
			
		||||
	 .matches = {
 | 
			
		||||
		DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
 | 
			
		||||
		DMI_MATCH(DMI_PRODUCT_NAME, "MS-7721"),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -522,6 +522,16 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
 | 
			
		|||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
 | 
			
		||||
 | 
			
		||||
bool i2c_acpi_waive_d0_probe(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct i2c_driver *driver = to_i2c_driver(dev->driver);
 | 
			
		||||
	struct acpi_device *adev = ACPI_COMPANION(dev);
 | 
			
		||||
 | 
			
		||||
	return driver->flags & I2C_DRV_ACPI_WAIVE_D0_PROBE &&
 | 
			
		||||
		adev && adev->power.state_for_enumeration >= adev->power.state;
 | 
			
		||||
}
 | 
			
		||||
EXPORT_SYMBOL_GPL(i2c_acpi_waive_d0_probe);
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_ACPI_I2C_OPREGION
 | 
			
		||||
static int acpi_gsb_i2c_read_bytes(struct i2c_client *client,
 | 
			
		||||
		u8 cmd, u8 *data, u8 data_len)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -551,7 +551,8 @@ static int i2c_device_probe(struct device *dev)
 | 
			
		|||
	if (status < 0)
 | 
			
		||||
		goto err_clear_wakeup_irq;
 | 
			
		||||
 | 
			
		||||
	status = dev_pm_domain_attach(&client->dev, true);
 | 
			
		||||
	status = dev_pm_domain_attach(&client->dev,
 | 
			
		||||
				      !i2c_acpi_waive_d0_probe(dev));
 | 
			
		||||
	if (status)
 | 
			
		||||
		goto err_clear_wakeup_irq;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -590,7 +591,7 @@ static int i2c_device_probe(struct device *dev)
 | 
			
		|||
err_release_driver_resources:
 | 
			
		||||
	devres_release_group(&client->dev, client->devres_group_id);
 | 
			
		||||
err_detach_pm_domain:
 | 
			
		||||
	dev_pm_domain_detach(&client->dev, true);
 | 
			
		||||
	dev_pm_domain_detach(&client->dev, !i2c_acpi_waive_d0_probe(dev));
 | 
			
		||||
err_clear_wakeup_irq:
 | 
			
		||||
	dev_pm_clear_wake_irq(&client->dev);
 | 
			
		||||
	device_init_wakeup(&client->dev, false);
 | 
			
		||||
| 
						 | 
				
			
			@ -621,7 +622,7 @@ static void i2c_device_remove(struct device *dev)
 | 
			
		|||
 | 
			
		||||
	devres_release_group(&client->dev, client->devres_group_id);
 | 
			
		||||
 | 
			
		||||
	dev_pm_domain_detach(&client->dev, true);
 | 
			
		||||
	dev_pm_domain_detach(&client->dev, !i2c_acpi_waive_d0_probe(dev));
 | 
			
		||||
	if (!pm_runtime_status_suspended(&client->dev) && adap->bus_regulator)
 | 
			
		||||
		regulator_disable(adap->bus_regulator);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -140,6 +140,8 @@ struct imx319 {
 | 
			
		|||
 | 
			
		||||
	/* Streaming on/off */
 | 
			
		||||
	bool streaming;
 | 
			
		||||
	/* True if the device has been identified */
 | 
			
		||||
	bool identified;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct imx319_reg imx319_global_regs[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -2084,6 +2086,31 @@ imx319_set_pad_format(struct v4l2_subdev *sd,
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Verify chip ID */
 | 
			
		||||
static int imx319_identify_module(struct imx319 *imx319)
 | 
			
		||||
{
 | 
			
		||||
	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
 | 
			
		||||
	int ret;
 | 
			
		||||
	u32 val;
 | 
			
		||||
 | 
			
		||||
	if (imx319->identified)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	if (val != IMX319_CHIP_ID) {
 | 
			
		||||
		dev_err(&client->dev, "chip id mismatch: %x!=%x",
 | 
			
		||||
			IMX319_CHIP_ID, val);
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	imx319->identified = true;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Start streaming */
 | 
			
		||||
static int imx319_start_streaming(struct imx319 *imx319)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -2091,6 +2118,10 @@ static int imx319_start_streaming(struct imx319 *imx319)
 | 
			
		|||
	const struct imx319_reg_list *reg_list;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = imx319_identify_module(imx319);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	/* Global Setting */
 | 
			
		||||
	reg_list = &imx319_global_setting;
 | 
			
		||||
	ret = imx319_write_regs(imx319, reg_list->regs, reg_list->num_of_regs);
 | 
			
		||||
| 
						 | 
				
			
			@ -2206,26 +2237,6 @@ static int __maybe_unused imx319_resume(struct device *dev)
 | 
			
		|||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Verify chip ID */
 | 
			
		||||
static int imx319_identify_module(struct imx319 *imx319)
 | 
			
		||||
{
 | 
			
		||||
	struct i2c_client *client = v4l2_get_subdevdata(&imx319->sd);
 | 
			
		||||
	int ret;
 | 
			
		||||
	u32 val;
 | 
			
		||||
 | 
			
		||||
	ret = imx319_read_reg(imx319, IMX319_REG_CHIP_ID, 2, &val);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	if (val != IMX319_CHIP_ID) {
 | 
			
		||||
		dev_err(&client->dev, "chip id mismatch: %x!=%x",
 | 
			
		||||
			IMX319_CHIP_ID, val);
 | 
			
		||||
		return -EIO;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct v4l2_subdev_core_ops imx319_subdev_core_ops = {
 | 
			
		||||
	.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
 | 
			
		||||
	.unsubscribe_event = v4l2_event_subdev_unsubscribe,
 | 
			
		||||
| 
						 | 
				
			
			@ -2420,6 +2431,7 @@ static struct imx319_hwcfg *imx319_get_hwcfg(struct device *dev)
 | 
			
		|||
static int imx319_probe(struct i2c_client *client)
 | 
			
		||||
{
 | 
			
		||||
	struct imx319 *imx319;
 | 
			
		||||
	bool full_power;
 | 
			
		||||
	int ret;
 | 
			
		||||
	u32 i;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2432,12 +2444,15 @@ static int imx319_probe(struct i2c_client *client)
 | 
			
		|||
	/* Initialize subdev */
 | 
			
		||||
	v4l2_i2c_subdev_init(&imx319->sd, client, &imx319_subdev_ops);
 | 
			
		||||
 | 
			
		||||
	full_power = acpi_dev_state_d0(&client->dev);
 | 
			
		||||
	if (full_power) {
 | 
			
		||||
		/* Check module identity */
 | 
			
		||||
		ret = imx319_identify_module(imx319);
 | 
			
		||||
		if (ret) {
 | 
			
		||||
			dev_err(&client->dev, "failed to find sensor: %d", ret);
 | 
			
		||||
			goto error_probe;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	imx319->hwcfg = imx319_get_hwcfg(&client->dev);
 | 
			
		||||
	if (!imx319->hwcfg) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2488,10 +2503,8 @@ static int imx319_probe(struct i2c_client *client)
 | 
			
		|||
	if (ret < 0)
 | 
			
		||||
		goto error_media_entity;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Device is already turned on by i2c-core with ACPI domain PM.
 | 
			
		||||
	 * Enable runtime PM and turn off the device.
 | 
			
		||||
	 */
 | 
			
		||||
	/* Set the device's state to active if it's in D0 state. */
 | 
			
		||||
	if (full_power)
 | 
			
		||||
		pm_runtime_set_active(&client->dev);
 | 
			
		||||
	pm_runtime_enable(&client->dev);
 | 
			
		||||
	pm_runtime_idle(&client->dev);
 | 
			
		||||
| 
						 | 
				
			
			@ -2545,6 +2558,7 @@ static struct i2c_driver imx319_i2c_driver = {
 | 
			
		|||
	},
 | 
			
		||||
	.probe_new = imx319_probe,
 | 
			
		||||
	.remove = imx319_remove,
 | 
			
		||||
	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
 | 
			
		||||
};
 | 
			
		||||
module_i2c_driver(imx319_i2c_driver);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -595,6 +595,7 @@ static int at24_probe(struct i2c_client *client)
 | 
			
		|||
	bool i2c_fn_i2c, i2c_fn_block;
 | 
			
		||||
	unsigned int i, num_addresses;
 | 
			
		||||
	struct at24_data *at24;
 | 
			
		||||
	bool full_power;
 | 
			
		||||
	struct regmap *regmap;
 | 
			
		||||
	bool writable;
 | 
			
		||||
	u8 test_byte;
 | 
			
		||||
| 
						 | 
				
			
			@ -747,14 +748,16 @@ static int at24_probe(struct i2c_client *client)
 | 
			
		|||
 | 
			
		||||
	i2c_set_clientdata(client, at24);
 | 
			
		||||
 | 
			
		||||
	full_power = acpi_dev_state_d0(&client->dev);
 | 
			
		||||
	if (full_power) {
 | 
			
		||||
		err = regulator_enable(at24->vcc_reg);
 | 
			
		||||
		if (err) {
 | 
			
		||||
			dev_err(dev, "Failed to enable vcc regulator\n");
 | 
			
		||||
			return err;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* enable runtime pm */
 | 
			
		||||
		pm_runtime_set_active(dev);
 | 
			
		||||
	}
 | 
			
		||||
	pm_runtime_enable(dev);
 | 
			
		||||
 | 
			
		||||
	at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
 | 
			
		||||
| 
						 | 
				
			
			@ -766,9 +769,11 @@ static int at24_probe(struct i2c_client *client)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Perform a one-byte test read to verify that the
 | 
			
		||||
	 * chip is functional.
 | 
			
		||||
	 * Perform a one-byte test read to verify that the chip is functional,
 | 
			
		||||
	 * unless powering on the device is to be avoided during probe (i.e.
 | 
			
		||||
	 * it's powered off right now).
 | 
			
		||||
	 */
 | 
			
		||||
	if (full_power) {
 | 
			
		||||
		err = at24_read(at24, 0, &test_byte, 1);
 | 
			
		||||
		if (err) {
 | 
			
		||||
			pm_runtime_disable(dev);
 | 
			
		||||
| 
						 | 
				
			
			@ -776,6 +781,7 @@ static int at24_probe(struct i2c_client *client)
 | 
			
		|||
				regulator_disable(at24->vcc_reg);
 | 
			
		||||
			return -ENODEV;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pm_runtime_idle(dev);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -794,9 +800,11 @@ static int at24_remove(struct i2c_client *client)
 | 
			
		|||
	struct at24_data *at24 = i2c_get_clientdata(client);
 | 
			
		||||
 | 
			
		||||
	pm_runtime_disable(&client->dev);
 | 
			
		||||
	if (acpi_dev_state_d0(&client->dev)) {
 | 
			
		||||
		if (!pm_runtime_status_suspended(&client->dev))
 | 
			
		||||
			regulator_disable(at24->vcc_reg);
 | 
			
		||||
		pm_runtime_set_suspended(&client->dev);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -833,6 +841,7 @@ static struct i2c_driver at24_driver = {
 | 
			
		|||
	.probe_new = at24_probe,
 | 
			
		||||
	.remove = at24_remove,
 | 
			
		||||
	.id_table = at24_ids,
 | 
			
		||||
	.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int __init at24_init(void)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -278,6 +278,7 @@ struct acpi_device_power {
 | 
			
		|||
	int state;		/* Current state */
 | 
			
		||||
	struct acpi_device_power_flags flags;
 | 
			
		||||
	struct acpi_device_power_state states[ACPI_D_STATE_COUNT];	/* Power states (D0-D3Cold) */
 | 
			
		||||
	u8 state_for_enumeration; /* Deepest power state for enumeration */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct acpi_dep_data {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,25 +10,12 @@
 | 
			
		|||
#ifndef __ACGCC_H__
 | 
			
		||||
#define __ACGCC_H__
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Use compiler specific <stdarg.h> is a good practice for even when
 | 
			
		||||
 * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined.
 | 
			
		||||
 */
 | 
			
		||||
#ifndef va_arg
 | 
			
		||||
#ifdef ACPI_USE_BUILTIN_STDARG
 | 
			
		||||
typedef __builtin_va_list va_list;
 | 
			
		||||
#define va_start(v, l)          __builtin_va_start(v, l)
 | 
			
		||||
#define va_end(v)               __builtin_va_end(v)
 | 
			
		||||
#define va_arg(v, l)            __builtin_va_arg(v, l)
 | 
			
		||||
#define va_copy(d, s)           __builtin_va_copy(d, s)
 | 
			
		||||
#else
 | 
			
		||||
#ifdef __KERNEL__
 | 
			
		||||
#include <linux/stdarg.h>
 | 
			
		||||
#else
 | 
			
		||||
/* Used to build acpi tools */
 | 
			
		||||
#include <stdarg.h>
 | 
			
		||||
#endif /* __KERNEL__ */
 | 
			
		||||
#endif /* ACPI_USE_BUILTIN_STDARG */
 | 
			
		||||
#endif /* ! va_arg */
 | 
			
		||||
 | 
			
		||||
#define ACPI_INLINE             __inline__
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1014,6 +1014,7 @@ int acpi_subsys_runtime_suspend(struct device *dev);
 | 
			
		|||
int acpi_subsys_runtime_resume(struct device *dev);
 | 
			
		||||
int acpi_dev_pm_attach(struct device *dev, bool power_on);
 | 
			
		||||
bool acpi_storage_d3(struct device *dev);
 | 
			
		||||
bool acpi_dev_state_d0(struct device *dev);
 | 
			
		||||
#else
 | 
			
		||||
static inline int acpi_subsys_runtime_suspend(struct device *dev) { return 0; }
 | 
			
		||||
static inline int acpi_subsys_runtime_resume(struct device *dev) { return 0; }
 | 
			
		||||
| 
						 | 
				
			
			@ -1025,6 +1026,10 @@ static inline bool acpi_storage_d3(struct device *dev)
 | 
			
		|||
{
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
static inline bool acpi_dev_state_d0(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(CONFIG_ACPI) && defined(CONFIG_PM_SLEEP)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
#define _LINUX_I2C_H
 | 
			
		||||
 | 
			
		||||
#include <linux/acpi.h>		/* for acpi_handle */
 | 
			
		||||
#include <linux/bits.h>
 | 
			
		||||
#include <linux/mod_devicetable.h>
 | 
			
		||||
#include <linux/device.h>	/* for struct device */
 | 
			
		||||
#include <linux/sched.h>	/* for completion */
 | 
			
		||||
| 
						 | 
				
			
			@ -222,6 +223,15 @@ enum i2c_alert_protocol {
 | 
			
		|||
	I2C_PROTOCOL_SMBUS_HOST_NOTIFY,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * enum i2c_driver_flags - Flags for an I2C device driver
 | 
			
		||||
 *
 | 
			
		||||
 * @I2C_DRV_ACPI_WAIVE_D0_PROBE: Don't put the device in D0 state for probe
 | 
			
		||||
 */
 | 
			
		||||
enum i2c_driver_flags {
 | 
			
		||||
	I2C_DRV_ACPI_WAIVE_D0_PROBE = BIT(0),
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct i2c_driver - represent an I2C device driver
 | 
			
		||||
 * @class: What kind of i2c device we instantiate (for detect)
 | 
			
		||||
| 
						 | 
				
			
			@ -236,6 +246,7 @@ enum i2c_alert_protocol {
 | 
			
		|||
 * @detect: Callback for device detection
 | 
			
		||||
 * @address_list: The I2C addresses to probe (for detect)
 | 
			
		||||
 * @clients: List of detected clients we created (for i2c-core use only)
 | 
			
		||||
 * @flags: A bitmask of flags defined in &enum i2c_driver_flags
 | 
			
		||||
 *
 | 
			
		||||
 * The driver.owner field should be set to the module owner of this driver.
 | 
			
		||||
 * The driver.name field should be set to the name of this driver.
 | 
			
		||||
| 
						 | 
				
			
			@ -294,6 +305,8 @@ struct i2c_driver {
 | 
			
		|||
	int (*detect)(struct i2c_client *client, struct i2c_board_info *info);
 | 
			
		||||
	const unsigned short *address_list;
 | 
			
		||||
	struct list_head clients;
 | 
			
		||||
 | 
			
		||||
	u32 flags;
 | 
			
		||||
};
 | 
			
		||||
#define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1015,6 +1028,7 @@ u32 i2c_acpi_find_bus_speed(struct device *dev);
 | 
			
		|||
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
 | 
			
		||||
				       struct i2c_board_info *info);
 | 
			
		||||
struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle handle);
 | 
			
		||||
bool i2c_acpi_waive_d0_probe(struct device *dev);
 | 
			
		||||
#else
 | 
			
		||||
static inline bool i2c_acpi_get_i2c_resource(struct acpi_resource *ares,
 | 
			
		||||
					     struct acpi_resource_i2c_serialbus **i2c)
 | 
			
		||||
| 
						 | 
				
			
			@ -1038,6 +1052,10 @@ static inline struct i2c_adapter *i2c_acpi_find_adapter_by_handle(acpi_handle ha
 | 
			
		|||
{
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
static inline bool i2c_acpi_waive_d0_probe(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
#endif /* CONFIG_ACPI */
 | 
			
		||||
 | 
			
		||||
#endif /* _LINUX_I2C_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue