Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[pandora-kernel.git] / drivers / acpi / asus_acpi.c
index 099f92a..e9ee4c5 100644 (file)
@@ -310,7 +310,8 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_set = "SPLV",
         .brightness_get = "GPLV",
         .display_set = "SDSP",
-        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
+        .display_get = "\\SSTE"},
+
        {
         .name = "M6R",
         .mt_mled = "MLED",
@@ -320,7 +321,7 @@ static struct model_data model_conf[END_MODEL] = {
         .brightness_set = "SPLV",
         .brightness_get = "GPLV",
         .display_set = "SDSP",
-        .display_get = "\\SSTE"},
+        .display_get = "\\_SB.PCI0.P0P1.VGA.GETD"},
 
        {
         .name = "P30",
@@ -1043,6 +1044,65 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data)
        return;
 }
 
+/*
+ * Match the model string to the list of supported models. Return END_MODEL if
+ * no match or model is NULL.
+ */
+static int asus_model_match(char *model)
+{
+       if (model == NULL)
+               return END_MODEL;
+
+       if (strncmp(model, "L3D", 3) == 0)
+               return L3D;
+       else if (strncmp(model, "L2E", 3) == 0 ||
+                strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0)
+               return L3H;
+       else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0)
+               return L3C;
+       else if (strncmp(model, "L8L", 3) == 0)
+               return L8L;
+       else if (strncmp(model, "L4R", 3) == 0)
+               return L4R;
+       else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0)
+               return M6N;
+       else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0)
+               return M6R;
+       else if (strncmp(model, "M2N", 3) == 0 ||
+                strncmp(model, "M3N", 3) == 0 ||
+                strncmp(model, "M5N", 3) == 0 ||
+                strncmp(model, "M6N", 3) == 0 ||
+                strncmp(model, "S1N", 3) == 0 ||
+                strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0)
+               return xxN;
+       else if (strncmp(model, "M1", 2) == 0)
+               return M1A;
+       else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0)
+               return M2E;
+       else if (strncmp(model, "L2", 2) == 0)
+               return L2D;
+       else if (strncmp(model, "L8", 2) == 0)
+               return S1x;
+       else if (strncmp(model, "D1", 2) == 0)
+               return D1x;
+       else if (strncmp(model, "A1", 2) == 0)
+               return A1x;
+       else if (strncmp(model, "A2", 2) == 0)
+               return A2x;
+       else if (strncmp(model, "J1", 2) == 0)
+               return S2x;
+       else if (strncmp(model, "L5", 2) == 0)
+               return L5x;
+       else if (strncmp(model, "A4G", 3) == 0)
+               return A4G;
+       else if (strncmp(model, "W1N", 3) == 0)
+               return W1N;
+       else if (strncmp(model, "W5A", 3) == 0)
+               return W5A;
+       else
+               return END_MODEL;
+}
+
 /*
  * This function is used to initialize the hotk with right values. In this
  * method, we can make all the detection we want, and modify the hotk struct
@@ -1053,6 +1113,7 @@ static int asus_hotk_get_info(void)
        struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL };
        union acpi_object *model = NULL;
        int bsts_result;
+       char *string = NULL;
        acpi_status status;
 
        /*
@@ -1082,122 +1143,66 @@ static int asus_hotk_get_info(void)
                printk(KERN_NOTICE "  BSTS called, 0x%02x returned\n",
                       bsts_result);
 
-       /* This is unlikely with implicit return */
-       if (buffer.pointer == NULL)
-               return -EINVAL;
-
-       model = (union acpi_object *)buffer.pointer;
        /*
-        * Samsung P30 has a device with a valid _HID whose INIT does not 
-        * return anything. It used to be possible to catch this exception,
-        * but the implicit return code will now happily confuse the 
-        * driver. We assume that every ACPI_TYPE_STRING is a valid model
-        * identifier but it's still possible to get completely bogus data.
+        * Try to match the object returned by INIT to the specific model.
+        * Handle every possible object (or the lack of thereof) the DSDT 
+        * writers might throw at us. When in trouble, we pass NULL to 
+        * asus_model_match() and try something completely different.
         */
-       if (model->type == ACPI_TYPE_STRING) {
-               printk(KERN_NOTICE "  %s model detected, ",
-                      model->string.pointer);
-       } else {
-               if (asus_info &&        /* Samsung P30 */
+       if (buffer.pointer) {
+               model = (union acpi_object *)buffer.pointer;
+               switch (model->type) {
+               case ACPI_TYPE_STRING:
+                       string = model->string.pointer;
+                       break;
+               case ACPI_TYPE_BUFFER:
+                       string = model->buffer.pointer;
+                       break;
+               default:
+                       kfree(model);
+                       break;
+               }
+       }
+       hotk->model = asus_model_match(string);
+       if (hotk->model == END_MODEL) { /* match failed */
+               if (asus_info &&
                    strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) {
                        hotk->model = P30;
                        printk(KERN_NOTICE
                               "  Samsung P30 detected, supported\n");
                } else {
                        hotk->model = M2E;
-                       printk(KERN_WARNING "  no string returned by INIT\n");
-                       printk(KERN_WARNING "  trying default values, supply "
-                              "the developers with your DSDT\n");
+                       printk(KERN_NOTICE "  unsupported model %s, trying "
+                              "default values\n", string);
+                       printk(KERN_NOTICE
+                              "  send /proc/acpi/dsdt to the developers\n");
                }
                hotk->methods = &model_conf[hotk->model];
-
-               kfree(model);
-
                return AE_OK;
        }
-
-       hotk->model = END_MODEL;
-       if (strncmp(model->string.pointer, "L3D", 3) == 0)
-               hotk->model = L3D;
-       else if (strncmp(model->string.pointer, "L2E", 3) == 0 ||
-                strncmp(model->string.pointer, "L3H", 3) == 0 ||
-                strncmp(model->string.pointer, "L5D", 3) == 0)
-               hotk->model = L3H;
-       else if (strncmp(model->string.pointer, "L3", 2) == 0 ||
-                strncmp(model->string.pointer, "L2B", 3) == 0)
-               hotk->model = L3C;
-       else if (strncmp(model->string.pointer, "L8L", 3) == 0)
-               hotk->model = L8L;
-       else if (strncmp(model->string.pointer, "L4R", 3) == 0)
-               hotk->model = L4R;
-       else if (strncmp(model->string.pointer, "M6N", 3) == 0 ||
-                strncmp(model->string.pointer, "W3N", 3) == 0)
-               hotk->model = M6N;
-       else if (strncmp(model->string.pointer, "M6R", 3) == 0 ||
-                strncmp(model->string.pointer, "A3G", 3) == 0)
-               hotk->model = M6R;
-       else if (strncmp(model->string.pointer, "M2N", 3) == 0 ||
-                strncmp(model->string.pointer, "M3N", 3) == 0 ||
-                strncmp(model->string.pointer, "M5N", 3) == 0 ||
-                strncmp(model->string.pointer, "M6N", 3) == 0 ||
-                strncmp(model->string.pointer, "S1N", 3) == 0 ||
-                strncmp(model->string.pointer, "S5N", 3) == 0)
-               hotk->model = xxN;
-       else if (strncmp(model->string.pointer, "M1", 2) == 0)
-               hotk->model = M1A;
-       else if (strncmp(model->string.pointer, "M2", 2) == 0 ||
-                strncmp(model->string.pointer, "L4E", 3) == 0)
-               hotk->model = M2E;
-       else if (strncmp(model->string.pointer, "L2", 2) == 0)
-               hotk->model = L2D;
-       else if (strncmp(model->string.pointer, "L8", 2) == 0)
-               hotk->model = S1x;
-       else if (strncmp(model->string.pointer, "D1", 2) == 0)
-               hotk->model = D1x;
-       else if (strncmp(model->string.pointer, "A1", 2) == 0)
-               hotk->model = A1x;
-       else if (strncmp(model->string.pointer, "A2", 2) == 0)
-               hotk->model = A2x;
-       else if (strncmp(model->string.pointer, "J1", 2) == 0)
-               hotk->model = S2x;
-       else if (strncmp(model->string.pointer, "L5", 2) == 0)
-               hotk->model = L5x;
-       else if (strncmp(model->string.pointer, "A4G", 3) == 0)
-               hotk->model = A4G;
-       else if (strncmp(model->string.pointer, "W1N", 3) == 0)
-               hotk->model = W1N;
-       else if (strncmp(model->string.pointer, "W5A", 3) == 0)
-               hotk->model = W5A;
-
-       if (hotk->model == END_MODEL) {
-               printk("unsupported, trying default values, supply the "
-                      "developers with your DSDT\n");
-               hotk->model = M2E;
-       } else {
-               printk("supported\n");
-       }
-
        hotk->methods = &model_conf[hotk->model];
+       printk(KERN_NOTICE "  %s model detected, supported\n", string);
 
        /* Sort of per-model blacklist */
-       if (strncmp(model->string.pointer, "L2B", 3) == 0)
+       if (strncmp(string, "L2B", 3) == 0)
                hotk->methods->lcd_status = NULL;
        /* L2B is similar enough to L3C to use its settings, with this only 
           exception */
-       else if (strncmp(model->string.pointer, "A3G", 3) == 0)
+       else if (strncmp(string, "A3G", 3) == 0)
                hotk->methods->lcd_status = "\\BLFG";
        /* A3G is like M6R */
-       else if (strncmp(model->string.pointer, "S5N", 3) == 0 ||
-                strncmp(model->string.pointer, "M5N", 3) == 0 ||
-                strncmp(model->string.pointer, "W3N", 3) == 0)
+       else if (strncmp(string, "S5N", 3) == 0 ||
+                strncmp(string, "M5N", 3) == 0 ||
+                strncmp(string, "W3N", 3) == 0)
                hotk->methods->mt_mled = NULL;
        /* S5N, M5N and W3N have no MLED */
-       else if (strncmp(model->string.pointer, "L5D", 3) == 0)
+       else if (strncmp(string, "L5D", 3) == 0)
                hotk->methods->mt_wled = NULL;
        /* L5D's WLED is not controlled by ACPI */
-       else if (strncmp(model->string.pointer, "M2N", 3) == 0)
+       else if (strncmp(string, "M2N", 3) == 0 ||
+                strncmp(string, "S1N", 3) == 0)
                hotk->methods->mt_wled = "WLED";
-       /* M2N has a usable WLED */
+       /* M2N and S1N have a usable WLED */
        else if (asus_info) {
                if (strncmp(asus_info->oem_table_id, "L1", 2) == 0)
                        hotk->methods->mled_status = NULL;