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) { |
