Commit 27e8527e authored by Hans de Goede's avatar Hans de Goede Committed by Marcel Holtmann
Browse files

Bluetooth: hci_bcm: Add the Asus TF103C to the bcm_broken_irq_dmi_table



The DSDT for the Asus TF103C specifies a IOAPIC IRQ for the HCI -> host IRQ
but this is not correct. Unlike the previous entries in the table, this
time the correct GPIO to use instead is known; and the TF103C is battery
powered making runtime-pm support more important.

Extend the bcm_broken_irq_dmi_table mechanism to allow specifying the right
GPIO instead of just always disabling runtime-pm and add an entry to it for
the Asus TF103C.

Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 5ad80cfc
Loading
Loading
Loading
Loading
+36 −8
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@
#include <linux/regulator/consumer.h>
#include <linux/clk.h>
#include <linux/gpio/consumer.h>
#include <linux/gpio/machine.h>
#include <linux/tty.h>
#include <linux/interrupt.h>
#include <linux/dmi.h>
@@ -870,7 +871,23 @@ static int bcm_resume(struct device *dev)
#endif

/* Some firmware reports an IRQ which does not work (wrong pin in fw table?) */
static struct gpiod_lookup_table asus_tf103c_irq_gpios = {
	.dev_id = "serial0-0",
	.table = {
		GPIO_LOOKUP("INT33FC:02", 17, "host-wakeup-alt", GPIO_ACTIVE_HIGH),
		{ }
	},
};

static const struct dmi_system_id bcm_broken_irq_dmi_table[] = {
	{
		.ident = "Asus TF103C",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
			DMI_MATCH(DMI_PRODUCT_NAME, "TF103C"),
		},
		.driver_data = &asus_tf103c_irq_gpios,
	},
	{
		.ident = "Meegopad T08",
		.matches = {
@@ -1027,7 +1044,8 @@ static struct clk *bcm_get_txco(struct device *dev)

static int bcm_get_resources(struct bcm_device *dev)
{
	const struct dmi_system_id *dmi_id;
	const struct dmi_system_id *broken_irq_dmi_id;
	const char *irq_con_id = "host-wakeup";
	int err;

	dev->name = dev_name(dev->dev);
@@ -1083,24 +1101,34 @@ static int bcm_get_resources(struct bcm_device *dev)
	if (err)
		return err;

	broken_irq_dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
	if (broken_irq_dmi_id && broken_irq_dmi_id->driver_data) {
		gpiod_add_lookup_table(broken_irq_dmi_id->driver_data);
		irq_con_id = "host-wakeup-alt";
		dev->irq_active_low = false;
		dev->irq = 0;
	}

	/* IRQ can be declared in ACPI table as Interrupt or GpioInt */
	if (dev->irq <= 0) {
		struct gpio_desc *gpio;

		gpio = devm_gpiod_get_optional(dev->dev, "host-wakeup",
					       GPIOD_IN);
		gpio = devm_gpiod_get_optional(dev->dev, irq_con_id, GPIOD_IN);
		if (IS_ERR(gpio))
			return PTR_ERR(gpio);

		dev->irq = gpiod_to_irq(gpio);
	}

	dmi_id = dmi_first_match(bcm_broken_irq_dmi_table);
	if (dmi_id) {
	if (broken_irq_dmi_id) {
		if (broken_irq_dmi_id->driver_data) {
			gpiod_remove_lookup_table(broken_irq_dmi_id->driver_data);
		} else {
			dev_info(dev->dev, "%s: Has a broken IRQ config, disabling IRQ support / runtime-pm\n",
			 dmi_id->ident);
				 broken_irq_dmi_id->ident);
			dev->irq = 0;
		}
	}

	dev_dbg(dev->dev, "BCM irq: %d\n", dev->irq);
	return 0;