Browse Source

sony-laptop: refactor model types

Create mini drivers and allow callbacks for each model
to be specified.
Following patches will make use of this feature to handle
specific cases instead of just executing code and hope
not to break other models.

Signed-off-by: Mattia Dongili <malattia@linux.it>
Signed-off-by: Len Brown <len.brown@intel.com>
Mattia Dongili 17 năm trước cách đây
mục cha
commit
de92043001
1 tập tin đã thay đổi với 104 bổ sung82 xóa
  1. 104 82
      drivers/misc/sony-laptop.c

+ 104 - 82
drivers/misc/sony-laptop.c

@@ -1194,18 +1194,33 @@ struct sony_pic_irq {
 	struct list_head		list;
 	struct list_head		list;
 };
 };
 
 
+struct sonypi_eventtypes {
+	u8			data;
+	unsigned long		mask;
+	struct sonypi_event	*events;
+};
+
+struct device_ctrl {
+	int				model;
+	int				(*handle_irq)(void);
+	u16				evport_offset;
+	u8				has_camera;
+	u8				has_bluetooth;
+	u8				has_wwan;
+	struct sonypi_eventtypes	*event_types;
+};
+
 struct sony_pic_dev {
 struct sony_pic_dev {
-	int			model;
-	u16			evport_offset;
-	u8			camera_power;
-	u8			bluetooth_power;
-	u8			wwan_power;
+	struct device_ctrl	*control;
 	struct acpi_device	*acpi_dev;
 	struct acpi_device	*acpi_dev;
 	struct sony_pic_irq	*cur_irq;
 	struct sony_pic_irq	*cur_irq;
 	struct sony_pic_ioport	*cur_ioport;
 	struct sony_pic_ioport	*cur_ioport;
 	struct list_head	interrupts;
 	struct list_head	interrupts;
 	struct list_head	ioports;
 	struct list_head	ioports;
 	struct mutex		lock;
 	struct mutex		lock;
+	u8			camera_power;
+	u8			bluetooth_power;
+	u8			wwan_power;
 };
 };
 
 
 static struct sony_pic_dev spic_dev = {
 static struct sony_pic_dev spic_dev = {
@@ -1370,74 +1385,92 @@ static struct sonypi_event sonypi_batteryev[] = {
 	{ 0, 0 }
 	{ 0, 0 }
 };
 };
 
 
-static struct sonypi_eventtypes {
-	int			model;
-	u8			data;
-	unsigned long		mask;
-	struct sonypi_event *	events;
-} sony_pic_eventtypes[] = {
-	{ SONYPI_DEVICE_TYPE1, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE1, 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_LID_MASK, sonypi_lidev },
-	{ SONYPI_DEVICE_TYPE1, 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
-	{ SONYPI_DEVICE_TYPE1, 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
-	{ SONYPI_DEVICE_TYPE1, 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
-	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ SONYPI_DEVICE_TYPE1, 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE1, 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
-
-	{ SONYPI_DEVICE_TYPE2, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE2, 0x38, SONYPI_LID_MASK, sonypi_lidev },
-	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
-	{ SONYPI_DEVICE_TYPE2, 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
-	{ SONYPI_DEVICE_TYPE2, 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ SONYPI_DEVICE_TYPE2, 0x11, SONYPI_BACK_MASK, sonypi_backev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_HELP_MASK, sonypi_helpev },
-	{ SONYPI_DEVICE_TYPE2, 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
-	{ SONYPI_DEVICE_TYPE2, 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE2, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
-	{ SONYPI_DEVICE_TYPE2, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
-
-	{ SONYPI_DEVICE_TYPE3, 0, 0xffffffff, sonypi_releaseev },
-	{ SONYPI_DEVICE_TYPE3, 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
-	{ SONYPI_DEVICE_TYPE3, 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
-	{ SONYPI_DEVICE_TYPE3, 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
-	{ 0 }
+static struct sonypi_eventtypes type1_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x70, SONYPI_MEYE_MASK, sonypi_meyeev },
+	{ 0x30, SONYPI_LID_MASK, sonypi_lidev },
+	{ 0x60, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ 0x10, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ 0x20, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x30, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ 0x40, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0x30, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x40, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0 },
+};
+static struct sonypi_eventtypes type2_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x38, SONYPI_LID_MASK, sonypi_lidev },
+	{ 0x11, SONYPI_JOGGER_MASK, sonypi_joggerev },
+	{ 0x61, SONYPI_CAPTURE_MASK, sonypi_captureev },
+	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x31, SONYPI_BLUETOOTH_MASK, sonypi_blueev },
+	{ 0x08, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0x11, SONYPI_BACK_MASK, sonypi_backev },
+	{ 0x21, SONYPI_HELP_MASK, sonypi_helpev },
+	{ 0x21, SONYPI_ZOOM_MASK, sonypi_zoomev },
+	{ 0x20, SONYPI_THUMBPHRASE_MASK, sonypi_thumbphraseev },
+	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0 },
+};
+static struct sonypi_eventtypes type3_events[] = {
+	{ 0, 0xffffffff, sonypi_releaseev },
+	{ 0x21, SONYPI_FNKEY_MASK, sonypi_fnkeyev },
+	{ 0x31, SONYPI_WIRELESS_MASK, sonypi_wlessev },
+	{ 0x31, SONYPI_MEMORYSTICK_MASK, sonypi_memorystickev },
+	{ 0x41, SONYPI_BATTERY_MASK, sonypi_batteryev },
+	{ 0x31, SONYPI_PKEY_MASK, sonypi_pkeyev },
+	{ 0 },
 };
 };
 
 
-static int sony_pic_detect_device_type(void)
+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,
+	},
+};
+
+static void sony_pic_detect_device_type(struct sony_pic_dev *dev)
 {
 {
 	struct pci_dev *pcidev;
 	struct pci_dev *pcidev;
-	int model = 0;
 
 
 	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 	if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
 				     PCI_DEVICE_ID_INTEL_82371AB_3, NULL)))
-		model = SONYPI_DEVICE_TYPE1;
+		dev->control = &spic_types[0];
 
 
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
 					  PCI_DEVICE_ID_INTEL_ICH6_1, NULL)))
-		model = SONYPI_DEVICE_TYPE3;
+		dev->control = &spic_types[2];
 
 
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 	else if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
 					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
 					  PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
-		model = SONYPI_DEVICE_TYPE3;
+		dev->control = &spic_types[2];
 
 
 	else
 	else
-		model = SONYPI_DEVICE_TYPE2;
+		dev->control = &spic_types[1];
 
 
 	if (pcidev)
 	if (pcidev)
 		pci_dev_put(pcidev);
 		pci_dev_put(pcidev);
 
 
 	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
 	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
-			model == SONYPI_DEVICE_TYPE1 ? 1 :
-			model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
-	return model;
+			dev->control->model == SONYPI_DEVICE_TYPE1 ? 1 :
+			dev->control->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
 }
 }
 
 
 #define ITERATIONS_LONG		10000
 #define ITERATIONS_LONG		10000
@@ -2263,7 +2296,7 @@ static int sony_pic_enable(struct acpi_device *device,
 	buffer.pointer = resource;
 	buffer.pointer = resource;
 
 
 	/* setup Type 1 resources */
 	/* setup Type 1 resources */
-	if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
+	if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) {
 
 
 		/* setup io resources */
 		/* setup io resources */
 		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
 		resource->res1.type = ACPI_RESOURCE_TYPE_IO;
@@ -2345,39 +2378,42 @@ static irqreturn_t sony_pic_irq(int irq, void *dev_id)
 	if (dev->cur_ioport->io2.minimum)
 	if (dev->cur_ioport->io2.minimum)
 		data_mask = inb_p(dev->cur_ioport->io2.minimum);
 		data_mask = inb_p(dev->cur_ioport->io2.minimum);
 	else
 	else
-		data_mask = inb_p(dev->cur_ioport->io1.minimum + dev->evport_offset);
+		data_mask = inb_p(dev->cur_ioport->io1.minimum +
+				dev->control->evport_offset);
 
 
 	dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
 	dprintk("event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
-			ev, data_mask, dev->cur_ioport->io1.minimum, dev->evport_offset);
+			ev, data_mask, dev->cur_ioport->io1.minimum,
+			dev->control->evport_offset);
 
 
 	if (ev == 0x00 || ev == 0xff)
 	if (ev == 0x00 || ev == 0xff)
 		return IRQ_HANDLED;
 		return IRQ_HANDLED;
 
 
-	for (i = 0; sony_pic_eventtypes[i].model; i++) {
+	for (i = 0; dev->control->event_types[i].mask; i++) {
 
 
-		if (spic_dev.model != sony_pic_eventtypes[i].model)
+		if ((data_mask & dev->control->event_types[i].data) !=
+		    dev->control->event_types[i].data)
 			continue;
 			continue;
 
 
-		if ((data_mask & sony_pic_eventtypes[i].data) !=
-		    sony_pic_eventtypes[i].data)
+		if (!(mask & dev->control->event_types[i].mask))
 			continue;
 			continue;
 
 
-		if (!(mask & sony_pic_eventtypes[i].mask))
-			continue;
-
-		for (j = 0; sony_pic_eventtypes[i].events[j].event; j++) {
-			if (ev == sony_pic_eventtypes[i].events[j].data) {
+		for (j = 0; dev->control->event_types[i].events[j].event; j++) {
+			if (ev == dev->control->event_types[i].events[j].data) {
 				device_event =
 				device_event =
-					sony_pic_eventtypes[i].events[j].event;
+					dev->control->
+						event_types[i].events[j].event;
 				goto found;
 				goto found;
 			}
 			}
 		}
 		}
 	}
 	}
+	dprintk("unknown event ([%.2x] [%.2x]) at port 0x%.4x(+0x%.2x)\n",
+			ev, data_mask, dev->cur_ioport->io1.minimum,
+			dev->control->evport_offset);
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
 
 
 found:
 found:
 	sony_laptop_report_input_event(device_event);
 	sony_laptop_report_input_event(device_event);
-	acpi_bus_generate_proc_event(spic_dev.acpi_dev, 1, device_event);
+	acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
 	sonypi_compat_report_event(device_event);
 	sonypi_compat_report_event(device_event);
 
 
 	return IRQ_HANDLED;
 	return IRQ_HANDLED;
@@ -2439,23 +2475,9 @@ static int sony_pic_add(struct acpi_device *device)
 
 
 	spic_dev.acpi_dev = device;
 	spic_dev.acpi_dev = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");
 	strcpy(acpi_device_class(device), "sony/hotkey");
-	spic_dev.model = sony_pic_detect_device_type();
+	sony_pic_detect_device_type(&spic_dev);
 	mutex_init(&spic_dev.lock);
 	mutex_init(&spic_dev.lock);
 
 
-	/* model specific characteristics */
-	switch(spic_dev.model) {
-		case SONYPI_DEVICE_TYPE1:
-			spic_dev.evport_offset = SONYPI_TYPE1_OFFSET;
-			break;
-		case SONYPI_DEVICE_TYPE3:
-			spic_dev.evport_offset = SONYPI_TYPE3_OFFSET;
-			break;
-		case SONYPI_DEVICE_TYPE2:
-		default:
-			spic_dev.evport_offset = SONYPI_TYPE2_OFFSET;
-			break;
-	}
-
 	/* read _PRS resources */
 	/* read _PRS resources */
 	result = sony_pic_possible_resources(device);
 	result = sony_pic_possible_resources(device);
 	if (result) {
 	if (result) {