From patchwork Tue Apr 18 11:54:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hans de Goede X-Patchwork-Id: 9685411 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1B419602C9 for ; Tue, 18 Apr 2017 11:54:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0FF4828418 for ; Tue, 18 Apr 2017 11:54:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 046E62842B; Tue, 18 Apr 2017 11:54:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 6C69828418 for ; Tue, 18 Apr 2017 11:54:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4631D899B5; Tue, 18 Apr 2017 11:54:32 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by gabe.freedesktop.org (Postfix) with ESMTPS id C2FBB899B5 for ; Tue, 18 Apr 2017 11:54:30 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.phx2.redhat.com [10.5.11.14]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D109AC04B93D; Tue, 18 Apr 2017 11:54:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D109AC04B93D Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=hdegoede@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com D109AC04B93D Received: from shalem.localdomain.com (unknown [10.36.118.14]) by smtp.corp.redhat.com (Postfix) with ESMTP id 2A9F6749A0; Tue, 18 Apr 2017 11:54:27 +0000 (UTC) From: Hans de Goede To: Jani Nikula , =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= , "Rafael J . Wysocki" , Len Brown Date: Tue, 18 Apr 2017 13:54:23 +0200 Message-Id: <20170418115425.16068-1-hdegoede@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.14 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Tue, 18 Apr 2017 11:54:30 +0000 (UTC) Cc: linux-acpi@vger.kernel.org, Takashi Iwai , intel-gfx , Robert Moore , Hans de Goede , Andy Shevchenko Subject: [Intel-gfx] [PATCH v6 1/3] ACPI / bus: Introduce a list of ids for "always present" devices X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Virus-Scanned: ClamAV using ClamSMTP Several Cherry Trail devices (all of which ship with Windows 10) hide the LPSS PWM controller in ACPI, typically the _STA method looks like this: Method (_STA, 0, NotSerialized) // _STA: Status { If (OSID == One) { Return (Zero) } Return (0x0F) } Where OSID is some dark magic seen in all Cherry Trail ACPI tables making the machine behave differently depending on which OS it *thinks* it is booting, this gets set in a number of ways which we cannot control, on some newer machines it simple hardcoded to "One" aka win10. This causes the PWM controller to get hidden, which means Linux cannot control the backlight level on cht based tablets / laptops. Since loading the driver for this does no harm (the only in kernel user of it is the i915 driver, which will only use it when it needs it), this commit makes acpi_bus_get_status() always set status to ACPI_STA_DEFAULT for the 80862288 device, fixing the lack of backlight control. Signed-off-by: Hans de Goede --- Changes in v2: -Use pr_debug instead of ACPI_DEBUG_PRINT Changes in v3: -Un-inline acpi_set_device_status and do the always_present_device_ids table check inside the un-inlined version of it Changes in v4: -Use dev_info instead of pr_debug -Not only check for ACPI HID but also for CPU (SoC) model so as to not for devices present on other models then for which the quirk is intended and to avoid enabling unrelated ACPI devices which happen to use the same HID Changes in v5: -Only do the dev_info once per device (acpi_set_device_status gets called multiple times per device during boot) Changes in v6: -Allow specifying more then one CPU-model for a single HID -Not only match the HID but also the UID, like on Cherry Trail, on some Bay Trail Windows 10 tablets we need to enable the PWM controller to get working backlight even though _STA returns 0. The Bay Trail SoC has 2 PWM controllers and we only need the first one. UID matching will allows adding an entry for Bay Trail which only enables the first PWM controller --- drivers/acpi/bus.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++ include/acpi/acpi_bus.h | 6 +---- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 34fbe02..eb30630 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -34,6 +34,8 @@ #include #include #ifdef CONFIG_X86 +#include +#include #include #endif #include @@ -132,6 +134,69 @@ int acpi_bus_get_status(struct acpi_device *device) } EXPORT_SYMBOL(acpi_bus_get_status); +#ifdef CONFIG_X86 +/* + * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because + * some recent Windows drivers bind to one device but poke at multiple + * devices at the same time, so the others get hidden. + * We work around this by always reporting ACPI_STA_DEFAULT for these + * devices. Note this MUST only be done for devices where this is safe. + * + * This forcing of devices to be present is limited to specific CPU (SoC) + * models both to avoid potentially causing trouble on other models and + * because some HIDs are re-used on different SoCs for completely + * different devices. + */ +struct always_present_device_id { + struct acpi_device_id hid[2]; + struct x86_cpu_id cpu_ids[2]; + const char *uid; +}; + +#define ICPU(model) { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, } + +#define ENTRY(hid, uid, cpu_models) { \ + { { hid, }, {} }, \ + { cpu_models, {} }, \ + uid, \ +} + +static const struct always_present_device_id always_present_device_ids[] = { + /* + * Cherry Trail PWM directly poked by GPU driver in win10, + * but Linux uses a separate PWM driver, harmless if not used. + */ + ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)), +}; +#endif + +void acpi_set_device_status(struct acpi_device *adev, u32 sta) +{ + u32 *status = (u32 *)&adev->status; +#ifdef CONFIG_X86 + u32 old_status = *status; + int i; + + /* acpi_match_device_ids checks status, so start with default */ + *status = ACPI_STA_DEFAULT; + for (i = 0; i < ARRAY_SIZE(always_present_device_ids); i++) { + if (acpi_match_device_ids(adev, + always_present_device_ids[i].hid) == 0 && + adev->pnp.unique_id && + strcmp(adev->pnp.unique_id, + always_present_device_ids[i].uid) == 0 && + x86_match_cpu(always_present_device_ids[i].cpu_ids)) { + if (old_status != ACPI_STA_DEFAULT) + dev_info(&adev->dev, + "Device [%s] is in always present list setting status [%08x]\n", + adev->pnp.bus_id, ACPI_STA_DEFAULT); + return; + } + } +#endif + *status = sta; +} + void acpi_bus_private_data_handler(acpi_handle handle, void *context) { diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index b53c058..ef0794a 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -441,11 +441,6 @@ static inline void *acpi_driver_data(struct acpi_device *d) #define to_acpi_device(d) container_of(d, struct acpi_device, dev) #define to_acpi_driver(d) container_of(d, struct acpi_driver, drv) -static inline void acpi_set_device_status(struct acpi_device *adev, u32 sta) -{ - *((u32 *)&adev->status) = sta; -} - static inline void acpi_set_hp_context(struct acpi_device *adev, struct acpi_hotplug_context *hp) { @@ -494,6 +489,7 @@ void acpi_bus_put_acpi_device(struct acpi_device *adev); acpi_status acpi_bus_get_status_handle(acpi_handle handle, unsigned long long *sta); int acpi_bus_get_status(struct acpi_device *device); +void acpi_set_device_status(struct acpi_device *adev, u32 sta); int acpi_bus_set_power(acpi_handle handle, int state); const char *acpi_power_state_string(int state);