lkml.org 
[lkml]   [2014]   [Feb]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH] drm/i915/opregion: work around buggy firmware that provides 8+ output devices
    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 <aaron.lu@intel.com>
    Reported-and-tested-by: Oleksij Rempel <linux@rempel-privat.de>
    ---
    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:
    --
    1.8.5.3


    \
     
     \ /
      Last update: 2014-02-13 01:41    [W:0.025 / U:157.184 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site