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>
This commit is contained in:
Mattia Dongili 2008-01-14 18:05:43 +09:00 committed by Len Brown
parent 88877c2a2e
commit de92043001

View File

@ -1194,18 +1194,33 @@ struct sony_pic_irq {
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 {
int model;
u16 evport_offset;
u8 camera_power;
u8 bluetooth_power;
u8 wwan_power;
struct device_ctrl *control;
struct acpi_device *acpi_dev;
struct sony_pic_irq *cur_irq;
struct sony_pic_ioport *cur_ioport;
struct list_head interrupts;
struct list_head ioports;
struct mutex lock;
u8 camera_power;
u8 bluetooth_power;
u8 wwan_power;
};
static struct sony_pic_dev spic_dev = {
@ -1370,74 +1385,92 @@ static struct sonypi_event sonypi_batteryev[] = {
{ 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;
int model = 0;
if ((pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
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,
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,
PCI_DEVICE_ID_INTEL_ICH7_1, NULL)))
model = SONYPI_DEVICE_TYPE3;
dev->control = &spic_types[2];
else
model = SONYPI_DEVICE_TYPE2;
dev->control = &spic_types[1];
if (pcidev)
pci_dev_put(pcidev);
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
@ -2263,7 +2296,7 @@ static int sony_pic_enable(struct acpi_device *device,
buffer.pointer = resource;
/* setup Type 1 resources */
if (spic_dev.model == SONYPI_DEVICE_TYPE1) {
if (spic_dev.control->model == SONYPI_DEVICE_TYPE1) {
/* setup io resources */
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)
data_mask = inb_p(dev->cur_ioport->io2.minimum);
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",
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)
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;
if ((data_mask & sony_pic_eventtypes[i].data) !=
sony_pic_eventtypes[i].data)
if (!(mask & dev->control->event_types[i].mask))
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 =
sony_pic_eventtypes[i].events[j].event;
dev->control->
event_types[i].events[j].event;
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;
found:
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);
return IRQ_HANDLED;
@ -2439,23 +2475,9 @@ static int sony_pic_add(struct acpi_device *device)
spic_dev.acpi_dev = device;
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);
/* 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 */
result = sony_pic_possible_resources(device);
if (result) {