diff mbox

sony-laptop: support rfkill via ACPI interfaces

Message ID 20090322180321.GA10401@srcf.ucam.org (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Matthew Garrett March 22, 2009, 6:03 p.m. UTC
Actually, try this one instead - obvious think in the first one.

Comments

Norbert Preining March 22, 2009, 8:36 p.m. UTC | #1
On So, 22 Mär 2009, Matthew Garrett wrote:
> Actually, try this one instead - obvious think in the first one.

Tried it but acpi_listen still reports the same events:
sony/hotkey SNC 00000001 00000090
sony/hotkey SNC 00000001 00000090

Best wishes

Norbert

-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at>        Vienna University of Technology
Debian Developer <preining@debian.org>                         Debian TeX Group
gpg DSA: 0x09C5B094      fp: 14DF 2E6C 0307 BE6D AD76  A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
FIUNARY (n.)
The safe place you put something and then forget where it was.
			--- Douglas Adams, The Meaning of Liff
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Matthew Garrett March 22, 2009, 8:37 p.m. UTC | #2
On Sun, Mar 22, 2009 at 09:36:03PM +0100, Norbert Preining wrote:
> On So, 22 Mär 2009, Matthew Garrett wrote:
> > Actually, try this one instead - obvious think in the first one.
> 
> Tried it but acpi_listen still reports the same events:
> sony/hotkey SNC 00000001 00000090
> sony/hotkey SNC 00000001 00000090

Hm. Try changing 0x93 to 0x90 in the notify handler.
Norbert Preining March 22, 2009, 10:06 p.m. UTC | #3
On So, 22 Mär 2009, Matthew Garrett wrote:
> > sony/hotkey SNC 00000001 00000090
> > sony/hotkey SNC 00000001 00000090
> 
> Hm. Try changing 0x93 to 0x90 in the notify handler.

That did the trick, now different syms are reported.

BUT:
- suddenly the sony-laptop module is convinced that the *hardware*
  rfkill switch is always turned on, always. Not even reloading an older
  sony-laptop helped. Rebooting neither. Shutting down and rebooting
  with an older sony-laptop as default made wifi show up again.
  I am not sure if cold booting into the latest version of your patch
  will work, haven't tried till now, sorry, will do tomorrow.

- S1 and S2 do adjustment of the brightness, while Fn-F5 and Fn-F6 do
  not do anything, but this is probably only configuration stuff.

Thanks as usual

Best wishes

Norbert

-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at>        Vienna University of Technology
Debian Developer <preining@debian.org>                         Debian TeX Group
gpg DSA: 0x09C5B094      fp: 14DF 2E6C 0307 BE6D AD76  A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
TROSSACHS (pl.n.) The useless epaulettes on an expensive raincoat.
			--- Douglas Adams, The Meaning of Liff
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Matthew Garrett March 22, 2009, 10:46 p.m. UTC | #4
On Sun, Mar 22, 2009 at 11:06:55PM +0100, Norbert Preining wrote:

> BUT:
> - suddenly the sony-laptop module is convinced that the *hardware*
>   rfkill switch is always turned on, always. Not even reloading an older
>   sony-laptop helped. Rebooting neither. Shutting down and rebooting
>   with an older sony-laptop as default made wifi show up again.
>   I am not sure if cold booting into the latest version of your patch
>   will work, haven't tried till now, sorry, will do tomorrow.

Hmm. Don't /think/ I did anything that should affect that, but it's 
possible. If it's reproducable, can you try commenting out the 
sony_call_snc_handle calls in sony_nc_function_setup and see if they 
change the behaviour? You'll probably need to reboot in between.

> - S1 and S2 do adjustment of the brightness, while Fn-F5 and Fn-F6 do
>   not do anything, but this is probably only configuration stuff.

Ok, sounds like the mapping needs to be changed. Can you let me know 
which ACPI events are generated for each key?
Mattia Dongili March 22, 2009, 11:10 p.m. UTC | #5
On Sun, Mar 22, 2009 at 10:46:52PM +0000, Matthew Garrett wrote:
> On Sun, Mar 22, 2009 at 11:06:55PM +0100, Norbert Preining wrote:
> 
> > BUT:
> > - suddenly the sony-laptop module is convinced that the *hardware*
> >   rfkill switch is always turned on, always. Not even reloading an older
> >   sony-laptop helped. Rebooting neither. Shutting down and rebooting
> >   with an older sony-laptop as default made wifi show up again.
> >   I am not sure if cold booting into the latest version of your patch
> >   will work, haven't tried till now, sorry, will do tomorrow.
> 
> Hmm. Don't /think/ I did anything that should affect that, but it's 
> possible. If it's reproducable, can you try commenting out the 
> sony_call_snc_handle calls in sony_nc_function_setup and see if they 
> change the behaviour? You'll probably need to reboot in between.
> 
> > - S1 and S2 do adjustment of the brightness, while Fn-F5 and Fn-F6 do
> >   not do anything, but this is probably only configuration stuff.
> 
> Ok, sounds like the mapping needs to be changed. Can you let me know 
> which ACPI events are generated for each key?

Yes it does.
A vaio SR user sent me this list for 0x9c that after a call to SN07(202)
becomes:

+       { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
+       { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x82, SONYPI_EVENT_PKEY_P1 },
+       { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x83, SONYPI_EVENT_PKEY_P2 },
+       { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x84, SONYPI_EVENT_PKEY_P3 },
+       { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x85, SONYPI_EVENT_PKEY_P4 },
+       { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x86, SONYPI_EVENT_PKEY_P5 },
+       { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
+       { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
+       { 0, 0 },
Matthew Garrett March 22, 2009, 11:14 p.m. UTC | #6
On Mon, Mar 23, 2009 at 08:10:30AM +0900, Mattia Dongili wrote:
> On Sun, Mar 22, 2009 at 10:46:52PM +0000, Matthew Garrett wrote:
> > Ok, sounds like the mapping needs to be changed. Can you let me know 
> > which ACPI events are generated for each key?
> 
> Yes it does.
> A vaio SR user sent me this list for 0x9c that after a call to SN07(202)
> becomes:

0x9c as well? Interesting. Easy enough to generalise that code, I guess. 
If we don't have a match, maybe we should just send the scancode with 
KEY_UNKNOWN and let hal remap them?
Mattia Dongili March 23, 2009, 12:08 a.m. UTC | #7
On Sun, Mar 22, 2009 at 11:14:49PM +0000, Matthew Garrett wrote:
> On Mon, Mar 23, 2009 at 08:10:30AM +0900, Mattia Dongili wrote:
> > On Sun, Mar 22, 2009 at 10:46:52PM +0000, Matthew Garrett wrote:
> > > Ok, sounds like the mapping needs to be changed. Can you let me know 
> > > which ACPI events are generated for each key?
> > 
> > Yes it does.
> > A vaio SR user sent me this list for 0x9c that after a call to SN07(202)
> > becomes:
> 
> 0x9c as well? Interesting. Easy enough to generalise that code, I guess. 

well, I was thinking of a two layer lookup keyed on the event code
(0x9[02ce]).

> If we don't have a match, maybe we should just send the scancode with 
> KEY_UNKNOWN and let hal remap them?

the problem is that the decoded keypress (after the SN07 call) generates
duplicates, i.e.: 0x81 is fn+f1 for the 0x92 case and some "Mode" key
for 0x9c the an SR model.
I guess sending the whole combination as the scancode would do the trick
(0x9c81).
But as long as we can make it consistent with what sony-laptop currently
sends to userspace then we should try to have a map.
Matthew Garrett March 23, 2009, 12:10 a.m. UTC | #8
On Mon, Mar 23, 2009 at 09:08:54AM +0900, Mattia Dongili wrote:

> the problem is that the decoded keypress (after the SN07 call) generates
> duplicates, i.e.: 0x81 is fn+f1 for the 0x92 case and some "Mode" key
> for 0x9c the an SR model.
> I guess sending the whole combination as the scancode would do the trick
> (0x9c81).

Mm. That ought to work. Still, if we can get a map from the new models, 
it might not be too urgent.
Norbert Preining March 23, 2009, 12:29 p.m. UTC | #9
Hi Matthew,

On So, 22 Mär 2009, Matthew Garrett wrote:
> > - suddenly the sony-laptop module is convinced that the *hardware*
> >   rfkill switch is always turned on, always. Not even reloading an older
> >   sony-laptop helped. Rebooting neither. Shutting down and rebooting
> >   with an older sony-laptop as default made wifi show up again.
> >   I am not sure if cold booting into the latest version of your patch
> >   will work, haven't tried till now, sorry, will do tomorrow.
> 
> Hmm. Don't /think/ I did anything that should affect that, but it's 
> possible. If it's reproducable, can you try commenting out the 

Forget it, as I said, I will retry cold booting and that made it work
without a problem.

> > - S1 and S2 do adjustment of the brightness, while Fn-F5 and Fn-F6 do
> >   not do anything, but this is probably only configuration stuff.
> 
> Ok, sounds like the mapping needs to be changed. Can you let me know 
> which ACPI events are generated for each key?

S1
	sony/hotkey SNC 00000001 00000090
	sony/hotkey SNC 00000001 00000010

S2
	sony/hotkey SNC 00000001 00000091
	sony/hotkey SNC 00000001 00000011
Fn-F5 (brightness -)
	sony/hotkey SNC 00000001 00000010
	sony/hotkey SNC 00000001 0000003b
Fn-F6 (brightness +)
	sony/hotkey SNC 00000001 00000011
	sony/hotkey SNC 00000001 0000003b
Fn-F7 (switch output mode)
	sony/hotkey SNC 00000001 00000012
	sony/hotkey SNC 00000001 0000003b
Fn-F9 (Zoom minus)
	sony/hotkey SNC 00000001 00000089
	sony/hotkey SNC 00000001 00000009
Fn-F10
	sony/hotkey SNC 00000001 00000015
	sony/hotkey SNC 00000001 0000003b
Fn-F12 (suspend to disk)
	(not sure about that, it actuallyDID suspend and I am not
	sure. At least NOW I know that S2D works ;-)
	sony/hotkey SNC 00000001 00000017
	sony/hotkey SNC 00000001 0000003b

Hope that helps

Best wishes

Norbert

-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at>        Vienna University of Technology
Debian Developer <preining@debian.org>                         Debian TeX Group
gpg DSA: 0x09C5B094      fp: 14DF 2E6C 0307 BE6D AD76  A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
SHIFNAL (n.,vb.)
An awkward shuffling walk caused by two or more people in a hurry
accidentally getting into the same segment of revolving door. A
similar effect is achieved by people entering three-legged races
unwisely joined at the neck instead of the ankles.
			--- Douglas Adams, The Meaning of Liff
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Norbert Preining March 23, 2009, 12:30 p.m. UTC | #10
On Mo, 23 Mär 2009, Mattia Dongili wrote:
> A vaio SR user sent me this list for 0x9c that after a call to SN07(202)
> becomes:
> 
> +       { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
> +       { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x82, SONYPI_EVENT_PKEY_P1 },
> +       { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x83, SONYPI_EVENT_PKEY_P2 },
> +       { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x84, SONYPI_EVENT_PKEY_P3 },
> +       { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x85, SONYPI_EVENT_PKEY_P4 },
> +       { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x86, SONYPI_EVENT_PKEY_P5 },
> +       { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
> +       { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
> +       { 0, 0 },

Couldn't test that since several SONYPI_EVENT* are not defined in
current -rc8 plus Matthew patch. And I didn't want to try it out. 

Best wishes

Norbert

-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at>        Vienna University of Technology
Debian Developer <preining@debian.org>                         Debian TeX Group
gpg DSA: 0x09C5B094      fp: 14DF 2E6C 0307 BE6D AD76  A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
BABWORTH
Something which justifies having a really good cry.
			--- Douglas Adams, The Meaning of Liff
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mattia Dongili March 23, 2009, 1:04 p.m. UTC | #11
On Mon, Mar 23, 2009 at 01:30:30PM +0100, Norbert Preining wrote:
> On Mo, 23 Mär 2009, Mattia Dongili wrote:
> > A vaio SR user sent me this list for 0x9c that after a call to SN07(202)
> > becomes:
> > 
> > +       { 0x81, SONYPI_EVENT_MODEKEY_PRESSED },
> > +       { 0x01, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x82, SONYPI_EVENT_PKEY_P1 },
> > +       { 0x02, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x83, SONYPI_EVENT_PKEY_P2 },
> > +       { 0x03, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x84, SONYPI_EVENT_PKEY_P3 },
> > +       { 0x04, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x85, SONYPI_EVENT_PKEY_P4 },
> > +       { 0x05, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x86, SONYPI_EVENT_PKEY_P5 },
> > +       { 0x06, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0x87, SONYPI_EVENT_SETTINGKEY_PRESSED },
> > +       { 0x07, SONYPI_EVENT_ANYBUTTON_RELEASED },
> > +       { 0, 0 },
> 
> Couldn't test that since several SONYPI_EVENT* are not defined in
> current -rc8 plus Matthew patch. And I didn't want to try it out. 

the above code was not meant to be tested. What you should do instead is
changing the line (after Matthew's patch):
	if (ev == 0x92 || ev == 0x93) {
in sony_acpi_notify to
	if (ev == 0x92 || ev == 0x93 || ev == 0x90) {
load the driver with debug=1 and press the unrecognized Fn keys.
You *should* get a bunch of "unknown input event XX" in the kernel log,
with those we can build the necessary mappings for your specific model
(hopefully not just yours).
Norbert Preining March 23, 2009, 3:32 p.m. UTC | #12
Hi you two,

On Mo, 23 Mär 2009, Matthew Garrett wrote:
> Ok, thanks. Can you try this instead of the other patches? I'm a touch 
> concerned about the release events on the S1 and S2 buttons looking like 
> the events for some of the Fn keys, which may mean that we need to find 
> some way of distinguishing them.

I tried your patch together with Mattia's remark:

On Mo, 23 Mär 2009, Mattia Dongili wrote:
> the above code was not meant to be tested. What you should do instead is
> changing the line (after Matthew's patch):
> 	if (ev == 0x92 || ev == 0x93) {
> in sony_acpi_notify to
> 	if (ev == 0x92 || ev == 0x93 || ev == 0x90) {

and it works fine.

Regarding the key press events I did what Mattia said (loading with
debug=1): Some created an "Unknown event" in the log, some not.

S1:
sony-laptop: sony_acpi_notify, event: 0x20
sony-laptop: sony_acpi_notify, event: 0x10

S2:
sony-laptop: sony_acpi_notify, event: 0x20
sony-laptop: sony_acpi_notify, event: 0x11

Fn-F5 (brightness -)
sony-laptop: Unknown event: 90 85
sony-laptop: sony_acpi_notify, event: 0x85
sony-laptop: sony_laptop_report_input_event, event not known: 133
sony-laptop: unknown input event 85
sony-laptop: Unknown event: 90 5
sony-laptop: sony_acpi_notify, event: 0x05

Fn-F6 (brightness +)
sony-laptop: Unknown event: 90 86
sony-laptop: sony_acpi_notify, event: 0x86
sony-laptop: sony_laptop_report_input_event, event not known: 134
sony-laptop: unknown input event 86
sony-laptop: Unknown event: 90 6
sony-laptop: sony_acpi_notify, event: 0x06
sony-laptop: unknown input event 06

Fn-F7 (switch output mode)
sony-laptop: Unknown event: 90 87
sony-laptop: sony_acpi_notify, event: 0x87
sony-laptop: sony_laptop_report_input_event, event not known: 135
sony-laptop: unknown input event 87
sony-laptop: Unknown event: 90 7
sony-laptop: sony_acpi_notify, event: 0x07

Fn-F9 (Zoom minus)
sony-laptop: sony_acpi_notify, event: 0x14
sony-laptop: sony_acpi_notify, event: 0x3b

Fn-F10 (Zoom plus)
sony-laptop: Unknown event: 90 8a
sony-laptop: sony_acpi_notify, event: 0x8a
sony-laptop: sony_laptop_report_input_event, event not known: 138
sony-laptop: unknown input event 8a
sony-laptop: Unknown event: 90 a
sony-laptop: sony_acpi_notify, event: 0x0a



Best wishes

Norbert

-------------------------------------------------------------------------------
Dr. Norbert Preining <preining@logic.at>        Vienna University of Technology
Debian Developer <preining@debian.org>                         Debian TeX Group
gpg DSA: 0x09C5B094      fp: 14DF 2E6C 0307 BE6D AD76  A9C0 D2BF 4AA3 09C5 B094
-------------------------------------------------------------------------------
LULWORTH (n.)
Measure of conversation. A lulworth defines the amount of the length,
loudness and embarrassment of a statement you make when everyone else
in the room unaccountably stops talking at the same time.
			--- Douglas Adams, The Meaning of Liff
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index 537959d..2486832 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -64,6 +64,7 @@ 
 #include <asm/uaccess.h>
 #include <linux/sonypi.h>
 #include <linux/sony-laptop.h>
+#include <linux/rfkill.h>
 #ifdef CONFIG_SONYPI_COMPAT
 #include <linux/poll.h>
 #include <linux/miscdevice.h>
@@ -123,6 +124,11 @@  MODULE_PARM_DESC(minor,
 		 "default is -1 (automatic)");
 #endif
 
+static struct rfkill *sony_wifi_rfkill;
+static struct rfkill *sony_bluetooth_rfkill;
+static struct rfkill *sony_wwan_rfkill;
+static struct rfkill *sony_wimax_rfkill;
+
 /*********** Input Devices ***********/
 
 #define SONY_LAPTOP_BUF_SIZE	128
@@ -134,6 +140,7 @@  struct sony_laptop_input_s {
 	spinlock_t		fifo_lock;
 	struct workqueue_struct	*wq;
 };
+
 static struct sony_laptop_input_s sony_laptop_input = {
 	.users = ATOMIC_INIT(0),
 };
@@ -689,6 +696,31 @@  static int acpi_callsetfunc(acpi_handle handle, char *name, int value,
 	return -1;
 }
 
+static int sony_find_snc_handle(int handle)
+{
+	int i;
+	int result;
+
+	for (i=0x20; i<0x30; i++) {
+		acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
+		if (result == handle)
+			return i-0x20;
+	}
+
+	return -1;
+}
+
+static int sony_call_snc_handle(int handle, int argument, int *result)
+{
+	int offset = sony_find_snc_handle(handle);
+
+	if (offset < 0)
+		return -1;
+
+	return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
+				result);
+}
+
 /*
  * sony_nc_values input/output validate functions
  */
@@ -809,32 +841,6 @@  struct sony_nc_event {
 	u8	event;
 };
 
-static struct sony_nc_event *sony_nc_events;
-
-/* Vaio C* --maybe also FE*, N* and AR* ?-- special init sequence
- * for Fn keys
- */
-static int sony_nc_C_enable(const struct dmi_system_id *id)
-{
-	int result = 0;
-
-	printk(KERN_NOTICE DRV_PFX "detected %s\n", id->ident);
-
-	sony_nc_events = id->driver_data;
-
-	if (acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x4, &result) < 0
-			|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x2, &result) < 0
-			|| acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0x10, &result) < 0
-			|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x0, &result) < 0
-			|| acpi_callsetfunc(sony_nc_acpi_handle, "SN03", 0x2, &result) < 0
-			|| acpi_callsetfunc(sony_nc_acpi_handle, "SN07", 0x101, &result) < 0) {
-		printk(KERN_WARNING DRV_PFX "failed to initialize SNC, some "
-				"functionalities may be missing\n");
-		return 1;
-	}
-	return 0;
-}
-
 static struct sony_nc_event sony_C_events[] = {
 	{ 0x81, SONYPI_EVENT_FNKEY_F1 },
 	{ 0x01, SONYPI_EVENT_FNKEY_RELEASED },
@@ -851,57 +857,17 @@  static struct sony_nc_event sony_C_events[] = {
 	{ 0, 0 },
 };
 
-/* SNC-only model map */
-static const struct dmi_system_id sony_nc_ids[] = {
-		{
-			.ident = "Sony Vaio FE Series",
-			.callback = sony_nc_C_enable,
-			.driver_data = sony_C_events,
-			.matches = {
-				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FE"),
-			},
-		},
-		{
-			.ident = "Sony Vaio FZ Series",
-			.callback = sony_nc_C_enable,
-			.driver_data = sony_C_events,
-			.matches = {
-				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ"),
-			},
-		},
-		{
-			.ident = "Sony Vaio C Series",
-			.callback = sony_nc_C_enable,
-			.driver_data = sony_C_events,
-			.matches = {
-				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"),
-			},
-		},
-		{
-			.ident = "Sony Vaio N Series",
-			.callback = sony_nc_C_enable,
-			.driver_data = sony_C_events,
-			.matches = {
-				DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
-				DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"),
-			},
-		},
-		{ }
-};
-
 /*
  * ACPI callbacks
  */
 static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
 {
-	struct sony_nc_event *evmap;
+	int i;
 	u32 ev = event;
 	int result;
 
-	if (ev == 0x92) {
+	if (ev == 0x92 || ev == 0x93) {
+		int origev = ev;
 		/* read the key pressed from EC.GECR
 		 * A call to SN07 with 0x0202 will do it as well respecting
 		 * the current protocol on different OSes
@@ -913,20 +879,23 @@  static void sony_acpi_notify(acpi_handle handle, u32 event, void *data)
 		 * TODO: we may want to do the same for the older GHKE -need
 		 *       dmi list- so this snippet may become one more callback.
 		 */
-		if (acpi_callsetfunc(handle, "SN07", 0x0202, &result) < 0)
+		if (sony_call_snc_handle(0x100, 0x200, &result))
 			dprintk("sony_acpi_notify, unable to decode event 0x%.2x\n", ev);
 		else
 			ev = result & 0xFF;
-	}
 
-	if (sony_nc_events)
-		for (evmap = sony_nc_events; evmap->event; evmap++) {
-			if (evmap->data == ev) {
-				ev = evmap->event;
+		for (i=0; sony_C_events[i].data; i++) {
+			if (sony_C_events[i].data == ev) {
+				ev = sony_C_events[i].event;
 				break;
 			}
 		}
 
+		if (!sony_C_events[i].data)
+			printk(KERN_INFO DRV_PFX "Unknown event: %x %x\n",
+			       origev, ev);
+	}
+
 	dprintk("sony_acpi_notify, event: 0x%.2x\n", ev);
 	sony_laptop_report_input_event(ev);
 	acpi_bus_generate_proc_event(sony_nc_acpi_device, 1, ev);
@@ -953,9 +922,24 @@  static acpi_status sony_walk_callback(acpi_handle handle, u32 level,
 /*
  * ACPI device
  */
+static int sony_nc_function_setup(struct acpi_device *device) {
+	int result;
+
+	/* Enable all events */
+	acpi_callsetfunc(sony_nc_acpi_handle, "SN02", 0xffff, &result);
+
+	/* Setup hotkeys */
+	sony_call_snc_handle(0x0100, 0, &result);
+	sony_call_snc_handle(0x0101, 0, &result);
+	sony_call_snc_handle(0x0102, 0x100, &result);
+
+	return 0;
+}
+
 static int sony_nc_resume(struct acpi_device *device)
 {
 	struct sony_nc_value *item;
+	acpi_handle handle;
 
 	for (item = sony_nc_values; item->name; item++) {
 		int ret;
@@ -970,13 +954,156 @@  static int sony_nc_resume(struct acpi_device *device)
 		}
 	}
 
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
+					 &handle))) {
+		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
+			dprintk("ECON Method failed\n");
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
+					 &handle))) {
+		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
+	}
+
 	/* set the last requested brightness level */
 	if (sony_backlight_device &&
 			!sony_backlight_update_status(sony_backlight_device))
 		printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
 
-	/* re-initialize models with specific requirements */
-	dmi_check_system(sony_nc_ids);
+	return 0;
+}
+
+static void sony_nc_rfkill_cleanup(void)
+{
+	if (sony_wifi_rfkill)
+		rfkill_unregister(sony_wifi_rfkill);
+	if (sony_bluetooth_rfkill)
+		rfkill_unregister(sony_bluetooth_rfkill);
+	if (sony_wwan_rfkill)
+		rfkill_unregister(sony_wwan_rfkill);
+	if (sony_wimax_rfkill)
+		rfkill_unregister(sony_wimax_rfkill);
+}
+
+static int sony_nc_rfkill_get(void *data, enum rfkill_state *state)
+{
+	int result;
+
+	sony_call_snc_handle(0x124, (long) data, &result);
+	if (result & 0xf)
+		*state = RFKILL_STATE_UNBLOCKED;
+	else
+		*state = RFKILL_STATE_SOFT_BLOCKED;
+	return 0;
+}
+
+static int sony_nc_rfkill_set(void *data, enum rfkill_state state)
+{
+	int result;
+	int argument = (long) data + 1;
+
+	if (state == RFKILL_STATE_UNBLOCKED)
+		argument |= 0xff0000;
+
+	return sony_call_snc_handle(0x124, argument, &result);
+}
+
+static int sony_nc_setup_wifi_rfkill(struct acpi_device *device)
+{
+	int err = 0;
+
+	sony_wifi_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WLAN);
+	if (!sony_wifi_rfkill)
+		return -1;
+	sony_wifi_rfkill->name = "sony-wifi";
+	sony_wifi_rfkill->toggle_radio = sony_nc_rfkill_set;
+	sony_wifi_rfkill->get_state = sony_nc_rfkill_get;
+	sony_wifi_rfkill->user_claim_unsupported = 1;
+	sony_wifi_rfkill->data = (void *)0x300;
+	err = rfkill_register(sony_wifi_rfkill);
+	if (err)
+		rfkill_free(sony_wifi_rfkill);
+	return err;
+}
+
+static int sony_nc_setup_bluetooth_rfkill(struct acpi_device *device)
+{
+	int err = 0;
+
+	sony_bluetooth_rfkill = rfkill_allocate(&device->dev,
+						RFKILL_TYPE_BLUETOOTH);
+       if (!sony_bluetooth_rfkill)
+	       return -1;
+       sony_bluetooth_rfkill->name = "sony-bluetooth";
+       sony_bluetooth_rfkill->toggle_radio = sony_nc_rfkill_set;
+       sony_bluetooth_rfkill->get_state = sony_nc_rfkill_get;
+       sony_bluetooth_rfkill->user_claim_unsupported = 1;
+       sony_bluetooth_rfkill->data = (void *)0x500;
+       err = rfkill_register(sony_bluetooth_rfkill);
+       if (err)
+	       rfkill_free(sony_bluetooth_rfkill);
+       return err;
+}
+
+static int sony_nc_setup_wwan_rfkill(struct acpi_device *device)
+{
+	int err = 0;
+
+	sony_wwan_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WWAN);
+	if (!sony_wwan_rfkill)
+		return -1;
+	sony_wwan_rfkill->name = "sony-wwan";
+	sony_wwan_rfkill->toggle_radio = sony_nc_rfkill_set;
+	sony_wwan_rfkill->get_state = sony_nc_rfkill_get;
+	sony_wwan_rfkill->user_claim_unsupported = 1;
+	sony_wwan_rfkill->data = (void *)0x700;
+	err = rfkill_register(sony_wwan_rfkill);
+	if (err)
+		rfkill_free(sony_wwan_rfkill);
+	return err;
+}
+
+static int sony_nc_setup_wimax_rfkill(struct acpi_device *device)
+{
+	int err = 0;
+
+	sony_wimax_rfkill = rfkill_allocate(&device->dev, RFKILL_TYPE_WIMAX);
+	if (!sony_wimax_rfkill)
+		return -1;
+	sony_wimax_rfkill->name = "sony-wimax";
+	sony_wimax_rfkill->toggle_radio = sony_nc_rfkill_set;
+	sony_wimax_rfkill->get_state = sony_nc_rfkill_get;
+	sony_wimax_rfkill->user_claim_unsupported = 1;
+	sony_wimax_rfkill->data = (void *)0x900;
+	err = rfkill_register(sony_wimax_rfkill);
+	if (err)
+		rfkill_free(sony_wimax_rfkill);
+	return err;
+}
+
+static int sony_nc_rfkill_setup(struct acpi_device *device)
+{
+	int result, ret;
+
+	if (sony_find_snc_handle(0x124) == -1)
+		return -1;
+
+	ret = sony_call_snc_handle(0x124, 0xb00, &result);
+	if (ret) {
+		printk(KERN_INFO DRV_PFX
+		       "Unable to enumerate rfkill devices: %x\n", ret);
+		return ret;
+	}
+
+	if (result & 0x1)
+		sony_nc_setup_wifi_rfkill(device);
+	if (result & 0x2)
+		sony_nc_setup_bluetooth_rfkill(device);
+	if (result & 0x1c)
+		sony_nc_setup_wwan_rfkill(device);
+	if (result & 0x20)
+		sony_nc_setup_wimax_rfkill(device);
 
 	return 0;
 }
@@ -1024,6 +1151,19 @@  static int sony_nc_add(struct acpi_device *device)
 			dprintk("_INI Method failed\n");
 	}
 
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "ECON",
+					 &handle))) {
+		if (acpi_callsetfunc(sony_nc_acpi_handle, "ECON", 1, NULL))
+			dprintk("ECON Method failed\n");
+	}
+
+	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
+					 &handle))) {
+		dprintk("Doing SNC setup\n");
+		sony_nc_function_setup(device);
+		sony_nc_rfkill_setup(device);
+	}
+
 	/* setup input devices and helper fifo */
 	result = sony_laptop_setup_input(device);
 	if (result) {
@@ -1063,9 +1203,6 @@  static int sony_nc_add(struct acpi_device *device)
 
 	}
 
-	/* initialize models with specific requirements */
-	dmi_check_system(sony_nc_ids);
-
 	result = sony_pf_add();
 	if (result)
 		goto outbacklight;
@@ -1131,6 +1268,7 @@  static int sony_nc_add(struct acpi_device *device)
 	sony_laptop_remove_input();
 
       outwalk:
+	sony_nc_rfkill_cleanup();
 	return result;
 }
 
@@ -1156,6 +1294,7 @@  static int sony_nc_remove(struct acpi_device *device, int type)
 
 	sony_pf_remove();
 	sony_laptop_remove_input();
+	sony_nc_rfkill_cleanup();
 	dprintk(SONY_NC_DRIVER_NAME " removed.\n");
 
 	return 0;