hp-wmi: Add support for SMBus hotkeys
[deliverable/linux.git] / drivers / platform / x86 / hp-wmi.c
index 1dde7accf27ccb9f4b9150a3927e7c9e8b0a3189..be9227dd82be220dab994e52832812617db6d6f3 100644 (file)
@@ -60,6 +60,7 @@ enum hp_wmi_radio {
        HPWMI_WIFI = 0,
        HPWMI_BLUETOOTH = 1,
        HPWMI_WWAN = 2,
+       HPWMI_GPS = 3,
 };
 
 enum hp_wmi_event_ids {
@@ -137,6 +138,7 @@ static const struct key_entry hp_wmi_keymap[] = {
        { KE_KEY, 0x2142, { KEY_MEDIA } },
        { KE_KEY, 0x213b, { KEY_INFO } },
        { KE_KEY, 0x2169, { KEY_DIRECTION } },
+       { KE_KEY, 0x216a, { KEY_SETUP } },
        { KE_KEY, 0x231b, { KEY_HELP } },
        { KE_END, 0 }
 };
@@ -147,6 +149,7 @@ static struct platform_device *hp_wmi_platform_dev;
 static struct rfkill *wifi_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *wwan_rfkill;
+static struct rfkill *gps_rfkill;
 
 struct rfkill2_device {
        u8 id;
@@ -543,6 +546,10 @@ static void hp_wmi_notify(u32 value, void *context)
                        rfkill_set_states(wwan_rfkill,
                                          hp_wmi_get_sw_state(HPWMI_WWAN),
                                          hp_wmi_get_hw_state(HPWMI_WWAN));
+               if (gps_rfkill)
+                       rfkill_set_states(gps_rfkill,
+                                         hp_wmi_get_sw_state(HPWMI_GPS),
+                                         hp_wmi_get_hw_state(HPWMI_GPS));
                break;
        case HPWMI_CPU_BATTERY_THROTTLE:
                pr_info("Unimplemented CPU throttle because of 3 Cell battery event detected\n");
@@ -670,7 +677,7 @@ static int hp_wmi_rfkill_setup(struct platform_device *device)
                                           (void *) HPWMI_WWAN);
                if (!wwan_rfkill) {
                        err = -ENOMEM;
-                       goto register_bluetooth_error;
+                       goto register_gps_error;
                }
                rfkill_init_sw_state(wwan_rfkill,
                                     hp_wmi_get_sw_state(HPWMI_WWAN));
@@ -681,10 +688,33 @@ static int hp_wmi_rfkill_setup(struct platform_device *device)
                        goto register_wwan_err;
        }
 
+       if (wireless & 0x8) {
+               gps_rfkill = rfkill_alloc("hp-gps", &device->dev,
+                                               RFKILL_TYPE_GPS,
+                                               &hp_wmi_rfkill_ops,
+                                               (void *) HPWMI_GPS);
+               if (!gps_rfkill) {
+                       err = -ENOMEM;
+                       goto register_bluetooth_error;
+               }
+               rfkill_init_sw_state(gps_rfkill,
+                                    hp_wmi_get_sw_state(HPWMI_GPS));
+               rfkill_set_hw_state(bluetooth_rfkill,
+                                   hp_wmi_get_hw_state(HPWMI_GPS));
+               err = rfkill_register(gps_rfkill);
+               if (err)
+                       goto register_gps_error;
+       }
+
        return 0;
 register_wwan_err:
        rfkill_destroy(wwan_rfkill);
        wwan_rfkill = NULL;
+       if (gps_rfkill)
+               rfkill_unregister(gps_rfkill);
+register_gps_error:
+       rfkill_destroy(gps_rfkill);
+       gps_rfkill = NULL;
        if (bluetooth_rfkill)
                rfkill_unregister(bluetooth_rfkill);
 register_bluetooth_error:
@@ -729,6 +759,10 @@ static int hp_wmi_rfkill2_setup(struct platform_device *device)
                        type = RFKILL_TYPE_WWAN;
                        name = "hp-wwan";
                        break;
+               case HPWMI_GPS:
+                       type = RFKILL_TYPE_GPS;
+                       name = "hp-gps";
+                       break;
                default:
                        pr_warn("unknown device type 0x%x\n",
                                state.device[i].radio_type);
@@ -786,6 +820,7 @@ static int hp_wmi_bios_setup(struct platform_device *device)
        wifi_rfkill = NULL;
        bluetooth_rfkill = NULL;
        wwan_rfkill = NULL;
+       gps_rfkill = NULL;
        rfkill2_count = 0;
 
        if (hp_wmi_rfkill_setup(device))
@@ -835,6 +870,10 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device)
                rfkill_unregister(wwan_rfkill);
                rfkill_destroy(wwan_rfkill);
        }
+       if (gps_rfkill) {
+               rfkill_unregister(gps_rfkill);
+               rfkill_destroy(gps_rfkill);
+       }
 
        return 0;
 }
@@ -870,6 +909,10 @@ static int hp_wmi_resume_handler(struct device *device)
                rfkill_set_states(wwan_rfkill,
                                  hp_wmi_get_sw_state(HPWMI_WWAN),
                                  hp_wmi_get_hw_state(HPWMI_WWAN));
+       if (gps_rfkill)
+               rfkill_set_states(gps_rfkill,
+                                 hp_wmi_get_sw_state(HPWMI_GPS),
+                                 hp_wmi_get_hw_state(HPWMI_GPS));
 
        return 0;
 }
@@ -884,6 +927,9 @@ static int __init hp_wmi_init(void)
                err = hp_wmi_input_setup();
                if (err)
                        return err;
+               
+               //Enable magic for hotkeys that run on the SMBus
+               ec_write(0xe6,0x6e);
        }
 
        if (bios_capable) {
This page took 0.028679 seconds and 5 git commands to generate.