#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */
-#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6 bytes) */
-#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6 bytes) */
+#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */
+#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */
#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */
#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */
"TH1P", "TH2P", "TH3P", "TMAP", "TMAS", "TMBS", "TM0P", "TM0S",
"TM1P", "TM1S", "TM2P", "TM2S", "TM3S", "TM8P", "TM8S", "TM9P",
"TM9S", "TN0H", "TS0C", NULL },
+/* Set 5: iMac */
+ { "TC0D", "TA0P", "TG0P", "TG0D", "TG0H", "TH0P", "Tm0P", "TO0P",
+ "Tp0C", NULL },
+/* Set 6: Macbook3 set */
+ { "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TTF0", "TW0P", "Th0H",
+ "Th0S", "Th1H", NULL },
};
/* List of keys used to read/write fan speeds */
static struct workqueue_struct *applesmc_led_wq;
/*
- * __wait_status - Wait up to 2ms for the status port to get a certain value
+ * __wait_status - Wait up to 10ms for the status port to get a certain value
* (masked with 0x0f), returning zero if the value is obtained. Callers must
* hold applesmc_lock.
*/
val = val & APPLESMC_STATUS_MASK;
- for (i = 0; i < 200; i++) {
+ for (i = 0; i < 1000; i++) {
if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) {
if (debug)
printk(KERN_DEBUG
return -EIO;
}
+/*
+ * special treatment of command port - on newer macbooks, it seems necessary
+ * to resend the command byte before polling the status again. Callers must
+ * hold applesmc_lock.
+ */
+static int send_command(u8 cmd)
+{
+ int i;
+ for (i = 0; i < 1000; i++) {
+ outb(cmd, APPLESMC_CMD_PORT);
+ udelay(5);
+ if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c)
+ return 0;
+ udelay(5);
+ }
+ printk(KERN_WARNING "applesmc: command failed: %x -> %x\n",
+ cmd, inb(APPLESMC_CMD_PORT));
+ return -EIO;
+}
+
/*
* applesmc_read_key - reads len bytes from a given key, and put them in buffer.
* Returns zero on success or a negative error on failure. Callers must
return -EINVAL;
}
- outb(APPLESMC_READ_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_READ_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
return -EINVAL;
}
- outb(APPLESMC_WRITE_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_WRITE_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
readkey[2] = index >> 8;
readkey[3] = index;
- outb(APPLESMC_GET_KEY_BY_INDEX_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_GET_KEY_BY_INDEX_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
{
int i;
- outb(APPLESMC_GET_KEY_TYPE_CMD, APPLESMC_CMD_PORT);
- if (__wait_status(0x0c))
+ if (send_command(APPLESMC_GET_KEY_TYPE_CMD))
return -EIO;
for (i = 0; i < 4; i++) {
return -EIO;
}
- outb(5, APPLESMC_DATA_PORT);
+ outb(6, APPLESMC_DATA_PORT);
for (i = 0; i < 6; i++) {
if (__wait_status(0x05))
static ssize_t applesmc_light_show(struct device *dev,
struct device_attribute *attr, char *sysfsbuf)
{
+ static int data_length;
int ret;
u8 left = 0, right = 0;
- u8 buffer[6];
+ u8 buffer[10], query[6];
mutex_lock(&applesmc_lock);
- ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, 6);
+ if (!data_length) {
+ ret = applesmc_get_key_type(LIGHT_SENSOR_LEFT_KEY, query);
+ if (ret)
+ goto out;
+ data_length = clamp_val(query[0], 0, 10);
+ printk(KERN_INFO "applesmc: light sensor data length set to "
+ "%d\n", data_length);
+ }
+
+ ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length);
left = buffer[2];
if (ret)
goto out;
- ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, 6);
+ ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length);
right = buffer[2];
out:
{ .accelerometer = 0, .light = 0, .temperature_set = 3 },
/* MacPro: temperature set 4 */
{ .accelerometer = 0, .light = 0, .temperature_set = 4 },
+/* iMac: temperature set 5 */
+ { .accelerometer = 0, .light = 0, .temperature_set = 5 },
+/* MacBook3: accelerometer and temperature set 6 */
+ { .accelerometer = 1, .light = 0, .temperature_set = 6 },
};
/* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBookPro") },
(void*)&applesmc_dmi_data[0]},
- { applesmc_dmi_match, "Apple MacBook", {
+ { applesmc_dmi_match, "Apple MacBook (v2)", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook2") },
(void*)&applesmc_dmi_data[1]},
+ { applesmc_dmi_match, "Apple MacBook (v3)", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"MacBook3") },
+ (void*)&applesmc_dmi_data[6]},
{ applesmc_dmi_match, "Apple MacBook", {
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacBook") },
DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
DMI_MATCH(DMI_PRODUCT_NAME,"MacPro2") },
(void*)&applesmc_dmi_data[4]},
+ { applesmc_dmi_match, "Apple iMac", {
+ DMI_MATCH(DMI_BOARD_VENDOR,"Apple"),
+ DMI_MATCH(DMI_PRODUCT_NAME,"iMac") },
+ (void*)&applesmc_dmi_data[5]},
{ .ident = NULL }
};