diff options
Diffstat (limited to 'drivers/platform/x86/x86-android-tablets')
-rw-r--r-- | drivers/platform/x86/x86-android-tablets/Kconfig | 4 | ||||
-rw-r--r-- | drivers/platform/x86/x86-android-tablets/core.c | 60 | ||||
-rw-r--r-- | drivers/platform/x86/x86-android-tablets/dmi.c | 10 | ||||
-rw-r--r-- | drivers/platform/x86/x86-android-tablets/other.c | 163 | ||||
-rw-r--r-- | drivers/platform/x86/x86-android-tablets/x86-android-tablets.h | 2 |
5 files changed, 229 insertions, 10 deletions
diff --git a/drivers/platform/x86/x86-android-tablets/Kconfig b/drivers/platform/x86/x86-android-tablets/Kconfig index 88d9e8f2ff24..a67bddc43007 100644 --- a/drivers/platform/x86/x86-android-tablets/Kconfig +++ b/drivers/platform/x86/x86-android-tablets/Kconfig @@ -5,7 +5,9 @@ config X86_ANDROID_TABLETS tristate "X86 Android tablet support" - depends on I2C && SPI && SERIAL_DEV_BUS && ACPI && EFI && GPIOLIB && PMIC_OPREGION + depends on I2C && SPI && SERIAL_DEV_BUS + depends on GPIOLIB && PMIC_OPREGION + depends on ACPI && EFI && PCI select NEW_LEDS select LEDS_CLASS help diff --git a/drivers/platform/x86/x86-android-tablets/core.c b/drivers/platform/x86/x86-android-tablets/core.c index ef572b90e06b..4218afcec0e9 100644 --- a/drivers/platform/x86/x86-android-tablets/core.c +++ b/drivers/platform/x86/x86-android-tablets/core.c @@ -11,11 +11,13 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/acpi.h> +#include <linux/device.h> #include <linux/dmi.h> #include <linux/gpio/consumer.h> #include <linux/gpio/machine.h> #include <linux/irq.h> #include <linux/module.h> +#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/serdev.h> #include <linux/string.h> @@ -155,26 +157,66 @@ static struct gpiod_lookup_table * const *gpiod_lookup_tables; static const struct software_node *bat_swnode; static void (*exit_handler)(void); +static struct i2c_adapter * +get_i2c_adap_by_handle(const struct x86_i2c_client_info *client_info) +{ + acpi_handle handle; + acpi_status status; + + status = acpi_get_handle(NULL, client_info->adapter_path, &handle); + if (ACPI_FAILURE(status)) { + pr_err("Error could not get %s handle\n", client_info->adapter_path); + return NULL; + } + + return i2c_acpi_find_adapter_by_handle(handle); +} + +static __init int match_parent(struct device *dev, const void *data) +{ + return dev->parent == data; +} + +static struct i2c_adapter * +get_i2c_adap_by_pci_parent(const struct x86_i2c_client_info *client_info) +{ + struct i2c_adapter *adap = NULL; + struct device *pdev, *adap_dev; + + pdev = bus_find_device_by_name(&pci_bus_type, NULL, client_info->adapter_path); + if (!pdev) { + pr_err("Error could not find %s PCI device\n", client_info->adapter_path); + return NULL; + } + + adap_dev = bus_find_device(&i2c_bus_type, NULL, pdev, match_parent); + if (adap_dev) { + adap = i2c_verify_adapter(adap_dev); + if (!adap) + put_device(adap_dev); + } + + put_device(pdev); + + return adap; +} + static __init int x86_instantiate_i2c_client(const struct x86_dev_info *dev_info, int idx) { const struct x86_i2c_client_info *client_info = &dev_info->i2c_client_info[idx]; struct i2c_board_info board_info = client_info->board_info; struct i2c_adapter *adap; - acpi_handle handle; - acpi_status status; board_info.irq = x86_acpi_irq_helper_get(&client_info->irq_data); if (board_info.irq < 0) return board_info.irq; - status = acpi_get_handle(NULL, client_info->adapter_path, &handle); - if (ACPI_FAILURE(status)) { - pr_err("Error could not get %s handle\n", client_info->adapter_path); - return -ENODEV; - } + if (dev_info->use_pci_devname) + adap = get_i2c_adap_by_pci_parent(client_info); + else + adap = get_i2c_adap_by_handle(client_info); - adap = i2c_acpi_find_adapter_by_handle(handle); if (!adap) { pr_err("error could not get %s adapter\n", client_info->adapter_path); return -ENODEV; @@ -458,7 +500,7 @@ static struct platform_driver x86_android_tablet_driver = { .driver = { .name = KBUILD_MODNAME, }, - .remove_new = x86_android_tablet_remove, + .remove = x86_android_tablet_remove, }; static int __init x86_android_tablet_init(void) diff --git a/drivers/platform/x86/x86-android-tablets/dmi.c b/drivers/platform/x86/x86-android-tablets/dmi.c index 17f6da96aa01..3e5fa3b6e2fd 100644 --- a/drivers/platform/x86/x86-android-tablets/dmi.c +++ b/drivers/platform/x86/x86-android-tablets/dmi.c @@ -180,6 +180,16 @@ const struct dmi_system_id x86_android_tablet_ids[] __initconst = { .driver_data = (void *)&peaq_c1010_info, }, { + /* Vexia Edu Atla 10 tablet 9V version */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Above strings are too generic, also match on BIOS date */ + DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"), + }, + .driver_data = (void *)&vexia_edu_atla10_info, + }, + { /* Whitelabel (sold as various brands) TM800A550L */ .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), diff --git a/drivers/platform/x86/x86-android-tablets/other.c b/drivers/platform/x86/x86-android-tablets/other.c index 7db8aa58b907..725948044da4 100644 --- a/drivers/platform/x86/x86-android-tablets/other.c +++ b/drivers/platform/x86/x86-android-tablets/other.c @@ -12,6 +12,7 @@ #include <linux/gpio/machine.h> #include <linux/input.h> #include <linux/leds.h> +#include <linux/pci.h> #include <linux/platform_device.h> #include <linux/pwm.h> @@ -598,6 +599,168 @@ const struct x86_dev_info whitelabel_tm800a550l_info __initconst = { }; /* + * Vexia EDU ATLA 10 tablet, Android 4.2 / 4.4 + Guadalinex Ubuntu tablet + * distributed to schools in the Spanish AndalucĂa region. + */ +const char * const crystal_cove_pwrsrc_psy[] = { "crystal_cove_pwrsrc" }; + +static const struct property_entry vexia_edu_atla10_ulpmc_props[] = { + PROPERTY_ENTRY_STRING_ARRAY("supplied-from", crystal_cove_pwrsrc_psy), + { } +}; + +const struct software_node vexia_edu_atla10_ulpmc_node = { + .properties = vexia_edu_atla10_ulpmc_props, +}; + +static const char * const vexia_edu_atla10_accel_mount_matrix[] = { + "0", "-1", "0", + "1", "0", "0", + "0", "0", "1" +}; + +static const struct property_entry vexia_edu_atla10_accel_props[] = { + PROPERTY_ENTRY_STRING_ARRAY("mount-matrix", vexia_edu_atla10_accel_mount_matrix), + { } +}; + +static const struct software_node vexia_edu_atla10_accel_node = { + .properties = vexia_edu_atla10_accel_props, +}; + +static const struct property_entry vexia_edu_atla10_touchscreen_props[] = { + PROPERTY_ENTRY_U32("hid-descr-addr", 0x0000), + PROPERTY_ENTRY_U32("post-reset-deassert-delay-ms", 120), + { } +}; + +static const struct software_node vexia_edu_atla10_touchscreen_node = { + .properties = vexia_edu_atla10_touchscreen_props, +}; + +static const struct property_entry vexia_edu_atla10_pmic_props[] = { + PROPERTY_ENTRY_BOOL("linux,register-pwrsrc-power_supply"), + { } +}; + +static const struct software_node vexia_edu_atla10_pmic_node = { + .properties = vexia_edu_atla10_pmic_props, +}; + +static const struct x86_i2c_client_info vexia_edu_atla10_i2c_clients[] __initconst = { + { + /* I2C attached embedded controller, used to access fuel-gauge */ + .board_info = { + .type = "vexia_atla10_ec", + .addr = 0x76, + .dev_name = "ulpmc", + .swnode = &vexia_edu_atla10_ulpmc_node, + }, + .adapter_path = "0000:00:18.1", + }, { + /* RT5642 audio codec */ + .board_info = { + .type = "rt5640", + .addr = 0x1c, + .dev_name = "rt5640", + }, + .adapter_path = "0000:00:18.2", + .irq_data = { + .type = X86_ACPI_IRQ_TYPE_GPIOINT, + .chip = "INT33FC:02", + .index = 4, + .trigger = ACPI_EDGE_SENSITIVE, + .polarity = ACPI_ACTIVE_HIGH, + .con_id = "rt5640_irq", + }, + }, { + /* kxtj21009 accelerometer */ + .board_info = { + .type = "kxtj21009", + .addr = 0x0f, + .dev_name = "kxtj21009", + .swnode = &vexia_edu_atla10_accel_node, + }, + .adapter_path = "0000:00:18.5", + }, { + /* FT5416DQ9 touchscreen controller */ + .board_info = { + .type = "hid-over-i2c", + .addr = 0x38, + .dev_name = "FTSC1000", + .swnode = &vexia_edu_atla10_touchscreen_node, + }, + .adapter_path = "0000:00:18.6", + .irq_data = { + .type = X86_ACPI_IRQ_TYPE_APIC, + .index = 0x45, + .trigger = ACPI_LEVEL_SENSITIVE, + .polarity = ACPI_ACTIVE_HIGH, + }, + }, { + /* Crystal Cove PMIC */ + .board_info = { + .type = "intel_soc_pmic_crc", + .addr = 0x6e, + .dev_name = "intel_soc_pmic_crc", + .swnode = &vexia_edu_atla10_pmic_node, + }, + .adapter_path = "0000:00:18.7", + .irq_data = { + .type = X86_ACPI_IRQ_TYPE_APIC, + .index = 0x43, + .trigger = ACPI_LEVEL_SENSITIVE, + .polarity = ACPI_ACTIVE_HIGH, + }, + } +}; + +static struct gpiod_lookup_table vexia_edu_atla10_ft5416_gpios = { + .dev_id = "i2c-FTSC1000", + .table = { + GPIO_LOOKUP("INT33FC:00", 60, "reset", GPIO_ACTIVE_LOW), + { } + }, +}; + +static struct gpiod_lookup_table * const vexia_edu_atla10_gpios[] = { + &vexia_edu_atla10_ft5416_gpios, + NULL +}; + +static int __init vexia_edu_atla10_init(struct device *dev) +{ + struct pci_dev *pdev; + int ret; + + /* Enable the Wifi module by setting the wifi_enable pin to 1 */ + ret = x86_android_tablet_get_gpiod("INT33FC:02", 20, "wifi_enable", + false, GPIOD_OUT_HIGH, NULL); + if (ret) + return ret; + + /* Reprobe the SDIO controller to enumerate the now enabled Wifi module */ + pdev = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x11, 0)); + if (!pdev) + return -EPROBE_DEFER; + + ret = device_reprobe(&pdev->dev); + if (ret) + pci_warn(pdev, "Reprobing error: %d\n", ret); + + pci_dev_put(pdev); + return 0; +} + +const struct x86_dev_info vexia_edu_atla10_info __initconst = { + .i2c_client_info = vexia_edu_atla10_i2c_clients, + .i2c_client_count = ARRAY_SIZE(vexia_edu_atla10_i2c_clients), + .gpiod_lookup_tables = vexia_edu_atla10_gpios, + .init = vexia_edu_atla10_init, + .use_pci_devname = true, +}; + +/* * The firmware node for ktd2026 on Xaomi pad2. It composed of a RGB LED node * with three subnodes for each color (B/G/R). The RGB LED node is named * "multi-led" to align with the name in the device tree. diff --git a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h index 5517e438c7b6..0fc7e8cff672 100644 --- a/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h +++ b/drivers/platform/x86/x86-android-tablets/x86-android-tablets.h @@ -91,6 +91,7 @@ struct x86_dev_info { int gpio_button_count; int (*init)(struct device *dev); void (*exit)(void); + bool use_pci_devname; }; int x86_android_tablet_get_gpiod(const char *chip, int pin, const char *con_id, @@ -119,6 +120,7 @@ extern const struct x86_dev_info nextbook_ares8_info; extern const struct x86_dev_info nextbook_ares8a_info; extern const struct x86_dev_info peaq_c1010_info; extern const struct x86_dev_info whitelabel_tm800a550l_info; +extern const struct x86_dev_info vexia_edu_atla10_info; extern const struct x86_dev_info xiaomi_mipad2_info; extern const struct dmi_system_id x86_android_tablet_ids[]; |