diff options
-rw-r--r-- | drivers/i2c/busses/i2c-i801.c | 50 | ||||
-rw-r--r-- | drivers/input/misc/apanel.c | 81 |
2 files changed, 76 insertions, 55 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 5123eb69a971..526625eaa84b 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c | |||
@@ -64,7 +64,7 @@ | |||
64 | #include <linux/init.h> | 64 | #include <linux/init.h> |
65 | #include <linux/i2c.h> | 65 | #include <linux/i2c.h> |
66 | #include <linux/acpi.h> | 66 | #include <linux/acpi.h> |
67 | #include <asm/io.h> | 67 | #include <linux/io.h> |
68 | 68 | ||
69 | /* I801 SMBus address offsets */ | 69 | /* I801 SMBus address offsets */ |
70 | #define SMBHSTSTS (0 + i801_smba) | 70 | #define SMBHSTSTS (0 + i801_smba) |
@@ -583,6 +583,40 @@ static struct pci_device_id i801_ids[] = { | |||
583 | 583 | ||
584 | MODULE_DEVICE_TABLE (pci, i801_ids); | 584 | MODULE_DEVICE_TABLE (pci, i801_ids); |
585 | 585 | ||
586 | #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE | ||
587 | static unsigned char apanel_addr; | ||
588 | |||
589 | /* Scan the system ROM for the signature "FJKEYINF" */ | ||
590 | static __init const void __iomem *bios_signature(const void __iomem *bios) | ||
591 | { | ||
592 | ssize_t offset; | ||
593 | const unsigned char signature[] = "FJKEYINF"; | ||
594 | |||
595 | for (offset = 0; offset < 0x10000; offset += 0x10) { | ||
596 | if (check_signature(bios + offset, signature, | ||
597 | sizeof(signature)-1)) | ||
598 | return bios + offset; | ||
599 | } | ||
600 | return NULL; | ||
601 | } | ||
602 | |||
603 | static void __init input_apanel_init(void) | ||
604 | { | ||
605 | void __iomem *bios; | ||
606 | const void __iomem *p; | ||
607 | |||
608 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | ||
609 | p = bios_signature(bios); | ||
610 | if (p) { | ||
611 | /* just use the first address */ | ||
612 | apanel_addr = readb(p + 8 + 3) >> 1; | ||
613 | } | ||
614 | iounmap(bios); | ||
615 | } | ||
616 | #else | ||
617 | static void __init input_apanel_init(void) {} | ||
618 | #endif | ||
619 | |||
586 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) | 620 | static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id) |
587 | { | 621 | { |
588 | unsigned char temp; | 622 | unsigned char temp; |
@@ -667,6 +701,19 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id | |||
667 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); | 701 | dev_err(&dev->dev, "Failed to add SMBus adapter\n"); |
668 | goto exit_release; | 702 | goto exit_release; |
669 | } | 703 | } |
704 | |||
705 | /* Register optional slaves */ | ||
706 | #if defined CONFIG_INPUT_APANEL || defined CONFIG_INPUT_APANEL_MODULE | ||
707 | if (apanel_addr) { | ||
708 | struct i2c_board_info info; | ||
709 | |||
710 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
711 | info.addr = apanel_addr; | ||
712 | strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); | ||
713 | i2c_new_device(&i801_adapter, &info); | ||
714 | } | ||
715 | #endif | ||
716 | |||
670 | return 0; | 717 | return 0; |
671 | 718 | ||
672 | exit_release: | 719 | exit_release: |
@@ -717,6 +764,7 @@ static struct pci_driver i801_driver = { | |||
717 | 764 | ||
718 | static int __init i2c_i801_init(void) | 765 | static int __init i2c_i801_init(void) |
719 | { | 766 | { |
767 | input_apanel_init(); | ||
720 | return pci_register_driver(&i801_driver); | 768 | return pci_register_driver(&i801_driver); |
721 | } | 769 | } |
722 | 770 | ||
diff --git a/drivers/input/misc/apanel.c b/drivers/input/misc/apanel.c index d82f7f727f7a..71b82434264d 100644 --- a/drivers/input/misc/apanel.c +++ b/drivers/input/misc/apanel.c | |||
@@ -57,7 +57,7 @@ static enum apanel_chip device_chip[APANEL_DEV_MAX]; | |||
57 | 57 | ||
58 | struct apanel { | 58 | struct apanel { |
59 | struct input_polled_dev *ipdev; | 59 | struct input_polled_dev *ipdev; |
60 | struct i2c_client client; | 60 | struct i2c_client *client; |
61 | unsigned short keymap[MAX_PANEL_KEYS]; | 61 | unsigned short keymap[MAX_PANEL_KEYS]; |
62 | u16 nkeys; | 62 | u16 nkeys; |
63 | u16 led_bits; | 63 | u16 led_bits; |
@@ -66,16 +66,7 @@ struct apanel { | |||
66 | }; | 66 | }; |
67 | 67 | ||
68 | 68 | ||
69 | static int apanel_probe(struct i2c_adapter *, int, int); | 69 | static int apanel_probe(struct i2c_client *, const struct i2c_device_id *); |
70 | |||
71 | /* for now, we only support one address */ | ||
72 | static unsigned short normal_i2c[] = {0, I2C_CLIENT_END}; | ||
73 | static unsigned short ignore = I2C_CLIENT_END; | ||
74 | static struct i2c_client_address_data addr_data = { | ||
75 | .normal_i2c = normal_i2c, | ||
76 | .probe = &ignore, | ||
77 | .ignore = &ignore, | ||
78 | }; | ||
79 | 70 | ||
80 | static void report_key(struct input_dev *input, unsigned keycode) | 71 | static void report_key(struct input_dev *input, unsigned keycode) |
81 | { | 72 | { |
@@ -103,12 +94,12 @@ static void apanel_poll(struct input_polled_dev *ipdev) | |||
103 | s32 data; | 94 | s32 data; |
104 | int i; | 95 | int i; |
105 | 96 | ||
106 | data = i2c_smbus_read_word_data(&ap->client, cmd); | 97 | data = i2c_smbus_read_word_data(ap->client, cmd); |
107 | if (data < 0) | 98 | if (data < 0) |
108 | return; /* ignore errors (due to ACPI??) */ | 99 | return; /* ignore errors (due to ACPI??) */ |
109 | 100 | ||
110 | /* write back to clear latch */ | 101 | /* write back to clear latch */ |
111 | i2c_smbus_write_word_data(&ap->client, cmd, 0); | 102 | i2c_smbus_write_word_data(ap->client, cmd, 0); |
112 | 103 | ||
113 | if (!data) | 104 | if (!data) |
114 | return; | 105 | return; |
@@ -124,7 +115,7 @@ static void led_update(struct work_struct *work) | |||
124 | { | 115 | { |
125 | struct apanel *ap = container_of(work, struct apanel, led_work); | 116 | struct apanel *ap = container_of(work, struct apanel, led_work); |
126 | 117 | ||
127 | i2c_smbus_write_word_data(&ap->client, 0x10, ap->led_bits); | 118 | i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits); |
128 | } | 119 | } |
129 | 120 | ||
130 | static void mail_led_set(struct led_classdev *led, | 121 | static void mail_led_set(struct led_classdev *led, |
@@ -140,7 +131,7 @@ static void mail_led_set(struct led_classdev *led, | |||
140 | schedule_work(&ap->led_work); | 131 | schedule_work(&ap->led_work); |
141 | } | 132 | } |
142 | 133 | ||
143 | static int apanel_detach_client(struct i2c_client *client) | 134 | static int apanel_remove(struct i2c_client *client) |
144 | { | 135 | { |
145 | struct apanel *ap = i2c_get_clientdata(client); | 136 | struct apanel *ap = i2c_get_clientdata(client); |
146 | 137 | ||
@@ -148,43 +139,33 @@ static int apanel_detach_client(struct i2c_client *client) | |||
148 | led_classdev_unregister(&ap->mail_led); | 139 | led_classdev_unregister(&ap->mail_led); |
149 | 140 | ||
150 | input_unregister_polled_device(ap->ipdev); | 141 | input_unregister_polled_device(ap->ipdev); |
151 | i2c_detach_client(&ap->client); | ||
152 | input_free_polled_device(ap->ipdev); | 142 | input_free_polled_device(ap->ipdev); |
153 | 143 | ||
154 | return 0; | 144 | return 0; |
155 | } | 145 | } |
156 | 146 | ||
157 | /* Function is invoked for every i2c adapter. */ | ||
158 | static int apanel_attach_adapter(struct i2c_adapter *adap) | ||
159 | { | ||
160 | dev_dbg(&adap->dev, APANEL ": attach adapter id=%d\n", adap->id); | ||
161 | |||
162 | /* Our device is connected only to i801 on laptop */ | ||
163 | if (adap->id != I2C_HW_SMBUS_I801) | ||
164 | return -ENODEV; | ||
165 | |||
166 | return i2c_probe(adap, &addr_data, apanel_probe); | ||
167 | } | ||
168 | |||
169 | static void apanel_shutdown(struct i2c_client *client) | 147 | static void apanel_shutdown(struct i2c_client *client) |
170 | { | 148 | { |
171 | apanel_detach_client(client); | 149 | apanel_remove(client); |
172 | } | 150 | } |
173 | 151 | ||
152 | static struct i2c_device_id apanel_id[] = { | ||
153 | { "fujitsu_apanel", 0 }, | ||
154 | { } | ||
155 | }; | ||
156 | MODULE_DEVICE_TABLE(i2c, apanel_id); | ||
157 | |||
174 | static struct i2c_driver apanel_driver = { | 158 | static struct i2c_driver apanel_driver = { |
175 | .driver = { | 159 | .driver = { |
176 | .name = APANEL, | 160 | .name = APANEL, |
177 | }, | 161 | }, |
178 | .attach_adapter = &apanel_attach_adapter, | 162 | .probe = &apanel_probe, |
179 | .detach_client = &apanel_detach_client, | 163 | .remove = &apanel_remove, |
180 | .shutdown = &apanel_shutdown, | 164 | .shutdown = &apanel_shutdown, |
165 | .id_table = apanel_id, | ||
181 | }; | 166 | }; |
182 | 167 | ||
183 | static struct apanel apanel = { | 168 | static struct apanel apanel = { |
184 | .client = { | ||
185 | .driver = &apanel_driver, | ||
186 | .name = APANEL, | ||
187 | }, | ||
188 | .keymap = { | 169 | .keymap = { |
189 | [0] = KEY_MAIL, | 170 | [0] = KEY_MAIL, |
190 | [1] = KEY_WWW, | 171 | [1] = KEY_WWW, |
@@ -204,7 +185,8 @@ static struct apanel apanel = { | |||
204 | }; | 185 | }; |
205 | 186 | ||
206 | /* NB: Only one panel on the i2c. */ | 187 | /* NB: Only one panel on the i2c. */ |
207 | static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | 188 | static int apanel_probe(struct i2c_client *client, |
189 | const struct i2c_device_id *id) | ||
208 | { | 190 | { |
209 | struct apanel *ap; | 191 | struct apanel *ap; |
210 | struct input_polled_dev *ipdev; | 192 | struct input_polled_dev *ipdev; |
@@ -212,9 +194,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
212 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; | 194 | u8 cmd = device_chip[APANEL_DEV_APPBTN] == CHIP_OZ992C ? 0 : 8; |
213 | int i, err = -ENOMEM; | 195 | int i, err = -ENOMEM; |
214 | 196 | ||
215 | dev_dbg(&bus->dev, APANEL ": probe adapter %p addr %d kind %d\n", | ||
216 | bus, address, kind); | ||
217 | |||
218 | ap = &apanel; | 197 | ap = &apanel; |
219 | 198 | ||
220 | ipdev = input_allocate_polled_device(); | 199 | ipdev = input_allocate_polled_device(); |
@@ -222,18 +201,13 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
222 | goto out1; | 201 | goto out1; |
223 | 202 | ||
224 | ap->ipdev = ipdev; | 203 | ap->ipdev = ipdev; |
225 | ap->client.adapter = bus; | 204 | ap->client = client; |
226 | ap->client.addr = address; | ||
227 | |||
228 | i2c_set_clientdata(&ap->client, ap); | ||
229 | 205 | ||
230 | err = i2c_attach_client(&ap->client); | 206 | i2c_set_clientdata(client, ap); |
231 | if (err) | ||
232 | goto out2; | ||
233 | 207 | ||
234 | err = i2c_smbus_write_word_data(&ap->client, cmd, 0); | 208 | err = i2c_smbus_write_word_data(client, cmd, 0); |
235 | if (err) { | 209 | if (err) { |
236 | dev_warn(&ap->client.dev, APANEL ": smbus write error %d\n", | 210 | dev_warn(&client->dev, APANEL ": smbus write error %d\n", |
237 | err); | 211 | err); |
238 | goto out3; | 212 | goto out3; |
239 | } | 213 | } |
@@ -246,7 +220,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
246 | idev->name = APANEL_NAME " buttons"; | 220 | idev->name = APANEL_NAME " buttons"; |
247 | idev->phys = "apanel/input0"; | 221 | idev->phys = "apanel/input0"; |
248 | idev->id.bustype = BUS_HOST; | 222 | idev->id.bustype = BUS_HOST; |
249 | idev->dev.parent = &ap->client.dev; | 223 | idev->dev.parent = &client->dev; |
250 | 224 | ||
251 | set_bit(EV_KEY, idev->evbit); | 225 | set_bit(EV_KEY, idev->evbit); |
252 | 226 | ||
@@ -264,7 +238,7 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
264 | 238 | ||
265 | INIT_WORK(&ap->led_work, led_update); | 239 | INIT_WORK(&ap->led_work, led_update); |
266 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { | 240 | if (device_chip[APANEL_DEV_LED] != CHIP_NONE) { |
267 | err = led_classdev_register(&ap->client.dev, &ap->mail_led); | 241 | err = led_classdev_register(&client->dev, &ap->mail_led); |
268 | if (err) | 242 | if (err) |
269 | goto out4; | 243 | goto out4; |
270 | } | 244 | } |
@@ -273,8 +247,6 @@ static int apanel_probe(struct i2c_adapter *bus, int address, int kind) | |||
273 | out4: | 247 | out4: |
274 | input_unregister_polled_device(ipdev); | 248 | input_unregister_polled_device(ipdev); |
275 | out3: | 249 | out3: |
276 | i2c_detach_client(&ap->client); | ||
277 | out2: | ||
278 | input_free_polled_device(ipdev); | 250 | input_free_polled_device(ipdev); |
279 | out1: | 251 | out1: |
280 | return err; | 252 | return err; |
@@ -301,6 +273,7 @@ static int __init apanel_init(void) | |||
301 | void __iomem *bios; | 273 | void __iomem *bios; |
302 | const void __iomem *p; | 274 | const void __iomem *p; |
303 | u8 devno; | 275 | u8 devno; |
276 | unsigned char i2c_addr; | ||
304 | int found = 0; | 277 | int found = 0; |
305 | 278 | ||
306 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ | 279 | bios = ioremap(0xF0000, 0x10000); /* Can't fail */ |
@@ -313,7 +286,7 @@ static int __init apanel_init(void) | |||
313 | 286 | ||
314 | /* just use the first address */ | 287 | /* just use the first address */ |
315 | p += 8; | 288 | p += 8; |
316 | normal_i2c[0] = readb(p+3) >> 1; | 289 | i2c_addr = readb(p + 3) >> 1; |
317 | 290 | ||
318 | for ( ; (devno = readb(p)) & 0x7f; p += 4) { | 291 | for ( ; (devno = readb(p)) & 0x7f; p += 4) { |
319 | unsigned char method, slave, chip; | 292 | unsigned char method, slave, chip; |
@@ -322,7 +295,7 @@ static int __init apanel_init(void) | |||
322 | chip = readb(p + 2); | 295 | chip = readb(p + 2); |
323 | slave = readb(p + 3) >> 1; | 296 | slave = readb(p + 3) >> 1; |
324 | 297 | ||
325 | if (slave != normal_i2c[0]) { | 298 | if (slave != i2c_addr) { |
326 | pr_notice(APANEL ": only one SMBus slave " | 299 | pr_notice(APANEL ": only one SMBus slave " |
327 | "address supported, skiping device...\n"); | 300 | "address supported, skiping device...\n"); |
328 | continue; | 301 | continue; |