From patchwork Thu Mar 22 05:37:58 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AceLan Kao X-Patchwork-Id: 148165 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from chlorine.canonical.com (chlorine.canonical.com [91.189.94.204]) by ozlabs.org (Postfix) with ESMTP id 5DDBCB6FBD for ; Thu, 22 Mar 2012 16:38:34 +1100 (EST) Received: from localhost ([127.0.0.1] helo=chlorine.canonical.com) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SAaiz-0001dR-4z; Thu, 22 Mar 2012 05:38:13 +0000 Received: from mail-pz0-f49.google.com ([209.85.210.49]) by chlorine.canonical.com with esmtp (Exim 4.71) (envelope-from ) id 1SAaix-0001d4-2B for kernel-team@lists.ubuntu.com; Thu, 22 Mar 2012 05:38:11 +0000 Received: by mail-pz0-f49.google.com with SMTP id p5so2821563dak.8 for ; Wed, 21 Mar 2012 22:38:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:subject:date:message-id:x-mailer:in-reply-to :references; bh=4wu7i74DUFsiqDPsB0p/XlicIoioA+poBUDbBIAD+WM=; b=LrOq74GTZq1aoSVg9KJSh3w3h7R/n3mzKtnM91aMlOCRFoILFXOnomBjacDr3J39mP nL9BCzH/Zpt+zZCUt5ZqxnvtxkJMtZO22ZXic7gRz6h2GHJodVl+vEG7KUiOA36PO8Tk jcylYBCehZhfupI8saOQmJ6fHR+zL6kyQWrcHW9WmeS6C3KQz2sgvNSy8TaLVezlvpcT yCj6aAqr1m0tmzJTkj2veKediX/UVFV0cNkPHRt9zxRieGG+tbzhAKw3+pOirpbNdB39 uY+jG+XOJ8ul5m8f+hnSqnSgd98XfXBLJq3bkbZasbz9ciu5Vso2oV0uMl5H0rYfaiAu 8v4w== Received: by 10.68.230.229 with SMTP id tb5mr18116792pbc.0.1332394690631; Wed, 21 Mar 2012 22:38:10 -0700 (PDT) Received: from localhost ([210.242.151.101]) by mx.google.com with ESMTPS id l1sm3005747pbe.54.2012.03.21.22.38.07 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 21 Mar 2012 22:38:09 -0700 (PDT) From: AceLan Kao To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/2][Precise] asus-wmi: add scalar board brightness adj. support Date: Thu, 22 Mar 2012 13:37:58 +0800 Message-Id: <1332394679-26101-2-git-send-email-acelan.kao@canonical.com> X-Mailer: git-send-email 1.7.9.1 In-Reply-To: <1332394679-26101-1-git-send-email-acelan.kao@canonical.com> References: <1332394679-26101-1-git-send-email-acelan.kao@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.13 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: kernel-team-bounces@lists.ubuntu.com Errors-To: kernel-team-bounces@lists.ubuntu.com BugLink: https://bugs.launchpad.net/bugs/961879 Some ASUS ET2012E/I All-in-One machines that use a scalar board to control the brightness, and they only accept brightness up and down command. So, I introduced a get_scalar_command() function to pass the command to the scalar board through WMI. Besides, we have to store the brightness value locally, for we need the old value to know the brightness value is increasing or decreasing. BTW, since there is no way to retrieve the actual brightness(it would be a fixed value), and the max brightness value would be fixed to 1, so we have to keep passing the brightness up/down command when we reached the max brightness value or 0. Signed-off-by: AceLan Kao --- drivers/platform/x86/asus-nb-wmi.c | 2 +- drivers/platform/x86/asus-wmi.c | 33 ++++++++++++-- drivers/platform/x86/asus-wmi.h | 10 +++- drivers/platform/x86/eeepc-wmi.c | 85 +++++++++++++++++++++++++----------- 4 files changed, 97 insertions(+), 33 deletions(-) diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index b0859d4..396dafc 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -99,7 +99,7 @@ static struct asus_wmi_driver asus_nb_wmi_driver = { .keymap = asus_nb_wmi_keymap, .input_name = "Asus WMI hotkeys", .input_phys = ASUS_NB_WMI_FILE "/input0", - .quirks = asus_nb_wmi_quirks, + .detect_quirks = asus_nb_wmi_quirks, }; diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index d1049ee..d642e31 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -784,7 +784,8 @@ static int asus_new_rfkill(struct asus_wmi *asus, arfkill->dev_id = dev_id; arfkill->asus = asus; - if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless) + if (dev_id == ASUS_WMI_DEVID_WLAN && + asus->driver->quirks->hotplug_wireless) *rfkill = rfkill_alloc(name, &asus->platform_device->dev, type, &asus_rfkill_wlan_ops, arfkill); else @@ -895,7 +896,7 @@ static int asus_wmi_rfkill_init(struct asus_wmi *asus) if (result && result != -ENODEV) goto exit; - if (!asus->driver->hotplug_wireless) + if (!asus->driver->quirks->hotplug_wireless) goto exit; result = asus_setup_pci_hotplug(asus); @@ -1116,13 +1117,33 @@ static int read_brightness(struct backlight_device *bd) return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK; } +static u32 get_scalar_command(struct backlight_device *bd) +{ + struct asus_wmi *asus = bl_get_data(bd); + u32 ctrl_param = 0; + + if ((asus->driver->brightness < bd->props.brightness) || + bd->props.brightness == bd->props.max_brightness) + ctrl_param = 0x00008001; + else if ((asus->driver->brightness > bd->props.brightness) || + bd->props.brightness == 0) + ctrl_param = 0x00008000; + + asus->driver->brightness = bd->props.brightness; + + return ctrl_param; +} + static int update_bl_status(struct backlight_device *bd) { struct asus_wmi *asus = bl_get_data(bd); u32 ctrl_param; int power, err; - ctrl_param = bd->props.brightness; + if (asus->driver->quirks->scalar_panel_brightness) + ctrl_param = get_scalar_command(bd); + else + ctrl_param = bd->props.brightness; err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS, ctrl_param, NULL); @@ -1200,6 +1221,8 @@ static int asus_wmi_backlight_init(struct asus_wmi *asus) bd->props.power = power; backlight_update_status(bd); + asus->driver->brightness = bd->props.brightness; + return 0; } @@ -1622,8 +1645,8 @@ static int asus_wmi_add(struct platform_device *pdev) wdrv->platform_device = pdev; platform_set_drvdata(asus->platform_device, asus); - if (wdrv->quirks) - wdrv->quirks(asus->driver); + if (wdrv->detect_quirks) + wdrv->detect_quirks(asus->driver); err = asus_wmi_platform_init(asus); if (err) diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h index 8147c10..ac7dd4e 100644 --- a/drivers/platform/x86/asus-wmi.h +++ b/drivers/platform/x86/asus-wmi.h @@ -35,9 +35,14 @@ struct module; struct key_entry; struct asus_wmi; +struct quirk_entry { + bool hotplug_wireless; + bool scalar_panel_brightness; +}; + struct asus_wmi_driver { - bool hotplug_wireless; int wapf; + int brightness; const char *name; struct module *owner; @@ -47,13 +52,14 @@ struct asus_wmi_driver { const struct key_entry *keymap; const char *input_name; const char *input_phys; + struct quirk_entry *quirks; /* Returns new code, value, and autorelease values in arguments. * Return ASUS_WMI_KEY_IGNORE in code if event should be ignored. */ void (*key_filter) (struct asus_wmi_driver *driver, int *code, unsigned int *value, bool *autorelease); int (*probe) (struct platform_device *device); - void (*quirks) (struct asus_wmi_driver *driver); + void (*detect_quirks) (struct asus_wmi_driver *driver); struct platform_driver platform_driver; struct platform_device *platform_device; diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c index 9f6e643..6f60ef0 100644 --- a/drivers/platform/x86/eeepc-wmi.c +++ b/drivers/platform/x86/eeepc-wmi.c @@ -48,6 +48,7 @@ MODULE_LICENSE("GPL"); MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID); +static struct quirk_entry *quirks; static bool hotplug_wireless; module_param(hotplug_wireless, bool, 0444); @@ -87,6 +88,60 @@ static const struct key_entry eeepc_wmi_keymap[] = { { KE_END, 0}, }; +static struct quirk_entry quirk_asus_unknown = { +}; + +static struct quirk_entry quirk_asus_1000h = { + .hotplug_wireless = true, +}; + +static struct quirk_entry quirk_asus_et2012_type3 = { + .scalar_panel_brightness = true, +}; + +static int dmi_matched(const struct dmi_system_id *dmi) +{ + char *model; + quirks = dmi->driver_data; + + model = (char *)dmi->matches[1].substr; + if (unlikely(strncmp(model, "ET2012", 6) == 0)) { + const struct dmi_device *dev = NULL; + char oemstring[30]; + while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, NULL, + dev))) { + if (sscanf(dev->name, "AEMS%24c", oemstring) == 1) { + if (oemstring[18] == '3') + quirks = &quirk_asus_et2012_type3; + break; + } + } + } + return 1; +} + +static struct dmi_system_id asus_quirks[] = { + { + .callback = dmi_matched, + .ident = "ASUSTeK Computer INC. 1000H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "1000H"), + }, + .driver_data = &quirk_asus_1000h, + }, + { + .callback = dmi_matched, + .ident = "ASUSTeK Computer INC. ET2012E/I", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "ET2012"), + }, + .driver_data = &quirk_asus_unknown, + }, + {}, +}; + static void eeepc_wmi_key_filter(struct asus_wmi_driver *asus_wmi, int *code, unsigned int *value, bool *autorelease) { @@ -141,33 +196,13 @@ static int eeepc_wmi_probe(struct platform_device *pdev) return 0; } -static void eeepc_dmi_check(struct asus_wmi_driver *driver) -{ - const char *model; - - model = dmi_get_system_info(DMI_PRODUCT_NAME); - if (!model) - return; - - /* - * Whitelist for wlan hotplug - * - * Asus 1000H needs the current hotplug code to handle - * Fn+F2 correctly. We may add other Asus here later, but - * it seems that most of the laptops supported by asus-wmi - * don't need to be on this list - */ - if (strcmp(model, "1000H") == 0) { - driver->hotplug_wireless = true; - pr_info("wlan hotplug enabled\n"); - } -} - static void eeepc_wmi_quirks(struct asus_wmi_driver *driver) { - driver->hotplug_wireless = hotplug_wireless; driver->wapf = -1; - eeepc_dmi_check(driver); + driver->quirks = &quirk_asus_unknown; + driver->quirks->hotplug_wireless = hotplug_wireless; + dmi_check_system(asus_quirks); + driver->quirks = quirks; } static struct asus_wmi_driver asus_wmi_driver = { @@ -179,7 +214,7 @@ static struct asus_wmi_driver asus_wmi_driver = { .input_phys = EEEPC_WMI_FILE "/input0", .key_filter = eeepc_wmi_key_filter, .probe = eeepc_wmi_probe, - .quirks = eeepc_wmi_quirks, + .detect_quirks = eeepc_wmi_quirks, };