Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[pandora-kernel.git] / drivers / i2c / busses / i2c-i801.c
index 230238d..1041184 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/i2c.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
+#include <linux/dmi.h>
 
 /* I801 SMBus address offsets */
 #define SMBHSTSTS      (0 + i801_smba)
@@ -616,10 +617,81 @@ static void __init input_apanel_init(void)
 static void __init input_apanel_init(void) {}
 #endif
 
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+struct dmi_onboard_device_info {
+       const char *name;
+       u8 type;
+       unsigned short i2c_addr;
+       const char *i2c_type;
+};
+
+static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
+       { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
+       { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
+       { "Hades",  DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
+};
+
+static void __devinit dmi_check_onboard_device(u8 type, const char *name,
+                                              struct i2c_adapter *adap)
+{
+       int i;
+       struct i2c_board_info info;
+
+       for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
+               /* & ~0x80, ignore enabled/disabled bit */
+               if ((type & ~0x80) != dmi_devices[i].type)
+                       continue;
+               if (strcmp(name, dmi_devices[i].name))
+                       continue;
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               info.addr = dmi_devices[i].i2c_addr;
+               strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
+               i2c_new_device(adap, &info);
+               break;
+       }
+}
+
+/* We use our own function to check for onboard devices instead of
+   dmi_find_device() as some buggy BIOS's have the devices we are interested
+   in marked as disabled */
+static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
+                                               void *adap)
+{
+       int i, count;
+
+       if (dm->type != 10)
+               return;
+
+       count = (dm->length - sizeof(struct dmi_header)) / 2;
+       for (i = 0; i < count; i++) {
+               const u8 *d = (char *)(dm + 1) + (i * 2);
+               const char *name = ((char *) dm) + dm->length;
+               u8 type = d[0];
+               u8 s = d[1];
+
+               if (!s)
+                       continue;
+               s--;
+               while (s > 0 && name[0]) {
+                       name += strlen(name) + 1;
+                       s--;
+               }
+               if (name[0] == 0) /* Bogus string reference */
+                       continue;
+
+               dmi_check_onboard_device(type, name, adap);
+       }
+}
+#endif
+
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned char temp;
        int err;
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+       const char *vendor;
+#endif
 
        I801_dev = dev;
        i801_features = 0;
@@ -712,6 +784,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
                i2c_new_device(&i801_adapter, &info);
        }
 #endif
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+       vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+       if (vendor && !strcmp(vendor, "FUJITSU SIEMENS"))
+               dmi_walk(dmi_check_onboard_devices, &i801_adapter);
+#endif
 
        return 0;