Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3eb8749a authored by Mattia Dongili's avatar Mattia Dongili Committed by Len Brown
Browse files

sony-laptop: add Type4 model



Recent Vaio models (UX, SZ and presumably TZ and others) add more
events and a slightly different handling of Fn key events for
additional hotkeys (s1, s2, zoom-in/out, etc.).

Signed-off-by: default avatarMattia Dongili <malattia@linux.it>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 425ef5d7
Loading
Loading
Loading
Loading
+184 −111
Original line number Original line Diff line number Diff line
@@ -146,68 +146,70 @@ struct sony_laptop_keypress {
 * and input layer indexes in the keymap
 * and input layer indexes in the keymap
 */
 */
static int sony_laptop_input_index[] = {
static int sony_laptop_input_index[] = {
	-1,	/* no event */
	-1,	/*  0 no event */
	-1,	/* SONYPI_EVENT_JOGDIAL_DOWN */
	-1,	/*  1 SONYPI_EVENT_JOGDIAL_DOWN */
	-1,	/* SONYPI_EVENT_JOGDIAL_UP */
	-1,	/*  2 SONYPI_EVENT_JOGDIAL_UP */
	-1,	/* SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
	-1,	/*  3 SONYPI_EVENT_JOGDIAL_DOWN_PRESSED */
	-1,	/* SONYPI_EVENT_JOGDIAL_UP_PRESSED */
	-1,	/*  4 SONYPI_EVENT_JOGDIAL_UP_PRESSED */
	-1,	/* SONYPI_EVENT_JOGDIAL_PRESSED */
	-1,	/*  5 SONYPI_EVENT_JOGDIAL_PRESSED */
	-1,	/* SONYPI_EVENT_JOGDIAL_RELEASED */
	-1,	/*  6 SONYPI_EVENT_JOGDIAL_RELEASED */
	 0,	/* SONYPI_EVENT_CAPTURE_PRESSED */
	 0,	/*  7 SONYPI_EVENT_CAPTURE_PRESSED */
	 1,	/* SONYPI_EVENT_CAPTURE_RELEASED */
	 1,	/*  8 SONYPI_EVENT_CAPTURE_RELEASED */
	 2,	/* SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
	 2,	/*  9 SONYPI_EVENT_CAPTURE_PARTIALPRESSED */
	 3,	/* SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
	 3,	/* 10 SONYPI_EVENT_CAPTURE_PARTIALRELEASED */
	 4,	/* SONYPI_EVENT_FNKEY_ESC */
	 4,	/* 11 SONYPI_EVENT_FNKEY_ESC */
	 5,	/* SONYPI_EVENT_FNKEY_F1 */
	 5,	/* 12 SONYPI_EVENT_FNKEY_F1 */
	 6,	/* SONYPI_EVENT_FNKEY_F2 */
	 6,	/* 13 SONYPI_EVENT_FNKEY_F2 */
	 7,	/* SONYPI_EVENT_FNKEY_F3 */
	 7,	/* 14 SONYPI_EVENT_FNKEY_F3 */
	 8,	/* SONYPI_EVENT_FNKEY_F4 */
	 8,	/* 15 SONYPI_EVENT_FNKEY_F4 */
	 9,	/* SONYPI_EVENT_FNKEY_F5 */
	 9,	/* 16 SONYPI_EVENT_FNKEY_F5 */
	10,	/* SONYPI_EVENT_FNKEY_F6 */
	10,	/* 17 SONYPI_EVENT_FNKEY_F6 */
	11,	/* SONYPI_EVENT_FNKEY_F7 */
	11,	/* 18 SONYPI_EVENT_FNKEY_F7 */
	12,	/* SONYPI_EVENT_FNKEY_F8 */
	12,	/* 19 SONYPI_EVENT_FNKEY_F8 */
	13,	/* SONYPI_EVENT_FNKEY_F9 */
	13,	/* 20 SONYPI_EVENT_FNKEY_F9 */
	14,	/* SONYPI_EVENT_FNKEY_F10 */
	14,	/* 21 SONYPI_EVENT_FNKEY_F10 */
	15,	/* SONYPI_EVENT_FNKEY_F11 */
	15,	/* 22 SONYPI_EVENT_FNKEY_F11 */
	16,	/* SONYPI_EVENT_FNKEY_F12 */
	16,	/* 23 SONYPI_EVENT_FNKEY_F12 */
	17,	/* SONYPI_EVENT_FNKEY_1 */
	17,	/* 24 SONYPI_EVENT_FNKEY_1 */
	18,	/* SONYPI_EVENT_FNKEY_2 */
	18,	/* 25 SONYPI_EVENT_FNKEY_2 */
	19,	/* SONYPI_EVENT_FNKEY_D */
	19,	/* 26 SONYPI_EVENT_FNKEY_D */
	20,	/* SONYPI_EVENT_FNKEY_E */
	20,	/* 27 SONYPI_EVENT_FNKEY_E */
	21,	/* SONYPI_EVENT_FNKEY_F */
	21,	/* 28 SONYPI_EVENT_FNKEY_F */
	22,	/* SONYPI_EVENT_FNKEY_S */
	22,	/* 29 SONYPI_EVENT_FNKEY_S */
	23,	/* SONYPI_EVENT_FNKEY_B */
	23,	/* 30 SONYPI_EVENT_FNKEY_B */
	24,	/* SONYPI_EVENT_BLUETOOTH_PRESSED */
	24,	/* 31 SONYPI_EVENT_BLUETOOTH_PRESSED */
	25,	/* SONYPI_EVENT_PKEY_P1 */
	25,	/* 32 SONYPI_EVENT_PKEY_P1 */
	26,	/* SONYPI_EVENT_PKEY_P2 */
	26,	/* 33 SONYPI_EVENT_PKEY_P2 */
	27,	/* SONYPI_EVENT_PKEY_P3 */
	27,	/* 34 SONYPI_EVENT_PKEY_P3 */
	28,	/* SONYPI_EVENT_BACK_PRESSED */
	28,	/* 35 SONYPI_EVENT_BACK_PRESSED */
	-1,	/* SONYPI_EVENT_LID_CLOSED */
	-1,	/* 36 SONYPI_EVENT_LID_CLOSED */
	-1,	/* SONYPI_EVENT_LID_OPENED */
	-1,	/* 37 SONYPI_EVENT_LID_OPENED */
	29,	/* SONYPI_EVENT_BLUETOOTH_ON */
	29,	/* 38 SONYPI_EVENT_BLUETOOTH_ON */
	30,	/* SONYPI_EVENT_BLUETOOTH_OFF */
	30,	/* 39 SONYPI_EVENT_BLUETOOTH_OFF */
	31,	/* SONYPI_EVENT_HELP_PRESSED */
	31,	/* 40 SONYPI_EVENT_HELP_PRESSED */
	32,	/* SONYPI_EVENT_FNKEY_ONLY */
	32,	/* 41 SONYPI_EVENT_FNKEY_ONLY */
	33,	/* SONYPI_EVENT_JOGDIAL_FAST_DOWN */
	33,	/* 42 SONYPI_EVENT_JOGDIAL_FAST_DOWN */
	34,	/* SONYPI_EVENT_JOGDIAL_FAST_UP */
	34,	/* 43 SONYPI_EVENT_JOGDIAL_FAST_UP */
	35,	/* SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
	35,	/* 44 SONYPI_EVENT_JOGDIAL_FAST_DOWN_PRESSED */
	36,	/* SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
	36,	/* 45 SONYPI_EVENT_JOGDIAL_FAST_UP_PRESSED */
	37,	/* SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
	37,	/* 46 SONYPI_EVENT_JOGDIAL_VFAST_DOWN */
	38,	/* SONYPI_EVENT_JOGDIAL_VFAST_UP */
	38,	/* 47 SONYPI_EVENT_JOGDIAL_VFAST_UP */
	39,	/* SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
	39,	/* 48 SONYPI_EVENT_JOGDIAL_VFAST_DOWN_PRESSED */
	40,	/* SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
	40,	/* 49 SONYPI_EVENT_JOGDIAL_VFAST_UP_PRESSED */
	41,	/* SONYPI_EVENT_ZOOM_PRESSED */
	41,	/* 50 SONYPI_EVENT_ZOOM_PRESSED */
	42,	/* SONYPI_EVENT_THUMBPHRASE_PRESSED */
	42,	/* 51 SONYPI_EVENT_THUMBPHRASE_PRESSED */
	43,	/* SONYPI_EVENT_MEYE_FACE */
	43,	/* 52 SONYPI_EVENT_MEYE_FACE */
	44,	/* SONYPI_EVENT_MEYE_OPPOSITE */
	44,	/* 53 SONYPI_EVENT_MEYE_OPPOSITE */
	45,	/* SONYPI_EVENT_MEMORYSTICK_INSERT */
	45,	/* 54 SONYPI_EVENT_MEMORYSTICK_INSERT */
	46,	/* SONYPI_EVENT_MEMORYSTICK_EJECT */
	46,	/* 55 SONYPI_EVENT_MEMORYSTICK_EJECT */
	-1,	/* SONYPI_EVENT_ANYBUTTON_RELEASED */
	-1,	/* 56 SONYPI_EVENT_ANYBUTTON_RELEASED */
	-1,	/* SONYPI_EVENT_BATTERY_INSERT */
	-1,	/* 57 SONYPI_EVENT_BATTERY_INSERT */
	-1,	/* SONYPI_EVENT_BATTERY_REMOVE */
	-1,	/* 58 SONYPI_EVENT_BATTERY_REMOVE */
	-1,	/* SONYPI_EVENT_FNKEY_RELEASED */
	-1,	/* 59 SONYPI_EVENT_FNKEY_RELEASED */
	47,	/* SONYPI_EVENT_WIRELESS_ON */
	47,	/* 60 SONYPI_EVENT_WIRELESS_ON */
	48,	/* SONYPI_EVENT_WIRELESS_OFF */
	48,	/* 61 SONYPI_EVENT_WIRELESS_OFF */
	49,	/* 62 SONYPI_EVENT_ZOOM_IN_PRESSED */
	50,	/* 63 SONYPI_EVENT_ZOOM_OUT_PRESSED */
};
};


static int sony_laptop_input_keycode_map[] = {
static int sony_laptop_input_keycode_map[] = {
@@ -260,6 +262,8 @@ static int sony_laptop_input_keycode_map[] = {
	KEY_RESERVED,	/* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
	KEY_RESERVED,	/* 46 SONYPI_EVENT_MEMORYSTICK_EJECT */
	KEY_WLAN,	/* 47 SONYPI_EVENT_WIRELESS_ON */
	KEY_WLAN,	/* 47 SONYPI_EVENT_WIRELESS_ON */
	KEY_WLAN,	/* 48 SONYPI_EVENT_WIRELESS_OFF */
	KEY_WLAN,	/* 48 SONYPI_EVENT_WIRELESS_OFF */
	KEY_ZOOMIN,	/* 49 SONYPI_EVENT_ZOOM_IN_PRESSED */
	KEY_ZOOMOUT	/* 50 SONYPI_EVENT_ZOOM_OUT_PRESSED */
};
};


/* release buttons after a short delay if pressed */
/* release buttons after a short delay if pressed */
@@ -1178,10 +1182,12 @@ static struct acpi_driver sony_nc_driver = {
#define SONYPI_DEVICE_TYPE1	0x00000001
#define SONYPI_DEVICE_TYPE1	0x00000001
#define SONYPI_DEVICE_TYPE2	0x00000002
#define SONYPI_DEVICE_TYPE2	0x00000002
#define SONYPI_DEVICE_TYPE3	0x00000004
#define SONYPI_DEVICE_TYPE3	0x00000004
#define SONYPI_DEVICE_TYPE4	0x00000008


#define SONYPI_TYPE1_OFFSET	0x04
#define SONYPI_TYPE1_OFFSET	0x04
#define SONYPI_TYPE2_OFFSET	0x12
#define SONYPI_TYPE2_OFFSET	0x12
#define SONYPI_TYPE3_OFFSET	0x12
#define SONYPI_TYPE3_OFFSET	0x12
#define SONYPI_TYPE4_OFFSET	0x12


struct sony_pic_ioport {
struct sony_pic_ioport {
	struct acpi_resource_io	io1;
	struct acpi_resource_io	io1;
@@ -1202,7 +1208,7 @@ struct sonypi_eventtypes {


struct device_ctrl {
struct device_ctrl {
	int				model;
	int				model;
	int				(*handle_irq)(void);
	int				(*handle_irq)(const u8, const u8);
	u16				evport_offset;
	u16				evport_offset;
	u8				has_camera;
	u8				has_camera;
	u8				has_bluetooth;
	u8				has_bluetooth;
@@ -1277,6 +1283,7 @@ static struct sonypi_event sonypi_joggerev[] = {
static struct sonypi_event sonypi_captureev[] = {
static struct sonypi_event sonypi_captureev[] = {
	{ 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
	{ 0x05, SONYPI_EVENT_CAPTURE_PARTIALPRESSED },
	{ 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
	{ 0x07, SONYPI_EVENT_CAPTURE_PRESSED },
	{ 0x40, SONYPI_EVENT_CAPTURE_PRESSED },
	{ 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
	{ 0x01, SONYPI_EVENT_CAPTURE_PARTIALRELEASED },
	{ 0, 0 }
	{ 0, 0 }
};
};
@@ -1313,7 +1320,6 @@ static struct sonypi_event sonypi_pkeyev[] = {
	{ 0x01, SONYPI_EVENT_PKEY_P1 },
	{ 0x01, SONYPI_EVENT_PKEY_P1 },
	{ 0x02, SONYPI_EVENT_PKEY_P2 },
	{ 0x02, SONYPI_EVENT_PKEY_P2 },
	{ 0x04, SONYPI_EVENT_PKEY_P3 },
	{ 0x04, SONYPI_EVENT_PKEY_P3 },
	{ 0x5c, SONYPI_EVENT_PKEY_P1 },
	{ 0, 0 }
	{ 0, 0 }
};
};


@@ -1355,6 +1361,8 @@ static struct sonypi_event sonypi_lidev[] = {
/* The set of possible zoom events */
/* The set of possible zoom events */
static struct sonypi_event sonypi_zoomev[] = {
static struct sonypi_event sonypi_zoomev[] = {
	{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
	{ 0x39, SONYPI_EVENT_ZOOM_PRESSED },
	{ 0x10, SONYPI_EVENT_ZOOM_IN_PRESSED },
	{ 0x20, SONYPI_EVENT_ZOOM_OUT_PRESSED },
	{ 0, 0 }
	{ 0, 0 }
};
};


@@ -1424,55 +1432,19 @@ static struct sonypi_eventtypes type3_events[] = {
	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
	{ 0 },
	{ 0 },
};
};

static struct sonypi_eventtypes type4_events[] = {
static struct device_ctrl spic_types[] = {
	{ 0, 0xffffffff, sonypi_releaseev },
	{
	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
		.model = SONYPI_DEVICE_TYPE1,
	{ 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
		.handle_irq = NULL,
	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
		.evport_offset = SONYPI_TYPE1_OFFSET,
	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
		.event_types = type1_events,
	{ 0x05, SONYPI_PKEY_MASK, sonypi_pkeyev },
	},
	{ 0x05, SONYPI_ZOOM_MASK, sonypi_zoomev },
	{
	{ 0x05, SONYPI_CAPTURE_MASK, sonypi_captureev },
		.model = SONYPI_DEVICE_TYPE2,
	{ 0 },
		.handle_irq = NULL,
		.evport_offset = SONYPI_TYPE2_OFFSET,
		.event_types = type2_events,
	},
	{
		.model = SONYPI_DEVICE_TYPE3,
		.handle_irq = NULL,
		.evport_offset = SONYPI_TYPE3_OFFSET,
		.event_types = type3_events,
	},
};
};


static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
/* low level spic calls */
{
	struct pci_dev *pcidev;

	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
		dev->control = &spic_types[0];

	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
		dev->control = &spic_types[2];

	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
		dev->control = &spic_types[2];

	else
		dev->control = &spic_types[1];

	if (pcidev)
		pci_dev_put(pcidev);

	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
}

#define ITERATIONS_LONG		10000
#define ITERATIONS_LONG		10000
#define ITERATIONS_SHORT	10
#define ITERATIONS_SHORT	10
#define wait_on_command(command, iterations) {				\
#define wait_on_command(command, iterations) {				\
@@ -1528,6 +1500,100 @@ static u8 sony_pic_call3(u8 dev, u8 fn, u8 v)
	return v1;
	return v1;
}
}


/*
 * minidrivers for SPIC models
 */
static int type4_handle_irq(const u8 data_mask, const u8 ev)
{
	/*
	 * 0x31 could mean we have to take some extra action and wait for
	 * the next irq for some Type4 models, it will generate a new
	 * irq and we can read new data from the device:
	 *  - 0x5c and 0x5f requires 0xA0
	 *  - 0x61 requires 0xB3
	 */
	if (data_mask == 0x31) {
		if (ev == 0x5c || ev == 0x5f)
			sony_pic_call1(0xA0);
		else if (ev == 0x61)
			sony_pic_call1(0xB3);
		return 0;
	}
	return 1;
}

static struct device_ctrl spic_types[] = {
	{
		.model = SONYPI_DEVICE_TYPE1,
		.handle_irq = NULL,
		.evport_offset = SONYPI_TYPE1_OFFSET,
		.event_types = type1_events,
	},
	{
		.model = SONYPI_DEVICE_TYPE2,
		.handle_irq = NULL,
		.evport_offset = SONYPI_TYPE2_OFFSET,
		.event_types = type2_events,
	},
	{
		.model = SONYPI_DEVICE_TYPE3,
		.handle_irq = NULL,
		.evport_offset = SONYPI_TYPE3_OFFSET,
		.event_types = type3_events,
	},
	{
		.model = SONYPI_DEVICE_TYPE4,
		.handle_irq = type4_handle_irq,
		.evport_offset = SONYPI_TYPE4_OFFSET,
		.event_types = type4_events,
	},
};

static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
{
	struct pci_dev *pcidev;

	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
			PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
	if (pcidev) {
		dev->control = &spic_types[0];
		goto out;
	}

	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
			PCI_DEVICE_ID_INTEL_ICH6_1, NULL);
	if (pcidev) {
		dev->control = &spic_types[2];
		goto out;
	}

	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
			PCI_DEVICE_ID_INTEL_ICH7_1, NULL);
	if (pcidev) {
		dev->control = &spic_types[3];
		goto out;
	}

	pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
			PCI_DEVICE_ID_INTEL_ICH8_4, NULL);
	if (pcidev) {
		dev->control = &spic_types[3];
		goto out;
	}

	/* default */
	dev->control = &spic_types[1];

out:
	if (pcidev)
		pci_dev_put(pcidev);

	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 :
			dev->control->model == SONYPI_DEVICE_TYPE3 ? 3 : 4);
}

/* camera tests and poweron/poweroff */
/* camera tests and poweron/poweroff */
#define SONYPI_CAMERA_PICTURE		5
#define SONYPI_CAMERA_PICTURE		5
#define SONYPI_CAMERA_CONTROL		0x10
#define SONYPI_CAMERA_CONTROL		0x10
@@ -2406,6 +2472,13 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
			}
			}
		}
		}
	}
	}
	/* Still not able to decode the event try to pass
	 * it over to the minidriver
	 */
	if (dev->control->handle_irq &&
			dev->control->handle_irq(data_mask, ev) == 0)
		return IRQ_HANDLED;

	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
			ev, data_mask, dev->cur_ioport->io1.minimum,
			ev, data_mask, dev->cur_ioport->io1.minimum,
			dev->control->evport_offset);
			dev->control->evport_offset);
+2 −0
Original line number Original line Diff line number Diff line
@@ -101,6 +101,8 @@
#define SONYPI_EVENT_FNKEY_RELEASED		59
#define SONYPI_EVENT_FNKEY_RELEASED		59
#define SONYPI_EVENT_WIRELESS_ON		60
#define SONYPI_EVENT_WIRELESS_ON		60
#define SONYPI_EVENT_WIRELESS_OFF		61
#define SONYPI_EVENT_WIRELESS_OFF		61
#define SONYPI_EVENT_ZOOM_IN_PRESSED		62
#define SONYPI_EVENT_ZOOM_OUT_PRESSED		63


/* get/set brightness */
/* get/set brightness */
#define SONYPI_IOCGBRT		_IOR('v', 0, __u8)
#define SONYPI_IOCGBRT		_IOR('v', 0, __u8)