From patchwork Wed Dec 16 15:08:36 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mattia Dongili X-Patchwork-Id: 68385 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id nBI4ixoh005715 for ; Fri, 18 Dec 2009 04:46:16 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1762195AbZLPPJF (ORCPT ); Wed, 16 Dec 2009 10:09:05 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1762202AbZLPPJF (ORCPT ); Wed, 16 Dec 2009 10:09:05 -0500 Received: from static-220-247-10-204.b-man.svips.gol.ne.jp ([220.247.10.204]:38836 "EHLO smtp.kamineko.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1762195AbZLPPJD (ORCPT ); Wed, 16 Dec 2009 10:09:03 -0500 Received: by smtp.kamineko.org (Postfix, from userid 1004) id 1C306742B9; Thu, 17 Dec 2009 00:09:03 +0900 (JST) Received: from caligola.kamineko.org (unknown [192.168.1.10]) by smtp.kamineko.org (Postfix) with ESMTP id 40C64742AD; Thu, 17 Dec 2009 00:09:02 +0900 (JST) Received: by caligola.kamineko.org (Postfix, from userid 1000) id 3BA4F16128; Thu, 17 Dec 2009 00:09:02 +0900 (JST) From: Mattia Dongili To: Len Brown Cc: linux-acpi@vger.kernel.org, Mattia Dongili Subject: [PATCH 4/4] sony-laptop: enumerate rfkill devices using SN06 Date: Thu, 17 Dec 2009 00:08:36 +0900 Message-Id: <1260976116-6369-5-git-send-email-malattia@linux.it> X-Mailer: git-send-email 1.6.5.4 In-Reply-To: <1260976116-6369-4-git-send-email-malattia@linux.it> References: <1260976116-6369-1-git-send-email-malattia@linux.it> <1260976116-6369-2-git-send-email-malattia@linux.it> <1260976116-6369-3-git-send-email-malattia@linux.it> <1260976116-6369-4-git-send-email-malattia@linux.it> MIME-Version: 1.0 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index cc7d30d..178faa2 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c @@ -1161,35 +1161,73 @@ static void sony_nc_rfkill_update() } } -static int sony_nc_rfkill_setup(struct acpi_device *device) +static void sony_nc_rfkill_setup(struct acpi_device *device) { - int result, ret; + int offset; + u8 dev_code, i; + acpi_status status; + struct acpi_object_list params; + union acpi_object in_obj; + union acpi_object *device_enum; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - if (sony_find_snc_handle(0x124) == -1) { - if (sony_find_snc_handle(0x135) == -1) - return -1; + offset = sony_find_snc_handle(0x124); + if (offset == -1) { + offset = sony_find_snc_handle(0x135); + if (offset == -1) + return; else sony_rfkill_handle = 0x135; } else sony_rfkill_handle = 0x124; + dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); - ret = sony_call_snc_handle(sony_rfkill_handle, 0xb00, &result); - if (ret) { - printk(KERN_INFO DRV_PFX - "Unable to enumerate rfkill devices: %x\n", ret); - return ret; + /* need to read the whole buffer returned by the acpi call to SN06 + * here otherwise we may miss some features + */ + params.count = 1; + params.pointer = &in_obj; + in_obj.type = ACPI_TYPE_INTEGER; + in_obj.integer.value = offset; + status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, + &buffer); + if (ACPI_FAILURE(status)) { + dprintk("Radio device enumeration failed\n"); + return; } - if (result & 0x1) - sony_nc_setup_rfkill(device, SONY_WIFI); - if (result & 0x2) - sony_nc_setup_rfkill(device, SONY_BLUETOOTH); - if (result & 0x1c) - sony_nc_setup_rfkill(device, SONY_WWAN); - if (result & 0x20) - sony_nc_setup_rfkill(device, SONY_WIMAX); + device_enum = (union acpi_object *) buffer.pointer; + if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { + printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", + device_enum->type); + goto out_no_enum; + } - return 0; + /* the buffer is filled with magic numbers describing the devices + * available, 0xff terminates the enumeration + */ + while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && + i < device_enum->buffer.length) { + i++; + dprintk("Radio devices, looking at 0x%.2x\n", dev_code); + + if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) + sony_nc_setup_rfkill(device, SONY_WIFI); + + if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) + sony_nc_setup_rfkill(device, SONY_BLUETOOTH); + + if ((0xf0 & dev_code) == 0x20 && + !sony_rfkill_devices[SONY_WWAN]) + sony_nc_setup_rfkill(device, SONY_WWAN); + + if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) + sony_nc_setup_rfkill(device, SONY_WIMAX); + } + +out_no_enum: + kfree(buffer.pointer); + return; } static int sony_nc_add(struct acpi_device *device)