platform-drivers-x86 for v6.14-3
Fixes and new HW support: - thinkpad_acpi: - Fix registration of tpacpi platform driver - Support fan speed in ticks per revolution (Thinkpad X120e) - Support V9 DYTC profiles (new Thinkpad AMD platforms) - int3472: Handle GPIO "enable" vs "reset" variation (ov7251) The following is an automated shortlog grouped by driver: int3472: - Call "reset" GPIO "enable" for INT347E - Use correct type for "polarity", call it gpio_flags thinkpad_acpi: - Fix invalid fan speed on ThinkPad X120e - Fix registration of tpacpi platform driver - Support for V9 DYTC platform profiles -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZ63igAAKCRBZrE9hU+XO MW/TAQDbeIrh8Oy17XBXVYUMcLhuyQNGXQLQntMzxPzCL+aL7AD/T39y8bZFWlYg lEvrv4B/YOjCZyfcst8lR7RrcMFo/Qs= =olZn -----END PGP SIGNATURE----- Merge tag 'platform-drivers-x86-v6.14-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86 Pull x86 platform driver fixes from Ilpo Järvinen: - thinkpad_acpi: - Fix registration of tpacpi platform driver - Support fan speed in ticks per revolution (Thinkpad X120e) - Support V9 DYTC profiles (new Thinkpad AMD platforms) - int3472: Handle GPIO "enable" vs "reset" variation (ov7251) * tag 'platform-drivers-x86-v6.14-3' of git://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86: platform/x86: thinkpad_acpi: Fix registration of tpacpi platform driver platform/x86: int3472: Call "reset" GPIO "enable" for INT347E platform/x86: int3472: Use correct type for "polarity", call it gpio_flags platform/x86: thinkpad_acpi: Support for V9 DYTC platform profiles platform/x86: thinkpad_acpi: Fix invalid fan speed on ThinkPad X120e
This commit is contained in:
commit
d63609e412
2 changed files with 110 additions and 36 deletions
|
@ -2,6 +2,7 @@
|
||||||
/* Author: Dan Scally <djrscally@gmail.com> */
|
/* Author: Dan Scally <djrscally@gmail.com> */
|
||||||
|
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
|
#include <linux/array_size.h>
|
||||||
#include <linux/bitfield.h>
|
#include <linux/bitfield.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/gpio/consumer.h>
|
#include <linux/gpio/consumer.h>
|
||||||
|
@ -55,7 +56,7 @@ static void skl_int3472_log_sensor_module_name(struct int3472_discrete_device *i
|
||||||
|
|
||||||
static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry,
|
static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry,
|
||||||
struct acpi_resource_gpio *agpio,
|
struct acpi_resource_gpio *agpio,
|
||||||
const char *func, u32 polarity)
|
const char *func, unsigned long gpio_flags)
|
||||||
{
|
{
|
||||||
char *path = agpio->resource_source.string_ptr;
|
char *path = agpio->resource_source.string_ptr;
|
||||||
struct acpi_device *adev;
|
struct acpi_device *adev;
|
||||||
|
@ -70,14 +71,14 @@ static int skl_int3472_fill_gpiod_lookup(struct gpiod_lookup *table_entry,
|
||||||
if (!adev)
|
if (!adev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
*table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, polarity);
|
*table_entry = GPIO_LOOKUP(acpi_dev_name(adev), agpio->pin_table[0], func, gpio_flags);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
|
static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int3472,
|
||||||
struct acpi_resource_gpio *agpio,
|
struct acpi_resource_gpio *agpio,
|
||||||
const char *func, u32 polarity)
|
const char *func, unsigned long gpio_flags)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios],
|
ret = skl_int3472_fill_gpiod_lookup(&int3472->gpios.table[int3472->n_sensor_gpios],
|
||||||
agpio, func, polarity);
|
agpio, func, gpio_flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -100,7 +101,7 @@ static int skl_int3472_map_gpio_to_sensor(struct int3472_discrete_device *int347
|
||||||
static struct gpio_desc *
|
static struct gpio_desc *
|
||||||
skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
||||||
struct acpi_resource_gpio *agpio,
|
struct acpi_resource_gpio *agpio,
|
||||||
const char *func, u32 polarity)
|
const char *func, unsigned long gpio_flags)
|
||||||
{
|
{
|
||||||
struct gpio_desc *desc;
|
struct gpio_desc *desc;
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -111,7 +112,7 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
lookup->dev_id = dev_name(int3472->dev);
|
lookup->dev_id = dev_name(int3472->dev);
|
||||||
ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, polarity);
|
ret = skl_int3472_fill_gpiod_lookup(&lookup->table[0], agpio, func, gpio_flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
|
|
||||||
|
@ -122,32 +123,76 @@ skl_int3472_gpiod_get_from_temp_lookup(struct int3472_discrete_device *int3472,
|
||||||
return desc;
|
return desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void int3472_get_func_and_polarity(u8 type, const char **func, u32 *polarity)
|
/**
|
||||||
|
* struct int3472_gpio_map - Map GPIOs to whatever is expected by the
|
||||||
|
* sensor driver (as in DT bindings)
|
||||||
|
* @hid: The ACPI HID of the device without the instance number e.g. INT347E
|
||||||
|
* @type_from: The GPIO type from ACPI ?SDT
|
||||||
|
* @type_to: The assigned GPIO type, typically same as @type_from
|
||||||
|
* @func: The function, e.g. "enable"
|
||||||
|
* @polarity_low: GPIO_ACTIVE_LOW true if the @polarity_low is true,
|
||||||
|
* GPIO_ACTIVE_HIGH otherwise
|
||||||
|
*/
|
||||||
|
struct int3472_gpio_map {
|
||||||
|
const char *hid;
|
||||||
|
u8 type_from;
|
||||||
|
u8 type_to;
|
||||||
|
bool polarity_low;
|
||||||
|
const char *func;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct int3472_gpio_map int3472_gpio_map[] = {
|
||||||
|
{ "INT347E", INT3472_GPIO_TYPE_RESET, INT3472_GPIO_TYPE_RESET, false, "enable" },
|
||||||
|
};
|
||||||
|
|
||||||
|
static void int3472_get_func_and_polarity(struct acpi_device *adev, u8 *type,
|
||||||
|
const char **func, unsigned long *gpio_flags)
|
||||||
{
|
{
|
||||||
switch (type) {
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(int3472_gpio_map); i++) {
|
||||||
|
/*
|
||||||
|
* Map the firmware-provided GPIO to whatever a driver expects
|
||||||
|
* (as in DT bindings). First check if the type matches with the
|
||||||
|
* GPIO map, then further check that the device _HID matches.
|
||||||
|
*/
|
||||||
|
if (*type != int3472_gpio_map[i].type_from)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!acpi_dev_hid_uid_match(adev, int3472_gpio_map[i].hid, NULL))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*type = int3472_gpio_map[i].type_to;
|
||||||
|
*gpio_flags = int3472_gpio_map[i].polarity_low ?
|
||||||
|
GPIO_ACTIVE_LOW : GPIO_ACTIVE_HIGH;
|
||||||
|
*func = int3472_gpio_map[i].func;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (*type) {
|
||||||
case INT3472_GPIO_TYPE_RESET:
|
case INT3472_GPIO_TYPE_RESET:
|
||||||
*func = "reset";
|
*func = "reset";
|
||||||
*polarity = GPIO_ACTIVE_LOW;
|
*gpio_flags = GPIO_ACTIVE_LOW;
|
||||||
break;
|
break;
|
||||||
case INT3472_GPIO_TYPE_POWERDOWN:
|
case INT3472_GPIO_TYPE_POWERDOWN:
|
||||||
*func = "powerdown";
|
*func = "powerdown";
|
||||||
*polarity = GPIO_ACTIVE_LOW;
|
*gpio_flags = GPIO_ACTIVE_LOW;
|
||||||
break;
|
break;
|
||||||
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
||||||
*func = "clk-enable";
|
*func = "clk-enable";
|
||||||
*polarity = GPIO_ACTIVE_HIGH;
|
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||||
break;
|
break;
|
||||||
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
||||||
*func = "privacy-led";
|
*func = "privacy-led";
|
||||||
*polarity = GPIO_ACTIVE_HIGH;
|
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||||
break;
|
break;
|
||||||
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
||||||
*func = "power-enable";
|
*func = "power-enable";
|
||||||
*polarity = GPIO_ACTIVE_HIGH;
|
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
*func = "unknown";
|
*func = "unknown";
|
||||||
*polarity = GPIO_ACTIVE_HIGH;
|
*gpio_flags = GPIO_ACTIVE_HIGH;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +239,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
||||||
struct gpio_desc *gpio;
|
struct gpio_desc *gpio;
|
||||||
const char *err_msg;
|
const char *err_msg;
|
||||||
const char *func;
|
const char *func;
|
||||||
u32 polarity;
|
unsigned long gpio_flags;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!acpi_gpio_get_io_resource(ares, &agpio))
|
if (!acpi_gpio_get_io_resource(ares, &agpio))
|
||||||
|
@ -217,7 +262,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
||||||
|
|
||||||
type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value);
|
type = FIELD_GET(INT3472_GPIO_DSM_TYPE, obj->integer.value);
|
||||||
|
|
||||||
int3472_get_func_and_polarity(type, &func, &polarity);
|
int3472_get_func_and_polarity(int3472->sensor, &type, &func, &gpio_flags);
|
||||||
|
|
||||||
pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value);
|
pin = FIELD_GET(INT3472_GPIO_DSM_PIN, obj->integer.value);
|
||||||
/* Pin field is not really used under Windows and wraps around at 8 bits */
|
/* Pin field is not really used under Windows and wraps around at 8 bits */
|
||||||
|
@ -227,16 +272,16 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
||||||
|
|
||||||
active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value);
|
active_value = FIELD_GET(INT3472_GPIO_DSM_SENSOR_ON_VAL, obj->integer.value);
|
||||||
if (!active_value)
|
if (!active_value)
|
||||||
polarity ^= GPIO_ACTIVE_LOW;
|
gpio_flags ^= GPIO_ACTIVE_LOW;
|
||||||
|
|
||||||
dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func,
|
dev_dbg(int3472->dev, "%s %s pin %d active-%s\n", func,
|
||||||
agpio->resource_source.string_ptr, agpio->pin_table[0],
|
agpio->resource_source.string_ptr, agpio->pin_table[0],
|
||||||
str_high_low(polarity == GPIO_ACTIVE_HIGH));
|
str_high_low(gpio_flags == GPIO_ACTIVE_HIGH));
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case INT3472_GPIO_TYPE_RESET:
|
case INT3472_GPIO_TYPE_RESET:
|
||||||
case INT3472_GPIO_TYPE_POWERDOWN:
|
case INT3472_GPIO_TYPE_POWERDOWN:
|
||||||
ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, polarity);
|
ret = skl_int3472_map_gpio_to_sensor(int3472, agpio, func, gpio_flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
err_msg = "Failed to map GPIO pin to sensor\n";
|
err_msg = "Failed to map GPIO pin to sensor\n";
|
||||||
|
|
||||||
|
@ -244,7 +289,7 @@ static int skl_int3472_handle_gpio_resources(struct acpi_resource *ares,
|
||||||
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
case INT3472_GPIO_TYPE_CLK_ENABLE:
|
||||||
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
case INT3472_GPIO_TYPE_PRIVACY_LED:
|
||||||
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
case INT3472_GPIO_TYPE_POWER_ENABLE:
|
||||||
gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, polarity);
|
gpio = skl_int3472_gpiod_get_from_temp_lookup(int3472, agpio, func, gpio_flags);
|
||||||
if (IS_ERR(gpio)) {
|
if (IS_ERR(gpio)) {
|
||||||
ret = PTR_ERR(gpio);
|
ret = PTR_ERR(gpio);
|
||||||
err_msg = "Failed to get GPIO\n";
|
err_msg = "Failed to get GPIO\n";
|
||||||
|
|
|
@ -7885,6 +7885,7 @@ static struct ibm_struct volume_driver_data = {
|
||||||
|
|
||||||
#define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */
|
#define FAN_NS_CTRL_STATUS BIT(2) /* Bit which determines control is enabled or not */
|
||||||
#define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */
|
#define FAN_NS_CTRL BIT(4) /* Bit which determines control is by host or EC */
|
||||||
|
#define FAN_CLOCK_TPM (22500*60) /* Ticks per minute for a 22.5 kHz clock */
|
||||||
|
|
||||||
enum { /* Fan control constants */
|
enum { /* Fan control constants */
|
||||||
fan_status_offset = 0x2f, /* EC register 0x2f */
|
fan_status_offset = 0x2f, /* EC register 0x2f */
|
||||||
|
@ -7940,6 +7941,7 @@ static int fan_watchdog_maxinterval;
|
||||||
|
|
||||||
static bool fan_with_ns_addr;
|
static bool fan_with_ns_addr;
|
||||||
static bool ecfw_with_fan_dec_rpm;
|
static bool ecfw_with_fan_dec_rpm;
|
||||||
|
static bool fan_speed_in_tpr;
|
||||||
|
|
||||||
static struct mutex fan_mutex;
|
static struct mutex fan_mutex;
|
||||||
|
|
||||||
|
@ -8142,8 +8144,11 @@ static int fan_get_speed(unsigned int *speed)
|
||||||
!acpi_ec_read(fan_rpm_offset + 1, &hi)))
|
!acpi_ec_read(fan_rpm_offset + 1, &hi)))
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (likely(speed))
|
if (likely(speed)) {
|
||||||
*speed = (hi << 8) | lo;
|
*speed = (hi << 8) | lo;
|
||||||
|
if (fan_speed_in_tpr && *speed != 0)
|
||||||
|
*speed = FAN_CLOCK_TPM / *speed;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case TPACPI_FAN_RD_TPEC_NS:
|
case TPACPI_FAN_RD_TPEC_NS:
|
||||||
if (!acpi_ec_read(fan_rpm_status_ns, &lo))
|
if (!acpi_ec_read(fan_rpm_status_ns, &lo))
|
||||||
|
@ -8176,8 +8181,11 @@ static int fan2_get_speed(unsigned int *speed)
|
||||||
if (rc)
|
if (rc)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
|
|
||||||
if (likely(speed))
|
if (likely(speed)) {
|
||||||
*speed = (hi << 8) | lo;
|
*speed = (hi << 8) | lo;
|
||||||
|
if (fan_speed_in_tpr && *speed != 0)
|
||||||
|
*speed = FAN_CLOCK_TPM / *speed;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TPACPI_FAN_RD_TPEC_NS:
|
case TPACPI_FAN_RD_TPEC_NS:
|
||||||
|
@ -8788,6 +8796,7 @@ static const struct attribute_group fan_driver_attr_group = {
|
||||||
#define TPACPI_FAN_NOFAN 0x0008 /* no fan available */
|
#define TPACPI_FAN_NOFAN 0x0008 /* no fan available */
|
||||||
#define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */
|
#define TPACPI_FAN_NS 0x0010 /* For EC with non-Standard register addresses */
|
||||||
#define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */
|
#define TPACPI_FAN_DECRPM 0x0020 /* For ECFW's with RPM in register as decimal */
|
||||||
|
#define TPACPI_FAN_TPR 0x0040 /* Fan speed is in Ticks Per Revolution */
|
||||||
|
|
||||||
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
||||||
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
|
TPACPI_QEC_IBM('1', 'Y', TPACPI_FAN_Q1),
|
||||||
|
@ -8817,6 +8826,7 @@ static const struct tpacpi_quirk fan_quirk_table[] __initconst = {
|
||||||
TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */
|
TPACPI_Q_LNV3('R', '0', 'V', TPACPI_FAN_NS), /* 11e Gen5 KL-Y */
|
||||||
TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */
|
TPACPI_Q_LNV3('N', '1', 'O', TPACPI_FAN_NOFAN), /* X1 Tablet (2nd gen) */
|
||||||
TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */
|
TPACPI_Q_LNV3('R', '0', 'Q', TPACPI_FAN_DECRPM),/* L480 */
|
||||||
|
TPACPI_Q_LNV('8', 'F', TPACPI_FAN_TPR), /* ThinkPad x120e */
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init fan_init(struct ibm_init_struct *iibm)
|
static int __init fan_init(struct ibm_init_struct *iibm)
|
||||||
|
@ -8887,6 +8897,8 @@ static int __init fan_init(struct ibm_init_struct *iibm)
|
||||||
|
|
||||||
if (quirks & TPACPI_FAN_Q1)
|
if (quirks & TPACPI_FAN_Q1)
|
||||||
fan_quirk1_setup();
|
fan_quirk1_setup();
|
||||||
|
if (quirks & TPACPI_FAN_TPR)
|
||||||
|
fan_speed_in_tpr = true;
|
||||||
/* Try and probe the 2nd fan */
|
/* Try and probe the 2nd fan */
|
||||||
tp_features.second_fan = 1; /* needed for get_speed to work */
|
tp_features.second_fan = 1; /* needed for get_speed to work */
|
||||||
res = fan2_get_speed(&speed);
|
res = fan2_get_speed(&speed);
|
||||||
|
@ -10319,6 +10331,10 @@ static struct ibm_struct proxsensor_driver_data = {
|
||||||
#define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */
|
#define DYTC_MODE_PSC_BALANCE 5 /* Default mode aka balanced */
|
||||||
#define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */
|
#define DYTC_MODE_PSC_PERFORM 7 /* High power mode aka performance */
|
||||||
|
|
||||||
|
#define DYTC_MODE_PSCV9_LOWPOWER 1 /* Low power mode */
|
||||||
|
#define DYTC_MODE_PSCV9_BALANCE 3 /* Default mode aka balanced */
|
||||||
|
#define DYTC_MODE_PSCV9_PERFORM 4 /* High power mode aka performance */
|
||||||
|
|
||||||
#define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */
|
#define DYTC_ERR_MASK 0xF /* Bits 0-3 in cmd result are the error result */
|
||||||
#define DYTC_ERR_SUCCESS 1 /* CMD completed successful */
|
#define DYTC_ERR_SUCCESS 1 /* CMD completed successful */
|
||||||
|
|
||||||
|
@ -10339,6 +10355,10 @@ static int dytc_capabilities;
|
||||||
static bool dytc_mmc_get_available;
|
static bool dytc_mmc_get_available;
|
||||||
static int profile_force;
|
static int profile_force;
|
||||||
|
|
||||||
|
static int platform_psc_profile_lowpower = DYTC_MODE_PSC_LOWPOWER;
|
||||||
|
static int platform_psc_profile_balanced = DYTC_MODE_PSC_BALANCE;
|
||||||
|
static int platform_psc_profile_performance = DYTC_MODE_PSC_PERFORM;
|
||||||
|
|
||||||
static int convert_dytc_to_profile(int funcmode, int dytcmode,
|
static int convert_dytc_to_profile(int funcmode, int dytcmode,
|
||||||
enum platform_profile_option *profile)
|
enum platform_profile_option *profile)
|
||||||
{
|
{
|
||||||
|
@ -10360,19 +10380,15 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode,
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
case DYTC_FUNCTION_PSC:
|
case DYTC_FUNCTION_PSC:
|
||||||
switch (dytcmode) {
|
if (dytcmode == platform_psc_profile_lowpower)
|
||||||
case DYTC_MODE_PSC_LOWPOWER:
|
|
||||||
*profile = PLATFORM_PROFILE_LOW_POWER;
|
*profile = PLATFORM_PROFILE_LOW_POWER;
|
||||||
break;
|
else if (dytcmode == platform_psc_profile_balanced)
|
||||||
case DYTC_MODE_PSC_BALANCE:
|
|
||||||
*profile = PLATFORM_PROFILE_BALANCED;
|
*profile = PLATFORM_PROFILE_BALANCED;
|
||||||
break;
|
else if (dytcmode == platform_psc_profile_performance)
|
||||||
case DYTC_MODE_PSC_PERFORM:
|
|
||||||
*profile = PLATFORM_PROFILE_PERFORMANCE;
|
*profile = PLATFORM_PROFILE_PERFORMANCE;
|
||||||
break;
|
else
|
||||||
default: /* Unknown mode */
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
case DYTC_FUNCTION_AMT:
|
case DYTC_FUNCTION_AMT:
|
||||||
/* For now return balanced. It's the closest we have to 'auto' */
|
/* For now return balanced. It's the closest we have to 'auto' */
|
||||||
|
@ -10393,19 +10409,19 @@ static int convert_profile_to_dytc(enum platform_profile_option profile, int *pe
|
||||||
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
||||||
*perfmode = DYTC_MODE_MMC_LOWPOWER;
|
*perfmode = DYTC_MODE_MMC_LOWPOWER;
|
||||||
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
||||||
*perfmode = DYTC_MODE_PSC_LOWPOWER;
|
*perfmode = platform_psc_profile_lowpower;
|
||||||
break;
|
break;
|
||||||
case PLATFORM_PROFILE_BALANCED:
|
case PLATFORM_PROFILE_BALANCED:
|
||||||
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
||||||
*perfmode = DYTC_MODE_MMC_BALANCE;
|
*perfmode = DYTC_MODE_MMC_BALANCE;
|
||||||
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
||||||
*perfmode = DYTC_MODE_PSC_BALANCE;
|
*perfmode = platform_psc_profile_balanced;
|
||||||
break;
|
break;
|
||||||
case PLATFORM_PROFILE_PERFORMANCE:
|
case PLATFORM_PROFILE_PERFORMANCE:
|
||||||
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
if (dytc_capabilities & BIT(DYTC_FC_MMC))
|
||||||
*perfmode = DYTC_MODE_MMC_PERFORM;
|
*perfmode = DYTC_MODE_MMC_PERFORM;
|
||||||
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
else if (dytc_capabilities & BIT(DYTC_FC_PSC))
|
||||||
*perfmode = DYTC_MODE_PSC_PERFORM;
|
*perfmode = platform_psc_profile_performance;
|
||||||
break;
|
break;
|
||||||
default: /* Unknown profile */
|
default: /* Unknown profile */
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
@ -10599,6 +10615,7 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
|
||||||
if (output & BIT(DYTC_QUERY_ENABLE_BIT))
|
if (output & BIT(DYTC_QUERY_ENABLE_BIT))
|
||||||
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
|
dytc_version = (output >> DYTC_QUERY_REV_BIT) & 0xF;
|
||||||
|
|
||||||
|
dbg_printk(TPACPI_DBG_INIT, "DYTC version %d\n", dytc_version);
|
||||||
/* Check DYTC is enabled and supports mode setting */
|
/* Check DYTC is enabled and supports mode setting */
|
||||||
if (dytc_version < 5)
|
if (dytc_version < 5)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -10637,6 +10654,11 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
|
||||||
}
|
}
|
||||||
} else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
|
} else if (dytc_capabilities & BIT(DYTC_FC_PSC)) { /* PSC MODE */
|
||||||
pr_debug("PSC is supported\n");
|
pr_debug("PSC is supported\n");
|
||||||
|
if (dytc_version >= 9) { /* update profiles for DYTC 9 and up */
|
||||||
|
platform_psc_profile_lowpower = DYTC_MODE_PSCV9_LOWPOWER;
|
||||||
|
platform_psc_profile_balanced = DYTC_MODE_PSCV9_BALANCE;
|
||||||
|
platform_psc_profile_performance = DYTC_MODE_PSCV9_PERFORM;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
|
dbg_printk(TPACPI_DBG_INIT, "No DYTC support available\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
@ -10646,8 +10668,8 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
|
||||||
"DYTC version %d: thermal mode available\n", dytc_version);
|
"DYTC version %d: thermal mode available\n", dytc_version);
|
||||||
|
|
||||||
/* Create platform_profile structure and register */
|
/* Create platform_profile structure and register */
|
||||||
tpacpi_pprof = devm_platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi",
|
tpacpi_pprof = platform_profile_register(&tpacpi_pdev->dev, "thinkpad-acpi-profile",
|
||||||
NULL, &dytc_profile_ops);
|
NULL, &dytc_profile_ops);
|
||||||
/*
|
/*
|
||||||
* If for some reason platform_profiles aren't enabled
|
* If for some reason platform_profiles aren't enabled
|
||||||
* don't quit terminally.
|
* don't quit terminally.
|
||||||
|
@ -10665,8 +10687,15 @@ static int tpacpi_dytc_profile_init(struct ibm_init_struct *iibm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dytc_profile_exit(void)
|
||||||
|
{
|
||||||
|
if (!IS_ERR_OR_NULL(tpacpi_pprof))
|
||||||
|
platform_profile_remove(tpacpi_pprof);
|
||||||
|
}
|
||||||
|
|
||||||
static struct ibm_struct dytc_profile_driver_data = {
|
static struct ibm_struct dytc_profile_driver_data = {
|
||||||
.name = "dytc-profile",
|
.name = "dytc-profile",
|
||||||
|
.exit = dytc_profile_exit,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
Loading…
Add table
Reference in a new issue