aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc/sony-laptop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/misc/sony-laptop.c')
-rw-r--r--drivers/misc/sony-laptop.c445
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 */
148static int sony_laptop_input_index[] = { 148static 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
213static int sony_laptop_input_keycode_map[] = { 215static 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
1177struct sony_pic_ioport { 1192struct 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
1203struct sonypi_eventtypes {
1204 u8 data;
1205 unsigned long mask;
1206 struct sonypi_event *events;
1207};
1208
1209struct 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
1188struct sony_pic_dev { 1219struct 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
1202static struct sony_pic_dev spic_dev = { 1232static struct sony_pic_dev spic_dev = {
@@ -1253,6 +1283,7 @@ static struct sonypi_event sonypi_joggerev[] = {
1253static struct sonypi_event sonypi_captureev[] = { 1283static 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 */
1332static struct sonypi_event sonypi_zoomev[] = { 1362static 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
1364static struct sonypi_eventtypes { 1396static 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 }, 1409static 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 }, 1426static 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};
1435static 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
1405static 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 */
1506static 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
1525static 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
1552static 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
1587out:
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
2368found: 2487found:
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) {