Files
linux-net/include/linux/platform_data/x86/int3472.h
Hans de Goede 1e5d088a52 platform/x86: int3472: Stop using devm_gpiod_get()
The intent is to re-use the INT3472 code for parsing Intel camera sensor
GPIOs and mapping them to the sensor for the atomisp driver, which
currently has duplicate code.

On atomisp devices there is no special INT3472 ACPI device, instead
the Intel _DSM to get the GPIO type is part of the ACPI device for
the sensor itself.

To deal with this the mapping is done from ipu_bridge_init() instead of
from a platform-device probe() function, there is no device to tie
the lifetime of the gpiod_get() calls done by the INT3472 code to.

Switch from devm_gpiod_get() to plain gpiod_get() + explicit gpiod_put()
calls, to prepare for the code being re-used in the atomisp driver.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Reviewed-by: Andy Shevchenko <andy@kernel.org>
Link: https://lore.kernel.org/r/20250507184737.154747-3-hdegoede@redhat.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
2025-05-08 17:36:00 +03:00

166 lines
4.9 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/*
* Intel INT3472 ACPI camera sensor power-management support
*
* Author: Dan Scally <djrscally@gmail.com>
*/
#ifndef __PLATFORM_DATA_X86_INT3472_H
#define __PLATFORM_DATA_X86_INT3472_H
#include <linux/clk-provider.h>
#include <linux/gpio/machine.h>
#include <linux/leds.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/types.h>
/* FIXME drop this once the I2C_DEV_NAME_FORMAT macro has been added to include/linux/i2c.h */
#ifndef I2C_DEV_NAME_FORMAT
#define I2C_DEV_NAME_FORMAT "i2c-%s"
#endif
/* PMIC GPIO Types */
#define INT3472_GPIO_TYPE_RESET 0x00
#define INT3472_GPIO_TYPE_POWERDOWN 0x01
#define INT3472_GPIO_TYPE_POWER_ENABLE 0x0b
#define INT3472_GPIO_TYPE_CLK_ENABLE 0x0c
#define INT3472_GPIO_TYPE_PRIVACY_LED 0x0d
#define INT3472_GPIO_TYPE_HANDSHAKE 0x12
#define INT3472_PDEV_MAX_NAME_LEN 23
#define INT3472_MAX_SENSOR_GPIOS 3
#define INT3472_MAX_REGULATORS 3
/* E.g. "avdd\0" */
#define GPIO_SUPPLY_NAME_LENGTH 5
/* 12 chars for acpi_dev_name() + "-", e.g. "ABCD1234:00-" */
#define GPIO_REGULATOR_NAME_LENGTH (12 + GPIO_SUPPLY_NAME_LENGTH)
/* lower- and upper-case mapping */
#define GPIO_REGULATOR_SUPPLY_MAP_COUNT 2
/*
* Ensure the GPIO is driven low/high for at least 2 ms before changing.
*
* 2 ms has been chosen because it is the minimum time ovXXXX sensors need to
* have their reset line driven logical high to properly register a reset.
*/
#define GPIO_REGULATOR_ENABLE_TIME (2 * USEC_PER_MSEC)
#define GPIO_REGULATOR_OFF_ON_DELAY (2 * USEC_PER_MSEC)
#define INT3472_LED_MAX_NAME_LEN 32
#define CIO2_SENSOR_SSDB_MCLKSPEED_OFFSET 86
#define INT3472_REGULATOR(_name, _ops, _enable_time, _off_on_delay) \
(const struct regulator_desc) { \
.name = _name, \
.type = REGULATOR_VOLTAGE, \
.ops = _ops, \
.owner = THIS_MODULE, \
.enable_time = _enable_time, \
.off_on_delay = _off_on_delay, \
}
#define to_int3472_clk(hw) \
container_of(hw, struct int3472_clock, clk_hw)
#define to_int3472_device(clk) \
container_of(clk, struct int3472_discrete_device, clock)
struct acpi_device;
struct dmi_system_id;
struct i2c_client;
struct platform_device;
struct int3472_cldb {
u8 version;
/*
* control logic type
* 0: UNKNOWN
* 1: DISCRETE(CRD-D)
* 2: PMIC TPS68470
* 3: PMIC uP6641
*/
u8 control_logic_type;
u8 control_logic_id;
u8 sensor_card_sku;
u8 reserved[10];
u8 clock_source;
u8 reserved2[17];
};
struct int3472_discrete_quirks {
/* For models where AVDD GPIO is shared between sensors */
const char *avdd_second_sensor;
};
struct int3472_gpio_regulator {
/* SUPPLY_MAP_COUNT * 2 to make room for second sensor mappings */
struct regulator_consumer_supply supply_map[GPIO_REGULATOR_SUPPLY_MAP_COUNT * 2];
char supply_name_upper[GPIO_SUPPLY_NAME_LENGTH];
char regulator_name[GPIO_REGULATOR_NAME_LENGTH];
struct gpio_desc *ena_gpio;
struct regulator_dev *rdev;
struct regulator_desc rdesc;
};
struct int3472_discrete_device {
struct acpi_device *adev;
struct device *dev;
struct acpi_device *sensor;
const char *sensor_name;
const struct int3472_sensor_config *sensor_config;
struct int3472_gpio_regulator regulators[INT3472_MAX_REGULATORS];
struct int3472_clock {
struct clk *clk;
struct clk_hw clk_hw;
struct clk_lookup *cl;
struct gpio_desc *ena_gpio;
u32 frequency;
u8 imgclk_index;
} clock;
struct int3472_pled {
struct led_classdev classdev;
struct led_lookup_data lookup;
char name[INT3472_LED_MAX_NAME_LEN];
struct gpio_desc *gpio;
} pled;
struct int3472_discrete_quirks quirks;
unsigned int ngpios; /* how many GPIOs have we seen */
unsigned int n_sensor_gpios; /* how many have we mapped to sensor */
unsigned int n_regulator_gpios; /* how many have we mapped to a regulator */
struct gpiod_lookup_table gpios;
};
extern const struct dmi_system_id skl_int3472_discrete_quirks[];
union acpi_object *skl_int3472_get_acpi_buffer(struct acpi_device *adev,
char *id);
int skl_int3472_fill_cldb(struct acpi_device *adev, struct int3472_cldb *cldb);
int skl_int3472_get_sensor_adev_and_name(struct device *dev,
struct acpi_device **sensor_adev_ret,
const char **name_ret);
int skl_int3472_register_gpio_clock(struct int3472_discrete_device *int3472,
struct gpio_desc *gpio);
int skl_int3472_register_dsm_clock(struct int3472_discrete_device *int3472);
void skl_int3472_unregister_clock(struct int3472_discrete_device *int3472);
int skl_int3472_register_regulator(struct int3472_discrete_device *int3472,
struct gpio_desc *gpio,
unsigned int enable_time,
const char *supply_name,
const char *second_sensor);
void skl_int3472_unregister_regulator(struct int3472_discrete_device *int3472);
int skl_int3472_register_pled(struct int3472_discrete_device *int3472, struct gpio_desc *gpio);
void skl_int3472_unregister_pled(struct int3472_discrete_device *int3472);
#endif