diff options
| author | Len Brown <len.brown@intel.com> | 2009-12-24 01:17:41 -0500 |
|---|---|---|
| committer | Len Brown <len.brown@intel.com> | 2009-12-24 01:17:41 -0500 |
| commit | fe7fa9c51a76cf67934c2e77dc9d84800c9fbf79 (patch) | |
| tree | a12638a4069f7af6733a47aff8460040912d9d08 /drivers | |
| parent | 6d3bf6818a1d5527f44681d3f763051dfb1930e4 (diff) | |
| parent | 528809c35faebd8c50a4722c85ab8610725875cc (diff) | |
Merge branch 'sony' into release
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/platform/x86/sony-laptop.c | 94 |
1 files changed, 71 insertions, 23 deletions
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index 2896ca4cd9ab..5af53340da6f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
| @@ -131,6 +131,7 @@ enum sony_nc_rfkill { | |||
| 131 | N_SONY_RFKILL, | 131 | N_SONY_RFKILL, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | static int sony_rfkill_handle; | ||
| 134 | static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; | 135 | static struct rfkill *sony_rfkill_devices[N_SONY_RFKILL]; |
| 135 | static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; | 136 | static int sony_rfkill_address[N_SONY_RFKILL] = {0x300, 0x500, 0x700, 0x900}; |
| 136 | static void sony_nc_rfkill_update(void); | 137 | static void sony_nc_rfkill_update(void); |
| @@ -232,6 +233,7 @@ static int sony_laptop_input_index[] = { | |||
| 232 | 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ | 233 | 56, /* 69 SONYPI_EVENT_VOLUME_INC_PRESSED */ |
| 233 | 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | 234 | 57, /* 70 SONYPI_EVENT_VOLUME_DEC_PRESSED */ |
| 234 | -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ | 235 | -1, /* 71 SONYPI_EVENT_BRIGHTNESS_PRESSED */ |
| 236 | 58, /* 72 SONYPI_EVENT_MEDIA_PRESSED */ | ||
| 235 | }; | 237 | }; |
| 236 | 238 | ||
| 237 | static int sony_laptop_input_keycode_map[] = { | 239 | static int sony_laptop_input_keycode_map[] = { |
| @@ -293,6 +295,7 @@ static int sony_laptop_input_keycode_map[] = { | |||
| 293 | KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ | 295 | KEY_F15, /* 55 SONYPI_EVENT_SETTINGKEY_PRESSED */ |
| 294 | KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ | 296 | KEY_VOLUMEUP, /* 56 SONYPI_EVENT_VOLUME_INC_PRESSED */ |
| 295 | KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ | 297 | KEY_VOLUMEDOWN, /* 57 SONYPI_EVENT_VOLUME_DEC_PRESSED */ |
| 298 | KEY_MEDIA, /* 58 SONYPI_EVENT_MEDIA_PRESSED */ | ||
| 296 | }; | 299 | }; |
| 297 | 300 | ||
| 298 | /* release buttons after a short delay if pressed */ | 301 | /* release buttons after a short delay if pressed */ |
| @@ -890,6 +893,8 @@ static struct sony_nc_event sony_100_events[] = { | |||
| 890 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, | 893 | { 0x0C, SONYPI_EVENT_FNKEY_RELEASED }, |
| 891 | { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, | 894 | { 0x9f, SONYPI_EVENT_CD_EJECT_PRESSED }, |
| 892 | { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, | 895 | { 0x1f, SONYPI_EVENT_ANYBUTTON_RELEASED }, |
| 896 | { 0xa1, SONYPI_EVENT_MEDIA_PRESSED }, | ||
| 897 | { 0x21, SONYPI_EVENT_ANYBUTTON_RELEASED }, | ||
| 893 | { 0, 0 }, | 898 | { 0, 0 }, |
| 894 | }; | 899 | }; |
| 895 | 900 | ||
| @@ -961,7 +966,7 @@ static void sony_nc_notify(struct acpi_device *device, u32 event) | |||
| 961 | else | 966 | else |
| 962 | sony_laptop_report_input_event(ev); | 967 | sony_laptop_report_input_event(ev); |
| 963 | } | 968 | } |
| 964 | } else if (sony_find_snc_handle(0x124) == ev) { | 969 | } else if (sony_find_snc_handle(sony_rfkill_handle) == ev) { |
| 965 | sony_nc_rfkill_update(); | 970 | sony_nc_rfkill_update(); |
| 966 | return; | 971 | return; |
| 967 | } | 972 | } |
| @@ -1067,7 +1072,7 @@ static int sony_nc_rfkill_set(void *data, bool blocked) | |||
| 1067 | if (!blocked) | 1072 | if (!blocked) |
| 1068 | argument |= 0xff0000; | 1073 | argument |= 0xff0000; |
| 1069 | 1074 | ||
| 1070 | return sony_call_snc_handle(0x124, argument, &result); | 1075 | return sony_call_snc_handle(sony_rfkill_handle, argument, &result); |
| 1071 | } | 1076 | } |
| 1072 | 1077 | ||
| 1073 | static const struct rfkill_ops sony_rfkill_ops = { | 1078 | static const struct rfkill_ops sony_rfkill_ops = { |
| @@ -1110,7 +1115,7 @@ static int sony_nc_setup_rfkill(struct acpi_device *device, | |||
| 1110 | if (!rfk) | 1115 | if (!rfk) |
| 1111 | return -ENOMEM; | 1116 | return -ENOMEM; |
| 1112 | 1117 | ||
| 1113 | sony_call_snc_handle(0x124, 0x200, &result); | 1118 | sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); |
| 1114 | hwblock = !(result & 0x1); | 1119 | hwblock = !(result & 0x1); |
| 1115 | rfkill_set_hw_state(rfk, hwblock); | 1120 | rfkill_set_hw_state(rfk, hwblock); |
| 1116 | 1121 | ||
| @@ -1129,7 +1134,7 @@ static void sony_nc_rfkill_update() | |||
| 1129 | int result; | 1134 | int result; |
| 1130 | bool hwblock; | 1135 | bool hwblock; |
| 1131 | 1136 | ||
| 1132 | sony_call_snc_handle(0x124, 0x200, &result); | 1137 | sony_call_snc_handle(sony_rfkill_handle, 0x200, &result); |
| 1133 | hwblock = !(result & 0x1); | 1138 | hwblock = !(result & 0x1); |
| 1134 | 1139 | ||
| 1135 | for (i = 0; i < N_SONY_RFKILL; i++) { | 1140 | for (i = 0; i < N_SONY_RFKILL; i++) { |
| @@ -1145,36 +1150,79 @@ static void sony_nc_rfkill_update() | |||
| 1145 | continue; | 1150 | continue; |
| 1146 | } | 1151 | } |
| 1147 | 1152 | ||
| 1148 | sony_call_snc_handle(0x124, argument, &result); | 1153 | sony_call_snc_handle(sony_rfkill_handle, argument, &result); |
| 1149 | rfkill_set_states(sony_rfkill_devices[i], | 1154 | rfkill_set_states(sony_rfkill_devices[i], |
| 1150 | !(result & 0xf), false); | 1155 | !(result & 0xf), false); |
| 1151 | } | 1156 | } |
| 1152 | } | 1157 | } |
| 1153 | 1158 | ||
| 1154 | static int sony_nc_rfkill_setup(struct acpi_device *device) | 1159 | static void sony_nc_rfkill_setup(struct acpi_device *device) |
| 1155 | { | 1160 | { |
| 1156 | int result, ret; | 1161 | int offset; |
| 1162 | u8 dev_code, i; | ||
| 1163 | acpi_status status; | ||
| 1164 | struct acpi_object_list params; | ||
| 1165 | union acpi_object in_obj; | ||
| 1166 | union acpi_object *device_enum; | ||
| 1167 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 1157 | 1168 | ||
| 1158 | if (sony_find_snc_handle(0x124) == -1) | 1169 | offset = sony_find_snc_handle(0x124); |
| 1159 | return -1; | 1170 | if (offset == -1) { |
| 1171 | offset = sony_find_snc_handle(0x135); | ||
| 1172 | if (offset == -1) | ||
| 1173 | return; | ||
| 1174 | else | ||
| 1175 | sony_rfkill_handle = 0x135; | ||
| 1176 | } else | ||
| 1177 | sony_rfkill_handle = 0x124; | ||
| 1178 | dprintk("Found rkfill handle: 0x%.4x\n", sony_rfkill_handle); | ||
| 1160 | 1179 | ||
| 1161 | ret = sony_call_snc_handle(0x124, 0xb00, &result); | 1180 | /* need to read the whole buffer returned by the acpi call to SN06 |
| 1162 | if (ret) { | 1181 | * here otherwise we may miss some features |
| 1163 | printk(KERN_INFO DRV_PFX | 1182 | */ |
| 1164 | "Unable to enumerate rfkill devices: %x\n", ret); | 1183 | params.count = 1; |
| 1165 | return ret; | 1184 | params.pointer = &in_obj; |
| 1185 | in_obj.type = ACPI_TYPE_INTEGER; | ||
| 1186 | in_obj.integer.value = offset; | ||
| 1187 | status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", ¶ms, | ||
| 1188 | &buffer); | ||
| 1189 | if (ACPI_FAILURE(status)) { | ||
| 1190 | dprintk("Radio device enumeration failed\n"); | ||
| 1191 | return; | ||
| 1192 | } | ||
| 1193 | |||
| 1194 | device_enum = (union acpi_object *) buffer.pointer; | ||
| 1195 | if (!device_enum || device_enum->type != ACPI_TYPE_BUFFER) { | ||
| 1196 | printk(KERN_ERR "Invalid SN06 return object 0x%.2x\n", | ||
| 1197 | device_enum->type); | ||
| 1198 | goto out_no_enum; | ||
| 1166 | } | 1199 | } |
| 1167 | 1200 | ||
| 1168 | if (result & 0x1) | 1201 | /* the buffer is filled with magic numbers describing the devices |
| 1169 | sony_nc_setup_rfkill(device, SONY_WIFI); | 1202 | * available, 0xff terminates the enumeration |
| 1170 | if (result & 0x2) | 1203 | */ |
| 1171 | sony_nc_setup_rfkill(device, SONY_BLUETOOTH); | 1204 | while ((dev_code = *(device_enum->buffer.pointer + i)) != 0xff && |
| 1172 | if (result & 0x1c) | 1205 | i < device_enum->buffer.length) { |
| 1173 | sony_nc_setup_rfkill(device, SONY_WWAN); | 1206 | i++; |
| 1174 | if (result & 0x20) | 1207 | dprintk("Radio devices, looking at 0x%.2x\n", dev_code); |
| 1175 | sony_nc_setup_rfkill(device, SONY_WIMAX); | ||
| 1176 | 1208 | ||
| 1177 | return 0; | 1209 | if (dev_code == 0 && !sony_rfkill_devices[SONY_WIFI]) |
| 1210 | sony_nc_setup_rfkill(device, SONY_WIFI); | ||
| 1211 | |||
| 1212 | if (dev_code == 0x10 && !sony_rfkill_devices[SONY_BLUETOOTH]) | ||
| 1213 | sony_nc_setup_rfkill(device, SONY_BLUETOOTH); | ||
| 1214 | |||
| 1215 | if ((0xf0 & dev_code) == 0x20 && | ||
| 1216 | !sony_rfkill_devices[SONY_WWAN]) | ||
| 1217 | sony_nc_setup_rfkill(device, SONY_WWAN); | ||
| 1218 | |||
| 1219 | if (dev_code == 0x30 && !sony_rfkill_devices[SONY_WIMAX]) | ||
| 1220 | sony_nc_setup_rfkill(device, SONY_WIMAX); | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | out_no_enum: | ||
| 1224 | kfree(buffer.pointer); | ||
| 1225 | return; | ||
| 1178 | } | 1226 | } |
| 1179 | 1227 | ||
| 1180 | static int sony_nc_add(struct acpi_device *device) | 1228 | static int sony_nc_add(struct acpi_device *device) |
