From patchwork Wed Feb 12 03:05:40 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aaron Lu X-Patchwork-Id: 3633951 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 35683BF13A for ; Wed, 12 Feb 2014 03:05:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 49B8920158 for ; Wed, 12 Feb 2014 03:05:41 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 371C9201FA for ; Wed, 12 Feb 2014 03:05:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id A0D27FABBE; Tue, 11 Feb 2014 19:05:37 -0800 (PST) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by gabe.freedesktop.org (Postfix) with ESMTP id 42E48FABBE for ; Tue, 11 Feb 2014 19:05:36 -0800 (PST) Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga101.fm.intel.com with ESMTP; 11 Feb 2014 19:05:27 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.95,829,1384329600"; d="scan'208";a="480005421" Received: from aaronlu.sh.intel.com ([10.239.37.67]) by fmsmga002.fm.intel.com with ESMTP; 11 Feb 2014 19:05:26 -0800 Message-ID: <52FAE504.8020001@intel.com> Date: Wed, 12 Feb 2014 11:05:40 +0800 From: Aaron Lu MIME-Version: 1.0 To: Daniel Vetter Cc: Matthew Garrett , "intel-gfx@lists.freedesktop.org" , "Rafael J. Wysocki" , "linux-kernel@vger.kernel.org" , Oleksij Rempel , ACPI Devel Mailing List Subject: [Intel-gfx] [PATCH] drm/i915/opregion: work around buggy firmware that provides 8+ output devices X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces@lists.freedesktop.org Errors-To: intel-gfx-bounces@lists.freedesktop.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The ACPI table on ASUS UX302LA has more than 8 output devices under the graphics controller device node. The problem is, the real active output device, the LCD panel, is listed the last. The result is, the LCD's device id doesn't get recorded in the active device list CADL array and when the _DCS control method for the LCD device is executed, it returns 0x1d, meaning it is not active. This affects the hotkey delivery ASL code that will not deliver a notification if the output device is not active on backlight hotkey press. I don't see a clean way to solve this problem since the operation region spec doesn't allow more than 8 output devices so we have no way of storing all these output devices. The fact that output devices that have _BCM control method usually means they have a higher possibility of being used than those who don't made me choose a simple way to work around the buggy firmware by replacing the last entry in CADL array with the one that has _BCM control method. There is no specific reason why the last entry is picked instead of others. Buglink: https://bugzilla.kernel.org/show_bug.cgi?id=70241 Signed-off-by: Aaron Lu Reported-and-tested-by: Oleksij Rempel --- drivers/gpu/drm/i915/intel_opregion.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 4e960ec7419f..fc4348284f41 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -613,6 +613,7 @@ static void intel_didl_outputs(struct drm_device *dev) acpi_status status; u32 temp; int i = 0; + bool done; handle = ACPI_HANDLE(&dev->pdev->dev); if (!handle || acpi_bus_get_device(handle, &acpi_dev)) @@ -634,11 +635,20 @@ static void intel_didl_outputs(struct drm_device *dev) return; } + done = false; list_for_each_entry(acpi_cdev, &acpi_video_bus->children, node) { if (i >= 8) { dev_dbg(&dev->pdev->dev, - "More than 8 outputs detected via ACPI\n"); - return; + "More than 8 outputs detected via ACPI, %s\n", + acpi_device_bid(acpi_cdev)); + if (acpi_has_method(acpi_cdev->handle, "_BCM")) { + dev_dbg(&dev->pdev->dev, + "%s has _BCM, replacing 8th entry\n", + acpi_device_bid(acpi_cdev)); + i = 7; + done = true; + } else + continue; } status = acpi_evaluate_integer(acpi_cdev->handle, "_ADR", @@ -650,6 +660,9 @@ static void intel_didl_outputs(struct drm_device *dev) &opregion->acpi->didl[i]); i++; } + + if (done) + return; } end: