platform-drivers-x86 for v6.8-4
Highlights: - Fix P2SB regression causing ACPI errors and high CPU load - Fix error return path in amd_pmf_init_smart_pc() The following is an automated git shortlog grouped by driver: p2sb: - On Goldmont only cache P2SB and SPI devfn BAR platform/x86/amd/pmf: - Fix missing error code in amd_pmf_init_smart_pc() -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEEuvA7XScYQRpenhd+kuxHeUQDJ9wFAmXm5sIUHGhkZWdvZWRl QHJlZGhhdC5jb20ACgkQkuxHeUQDJ9ziBgf8DrSSHfwsLseOV0wqzv2ewn0/YwGD 0/KUWoEe8Q6RYU2iFPj912r3ky2qtA5I4ZUJXLcD6lTL23FzdOagsJMEr0iwPC5s p1nnNCsVChkZvyU6BOvPa8m7W9Od0FY2RnNqtGhC8x9hsnhWOVDW4yG0n7tC+gbN 3tNqUZDpPotY8jZhpO7kazVHS0gTbYw6ABOvaz73FcDjdfM0TnkVOjDy7+1CGH7t wSIo9bQvGvjXqjXk8NQg0GtQt1qZiwpbCycmkJEYXXMnx1HEkdi/UClW74CX2wmr YknM05A2hLBLSmHCyODjZnZ3689ODx4nv4H6226Az8B6dW8j81dmIQEPzQ== =8CgQ -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iHUEABYIAB0WIQSCSUwRdwTNL2MhaBlZrE9hU+XOMQUCZfAzvAAKCRBZrE9hU+XO MUOLAQDJIFvGoq6PZZ89ooX/6n1NmMS1Uz/MmXygOMGzjqH2KQEA7/5JdgQ5ZaMD Uy2lSkSk9K9PzMTuTAG3TcSUEuQrggo= =0QK+ -----END PGP SIGNATURE----- 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.
This commit is contained in:
commit
1c0a50de02
@ -297,7 +297,8 @@ static int amd_pmf_suspend_handler(struct device *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))
|
||||
amd_pmf_notify_sbios_heartbeat_event_v2(pdev, ON_SUSPEND);
|
||||
@ -319,6 +320,9 @@ static int amd_pmf_resume_handler(struct device *dev)
|
||||
if (is_apmf_func_supported(pdev, APMF_FUNC_SBIOS_HEARTBEAT_V2))
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
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");
|
||||
} 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);
|
||||
dev_dbg(dev->dev, "Auto Mode Init done\n");
|
||||
} 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)
|
||||
amd_pmf_deinit_sps(dev);
|
||||
}
|
||||
|
||||
if (!dev->smart_pc_enabled) {
|
||||
if (dev->smart_pc_enabled) {
|
||||
amd_pmf_deinit_smart_pc(dev);
|
||||
} else if (is_apmf_func_supported(dev, APMF_FUNC_AUTO_MODE)) {
|
||||
amd_pmf_deinit_auto_mode(dev);
|
||||
|
@ -524,11 +524,6 @@ struct apmf_dyn_slider_output {
|
||||
struct apmf_cnqf_power_set ps[APMF_CNQF_MAX];
|
||||
} __packed;
|
||||
|
||||
enum smart_pc_status {
|
||||
PMF_SMART_PC_ENABLED,
|
||||
PMF_SMART_PC_DISABLED,
|
||||
};
|
||||
|
||||
/* Smart PC - TA internals */
|
||||
enum system_state {
|
||||
SYSTEM_STATE_S0i3,
|
||||
|
@ -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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (dev->policy_sz < header->length + 512)
|
||||
return -EINVAL;
|
||||
@ -265,7 +267,7 @@ static int amd_pmf_start_policy_engine(struct amd_pmf_dev *dev)
|
||||
res = amd_pmf_invoke_cmd_init(dev);
|
||||
if (res == TA_PMF_TYPE_SUCCESS) {
|
||||
/* 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
|
||||
* 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)
|
||||
schedule_delayed_work(&dev->pb_work, msecs_to_jiffies(pb_actions_ms * 3));
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -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) {}
|
||||
#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)
|
||||
{
|
||||
return ver->impl_id == TEE_IMPL_ID_AMDTEE;
|
||||
@ -458,22 +441,59 @@ int amd_pmf_init_smart_pc(struct amd_pmf_dev *dev)
|
||||
return ret;
|
||||
|
||||
INIT_DELAYED_WORK(&dev->pb_work, amd_pmf_invoke_cmd);
|
||||
amd_pmf_set_dram_addr(dev, true);
|
||||
amd_pmf_get_bios_buffer(dev);
|
||||
dev->prev_data = kzalloc(sizeof(*dev->prev_data), GFP_KERNEL);
|
||||
if (!dev->prev_data)
|
||||
return -ENOMEM;
|
||||
|
||||
return dev->smart_pc_enabled;
|
||||
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);
|
||||
if (!dev->prev_data) {
|
||||
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;
|
||||
|
||||
error:
|
||||
amd_pmf_deinit_smart_pc(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
kfree(dev->prev_data);
|
||||
kfree(dev->policy_buf);
|
||||
cancel_delayed_work_sync(&dev->pb_work);
|
||||
kfree(dev->prev_data);
|
||||
dev->prev_data = NULL;
|
||||
kfree(dev->policy_buf);
|
||||
dev->policy_buf = NULL;
|
||||
kfree(dev->buf);
|
||||
dev->buf = NULL;
|
||||
amd_pmf_tee_deinit(dev);
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ static int int0002_probe(struct platform_device *pdev)
|
||||
* IRQs into gpiolib.
|
||||
*/
|
||||
ret = devm_request_irq(dev, irq, int0002_irq,
|
||||
IRQF_SHARED, "INT0002", chip);
|
||||
IRQF_ONESHOT | IRQF_SHARED, "INT0002", chip);
|
||||
if (ret) {
|
||||
dev_err(dev, "Error requesting IRQ %d: %d\n", irq, ret);
|
||||
return ret;
|
||||
|
@ -200,9 +200,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
|
||||
autorelease = val && (!ke_rel || ke_rel->type == KE_IGNORE);
|
||||
|
||||
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 @@
|
||||
#define P2SBC_HIDE BIT(8)
|
||||
|
||||
#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[] = {
|
||||
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)
|
||||
|
||||
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) {
|
||||
/*
|
||||
* When function number of the P2SB device is zero, scan it and
|
||||
* other function numbers, and if devices are available, cache
|
||||
* 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);
|
||||
}
|
||||
/* On Goldmont p2sb_bar() also gets called for the SPI controller */
|
||||
if (devfn == P2SB_DEVFN_GOLDMONT)
|
||||
p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT);
|
||||
|
||||
if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res))
|
||||
return -ENOENT;
|
||||
|
80
drivers/platform/x86/serdev_helpers.h
Normal file
80
drivers/platform/x86/serdev_helpers.h
Normal file
@ -0,0 +1,80 @@
|
||||
/* 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,
|
||||
* Note - this sets the variable and then the password as separate
|
||||
* WMI calls. Function tlmi_save_bios_settings will error if the
|
||||
* 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,
|
||||
new_setting);
|
||||
if (!set_str) {
|
||||
@ -1021,17 +1030,10 @@ static ssize_t current_value_store(struct kobject *kobj,
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
if (tlmi_priv.save_mode == TLMI_SAVE_BULK) {
|
||||
if (tlmi_priv.save_mode == TLMI_SAVE_BULK)
|
||||
tlmi_priv.save_required = true;
|
||||
} 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;
|
||||
}
|
||||
else
|
||||
ret = tlmi_save_bios_settings("");
|
||||
}
|
||||
} else { /* old non-opcode based authentication method (deprecated) */
|
||||
if (tlmi_priv.pwd_admin->valid && tlmi_priv.pwd_admin->password[0]) {
|
||||
auth_str = kasprintf(GFP_KERNEL, "%s,%s,%s;",
|
||||
|
@ -10379,6 +10379,7 @@ static int convert_dytc_to_profile(int funcmode, int dytcmode,
|
||||
return 0;
|
||||
default:
|
||||
/* Unknown function */
|
||||
pr_debug("unknown function 0x%x\n", funcmode);
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
return 0;
|
||||
@ -10564,8 +10565,8 @@ static void dytc_profile_refresh(void)
|
||||
return;
|
||||
|
||||
perfmode = (output >> DYTC_GET_MODE_BIT) & 0xF;
|
||||
convert_dytc_to_profile(funcmode, perfmode, &profile);
|
||||
if (profile != dytc_current_profile) {
|
||||
err = convert_dytc_to_profile(funcmode, perfmode, &profile);
|
||||
if (!err && profile != dytc_current_profile) {
|
||||
dytc_current_profile = profile;
|
||||
platform_profile_notify();
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ static const struct property_entry chuwi_hi8_air_props[] = {
|
||||
};
|
||||
|
||||
static const struct ts_dmi_data chuwi_hi8_air_data = {
|
||||
.acpi_name = "MSSL1680:00",
|
||||
.acpi_name = "MSSL1680",
|
||||
.properties = chuwi_hi8_air_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 = {
|
||||
.acpi_name = "GDIX1001:00",
|
||||
static const struct ts_dmi_data gdix1001_upside_down_data = {
|
||||
.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,
|
||||
};
|
||||
|
||||
static const struct ts_dmi_data gdix1002_00_upside_down_data = {
|
||||
.acpi_name = "GDIX1002:00",
|
||||
static const struct ts_dmi_data gdix1002_upside_down_data = {
|
||||
.acpi_name = "GDIX1002",
|
||||
.properties = gdix1001_upside_down_props,
|
||||
};
|
||||
|
||||
@ -1421,7 +1416,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* Juno Tablet */
|
||||
.driver_data = (void *)&gdix1002_00_upside_down_data,
|
||||
.driver_data = (void *)&gdix1002_upside_down_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "Default string"),
|
||||
/* Both product- and board-name being "Default string" is somewhat rare */
|
||||
@ -1667,7 +1662,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* Teclast X89 (Android version / BIOS) */
|
||||
.driver_data = (void *)&gdix1001_00_upside_down_data,
|
||||
.driver_data = (void *)&gdix1001_upside_down_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "WISKY"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "3G062i"),
|
||||
@ -1675,7 +1670,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* Teclast X89 (Windows version / BIOS) */
|
||||
.driver_data = (void *)&gdix1001_01_upside_down_data,
|
||||
.driver_data = (void *)&gdix1001_upside_down_data,
|
||||
.matches = {
|
||||
/* tPAD is too generic, also match on bios date */
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"),
|
||||
@ -1693,7 +1688,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* Teclast X98 Pro */
|
||||
.driver_data = (void *)&gdix1001_00_upside_down_data,
|
||||
.driver_data = (void *)&gdix1001_upside_down_data,
|
||||
.matches = {
|
||||
/*
|
||||
* Only match BIOS date, because the manufacturers
|
||||
@ -1797,7 +1792,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* "WinBook TW100" */
|
||||
.driver_data = (void *)&gdix1001_00_upside_down_data,
|
||||
.driver_data = (void *)&gdix1001_upside_down_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TW100")
|
||||
@ -1805,7 +1800,7 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
|
||||
},
|
||||
{
|
||||
/* WinBook TW700 */
|
||||
.driver_data = (void *)&gdix1001_00_upside_down_data,
|
||||
.driver_data = (void *)&gdix1001_upside_down_data,
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "WinBook"),
|
||||
DMI_MATCH(DMI_PRODUCT_NAME, "TW700")
|
||||
@ -1830,7 +1825,7 @@ static void ts_dmi_add_props(struct i2c_client *client)
|
||||
int error;
|
||||
|
||||
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);
|
||||
if (error)
|
||||
dev_err(dev, "failed to add properties: %d\n", error);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <linux/string.h>
|
||||
|
||||
#include "x86-android-tablets.h"
|
||||
#include "../serdev_helpers.h"
|
||||
|
||||
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)
|
||||
if (irq_type != IRQ_TYPE_NONE && irq_type != irq_get_trigger_type(irq))
|
||||
irq_set_irq_type(irq, irq_type);
|
||||
|
||||
if (data->free_gpio)
|
||||
devm_gpiod_put(&x86_android_tablet_device->dev, gpiod);
|
||||
|
||||
return irq;
|
||||
case X86_ACPI_IRQ_TYPE_PMIC:
|
||||
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
|
||||
|
||||
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 device *ctrl_dev;
|
||||
int ret = -ENODEV;
|
||||
|
||||
ctrl_adev = acpi_dev_get_first_match_dev(info->ctrl_hid, info->ctrl_uid, -1);
|
||||
if (!ctrl_adev) {
|
||||
pr_err("error could not get %s/%s ctrl adev\n",
|
||||
info->ctrl_hid, info->ctrl_uid);
|
||||
return -ENODEV;
|
||||
}
|
||||
ctrl_dev = get_serdev_controller(info->ctrl_hid, info->ctrl_uid, 0,
|
||||
info->ctrl_devname);
|
||||
if (IS_ERR(ctrl_dev))
|
||||
return PTR_ERR(ctrl_dev);
|
||||
|
||||
serdev_adev = acpi_dev_get_first_match_dev(info->serdev_hid, NULL, -1);
|
||||
if (!serdev_adev) {
|
||||
pr_err("error could not get %s serdev adev\n", info->serdev_hid);
|
||||
goto put_ctrl_adev;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
goto put_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
|
||||
|
||||
put_serdev_adev:
|
||||
acpi_dev_put(serdev_adev);
|
||||
put_ctrl_adev:
|
||||
acpi_dev_put(ctrl_adev);
|
||||
put_ctrl_dev:
|
||||
put_device(ctrl_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,7 @@ static const struct x86_i2c_client_info lenovo_yb1_x90_i2c_clients[] __initconst
|
||||
.trigger = ACPI_EDGE_SENSITIVE,
|
||||
.polarity = ACPI_ACTIVE_LOW,
|
||||
.con_id = "goodix_ts_irq",
|
||||
.free_gpio = true,
|
||||
},
|
||||
}, {
|
||||
/* Wacom Digitizer in keyboard half */
|
||||
|
@ -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",
|
||||
.table = {
|
||||
GPIO_LOOKUP("INT33FC:01", 26, "reset", GPIO_ACTIVE_LOW),
|
||||
@ -77,7 +77,7 @@ static struct gpiod_lookup_table acer_b1_750_goodix_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,
|
||||
NULL
|
||||
};
|
||||
|
@ -39,6 +39,7 @@ struct x86_acpi_irq_data {
|
||||
int index;
|
||||
int trigger; /* ACPI_EDGE_SENSITIVE / ACPI_LEVEL_SENSITIVE */
|
||||
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;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user