aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/asus_acpi.c
diff options
context:
space:
mode:
authorKarol Kozimor <sziwan@hell.org.pl>2006-06-30 19:11:00 -0400
committerLen Brown <len.brown@intel.com>2006-06-30 20:37:50 -0400
commitffab0d9507dc527ff6d704ec5e7e7ccfee119fb1 (patch)
treeb19a776fa4df3619583173f1b14348220eb7f294 /drivers/acpi/asus_acpi.c
parentebccb84810729f0e86a83a65681ba2de45ff84d8 (diff)
ACPI: asus_acpi: rework model detection
This patch reworks laptop model detection. This addresses the Samsung P30 issue, where the INIT method would return no object, but the implicit return in the AML interpreter would confuse the driver. It also accounts for a newer batch of Asus models whose INIT returns ACPI_TYPE_BUFFER instead of STRING. The handling is now much leaner, if we get a buffer or a string, we check against known values, in every other case we use a different path (currently DSDT signatures). The bulk of this patch is separating the string matching from asus_hotk_get_info() into a separate function. This patch properly fixes http://bugme.osdl.org/show_bug.cgi?id=5067 and http://bugme.osdl.org/show_bug.cgi?id=5092 and makes the driver fully functional again with acpi=strict on all machines. Signed-off-by: Karol Kozimor <sziwan@hell.org.pl> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/asus_acpi.c')
-rw-r--r--drivers/acpi/asus_acpi.c183
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 */
1050static 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) {