Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ideapad: add Lenovo IdeaPad Z570 support (part 3)

The patch adds support for Lenovo IdeaPad Z570 laptop. It makes all special
keys working, adds possibility to control fan like Windows does, controls
Touchpad Disabled LED, toggles touchpad state via keyboard controller and
corrects touchpad behavior on resume from suspend. It is new, modified
version of patch. Now it does not depend on psmouse and does not need patching
of input subsystem.

Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>

This is the part 3 for fan control

Signed-off-by: Ike Panhc <ike.pan@canonical.com>
Signed-off-by: Matthew Garrett <mjg@redhat.com>

authored by

Maxim Mikityanskiy and committed by
Matthew Garrett
0c7bbeb9 07a4a4fc

+51 -3
+11
Documentation/ABI/testing/sysfs-platform-ideapad-laptop
··· 5 5 Description: 6 6 Control the power of camera module. 1 means on, 0 means off. 7 7 8 + What: /sys/devices/platform/ideapad/fan_mode 9 + Date: June 2012 10 + KernelVersion: 3.6 11 + Contact: "Maxim Mikityanskiy <maxtram95@gmail.com>" 12 + Description: 13 + Change fan mode 14 + There are four available modes: 15 + * 0 -> Super Silent Mode 16 + * 1 -> Standard Mode 17 + * 2 -> Dust Cleaning 18 + * 4 -> Efficient Thermal Dissipation Mode 8 19
+40 -3
drivers/platform/x86/ideapad-laptop.c
··· 64 64 VPCCMD_R_3G, 65 65 VPCCMD_W_3G, 66 66 VPCCMD_R_ODD, /* 0x21 */ 67 - VPCCMD_R_RF = 0x23, 67 + VPCCMD_W_FAN, 68 + VPCCMD_R_RF, 68 69 VPCCMD_W_RF, 70 + VPCCMD_R_FAN = 0x2B, 69 71 VPCCMD_R_SPECIAL_BUTTONS = 0x31, 70 72 VPCCMD_W_BL_POWER = 0x33, 71 73 }; ··· 360 358 return -EINVAL; 361 359 ret = write_ec_cmd(ideapad_handle, VPCCMD_W_CAMERA, state); 362 360 if (ret < 0) 363 - return ret; 361 + return -EIO; 364 362 return count; 365 363 } 366 364 367 365 static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam); 368 366 367 + static ssize_t show_ideapad_fan(struct device *dev, 368 + struct device_attribute *attr, 369 + char *buf) 370 + { 371 + unsigned long result; 372 + 373 + if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result)) 374 + return sprintf(buf, "-1\n"); 375 + return sprintf(buf, "%lu\n", result); 376 + } 377 + 378 + static ssize_t store_ideapad_fan(struct device *dev, 379 + struct device_attribute *attr, 380 + const char *buf, size_t count) 381 + { 382 + int ret, state; 383 + 384 + if (!count) 385 + return 0; 386 + if (sscanf(buf, "%i", &state) != 1) 387 + return -EINVAL; 388 + if (state < 0 || state > 4 || state == 3) 389 + return -EINVAL; 390 + ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state); 391 + if (ret < 0) 392 + return -EIO; 393 + return count; 394 + } 395 + 396 + static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan); 397 + 369 398 static struct attribute *ideapad_attributes[] = { 370 399 &dev_attr_camera_power.attr, 400 + &dev_attr_fan_mode.attr, 371 401 NULL 372 402 }; 373 403 ··· 413 379 414 380 if (attr == &dev_attr_camera_power.attr) 415 381 supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg)); 416 - else 382 + else if (attr == &dev_attr_fan_mode.attr) { 383 + unsigned long value; 384 + supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value); 385 + } else 417 386 supported = true; 418 387 419 388 return supported ? attr->mode : 0;