Re: [PATCH 3/5] platform/x86: x86-android-tablets: Add Lenovo Yoga Tablet 2 830 / 1050 data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Feb 23, 2022 at 02:31:51PM +0100, Hans de Goede wrote:
> The Lenovo Yoga Tablet 2 series comes in 4 versions: 830F, 830L, 1050F and
> 1050L. The F postfix indicates a wifi only version and the L postfix
> indicates a LTE version. The 830 models are 8" and the 1050 models are 10".
> 
> Despite there being 8" and 10" versions all models use the same mainboard,
> with an identical BIOS and thus identical DMI strings, so support for all
> 4 models is added through a single DMI table entry.
> 
> As all devices dealt with in the x86-android-tablets modules, these are
> x86 ACPI tablets which ships with Android x86 as factory OS.
> The mainboard's DSDT contain a bunch of I2C devices which are not actually
> there, causing various resource conflicts. Enumeration of these is skipped
> through the acpi_quirk_skip_i2c_client_enumeration().
> 
> Add support for manually instantiating the I2C devices which are
> actually present on this tablet by adding the necessary device info to
> the x86-android-tablets module.
> 
> This has been tested on a 830F and a 1050L tablet.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>

> Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx>
> ---
>  drivers/platform/x86/x86-android-tablets.c | 184 +++++++++++++++++++++
>  1 file changed, 184 insertions(+)
> 
> diff --git a/drivers/platform/x86/x86-android-tablets.c b/drivers/platform/x86/x86-android-tablets.c
> index 61e526e048c3..89972723f546 100644
> --- a/drivers/platform/x86/x86-android-tablets.c
> +++ b/drivers/platform/x86/x86-android-tablets.c
> @@ -22,8 +22,10 @@
>  #include <linux/irqdomain.h>
>  #include <linux/module.h>
>  #include <linux/mod_devicetable.h>
> +#include <linux/platform_data/lp855x.h>
>  #include <linux/platform_device.h>
>  #include <linux/power/bq24190_charger.h>
> +#include <linux/rmi.h>
>  #include <linux/serdev.h>
>  #include <linux/string.h>
>  /* For gpio_get_desc() which is EXPORT_SYMBOL_GPL() */
> @@ -182,6 +184,15 @@ static const char * const tusb1211_chg_det_psy[] = { "tusb1211-charger-detect" }
>  static const char * const bq24190_psy[] = { "bq24190-charger" };
>  static const char * const bq25890_psy[] = { "bq25890-charger" };
>  
> +static const struct property_entry fg_bq24190_supply_props[] = {
> +	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq24190_psy),
> +	{ }
> +};
> +
> +static const struct software_node fg_bq24190_supply_node = {
> +	.properties = fg_bq24190_supply_props,
> +};
> +
>  static const struct property_entry fg_bq25890_supply_props[] = {
>  	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", bq25890_psy),
>  	{ }
> @@ -704,6 +715,165 @@ static const struct x86_dev_info lenovo_yogabook_x9x_info __initconst = {
>  	.i2c_client_count = ARRAY_SIZE(lenovo_yogabook_x9x_i2c_clients),
>  };
>  
> +/* Lenovo Yoga Tablet 2 1050F/L's Android factory img has everything hardcoded */
> +static const struct property_entry lenovo_yoga_tab2_830_1050_bq24190_props[] = {
> +	PROPERTY_ENTRY_STRING_ARRAY("supplied-from", tusb1211_chg_det_psy),
> +	PROPERTY_ENTRY_REF("monitored-battery", &generic_lipo_hv_4v35_battery_node),
> +	PROPERTY_ENTRY_BOOL("omit-battery-class"),
> +	PROPERTY_ENTRY_BOOL("disable-reset"),
> +	{ }
> +};
> +
> +static const struct software_node lenovo_yoga_tab2_830_1050_bq24190_node = {
> +	.properties = lenovo_yoga_tab2_830_1050_bq24190_props,
> +};
> +
> +/* This gets filled by lenovo_yoga_tab2_830_1050_init() */
> +static struct rmi_device_platform_data lenovo_yoga_tab2_830_1050_rmi_pdata = { };
> +
> +static struct lp855x_platform_data lenovo_yoga_tab2_830_1050_lp8557_pdata = {
> +	.device_control = 0x86,
> +	.initial_brightness = 128,
> +};
> +
> +static const struct x86_i2c_client_info lenovo_yoga_tab2_830_1050_i2c_clients[] __initconst = {
> +	{
> +		/* bq24292i battery charger */
> +		.board_info = {
> +			.type = "bq24190",
> +			.addr = 0x6b,
> +			.dev_name = "bq24292i",
> +			.swnode = &lenovo_yoga_tab2_830_1050_bq24190_node,
> +			.platform_data = &bq24190_pdata,
> +		},
> +		.adapter_path = "\\_SB_.I2C1",
> +		.irq_data = {
> +			.type = X86_ACPI_IRQ_TYPE_GPIOINT,
> +			.chip = "INT33FC:02",
> +			.index = 2,
> +			.trigger = ACPI_EDGE_SENSITIVE,
> +			.polarity = ACPI_ACTIVE_HIGH,
> +		},
> +	}, {
> +		/* BQ27541 fuel-gauge */
> +		.board_info = {
> +			.type = "bq27541",
> +			.addr = 0x55,
> +			.dev_name = "bq27541",
> +			.swnode = &fg_bq24190_supply_node,
> +		},
> +		.adapter_path = "\\_SB_.I2C1",
> +	}, {
> +		/* Synaptics RMI touchscreen */
> +		.board_info = {
> +			.type = "rmi4_i2c",
> +			.addr = 0x38,
> +			.dev_name = "rmi4_i2c",
> +			.platform_data = &lenovo_yoga_tab2_830_1050_rmi_pdata,
> +		},
> +		.adapter_path = "\\_SB_.I2C6",
> +		.irq_data = {
> +			.type = X86_ACPI_IRQ_TYPE_APIC,
> +			.index = 0x45,
> +			.trigger = ACPI_EDGE_SENSITIVE,
> +			.polarity = ACPI_ACTIVE_HIGH,
> +		},
> +	}, {
> +		/* LP8557 Backlight controller */
> +		.board_info = {
> +			.type = "lp8557",
> +			.addr = 0x2c,
> +			.dev_name = "lp8557",
> +			.platform_data = &lenovo_yoga_tab2_830_1050_lp8557_pdata,
> +		},
> +		.adapter_path = "\\_SB_.I2C3",
> +	},
> +};
> +
> +static struct gpiod_lookup_table lenovo_yoga_tab2_830_1050_int3496_gpios = {
> +	.dev_id = "intel-int3496",
> +	.table = {
> +		GPIO_LOOKUP("INT33FC:02", 1, "mux", GPIO_ACTIVE_LOW),
> +		GPIO_LOOKUP("INT33FC:02", 24, "id", GPIO_ACTIVE_HIGH),
> +		{ }
> +	},
> +};
> +
> +static struct gpiod_lookup_table * const lenovo_yoga_tab2_830_1050_gpios[] = {
> +	&lenovo_yoga_tab2_830_1050_int3496_gpios,
> +	NULL
> +};
> +
> +static int __init lenovo_yoga_tab2_830_1050_init(void);
> +static void lenovo_yoga_tab2_830_1050_exit(void);
> +
> +static struct x86_dev_info lenovo_yoga_tab2_830_1050_info __initdata = {
> +	.i2c_client_info = lenovo_yoga_tab2_830_1050_i2c_clients,
> +	/* i2c_client_count gets set by lenovo_yoga_tab2_830_1050_init() */
> +	.pdev_info = int3496_pdevs,
> +	.pdev_count = ARRAY_SIZE(int3496_pdevs),
> +	.gpiod_lookup_tables = lenovo_yoga_tab2_830_1050_gpios,
> +	.bat_swnode = &generic_lipo_hv_4v35_battery_node,
> +	.modules = bq24190_modules,
> +	.invalid_aei_gpiochip = "INT33FC:02",
> +	.init = lenovo_yoga_tab2_830_1050_init,
> +};
> +
> +/*
> + * The Lenovo Yoga Tablet 2 830 and 1050 (8" vs 10") versions use the same
> + * mainboard, but they need some different treatment related to the display:
> + * 1. The 830 uses a portrait LCD panel with a landscape touchscreen, requiring
> + *    the touchscreen driver to adjust the touch-coords to match the LCD.
> + * 2. Both use an TI LP8557 LED backlight controller. On the 1050 the LP8557's
> + *    PWM input is connected to the PMIC's PWM output and everything works fine
> + *    with the defaults programmed into the LP8557 by the BIOS.
> + *    But on the 830 the LP8557's PWM input is connected to a PWM output coming
> + *    from the LCD panel's controller. The Android code has a hack in the i915
> + *    driver to write the non-standard DSI reg 0x9f with the desired backlight
> + *    level to set the duty-cycle of the LCD's PWM output.
> + *
> + *    To avoid having to have a similar hack in the mainline kernel the LP8557
> + *    entry in lenovo_yoga_tab2_830_1050_i2c_clients instead just programs the
> + *    LP8557 to directly set the level, ignoring the PWM input. This means that
> + *    the LP8557 i2c_client should only be instantiated on the 830.
> + */
> +static int __init lenovo_yoga_tab2_830_1050_init_display(void)
> +{
> +	struct gpio_desc *gpiod;
> +	int ret;
> +
> +	/* Use PMIC GPIO 10 bootstrap pin to differentiate 830 vs 1050 */
> +	ret = x86_android_tablet_get_gpiod("gpio_crystalcove", 10, &gpiod);
> +	if (ret)
> +		return ret;
> +
> +	ret = gpiod_get_value_cansleep(gpiod);
> +	if (ret) {
> +		pr_info("detected Lenovo Yoga Tablet 2 1050F/L\n");
> +		lenovo_yoga_tab2_830_1050_info.i2c_client_count =
> +			ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients) - 1;
> +	} else {
> +		pr_info("detected Lenovo Yoga Tablet 2 830F/L\n");
> +		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.swap_axes = true;
> +		lenovo_yoga_tab2_830_1050_rmi_pdata.sensor_pdata.axis_align.flip_y = true;
> +		lenovo_yoga_tab2_830_1050_info.i2c_client_count =
> +			ARRAY_SIZE(lenovo_yoga_tab2_830_1050_i2c_clients);
> +	}
> +
> +	return 0;
> +}
> +
> +static int __init lenovo_yoga_tab2_830_1050_init(void)
> +{
> +	int ret;
> +
> +	ret = lenovo_yoga_tab2_830_1050_init_display();
> +	if (ret)
> +		return ret;
> +
> +	return 0;
> +}
> +
>  /* Nextbook Ares 8 tablets have an Android factory img with everything hardcoded */
>  static const char * const nextbook_ares8_accel_mount_matrix[] = {
>  	"0", "-1", "0",
> @@ -948,6 +1118,20 @@ static const struct dmi_system_id x86_android_tablet_ids[] __initconst = {
>  		},
>  		.driver_data = (void *)&lenovo_yogabook_x9x_info,
>  	},
> +	{
> +		/*
> +		 * Lenovo Yoga Tablet 2 830F/L or 1050F/L (The 8" and 10"
> +		 * Lenovo Yoga Tablet 2 use the same mainboard)
> +		 */
> +		.matches = {
> +			DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."),
> +			DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"),
> +			DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"),
> +			/* Partial match on beginning of BIOS version */
> +			DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"),
> +		},
> +		.driver_data = (void *)&lenovo_yoga_tab2_830_1050_info,
> +	},
>  	{
>  		/* Nextbook Ares 8 */
>  		.matches = {
> -- 
> 2.35.1
> 

-- 
With Best Regards,
Andy Shevchenko





[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux