diff options
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r-- | drivers/misc/sony-laptop.c | 445 |
1 files changed, 275 insertions, 170 deletions
diff --git a/drivers/misc/sony-laptop.c b/drivers/misc/sony-laptop.c index b0f68031b49d..899e3f75f288 100644 --- a/drivers/misc/sony-laptop.c +++ b/drivers/misc/sony-laptop.c | |||
@@ -73,7 +73,7 @@ | |||
73 | if (debug) printk(KERN_WARNING DRV_PFX msg); \ | 73 | if (debug) printk(KERN_WARNING DRV_PFX msg); \ |
74 | } while (0) | 74 | } while (0) |
75 | 75 | ||
76 | #define SONY_LAPTOP_DRIVER_VERSION "0.5" | 76 | #define SONY_LAPTOP_DRIVER_VERSION "0.6" |
77 | 77 | ||
78 | #define SONY_NC_CLASS "sony-nc" | 78 | #define SONY_NC_CLASS "sony-nc" |
79 | #define SONY_NC_HID "SNY5001" | 79 | #define SONY_NC_HID "SNY5001" |
@@ -146,68 +146,70 @@ struct sony_laptop_keypress { | |||
146 | * and input layer indexes in the keymap | 146 | * and input layer indexes in the keymap |
147 | */ | 147 | */ |
148 | static int sony_laptop_input_index[] = { | 148 | static int sony_laptop_input_index[] = { |
149 | -1, /* no event */ | 149 | -1, /* 0 no event */ |
150 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN */ | 150 | -1, /* 1 SONYPI_EVENT_JOGDIAL_DOWN */ |
151 | -1, /* SONYPI_EVENT_JOGDIAL_UP */ | 151 | -1, /* 2 SONYPI_EVENT_JOGDIAL_UP */ |
152 | -1, /* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ | 152 | -1, /* 3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */ |
153 | -1, /* SONYPI_EVENT_JOGDIAL_UP_PRESSED */ | 153 | -1, /* 4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */ |
154 | -1, /* SONYPI_EVENT_JOGDIAL_PRESSED */ | 154 | -1, /* 5 SONYPI_EVENT_JOGDIAL_PRESSED */ |
155 | -1, /* SONYPI_EVENT_JOGDIAL_RELEASED */ | 155 | -1, /* 6 SONYPI_EVENT_JOGDIAL_RELEASED */ |
156 | 0, /* SONYPI_EVENT_CAPTURE_PRESSED */ | 156 | 0, /* 7 SONYPI_EVENT_CAPTURE_PRESSED */ |
157 | 1, /* SONYPI_EVENT_CAPTURE_RELEASED */ | 157 | 1, /* 8 SONYPI_EVENT_CAPTURE_RELEASED */ |
158 | 2, /* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ | 158 | 2, /* 9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */ |
159 | 3, /* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ | 159 | 3, /* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */ |
160 | 4, /* SONYPI_EVENT_FNKEY_ESC */ | 160 | 4, /* 11 SONYPI_EVENT_FNKEY_ESC */ |
161 | 5, /* SONYPI_EVENT_FNKEY_F1 */ | 161 | 5, /* 12 SONYPI_EVENT_FNKEY_F1 */ |
162 | 6, /* SONYPI_EVENT_FNKEY_F2 */ | 162 | 6, /* 13 SONYPI_EVENT_FNKEY_F2 */ |
163 | 7, /* SONYPI_EVENT_FNKEY_F3 */ | 163 | 7, /* 14 SONYPI_EVENT_FNKEY_F3 */ |
164 | 8, /* SONYPI_EVENT_FNKEY_F4 */ | 164 | 8, /* 15 SONYPI_EVENT_FNKEY_F4 */ |
165 | 9, /* SONYPI_EVENT_FNKEY_F5 */ | 165 | 9, /* 16 SONYPI_EVENT_FNKEY_F5 */ |
166 | 10, /* SONYPI_EVENT_FNKEY_F6 */ | 166 | 10, /* 17 SONYPI_EVENT_FNKEY_F6 */ |
167 | 11, /* SONYPI_EVENT_FNKEY_F7 */ | 167 | 11, /* 18 SONYPI_EVENT_FNKEY_F7 */ |
168 | 12, /* SONYPI_EVENT_FNKEY_F8 */ | 168 | 12, /* 19 SONYPI_EVENT_FNKEY_F8 */ |
169 | 13, /* SONYPI_EVENT_FNKEY_F9 */ | 169 | 13, /* 20 SONYPI_EVENT_FNKEY_F9 */ |
170 | 14, /* SONYPI_EVENT_FNKEY_F10 */ | 170 | 14, /* 21 SONYPI_EVENT_FNKEY_F10 */ |
171 | 15, /* SONYPI_EVENT_FNKEY_F11 */ | 171 | 15, /* 22 SONYPI_EVENT_FNKEY_F11 */ |
172 | 16, /* SONYPI_EVENT_FNKEY_F12 */ | 172 | 16, /* 23 SONYPI_EVENT_FNKEY_F12 */ |
173 | 17, /* SONYPI_EVENT_FNKEY_1 */ | 173 | 17, /* 24 SONYPI_EVENT_FNKEY_1 */ |
174 | 18, /* SONYPI_EVENT_FNKEY_2 */ | 174 | 18, /* 25 SONYPI_EVENT_FNKEY_2 */ |
175 | 19, /* SONYPI_EVENT_FNKEY_D */ | 175 | 19, /* 26 SONYPI_EVENT_FNKEY_D */ |
176 | 20, /* SONYPI_EVENT_FNKEY_E */ | 176 | 20, /* 27 SONYPI_EVENT_FNKEY_E */ |
177 | 21, /* SONYPI_EVENT_FNKEY_F */ | 177 | 21, /* 28 SONYPI_EVENT_FNKEY_F */ |
178 | 22, /* SONYPI_EVENT_FNKEY_S */ | 178 | 22, /* 29 SONYPI_EVENT_FNKEY_S */ |
179 | 23, /* SONYPI_EVENT_FNKEY_B */ | 179 | 23, /* 30 SONYPI_EVENT_FNKEY_B */ |
180 | 24, /* SONYPI_EVENT_BLUETOOTH_PRESSED */ | 180 | 24, /* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */ |
181 | 25, /* SONYPI_EVENT_PKEY_P1 */ | 181 | 25, /* 32 SONYPI_EVENT_PKEY_P1 */ |
182 | 26, /* SONYPI_EVENT_PKEY_P2 */ | 182 | 26, /* 33 SONYPI_EVENT_PKEY_P2 */ |
183 | 27, /* SONYPI_EVENT_PKEY_P3 */ | 183 | 27, /* 34 SONYPI_EVENT_PKEY_P3 */ |
184 | 28, /* SONYPI_EVENT_BACK_PRESSED */ | 184 | 28, /* 35 SONYPI_EVENT_BACK_PRESSED */ |
185 | -1, /* SONYPI_EVENT_LID_CLOSED */ | 185 | -1, /* 36 SONYPI_EVENT_LID_CLOSED */ |
186 | -1, /* SONYPI_EVENT_LID_OPENED */ | 186 | -1, /* 37 SONYPI_EVENT_LID_OPENED */ |
187 | 29, /* SONYPI_EVENT_BLUETOOTH_ON */ | 187 | 29, /* 38 SONYPI_EVENT_BLUETOOTH_ON */ |
188 | 30, /* SONYPI_EVENT_BLUETOOTH_OFF */ | 188 | 30, /* 39 SONYPI_EVENT_BLUETOOTH_OFF */ |
189 | 31, /* SONYPI_EVENT_HELP_PRESSED */ | 189 | 31, /* 40 SONYPI_EVENT_HELP_PRESSED */ |
190 | 32, /* SONYPI_EVENT_FNKEY_ONLY */ | 190 | 32, /* 41 SONYPI_EVENT_FNKEY_ONLY */ |
191 | 33, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN */ | 191 | 33, /* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */ |
192 | 34, /* SONYPI_EVENT_JOGDIAL_FAST_UP */ | 192 | 34, /* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */ |
193 | 35, /* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ | 193 | 35, /* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */ |
194 | 36, /* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ | 194 | 36, /* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */ |
195 | 37, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ | 195 | 37, /* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */ |
196 | 38, /* SONYPI_EVENT_JOGDIAL_VFAST_UP */ | 196 | 38, /* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */ |
197 | 39, /* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ | 197 | 39, /* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */ |
198 | 40, /* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ | 198 | 40, /* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */ |
199 | 41, /* SONYPI_EVENT_ZOOM_PRESSED */ | 199 | 41, /* 50 SONYPI_EVENT_ZOOM_PRESSED */ |
200 | 42, /* SONYPI_EVENT_THUMBPHRASE_PRESSED */ | 200 | 42, /* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */ |
201 | 43, /* SONYPI_EVENT_MEYE_FACE */ | 201 | 43, /* 52 SONYPI_EVENT_MEYE_FACE */ |
202 | 44, /* SONYPI_EVENT_MEYE_OPPOSITE */ | 202 | 44, /* 53 SONYPI_EVENT_MEYE_OPPOSITE */ |
203 | 45, /* SONYPI_EVENT_MEMORYSTICK_INSERT */ | 203 | 45, /* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */ |
204 | 46, /* SONYPI_EVENT_MEMORYSTICK_EJECT */ | 204 | 46, /* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */ |
205 | -1, /* SONYPI_EVENT_ANYBUTTON_RELEASED */ | 205 | -1, /* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */ |
206 | -1, /* SONYPI_EVENT_BATTERY_INSERT */ | 206 | -1, /* 57 SONYPI_EVENT_BATTERY_INSERT */ |
207 | -1, /* SONYPI_EVENT_BATTERY_REMOVE */ | 207 | -1, /* 58 SONYPI_EVENT_BATTERY_REMOVE */ |
208 | -1, /* SONYPI_EVENT_FNKEY_RELEASED */ | 208 | -1, /* 59 SONYPI_EVENT_FNKEY_RELEASED */ |
209 | 47, /* SONYPI_EVENT_WIRELESS_ON */ | 209 | 47, /* 60 SONYPI_EVENT_WIRELESS_ON */ |
210 | 48, /* SONYPI_EVENT_WIRELESS_OFF */ | 210 | 48, /* 61 SONYPI_EVENT_WIRELESS_OFF */ |
211 | 49, /* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */ | ||
212 | 50, /* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */ | ||
211 | }; | 213 | }; |
212 | 214 | ||
213 | static int sony_laptop_input_keycode_map[] = { | 215 | static int sony_laptop_input_keycode_map[] = { |
@@ -260,6 +262,8 @@ static int sony_laptop_input_keycode_map[] = { | |||
260 | KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ | 262 | KEY_RESERVED, /* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */ |
261 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ | 263 | KEY_WLAN, /* 47 SONYPI_EVENT_WIRELESS_ON */ |
262 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ | 264 | KEY_WLAN, /* 48 SONYPI_EVENT_WIRELESS_OFF */ |
265 | KEY_ZOOMIN, /* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */ | ||
266 | KEY_ZOOMOUT /* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */ | ||
263 | }; | 267 | }; |
264 | 268 | ||
265 | /* release buttons after a short delay if pressed */ | 269 | /* release buttons after a short delay if pressed */ |
@@ -311,7 +315,7 @@ static void sony_laptop_report_input_event(u8 event) | |||
311 | break; | 315 | break; |
312 | 316 | ||
313 | default: | 317 | default: |
314 | if (event > ARRAY_SIZE (sony_laptop_input_keycode_map)) { | 318 | if (event > ARRAY_SIZE(sony_laptop_input_index)) { |
315 | dprintk("sony_laptop_report_input_event, event not known: %d\n", event); | 319 | dprintk("sony_laptop_report_input_event, event not known: %d\n", event); |
316 | break; | 320 | break; |
317 | } | 321 | } |
@@ -875,6 +879,15 @@ static const struct dmi_system_id sony_nc_ids[] = { | |||
875 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), | 879 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-C"), |
876 | }, | 880 | }, |
877 | }, | 881 | }, |
882 | { | ||
883 | .ident = "Sony Vaio N Series", | ||
884 | .callback = sony_nc_C_enable, | ||
885 | .driver_data = sony_C_events, | ||
886 | .matches = { | ||
887 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
888 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-N"), | ||
889 | }, | ||
890 | }, | ||
878 | { } | 891 | { } |
879 | }; | 892 | }; |
880 | 893 | ||
@@ -1169,10 +1182,12 @@ static struct acpi_driver sony_nc_driver = { | |||
1169 | #define SONYPI_DEVICE_TYPE1 0x00000001 | 1182 | #define SONYPI_DEVICE_TYPE1 0x00000001 |
1170 | #define SONYPI_DEVICE_TYPE2 0x00000002 | 1183 | #define SONYPI_DEVICE_TYPE2 0x00000002 |
1171 | #define SONYPI_DEVICE_TYPE3 0x00000004 | 1184 | #define SONYPI_DEVICE_TYPE3 0x00000004 |
1185 | #define SONYPI_DEVICE_TYPE4 0x00000008 | ||
1172 | 1186 | ||
1173 | #define SONYPI_TYPE1_OFFSET 0x04 | 1187 | #define SONYPI_TYPE1_OFFSET 0x04 |
1174 | #define SONYPI_TYPE2_OFFSET 0x12 | 1188 | #define SONYPI_TYPE2_OFFSET 0x12 |
1175 | #define SONYPI_TYPE3_OFFSET 0x12 | 1189 | #define SONYPI_TYPE3_OFFSET 0x12 |
1190 | #define SONYPI_TYPE4_OFFSET 0x12 | ||
1176 | 1191 | ||
1177 | struct sony_pic_ioport { | 1192 | struct sony_pic_ioport { |
1178 | struct acpi_resource_io io1; | 1193 | struct acpi_resource_io io1; |
@@ -1185,18 +1200,33 @@ struct sony_pic_irq { | |||
1185 | struct list_head list; | 1200 | struct list_head list; |
1186 | }; | 1201 | }; |
1187 | 1202 | ||
1203 | struct sonypi_eventtypes { | ||
1204 | u8 data; | ||
1205 | unsigned long mask; | ||
1206 | struct sonypi_event *events; | ||
1207 | }; | ||
1208 | |||
1209 | struct device_ctrl { | ||
1210 | int model; | ||
1211 | int (*handle_irq)(const u8, const u8); | ||
1212 | u16 evport_offset; | ||
1213 | u8 has_camera; | ||
1214 | u8 has_bluetooth; | ||
1215 | u8 has_wwan; | ||
1216 | struct sonypi_eventtypes *event_types; | ||
1217 | }; | ||
1218 | |||
1188 | struct sony_pic_dev { | 1219 | struct sony_pic_dev { |
1189 | int model; | 1220 | struct device_ctrl *control; |
1190 | u16 evport_offset; | ||
1191 | u8 camera_power; | ||
1192 | u8 bluetooth_power; | ||
1193 | u8 wwan_power; | ||
1194 | struct acpi_device *acpi_dev; | 1221 | struct acpi_device *acpi_dev; |
1195 | struct sony_pic_irq *cur_irq; | 1222 | struct sony_pic_irq *cur_irq; |
1196 | struct sony_pic_ioport *cur_ioport; | 1223 | struct sony_pic_ioport *cur_ioport; |
1197 | struct list_head interrupts; | 1224 | struct list_head interrupts; |
1198 | struct list_head ioports; | 1225 | struct list_head ioports; |
1199 | struct mutex lock; | 1226 | struct mutex lock; |
1227 | u8 camera_power; | ||
1228 | u8 bluetooth_power; | ||
1229 | u8 wwan_power; | ||
1200 | }; | 1230 | }; |
1201 | 1231 | ||
1202 | static struct sony_pic_dev spic_dev = { | 1232 | static struct sony_pic_dev spic_dev = { |
@@ -1253,6 +1283,7 @@ static struct sonypi_event sonypi_joggerev[] = { | |||
1253 | static struct sonypi_event sonypi_captureev[] = { | 1283 | static struct sonypi_event sonypi_captureev[] = { |
1254 | { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, | 1284 | { 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED }, |
1255 | { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, | 1285 | { 0x07, SONYPI_EVENT_CAPTURE_PRESSED }, |
1286 | { 0x40, SONYPI_EVENT_CAPTURE_PRESSED }, | ||
1256 | { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, | 1287 | { 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED }, |
1257 | { 0, 0 } | 1288 | { 0, 0 } |
1258 | }; | 1289 | }; |
@@ -1289,7 +1320,6 @@ static struct sonypi_event sonypi_pkeyev[] = { | |||
1289 | { 0x01, SONYPI_EVENT_PKEY_P1 }, | 1320 | { 0x01, SONYPI_EVENT_PKEY_P1 }, |
1290 | { 0x02, SONYPI_EVENT_PKEY_P2 }, | 1321 | { 0x02, SONYPI_EVENT_PKEY_P2 }, |
1291 | { 0x04, SONYPI_EVENT_PKEY_P3 }, | 1322 | { 0x04, SONYPI_EVENT_PKEY_P3 }, |
1292 | { 0x5c, SONYPI_EVENT_PKEY_P1 }, | ||
1293 | { 0, 0 } | 1323 | { 0, 0 } |
1294 | }; | 1324 | }; |
1295 | 1325 | ||
@@ -1331,6 +1361,8 @@ static struct sonypi_event sonypi_lidev[] = { | |||
1331 | /* The set of possible zoom events */ | 1361 | /* The set of possible zoom events */ |
1332 | static struct sonypi_event sonypi_zoomev[] = { | 1362 | static struct sonypi_event sonypi_zoomev[] = { |
1333 | { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, | 1363 | { 0x39, SONYPI_EVENT_ZOOM_PRESSED }, |
1364 | { 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED }, | ||
1365 | { 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED }, | ||
1334 | { 0, 0 } | 1366 | { 0, 0 } |
1335 | }; | 1367 | }; |
1336 | 1368 | ||
@@ -1361,76 +1393,58 @@ static struct sonypi_event sonypi_batteryev[] = { | |||
1361 | { 0, 0 } | 1393 | { 0, 0 } |
1362 | }; | 1394 | }; |
1363 | 1395 | ||
1364 | static struct sonypi_eventtypes { | 1396 | static struct sonypi_eventtypes type1_events[] = { |
1365 | int model; | 1397 | { 0, 0xffffffff, sonypi_releaseev }, |
1366 | u8 data; | 1398 | { 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, |
1367 | unsigned long mask; | 1399 | { 0x30, SONYPI_LID_MASK, sonypi_lidev }, |
1368 | struct sonypi_event * events; | 1400 | { 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, |
1369 | } sony_pic_eventtypes[] = { | 1401 | { 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, |
1370 | { SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev }, | 1402 | { 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1371 | { SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev }, | 1403 | { 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, |
1372 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev }, | 1404 | { 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1373 | { SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev }, | 1405 | { 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1374 | { SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev }, | 1406 | { 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1375 | { SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1407 | { 0 }, |
1376 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, | 1408 | }; |
1377 | { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1409 | static struct sonypi_eventtypes type2_events[] = { |
1378 | { SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1410 | { 0, 0xffffffff, sonypi_releaseev }, |
1379 | { SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1411 | { 0x38, SONYPI_LID_MASK, sonypi_lidev }, |
1380 | 1412 | { 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, | |
1381 | { SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev }, | 1413 | { 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, |
1382 | { SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev }, | 1414 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1383 | { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev }, | 1415 | { 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, |
1384 | { SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev }, | 1416 | { 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1385 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1417 | { 0x11, SONYPI_BACK_MASK, sonypi_backev }, |
1386 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev }, | 1418 | { 0x21, SONYPI_HELP_MASK, sonypi_helpev }, |
1387 | { SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1419 | { 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, |
1388 | { SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev }, | 1420 | { 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, |
1389 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev }, | 1421 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1390 | { SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev }, | 1422 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1391 | { SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev }, | 1423 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1392 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1424 | { 0 }, |
1393 | { SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1425 | }; |
1394 | { SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1426 | static struct sonypi_eventtypes type3_events[] = { |
1395 | 1427 | { 0, 0xffffffff, sonypi_releaseev }, | |
1396 | { SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev }, | 1428 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, |
1397 | { SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | 1429 | { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, |
1398 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | 1430 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, |
1399 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | 1431 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, |
1400 | { SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | 1432 | { 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, |
1401 | { SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev }, | 1433 | { 0 }, |
1402 | { 0 } | 1434 | }; |
1435 | static struct sonypi_eventtypes type4_events[] = { | ||
1436 | { 0, 0xffffffff, sonypi_releaseev }, | ||
1437 | { 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev }, | ||
1438 | { 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev }, | ||
1439 | { 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev }, | ||
1440 | { 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev }, | ||
1441 | { 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev }, | ||
1442 | { 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev }, | ||
1443 | { 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev }, | ||
1444 | { 0 }, | ||
1403 | }; | 1445 | }; |
1404 | 1446 | ||
1405 | static int sony_pic_detect_device_type(void) | 1447 | /* low level spic calls */ |
1406 | { | ||
1407 | struct pci_dev *pcidev; | ||
1408 | int model = 0; | ||
1409 | |||
1410 | if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1411 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL))) | ||
1412 | model = SONYPI_DEVICE_TYPE1; | ||
1413 | |||
1414 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1415 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL))) | ||
1416 | model = SONYPI_DEVICE_TYPE3; | ||
1417 | |||
1418 | else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1419 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL))) | ||
1420 | model = SONYPI_DEVICE_TYPE3; | ||
1421 | |||
1422 | else | ||
1423 | model = SONYPI_DEVICE_TYPE2; | ||
1424 | |||
1425 | if (pcidev) | ||
1426 | pci_dev_put(pcidev); | ||
1427 | |||
1428 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", | ||
1429 | model == SONYPI_DEVICE_TYPE1 ? 1 : | ||
1430 | model == SONYPI_DEVICE_TYPE2 ? 2 : 3); | ||
1431 | return model; | ||
1432 | } | ||
1433 | |||
1434 | #define ITERATIONS_LONG 10000 | 1448 | #define ITERATIONS_LONG 10000 |
1435 | #define ITERATIONS_SHORT 10 | 1449 | #define ITERATIONS_SHORT 10 |
1436 | #define wait_on_command(command, iterations) { \ | 1450 | #define wait_on_command(command, iterations) { \ |
@@ -1451,7 +1465,7 @@ static u8 sony_pic_call1(u8 dev) | |||
1451 | outb(dev, spic_dev.cur_ioport->io1.minimum + 4); | 1465 | outb(dev, spic_dev.cur_ioport->io1.minimum + 4); |
1452 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); | 1466 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum + 4); |
1453 | v2 = inb_p(spic_dev.cur_ioport->io1.minimum); | 1467 | v2 = inb_p(spic_dev.cur_ioport->io1.minimum); |
1454 | dprintk("sony_pic_call1: 0x%.4x\n", (v2 << 8) | v1); | 1468 | dprintk("sony_pic_call1(0x%.2x): 0x%.4x\n", dev, (v2 << 8) | v1); |
1455 | return v2; | 1469 | return v2; |
1456 | } | 1470 | } |
1457 | 1471 | ||
@@ -1466,7 +1480,7 @@ static u8 sony_pic_call2(u8 dev, u8 fn) | |||
1466 | ITERATIONS_LONG); | 1480 | ITERATIONS_LONG); |
1467 | outb(fn, spic_dev.cur_ioport->io1.minimum); | 1481 | outb(fn, spic_dev.cur_ioport->io1.minimum); |
1468 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); | 1482 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); |
1469 | dprintk("sony_pic_call2: 0x%.4x\n", v1); | 1483 | dprintk("sony_pic_call2(0x%.2x - 0x%.2x): 0x%.4x\n", dev, fn, v1); |
1470 | return v1; | 1484 | return v1; |
1471 | } | 1485 | } |
1472 | 1486 | ||
@@ -1481,10 +1495,105 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v) | |||
1481 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); | 1495 | wait_on_command(inb_p(spic_dev.cur_ioport->io1.minimum + 4) & 2, ITERATIONS_LONG); |
1482 | outb(v, spic_dev.cur_ioport->io1.minimum); | 1496 | outb(v, spic_dev.cur_ioport->io1.minimum); |
1483 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); | 1497 | v1 = inb_p(spic_dev.cur_ioport->io1.minimum); |
1484 | dprintk("sony_pic_call3: 0x%.4x\n", v1); | 1498 | dprintk("sony_pic_call3(0x%.2x - 0x%.2x - 0x%.2x): 0x%.4x\n", |
1499 | dev, fn, v, v1); | ||
1485 | return v1; | 1500 | return v1; |
1486 | } | 1501 | } |
1487 | 1502 | ||
1503 | /* | ||
1504 | * minidrivers for SPIC models | ||
1505 | */ | ||
1506 | static int type4_handle_irq(const u8 data_mask, const u8 ev) | ||
1507 | { | ||
1508 | /* | ||
1509 | * 0x31 could mean we have to take some extra action and wait for | ||
1510 | * the next irq for some Type4 models, it will generate a new | ||
1511 | * irq and we can read new data from the device: | ||
1512 | * - 0x5c and 0x5f requires 0xA0 | ||
1513 | * - 0x61 requires 0xB3 | ||
1514 | */ | ||
1515 | if (data_mask == 0x31) { | ||
1516 | if (ev == 0x5c || ev == 0x5f) | ||
1517 | sony_pic_call1(0xA0); | ||
1518 | else if (ev == 0x61) | ||
1519 | sony_pic_call1(0xB3); | ||
1520 | return 0; | ||
1521 | } | ||
1522 | return 1; | ||
1523 | } | ||
1524 | |||
1525 | static struct device_ctrl spic_types[] = { | ||
1526 | { | ||
1527 | .model = SONYPI_DEVICE_TYPE1, | ||
1528 | .handle_irq = NULL, | ||
1529 | .evport_offset = SONYPI_TYPE1_OFFSET, | ||
1530 | .event_types = type1_events, | ||
1531 | }, | ||
1532 | { | ||
1533 | .model = SONYPI_DEVICE_TYPE2, | ||
1534 | .handle_irq = NULL, | ||
1535 | .evport_offset = SONYPI_TYPE2_OFFSET, | ||
1536 | .event_types = type2_events, | ||
1537 | }, | ||
1538 | { | ||
1539 | .model = SONYPI_DEVICE_TYPE3, | ||
1540 | .handle_irq = NULL, | ||
1541 | .evport_offset = SONYPI_TYPE3_OFFSET, | ||
1542 | .event_types = type3_events, | ||
1543 | }, | ||
1544 | { | ||
1545 | .model = SONYPI_DEVICE_TYPE4, | ||
1546 | .handle_irq = type4_handle_irq, | ||
1547 | .evport_offset = SONYPI_TYPE4_OFFSET, | ||
1548 | .event_types = type4_events, | ||
1549 | }, | ||
1550 | }; | ||
1551 | |||
1552 | static void sony_pic_detect_device_type(struct sony_pic_dev *dev) | ||
1553 | { | ||
1554 | struct pci_dev *pcidev; | ||
1555 | |||
1556 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1557 | PCI_DEVICE_ID_INTEL_82371AB_3, NULL); | ||
1558 | if (pcidev) { | ||
1559 | dev->control = &spic_types[0]; | ||
1560 | goto out; | ||
1561 | } | ||
1562 | |||
1563 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1564 | PCI_DEVICE_ID_INTEL_ICH6_1, NULL); | ||
1565 | if (pcidev) { | ||
1566 | dev->control = &spic_types[2]; | ||
1567 | goto out; | ||
1568 | } | ||
1569 | |||
1570 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1571 | PCI_DEVICE_ID_INTEL_ICH7_1, NULL); | ||
1572 | if (pcidev) { | ||
1573 | dev->control = &spic_types[3]; | ||
1574 | goto out; | ||
1575 | } | ||
1576 | |||
1577 | pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, | ||
1578 | PCI_DEVICE_ID_INTEL_ICH8_4, NULL); | ||
1579 | if (pcidev) { | ||
1580 | dev->control = &spic_types[3]; | ||
1581 | goto out; | ||
1582 | } | ||
1583 | |||
1584 | /* default */ | ||
1585 | dev->control = &spic_types[1]; | ||
1586 | |||
1587 | out: | ||
1588 | if (pcidev) | ||
1589 | pci_dev_put(pcidev); | ||
1590 | |||
1591 | printk(KERN_INFO DRV_PFX "detected Type%d model\n", | ||
1592 | dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 : | ||
1593 | dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : | ||
1594 | dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4); | ||
1595 | } | ||
1596 | |||
1488 | /* camera tests and poweron/poweroff */ | 1597 | /* camera tests and poweron/poweroff */ |
1489 | #define SONYPI_CAMERA_PICTURE 5 | 1598 | #define SONYPI_CAMERA_PICTURE 5 |
1490 | #define SONYPI_CAMERA_CONTROL 0x10 | 1599 | #define SONYPI_CAMERA_CONTROL 0x10 |
@@ -2253,7 +2362,7 @@ static int sony_pic_enable(struct acpi_device *device, | |||
2253 | buffer.pointer = resource; | 2362 | buffer.pointer = resource; |
2254 | 2363 | ||
2255 | /* setup Type 1 resources */ | 2364 | /* setup Type 1 resources */ |
2256 | if (spic_dev.model == SONYPI_DEVICE_TYPE1) { | 2365 | if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) { |
2257 | 2366 | ||
2258 | /* setup io resources */ | 2367 | /* setup io resources */ |
2259 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; | 2368 | resource->res1.type = ACPI_RESOURCE_TYPE_IO; |
@@ -2335,39 +2444,49 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id) | |||
2335 | if (dev->cur_ioport->io2.minimum) | 2444 | if (dev->cur_ioport->io2.minimum) |
2336 | data_mask = inb_p(dev->cur_ioport->io2.minimum); | 2445 | data_mask = inb_p(dev->cur_ioport->io2.minimum); |
2337 | else | 2446 | else |
2338 | data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset); | 2447 | data_mask = inb_p(dev->cur_ioport->io1.minimum + |
2448 | dev->control->evport_offset); | ||
2339 | 2449 | ||
2340 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", | 2450 | dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", |
2341 | ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset); | 2451 | ev, data_mask, dev->cur_ioport->io1.minimum, |
2452 | dev->control->evport_offset); | ||
2342 | 2453 | ||
2343 | if (ev == 0x00 || ev == 0xff) | 2454 | if (ev == 0x00 || ev == 0xff) |
2344 | return IRQ_HANDLED; | 2455 | return IRQ_HANDLED; |
2345 | 2456 | ||
2346 | for (i = 0; sony_pic_eventtypes[i].model; i++) { | 2457 | for (i = 0; dev->control->event_types[i].mask; i++) { |
2347 | |||
2348 | if (spic_dev.model != sony_pic_eventtypes[i].model) | ||
2349 | continue; | ||
2350 | 2458 | ||
2351 | if ((data_mask & sony_pic_eventtypes[i].data) != | 2459 | if ((data_mask & dev->control->event_types[i].data) != |
2352 | sony_pic_eventtypes[i].data) | 2460 | dev->control->event_types[i].data) |
2353 | continue; | 2461 | continue; |
2354 | 2462 | ||
2355 | if (!(mask & sony_pic_eventtypes[i].mask)) | 2463 | if (!(mask & dev->control->event_types[i].mask)) |
2356 | continue; | 2464 | continue; |
2357 | 2465 | ||
2358 | for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) { | 2466 | for (j = 0; dev->control->event_types[i].events[j].event; j++) { |
2359 | if (ev == sony_pic_eventtypes[i].events[j].data) { | 2467 | if (ev == dev->control->event_types[i].events[j].data) { |
2360 | device_event = | 2468 | device_event = |
2361 | sony_pic_eventtypes[i].events[j].event; | 2469 | dev->control-> |
2470 | event_types[i].events[j].event; | ||
2362 | goto found; | 2471 | goto found; |
2363 | } | 2472 | } |
2364 | } | 2473 | } |
2365 | } | 2474 | } |
2475 | /* Still not able to decode the event try to pass | ||
2476 | * it over to the minidriver | ||
2477 | */ | ||
2478 | if (dev->control->handle_irq && | ||
2479 | dev->control->handle_irq(data_mask, ev) == 0) | ||
2480 | return IRQ_HANDLED; | ||
2481 | |||
2482 | dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n", | ||
2483 | ev, data_mask, dev->cur_ioport->io1.minimum, | ||
2484 | dev->control->evport_offset); | ||
2366 | return IRQ_HANDLED; | 2485 | return IRQ_HANDLED; |
2367 | 2486 | ||
2368 | found: | 2487 | found: |
2369 | sony_laptop_report_input_event(device_event); | 2488 | sony_laptop_report_input_event(device_event); |
2370 | acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event); | 2489 | acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event); |
2371 | sonypi_compat_report_event(device_event); | 2490 | sonypi_compat_report_event(device_event); |
2372 | 2491 | ||
2373 | return IRQ_HANDLED; | 2492 | return IRQ_HANDLED; |
@@ -2429,23 +2548,9 @@ static int sony_pic_add(struct acpi_device *device) | |||
2429 | 2548 | ||
2430 | spic_dev.acpi_dev = device; | 2549 | spic_dev.acpi_dev = device; |
2431 | strcpy(acpi_device_class(device), "sony/hotkey"); | 2550 | strcpy(acpi_device_class(device), "sony/hotkey"); |
2432 | spic_dev.model = sony_pic_detect_device_type(); | 2551 | sony_pic_detect_device_type(&spic_dev); |
2433 | mutex_init(&spic_dev.lock); | 2552 | mutex_init(&spic_dev.lock); |
2434 | 2553 | ||
2435 | /* model specific characteristics */ | ||
2436 | switch(spic_dev.model) { | ||
2437 | case SONYPI_DEVICE_TYPE1: | ||
2438 | spic_dev.evport_offset = SONYPI_TYPE1_OFFSET; | ||
2439 | break; | ||
2440 | case SONYPI_DEVICE_TYPE3: | ||
2441 | spic_dev.evport_offset = SONYPI_TYPE3_OFFSET; | ||
2442 | break; | ||
2443 | case SONYPI_DEVICE_TYPE2: | ||
2444 | default: | ||
2445 | spic_dev.evport_offset = SONYPI_TYPE2_OFFSET; | ||
2446 | break; | ||
2447 | } | ||
2448 | |||
2449 | /* read _PRS resources */ | 2554 | /* read _PRS resources */ |
2450 | result = sony_pic_possible_resources(device); | 2555 | result = sony_pic_possible_resources(device); |
2451 | if (result) { | 2556 | if (result) { |