diff options
-rw-r--r-- | drivers/acpi/asus_acpi.c | 183 |
1 files changed, 93 insertions, 90 deletions
diff --git a/drivers/acpi/asus_acpi.c b/drivers/acpi/asus_acpi.c index 099f92a2c6f2..07b4c8b872cb 100644 --- a/drivers/acpi/asus_acpi.c +++ b/drivers/acpi/asus_acpi.c | |||
@@ -1044,6 +1044,65 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) | |||
1044 | } | 1044 | } |
1045 | 1045 | ||
1046 | /* | 1046 | /* |
1047 | * Match the model string to the list of supported models. Return END_MODEL if | ||
1048 | * no match or model is NULL. | ||
1049 | */ | ||
1050 | static int asus_model_match(char *model) | ||
1051 | { | ||
1052 | if (model == NULL) | ||
1053 | return END_MODEL; | ||
1054 | |||
1055 | if (strncmp(model, "L3D", 3) == 0) | ||
1056 | return L3D; | ||
1057 | else if (strncmp(model, "L2E", 3) == 0 || | ||
1058 | strncmp(model, "L3H", 3) == 0 || strncmp(model, "L5D", 3) == 0) | ||
1059 | return L3H; | ||
1060 | else if (strncmp(model, "L3", 2) == 0 || strncmp(model, "L2B", 3) == 0) | ||
1061 | return L3C; | ||
1062 | else if (strncmp(model, "L8L", 3) == 0) | ||
1063 | return L8L; | ||
1064 | else if (strncmp(model, "L4R", 3) == 0) | ||
1065 | return L4R; | ||
1066 | else if (strncmp(model, "M6N", 3) == 0 || strncmp(model, "W3N", 3) == 0) | ||
1067 | return M6N; | ||
1068 | else if (strncmp(model, "M6R", 3) == 0 || strncmp(model, "A3G", 3) == 0) | ||
1069 | return M6R; | ||
1070 | else if (strncmp(model, "M2N", 3) == 0 || | ||
1071 | strncmp(model, "M3N", 3) == 0 || | ||
1072 | strncmp(model, "M5N", 3) == 0 || | ||
1073 | strncmp(model, "M6N", 3) == 0 || | ||
1074 | strncmp(model, "S1N", 3) == 0 || | ||
1075 | strncmp(model, "S5N", 3) == 0 || strncmp(model, "W1N", 3) == 0) | ||
1076 | return xxN; | ||
1077 | else if (strncmp(model, "M1", 2) == 0) | ||
1078 | return M1A; | ||
1079 | else if (strncmp(model, "M2", 2) == 0 || strncmp(model, "L4E", 3) == 0) | ||
1080 | return M2E; | ||
1081 | else if (strncmp(model, "L2", 2) == 0) | ||
1082 | return L2D; | ||
1083 | else if (strncmp(model, "L8", 2) == 0) | ||
1084 | return S1x; | ||
1085 | else if (strncmp(model, "D1", 2) == 0) | ||
1086 | return D1x; | ||
1087 | else if (strncmp(model, "A1", 2) == 0) | ||
1088 | return A1x; | ||
1089 | else if (strncmp(model, "A2", 2) == 0) | ||
1090 | return A2x; | ||
1091 | else if (strncmp(model, "J1", 2) == 0) | ||
1092 | return S2x; | ||
1093 | else if (strncmp(model, "L5", 2) == 0) | ||
1094 | return L5x; | ||
1095 | else if (strncmp(model, "A4G", 3) == 0) | ||
1096 | return A4G; | ||
1097 | else if (strncmp(model, "W1N", 3) == 0) | ||
1098 | return W1N; | ||
1099 | else if (strncmp(model, "W5A", 3) == 0) | ||
1100 | return W5A; | ||
1101 | else | ||
1102 | return END_MODEL; | ||
1103 | } | ||
1104 | |||
1105 | /* | ||
1047 | * This function is used to initialize the hotk with right values. In this | 1106 | * This function is used to initialize the hotk with right values. In this |
1048 | * method, we can make all the detection we want, and modify the hotk struct | 1107 | * method, we can make all the detection we want, and modify the hotk struct |
1049 | */ | 1108 | */ |
@@ -1053,6 +1112,7 @@ static int asus_hotk_get_info(void) | |||
1053 | struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; | 1112 | struct acpi_buffer dsdt = { ACPI_ALLOCATE_BUFFER, NULL }; |
1054 | union acpi_object *model = NULL; | 1113 | union acpi_object *model = NULL; |
1055 | int bsts_result; | 1114 | int bsts_result; |
1115 | char *string = NULL; | ||
1056 | acpi_status status; | 1116 | acpi_status status; |
1057 | 1117 | ||
1058 | /* | 1118 | /* |
@@ -1082,120 +1142,63 @@ static int asus_hotk_get_info(void) | |||
1082 | printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", | 1142 | printk(KERN_NOTICE " BSTS called, 0x%02x returned\n", |
1083 | bsts_result); | 1143 | bsts_result); |
1084 | 1144 | ||
1085 | /* This is unlikely with implicit return */ | ||
1086 | if (buffer.pointer == NULL) | ||
1087 | return -EINVAL; | ||
1088 | |||
1089 | model = (union acpi_object *)buffer.pointer; | ||
1090 | /* | 1145 | /* |
1091 | * Samsung P30 has a device with a valid _HID whose INIT does not | 1146 | * Try to match the object returned by INIT to the specific model. |
1092 | * return anything. It used to be possible to catch this exception, | 1147 | * Handle every possible object (or the lack of thereof) the DSDT |
1093 | * but the implicit return code will now happily confuse the | 1148 | * writers might throw at us. When in trouble, we pass NULL to |
1094 | * driver. We assume that every ACPI_TYPE_STRING is a valid model | 1149 | * asus_model_match() and try something completely different. |
1095 | * identifier but it's still possible to get completely bogus data. | ||
1096 | */ | 1150 | */ |
1097 | if (model->type == ACPI_TYPE_STRING) { | 1151 | if (buffer.pointer) { |
1098 | printk(KERN_NOTICE " %s model detected, ", | 1152 | model = (union acpi_object *)buffer.pointer; |
1099 | model->string.pointer); | 1153 | switch (model->type) { |
1100 | } else { | 1154 | case ACPI_TYPE_STRING: |
1101 | if (asus_info && /* Samsung P30 */ | 1155 | string = model->string.pointer; |
1156 | break; | ||
1157 | case ACPI_TYPE_BUFFER: | ||
1158 | string = model->buffer.pointer; | ||
1159 | break; | ||
1160 | default: | ||
1161 | kfree(model); | ||
1162 | break; | ||
1163 | } | ||
1164 | } | ||
1165 | hotk->model = asus_model_match(string); | ||
1166 | if (hotk->model == END_MODEL) { /* match failed */ | ||
1167 | if (asus_info && | ||
1102 | strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { | 1168 | strncmp(asus_info->oem_table_id, "ODEM", 4) == 0) { |
1103 | hotk->model = P30; | 1169 | hotk->model = P30; |
1104 | printk(KERN_NOTICE | 1170 | printk(KERN_NOTICE |
1105 | " Samsung P30 detected, supported\n"); | 1171 | " Samsung P30 detected, supported\n"); |
1106 | } else { | 1172 | } else { |
1107 | hotk->model = M2E; | 1173 | hotk->model = M2E; |
1108 | printk(KERN_WARNING " no string returned by INIT\n"); | 1174 | printk(KERN_NOTICE " unsupported model %s, trying " |
1109 | printk(KERN_WARNING " trying default values, supply " | 1175 | "default values\n", string); |
1110 | "the developers with your DSDT\n"); | 1176 | printk(KERN_NOTICE |
1177 | " send /proc/acpi/dsdt to the developers\n"); | ||
1111 | } | 1178 | } |
1112 | hotk->methods = &model_conf[hotk->model]; | 1179 | hotk->methods = &model_conf[hotk->model]; |
1113 | |||
1114 | kfree(model); | ||
1115 | |||
1116 | return AE_OK; | 1180 | return AE_OK; |
1117 | } | 1181 | } |
1118 | |||
1119 | hotk->model = END_MODEL; | ||
1120 | if (strncmp(model->string.pointer, "L3D", 3) == 0) | ||
1121 | hotk->model = L3D; | ||
1122 | else if (strncmp(model->string.pointer, "L2E", 3) == 0 || | ||
1123 | strncmp(model->string.pointer, "L3H", 3) == 0 || | ||
1124 | strncmp(model->string.pointer, "L5D", 3) == 0) | ||
1125 | hotk->model = L3H; | ||
1126 | else if (strncmp(model->string.pointer, "L3", 2) == 0 || | ||
1127 | strncmp(model->string.pointer, "L2B", 3) == 0) | ||
1128 | hotk->model = L3C; | ||
1129 | else if (strncmp(model->string.pointer, "L8L", 3) == 0) | ||
1130 | hotk->model = L8L; | ||
1131 | else if (strncmp(model->string.pointer, "L4R", 3) == 0) | ||
1132 | hotk->model = L4R; | ||
1133 | else if (strncmp(model->string.pointer, "M6N", 3) == 0 || | ||
1134 | strncmp(model->string.pointer, "W3N", 3) == 0) | ||
1135 | hotk->model = M6N; | ||
1136 | else if (strncmp(model->string.pointer, "M6R", 3) == 0 || | ||
1137 | strncmp(model->string.pointer, "A3G", 3) == 0) | ||
1138 | hotk->model = M6R; | ||
1139 | else if (strncmp(model->string.pointer, "M2N", 3) == 0 || | ||
1140 | strncmp(model->string.pointer, "M3N", 3) == 0 || | ||
1141 | strncmp(model->string.pointer, "M5N", 3) == 0 || | ||
1142 | strncmp(model->string.pointer, "M6N", 3) == 0 || | ||
1143 | strncmp(model->string.pointer, "S1N", 3) == 0 || | ||
1144 | strncmp(model->string.pointer, "S5N", 3) == 0) | ||
1145 | hotk->model = xxN; | ||
1146 | else if (strncmp(model->string.pointer, "M1", 2) == 0) | ||
1147 | hotk->model = M1A; | ||
1148 | else if (strncmp(model->string.pointer, "M2", 2) == 0 || | ||
1149 | strncmp(model->string.pointer, "L4E", 3) == 0) | ||
1150 | hotk->model = M2E; | ||
1151 | else if (strncmp(model->string.pointer, "L2", 2) == 0) | ||
1152 | hotk->model = L2D; | ||
1153 | else if (strncmp(model->string.pointer, "L8", 2) == 0) | ||
1154 | hotk->model = S1x; | ||
1155 | else if (strncmp(model->string.pointer, "D1", 2) == 0) | ||
1156 | hotk->model = D1x; | ||
1157 | else if (strncmp(model->string.pointer, "A1", 2) == 0) | ||
1158 | hotk->model = A1x; | ||
1159 | else if (strncmp(model->string.pointer, "A2", 2) == 0) | ||
1160 | hotk->model = A2x; | ||
1161 | else if (strncmp(model->string.pointer, "J1", 2) == 0) | ||
1162 | hotk->model = S2x; | ||
1163 | else if (strncmp(model->string.pointer, "L5", 2) == 0) | ||
1164 | hotk->model = L5x; | ||
1165 | else if (strncmp(model->string.pointer, "A4G", 3) == 0) | ||
1166 | hotk->model = A4G; | ||
1167 | else if (strncmp(model->string.pointer, "W1N", 3) == 0) | ||
1168 | hotk->model = W1N; | ||
1169 | else if (strncmp(model->string.pointer, "W5A", 3) == 0) | ||
1170 | hotk->model = W5A; | ||
1171 | |||
1172 | if (hotk->model == END_MODEL) { | ||
1173 | printk("unsupported, trying default values, supply the " | ||
1174 | "developers with your DSDT\n"); | ||
1175 | hotk->model = M2E; | ||
1176 | } else { | ||
1177 | printk("supported\n"); | ||
1178 | } | ||
1179 | |||
1180 | hotk->methods = &model_conf[hotk->model]; | 1182 | hotk->methods = &model_conf[hotk->model]; |
1183 | printk(KERN_NOTICE " %s model detected, supported\n", string); | ||
1181 | 1184 | ||
1182 | /* Sort of per-model blacklist */ | 1185 | /* Sort of per-model blacklist */ |
1183 | if (strncmp(model->string.pointer, "L2B", 3) == 0) | 1186 | if (strncmp(string, "L2B", 3) == 0) |
1184 | hotk->methods->lcd_status = NULL; | 1187 | hotk->methods->lcd_status = NULL; |
1185 | /* L2B is similar enough to L3C to use its settings, with this only | 1188 | /* L2B is similar enough to L3C to use its settings, with this only |
1186 | exception */ | 1189 | exception */ |
1187 | else if (strncmp(model->string.pointer, "A3G", 3) == 0) | 1190 | else if (strncmp(string, "A3G", 3) == 0) |
1188 | hotk->methods->lcd_status = "\\BLFG"; | 1191 | hotk->methods->lcd_status = "\\BLFG"; |
1189 | /* A3G is like M6R */ | 1192 | /* A3G is like M6R */ |
1190 | else if (strncmp(model->string.pointer, "S5N", 3) == 0 || | 1193 | else if (strncmp(string, "S5N", 3) == 0 || |
1191 | strncmp(model->string.pointer, "M5N", 3) == 0 || | 1194 | strncmp(string, "M5N", 3) == 0 || |
1192 | strncmp(model->string.pointer, "W3N", 3) == 0) | 1195 | strncmp(string, "W3N", 3) == 0) |
1193 | hotk->methods->mt_mled = NULL; | 1196 | hotk->methods->mt_mled = NULL; |
1194 | /* S5N, M5N and W3N have no MLED */ | 1197 | /* S5N, M5N and W3N have no MLED */ |
1195 | else if (strncmp(model->string.pointer, "L5D", 3) == 0) | 1198 | else if (strncmp(string, "L5D", 3) == 0) |
1196 | hotk->methods->mt_wled = NULL; | 1199 | hotk->methods->mt_wled = NULL; |
1197 | /* L5D's WLED is not controlled by ACPI */ | 1200 | /* L5D's WLED is not controlled by ACPI */ |
1198 | else if (strncmp(model->string.pointer, "M2N", 3) == 0) | 1201 | else if (strncmp(string, "M2N", 3) == 0) |
1199 | hotk->methods->mt_wled = "WLED"; | 1202 | hotk->methods->mt_wled = "WLED"; |
1200 | /* M2N has a usable WLED */ | 1203 | /* M2N has a usable WLED */ |
1201 | else if (asus_info) { | 1204 | else if (asus_info) { |