Commit 1c0a50de authored by Ilpo Järvinen's avatar Ilpo Järvinen

Merge tag 'platform-drivers-x86-v6.8-4' into pdx86/for-next

Merge tag 'platform-drivers-x86-v6.8-4' fixes into pdx86/for-next to
resolve amd/pmf conflicts.
parents 30f96b2c 0314cebb
...@@ -297,7 +297,8 @@ static int amd_pmf_suspend_handler(struct device *dev) ...@@ -297,7 +297,8 @@ static int amd_pmf_suspend_handler(struct device *dev)
{ {
struct amd_pmf_dev *pdev = dev_get_drvdata(dev); struct amd_pmf_dev *pdev = dev_get_drvdata(dev);
kfree(pdev->buf); if (pdev->smart_pc_enabled)
cancel_delayed_work_sync(&pdev->pb_work);
if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2)) if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_SUSPEND); amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_SUSPEND);
...@@ -319,6 +320,9 @@ static int amd_pmf_resume_handler(struct device *dev) ...@@ -319,6 +320,9 @@ static int amd_pmf_resume_handler(struct device *dev)
if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2)) if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_RESUME); amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_RESUME);
if (pdev->smart_pc_enabled)
schedule_delayed_work(&pdev->pb_work, msecs_to_jiffies(2000));
return 0; return 0;
} }
...@@ -337,9 +341,14 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev) ...@@ -337,9 +341,14 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n"); dev_dbg(dev->dev, "SPS enabled and Platform Profiles registered\n");
} }
if (!amd_pmf_init_smart_pc(dev)) { amd_pmf_init_smart_pc(dev);
if (dev->smart_pc_enabled) {
dev_dbg(dev->dev, "Smart PC Solution Enabled\n"); dev_dbg(dev->dev, "Smart PC Solution Enabled\n");
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { /* If Smart PC is enabled, no need to check for other features */
return;
}
if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_init_auto_mode(dev); amd_pmf_init_auto_mode(dev);
dev_dbg(dev->dev, "Auto Mode Init done\n"); dev_dbg(dev->dev, "Auto Mode Init done\n");
} else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) || } else if (is_apmf_func_supported(dev, APMF_FUNC_DYN_SLIDER_AC) ||
...@@ -358,7 +367,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev) ...@@ -358,7 +367,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
amd_pmf_deinit_sps(dev); amd_pmf_deinit_sps(dev);
} }
if (!dev->smart_pc_enabled) { if (dev->smart_pc_enabled) {
amd_pmf_deinit_smart_pc(dev); amd_pmf_deinit_smart_pc(dev);
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) { } else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
amd_pmf_deinit_auto_mode(dev); amd_pmf_deinit_auto_mode(dev);
......
...@@ -524,11 +524,6 @@ struct apmf_dyn_slider_output { ...@@ -524,11 +524,6 @@ struct apmf_dyn_slider_output {
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX]; struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
} __packed; } __packed;
enum smart_pc_status {
PMF_SMART_PC_ENABLED,
PMF_SMART_PC_DISABLED,
};
/* Smart PC - TA internals */ /* Smart PC - TA internals */
enum system_state { enum system_state {
SYSTEM_STATE_S0i3, SYSTEM_STATE_S0i3,
......
...@@ -254,8 +254,10 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) ...@@ -254,8 +254,10 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
header = (struct cookie_header *)(dev->policy_buf + POLICY_COOKIE_OFFSET); header = (struct cookie_header *)(dev->policy_buf + POLICY_COOKIE_OFFSET);
if (header->sign != POLICY_SIGN_COOKIE || !header->length) if (header->sign != POLICY_SIGN_COOKIE || !header->length) {
dev_dbg(dev->dev, "cookie doesn't match\n");
return -EINVAL; return -EINVAL;
}
if (dev->policy_sz < header->length + 512) if (dev->policy_sz < header->length + 512)
return -EINVAL; return -EINVAL;
...@@ -265,7 +267,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) ...@@ -265,7 +267,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
res = amd_pmf_invoke_cmd_init(dev); res = amd_pmf_invoke_cmd_init(dev);
if (res == TA_PMF_TYPE_SUCCESS) { if (res == TA_PMF_TYPE_SUCCESS) {
/* Now its safe to announce that smart pc is enabled */ /* Now its safe to announce that smart pc is enabled */
dev->smart_pc_enabled = PMF_SMART_PC_ENABLED; dev->smart_pc_enabled = true;
/* /*
* Start collecting the data from TA FW after a small delay * Start collecting the data from TA FW after a small delay
* or else, we might end up getting stale values. * or else, we might end up getting stale values.
...@@ -273,7 +275,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev) ...@@ -273,7 +275,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3)); schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
} else { } else {
dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res); dev_err(dev->dev, "ta invoke cmd init failed err: %x\n", res);
dev->smart_pc_enabled = PMF_SMART_PC_DISABLED; dev->smart_pc_enabled = false;
return -EIO; return -EIO;
} }
...@@ -341,25 +343,6 @@ static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {} ...@@ -341,25 +343,6 @@ static void amd_pmf_remove_pb(struct amd_pmf_dev *dev) {}
static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) {} static void amd_pmf_hex_dump_pb(struct amd_pmf_dev *dev) {}
#endif #endif
static int amd_pmf_get_bios_buffer(struct amd_pmf_dev *dev)
{
dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
if (!dev->policy_buf)
return -ENOMEM;
dev->policy_base = devm_ioremap(dev->dev, dev->policy_addr, dev->policy_sz);
if (!dev->policy_base)
return -ENOMEM;
memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz);
amd_pmf_hex_dump_pb(dev);
if (pb_side_load)
amd_pmf_open_pb(dev, dev->dbgfs_dir);
return amd_pmf_start_policy_engine(dev);
}
static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data) static int amd_pmf_amdtee_ta_match(struct tee_ioctl_version_data *ver, const void *data)
{ {
return ver->impl_id == TEE_IMPL_ID_AMDTEE; return ver->impl_id == TEE_IMPL_ID_AMDTEE;
...@@ -458,22 +441,59 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev) ...@@ -458,22 +441,59 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
return ret; return ret;
INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd); INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
amd_pmf_set_dram_addr(dev, true);
amd_pmf_get_bios_buffer(dev); ret = amd_pmf_set_dram_addr(dev, true);
if (ret)
goto error;
dev->policy_base = devm_ioremap(dev->dev, dev->policy_addr, dev->policy_sz);
if (!dev->policy_base) {
ret = -ENOMEM;
goto error;
}
dev->policy_buf = kzalloc(dev->policy_sz, GFP_KERNEL);
if (!dev->policy_buf) {
ret = -ENOMEM;
goto error;
}
memcpy_fromio(dev->policy_buf, dev->policy_base, dev->policy_sz);
amd_pmf_hex_dump_pb(dev);
dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL); dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
if (!dev->prev_data) if (!dev->prev_data) {
return -ENOMEM; ret = -ENOMEM;
goto error;
}
ret = amd_pmf_start_policy_engine(dev);
if (ret)
goto error;
if (pb_side_load)
amd_pmf_open_pb(dev, dev->dbgfs_dir);
return 0;
return dev->smart_pc_enabled; error:
amd_pmf_deinit_smart_pc(dev);
return ret;
} }
void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev) void amd_pmf_deinit_smart_pc(struct amd_pmf_dev *dev)
{ {
if (pb_side_load) if (pb_side_load && dev->esbin)
amd_pmf_remove_pb(dev); amd_pmf_remove_pb(dev);
cancel_delayed_work_sync(&dev->pb_work);
kfree(dev->prev_data); kfree(dev->prev_data);
dev->prev_data = NULL;
kfree(dev->policy_buf); kfree(dev->policy_buf);
cancel_delayed_work_sync(&dev->pb_work); dev->policy_buf = NULL;
kfree(dev->buf);
dev->buf = NULL;
amd_pmf_tee_deinit(dev); amd_pmf_tee_deinit(dev);
} }
...@@ -196,7 +196,7 @@ static int int0002_probe(struct platform_device *pdev) ...@@ -196,7 +196,7 @@ static int int0002_probe(struct platform_device *pdev)
* IRQs into gpiolib. * IRQs into gpiolib.
*/ */
ret = devm_request_irq(dev, irq, int0002_irq, ret = devm_request_irq(dev, irq, int0002_irq,
IRQF_SHARED, "INT0002", chip); IRQF_ONESHOT | IRQF_SHARED, "INT0002", chip);
if (ret) { if (ret) {
dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret); dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret);
return ret; return ret;
......
...@@ -200,9 +200,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) ...@@ -200,9 +200,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE); autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
sparse_keymap_report_event(input_dev, event, val, autorelease); sparse_keymap_report_event(input_dev, event, val, autorelease);
/* Some devices need this to report further events */
acpi_evaluate_object(handle, "VBDL", NULL, NULL);
} }
/* /*
......
...@@ -20,9 +20,11 @@ ...@@ -20,9 +20,11 @@
#define P2SBC_HIDE BIT(8) #define P2SBC_HIDE BIT(8)
#define P2SB_DEVFN_DEFAULT PCI_DEVFN(31, 1) #define P2SB_DEVFN_DEFAULT PCI_DEVFN(31, 1)
#define P2SB_DEVFN_GOLDMONT PCI_DEVFN(13, 0)
#define SPI_DEVFN_GOLDMONT PCI_DEVFN(13, 2)
static const struct x86_cpu_id p2sb_cpu_ids[] = { static const struct x86_cpu_id p2sb_cpu_ids[] = {
X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, PCI_DEVFN(13, 0)), X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, P2SB_DEVFN_GOLDMONT),
{} {}
}; };
...@@ -98,21 +100,12 @@ static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn) ...@@ -98,21 +100,12 @@ static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn)
static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn) static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
{ {
unsigned int slot, fn; /* Scan the P2SB device and cache its BAR0 */
p2sb_scan_and_cache_devfn(bus, devfn);
if (PCI_FUNC(devfn) == 0) {
/* /* On Goldmont p2sb_bar() also gets called for the SPI controller */
* When function number of the P2SB device is zero, scan it and if (devfn == P2SB_DEVFN_GOLDMONT)
* other function numbers, and if devices are available, cache p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT);
* their BAR0s.
*/
slot = PCI_SLOT(devfn);
for (fn = 0; fn < NR_P2SB_RES_CACHE; fn++)
p2sb_scan_and_cache_devfn(bus, PCI_DEVFN(slot, fn));
} else {
/* Scan the P2SB device and cache its BAR0 */
p2sb_scan_and_cache_devfn(bus, devfn);
}
if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res)) if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res))
return -ENOENT; return -ENOENT;
......
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* In some cases UART attached devices which require an in kernel driver,
* e.g. UART attached Bluetooth HCIs are described in the ACPI tables
* by an ACPI device with a broken or missing UartSerialBusV2() resource.
*
* This causes the kernel to create a /dev/ttyS# char-device for the UART
* instead of creating an in kernel serdev-controller + serdev-device pair
* for the in kernel driver.
*
* The quirk handling in acpi_quirk_skip_serdev_enumeration() makes the kernel
* create a serdev-controller device for these UARTs instead of a /dev/ttyS#.
*
* Instantiating the actual serdev-device to bind to is up to pdx86 code,
* this header provides a helper for getting the serdev-controller device.
*/
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/printk.h>
#include <linux/sprintf.h>
#include <linux/string.h>
static inline struct device *
get_serdev_controller(const char *serial_ctrl_hid,
const char *serial_ctrl_uid,
int serial_ctrl_port,
const char *serdev_ctrl_name)
{
struct device *ctrl_dev, *child;
struct acpi_device *ctrl_adev;
char name[32];
int i;
ctrl_adev = acpi_dev_get_first_match_dev(serial_ctrl_hid, serial_ctrl_uid, -1);
if (!ctrl_adev) {
pr_err("error could not get %s/%s serial-ctrl adev\n",
serial_ctrl_hid, serial_ctrl_uid);
return ERR_PTR(-ENODEV);
}
/* get_first_physical_node() returns a weak ref */
ctrl_dev = get_device(acpi_get_first_physical_node(ctrl_adev));
if (!ctrl_dev) {
pr_err("error could not get %s/%s serial-ctrl physical node\n",
serial_ctrl_hid, serial_ctrl_uid);
ctrl_dev = ERR_PTR(-ENODEV);
goto put_ctrl_adev;
}
/* Walk host -> uart-ctrl -> port -> serdev-ctrl */
for (i = 0; i < 3; i++) {
switch (i) {
case 0:
snprintf(name, sizeof(name), "%s:0", dev_name(ctrl_dev));
break;
case 1:
snprintf(name, sizeof(name), "%s.%d",
dev_name(ctrl_dev), serial_ctrl_port);
break;
case 2:
strscpy(name, serdev_ctrl_name, sizeof(name));
break;
}
child = device_find_child_by_name(ctrl_dev, name);
put_device(ctrl_dev);
if (!child) {
pr_err("error could not find '%s' device\n", name);
ctrl_dev = ERR_PTR(-ENODEV);
goto put_ctrl_adev;
}
ctrl_dev = child;
}
put_ctrl_adev:
acpi_dev_put(ctrl_adev);
return ctrl_dev;
}
...@@ -1009,7 +1009,16 @@ static ssize_t current_value_store(struct kobject *kobj, ...@@ -1009,7 +1009,16 @@ static ssize_t current_value_store(struct kobject *kobj,
* Note - this sets the variable and then the password as separate * Note - this sets the variable and then the password as separate
* WMI calls. Function tlmi_save_bios_settings will error if the * WMI calls. Function tlmi_save_bios_settings will error if the
* password is incorrect. * password is incorrect.
* Workstation's require the opcode to be set before changing the
* attribute.
*/ */
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password);
if (ret)
goto out;
}
set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name, set_str = kasprintf(GFP_KERNEL, "%s,%s;", setting->display_name,
new_setting); new_setting);
if (!set_str) { if (!set_str) {
...@@ -1021,17 +1030,10 @@ static ssize_t current_value_store(struct kobject *kobj, ...@@ -1021,17 +1030,10 @@ static ssize_t current_value_store(struct kobject *kobj,
if (ret) if (ret)
goto out; goto out;
if (tlmi_priv.save_mode == TLMI_SAVE_BULK) { if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
tlmi_priv.save_required = true; tlmi_priv.save_required = true;
} else { else
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
ret = tlmi_opcode_setting("WmiOpcodePasswordAdmin",
tlmi_priv.pwd_admin->password);
if (ret)
goto out;
}
ret = tlmi_save_bios_settings(""); ret = tlmi_save_bios_settings("");
}
} else { /* old non-opcode based authentication method (deprecated) */ } else { /* old non-opcode based authentication method (deprecated) */
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) { if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;", auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
......
...@@ -10379,6 +10379,7 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode, ...@@ -10379,6 +10379,7 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode,
return 0; return 0;
default: default:
/* Unknown function */ /* Unknown function */
pr_debug("unknown function 0x%x\n", funcmode);
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
return 0; return 0;
...@@ -10564,8 +10565,8 @@ static void dytc_profile_refresh(void) ...@@ -10564,8 +10565,8 @@ static void dytc_profile_refresh(void)
return; return;
perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF; perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
convert_dytc_to_profile(funcmode, perfmode, &profile); err = convert_dytc_to_profile(funcmode, perfmode, &profile);
if (profile != dytc_current_profile) { if (!err && profile != dytc_current_profile) {
dytc_current_profile = profile; dytc_current_profile = profile;
platform_profile_notify(); platform_profile_notify();
} }
......
...@@ -81,7 +81,7 @@ static const struct property_entry chuwi_hi8_air_props[] = { ...@@ -81,7 +81,7 @@ static const struct property_entry chuwi_hi8_air_props[] = {
}; };
static const struct ts_dmi_data chuwi_hi8_air_data = { static const struct ts_dmi_data chuwi_hi8_air_data = {
.acpi_name = "MSSL1680:00", .acpi_name = "MSSL1680",
.properties = chuwi_hi8_air_props, .properties = chuwi_hi8_air_props,
}; };
...@@ -415,18 +415,13 @@ static const struct property_entry gdix1001_upside_down_props[] = { ...@@ -415,18 +415,13 @@ static const struct property_entry gdix1001_upside_down_props[] = {
{ } { }
}; };
static const struct ts_dmi_data gdix1001_00_upside_down_data = { static const struct ts_dmi_data gdix1001_upside_down_data = {
.acpi_name = "GDIX1001:00", .acpi_name = "GDIX1001",
.properties = gdix1001_upside_down_props,
};
static const struct ts_dmi_data gdix1001_01_upside_down_data = {
.acpi_name = "GDIX1001:01",
.properties = gdix1001_upside_down_props, .properties = gdix1001_upside_down_props,
}; };
static const struct ts_dmi_data gdix1002_00_upside_down_data = { static const struct ts_dmi_data gdix1002_upside_down_data = {
.acpi_name = "GDIX1002:00", .acpi_name = "GDIX1002",
.properties = gdix1001_upside_down_props, .properties = gdix1001_upside_down_props,
}; };
...@@ -1421,7 +1416,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1421,7 +1416,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* Juno Tablet */ /* Juno Tablet */
.driver_data = (void *)&gdix1002_00_upside_down_data, .driver_data = (void *)&gdix1002_upside_down_data,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Default string"), DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
/* Both product- and board-name being "Default string" is somewhat rare */ /* Both product- and board-name being "Default string" is somewhat rare */
...@@ -1667,7 +1662,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1667,7 +1662,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* Teclast X89 (Android version / BIOS) */ /* Teclast X89 (Android version / BIOS) */
.driver_data = (void *)&gdix1001_00_upside_down_data, .driver_data = (void *)&gdix1001_upside_down_data,
.matches = { .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "WISKY"), DMI_MATCH(DMI_BOARD_VENDOR, "WISKY"),
DMI_MATCH(DMI_BOARD_NAME, "3G062i"), DMI_MATCH(DMI_BOARD_NAME, "3G062i"),
...@@ -1675,7 +1670,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1675,7 +1670,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* Teclast X89 (Windows version / BIOS) */ /* Teclast X89 (Windows version / BIOS) */
.driver_data = (void *)&gdix1001_01_upside_down_data, .driver_data = (void *)&gdix1001_upside_down_data,
.matches = { .matches = {
/* tPAD is too generic, also match on bios date */ /* tPAD is too generic, also match on bios date */
DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
...@@ -1693,7 +1688,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1693,7 +1688,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* Teclast X98 Pro */ /* Teclast X98 Pro */
.driver_data = (void *)&gdix1001_00_upside_down_data, .driver_data = (void *)&gdix1001_upside_down_data,
.matches = { .matches = {
/* /*
* Only match BIOS date, because the manufacturers * Only match BIOS date, because the manufacturers
...@@ -1797,7 +1792,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1797,7 +1792,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* "WinBook TW100" */ /* "WinBook TW100" */
.driver_data = (void *)&gdix1001_00_upside_down_data, .driver_data = (void *)&gdix1001_upside_down_data,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
DMI_MATCH(DMI_PRODUCT_NAME, "TW100") DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
...@@ -1805,7 +1800,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = { ...@@ -1805,7 +1800,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
}, },
{ {
/* WinBook TW700 */ /* WinBook TW700 */
.driver_data = (void *)&gdix1001_00_upside_down_data, .driver_data = (void *)&gdix1001_upside_down_data,
.matches = { .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
DMI_MATCH(DMI_PRODUCT_NAME, "TW700") DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
...@@ -1830,7 +1825,7 @@ static void ts_dmi_add_props(struct i2c_client *client) ...@@ -1830,7 +1825,7 @@ static void ts_dmi_add_props(struct i2c_client *client)
int error; int error;
if (has_acpi_companion(dev) && if (has_acpi_companion(dev) &&
!strncmp(ts_data->acpi_name, client->name, I2C_NAME_SIZE)) { strstarts(client->name, ts_data->acpi_name)) {
error = device_create_managed_software_node(dev, ts_data->properties, NULL); error = device_create_managed_software_node(dev, ts_data->properties, NULL);
if (error) if (error)
dev_err(dev, "failed to add properties: %d\n", error); dev_err(dev, "failed to add properties: %d\n", error);
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/string.h> #include <linux/string.h>
#include "x86-android-tablets.h" #include "x86-android-tablets.h"
#include "../serdev_helpers.h"
static struct platform_device *x86_android_tablet_device; static struct platform_device *x86_android_tablet_device;
...@@ -113,6 +114,9 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data) ...@@ -113,6 +114,9 @@ int x86_acpi_irq_helper_get(const struct x86_acpi_irq_data *data)
if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq)) if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
irq_set_irq_type(irq, irq_type); irq_set_irq_type(irq, irq_type);
if (data->free_gpio)
devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
return irq; return irq;
case X86_ACPI_IRQ_TYPE_PMIC: case X86_ACPI_IRQ_TYPE_PMIC:
status = acpi_get_handle(NULL, data->chip, &handle); status = acpi_get_handle(NULL, data->chip, &handle);
...@@ -229,38 +233,20 @@ static __init int x86_instantiate_spi_dev(const struct x86_dev_info *dev_info, i ...@@ -229,38 +233,20 @@ static __init int x86_instantiate_spi_dev(const struct x86_dev_info *dev_info, i
static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx) static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int idx)
{ {
struct acpi_device *ctrl_adev, *serdev_adev; struct acpi_device *serdev_adev;
struct serdev_device *serdev; struct serdev_device *serdev;
struct device *ctrl_dev; struct device *ctrl_dev;
int ret = -ENODEV; int ret = -ENODEV;
ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1); ctrl_dev = get_serdev_controller(info->ctrl_hid, info->ctrl_uid, 0,
if (!ctrl_adev) { info->ctrl_devname);
pr_err("error could not get %s/%s ctrl adev\n", if (IS_ERR(ctrl_dev))
info->ctrl_hid, info->ctrl_uid); return PTR_ERR(ctrl_dev);
return -ENODEV;
}
serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1); serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
if (!serdev_adev) { if (!serdev_adev) {
pr_err("error could not get %s serdev adev\n", info->serdev_hid); pr_err("error could not get %s serdev adev\n", info->serdev_hid);
goto put_ctrl_adev; goto put_ctrl_dev;
}
/* get_first_physical_node() returns a weak ref, no need to put() it */
ctrl_dev = acpi_get_first_physical_node(ctrl_adev);
if (!ctrl_dev) {
pr_err("error could not get %s/%s ctrl physical dev\n",
info->ctrl_hid, info->ctrl_uid);
goto put_serdev_adev;
}
/* ctrl_dev now points to the controller's parent, get the controller */
ctrl_dev = device_find_child_by_name(ctrl_dev, info->ctrl_devname);
if (!ctrl_dev) {
pr_err("error could not get %s/%s %s ctrl dev\n",
info->ctrl_hid, info->ctrl_uid, info->ctrl_devname);
goto put_serdev_adev;
} }
serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev)); serdev = serdev_device_alloc(to_serdev_controller(ctrl_dev));
...@@ -283,8 +269,8 @@ static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int ...@@ -283,8 +269,8 @@ static __init int x86_instantiate_serdev(const struct x86_serdev_info *info, int
put_serdev_adev: put_serdev_adev:
acpi_dev_put(serdev_adev); acpi_dev_put(serdev_adev);
put_ctrl_adev: put_ctrl_dev:
acpi_dev_put(ctrl_adev); put_device(ctrl_dev);
return ret; return ret;
} }
......
...@@ -116,6 +116,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst ...@@ -116,6 +116,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
.trigger = ACPI_EDGE_SENSITIVE, .trigger = ACPI_EDGE_SENSITIVE,
.polarity = ACPI_ACTIVE_LOW, .polarity = ACPI_ACTIVE_LOW,
.con_id = "goodix_ts_irq", .con_id = "goodix_ts_irq",
.free_gpio = true,
}, },
}, { }, {
/* Wacom Digitizer in keyboard half */ /* Wacom Digitizer in keyboard half */
......
...@@ -68,7 +68,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst = ...@@ -68,7 +68,7 @@ static const struct x86_i2c_client_info acer_b1_750_i2c_clients[] __initconst =
}, },
}; };
static struct gpiod_lookup_table acer_b1_750_goodix_gpios = { static struct gpiod_lookup_table acer_b1_750_nvt_ts_gpios = {
.dev_id = "i2c-NVT-ts", .dev_id = "i2c-NVT-ts",
.table = { .table = {
GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW), GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW),
...@@ -77,7 +77,7 @@ static struct gpiod_lookup_table acer_b1_750_goodix_gpios = { ...@@ -77,7 +77,7 @@ static struct gpiod_lookup_table acer_b1_750_goodix_gpios = {
}; };
static struct gpiod_lookup_table * const acer_b1_750_gpios[] = { static struct gpiod_lookup_table * const acer_b1_750_gpios[] = {
&acer_b1_750_goodix_gpios, &acer_b1_750_nvt_ts_gpios,
&int3496_reference_gpios, &int3496_reference_gpios,
NULL NULL
}; };
......
...@@ -39,6 +39,7 @@ struct x86_acpi_irq_data { ...@@ -39,6 +39,7 @@ struct x86_acpi_irq_data {
int index; int index;
int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */ int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */ int polarity; /* ACPI_ACTIVE_HIGH / ACPI_ACTIVE_LOW / ACPI_ACTIVE_BOTH */
bool free_gpio; /* Release GPIO after getting IRQ (for TYPE_GPIOINT) */
const char *con_id; const char *con_id;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment