Re: [PATCH 2/2] drivers/input/mouse, drivers/platform/x86: add Lenovo IdeaPad Z570 support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 06/20/2012 03:23 AM, Maxim Mikityanskiy wrote:
> From: Maxim Mikityanskiy <maxtram95@xxxxxxxxx>
> 
> 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 psmouse with previous
> patch and corrects touchpad behavior on resume from suspend. It is new,
> modified version of patch.
> 
> Signed-off-by: Maxim Mikityanskiy <maxtram95@xxxxxxxxx>
> --- linux/drivers/platform/x86/ideapad-laptop.c.orig
> +++ linux/drivers/platform/x86/ideapad-laptop.c
> @@ -36,6 +36,7 @@
>  #include <linux/fb.h>
>  #include <linux/debugfs.h>
>  #include <linux/seq_file.h>
> +#include <linux/input/psmouse.h>

let IDEAPAD_LAPTOP depends on MOUSE_PS2 in Kconfig. Other build will fail without MOUSE_PS2 selected. Of course I know the chance is rare.

>  
>  #define IDEAPAD_RFKILL_DEV_NUM	(3)
>  
> @@ -62,9 +63,12 @@ enum {
>  	VPCCMD_W_CAMERA,
>  	VPCCMD_R_3G,
>  	VPCCMD_W_3G,
> -	VPCCMD_R_ODD, /* 0x21 */
> -	VPCCMD_R_RF = 0x23,
> -	VPCCMD_W_RF,
> +	VPCCMD_R_ODD,
> +	VPCCMD_W_FAN,
> +	VPCCMD_R_RF,
> +	VPCCMD_W_RF, /* 0x24 */
> +	VPCCMD_R_FAN = 0x2B,
> +	VPCCMD_R_SPECIAL_BUTTONS = 0x31,
>  	VPCCMD_W_BL_POWER = 0x33,
>  };
>  
> @@ -363,8 +367,47 @@ static ssize_t store_ideapad_cam(struct
>  
>  static DEVICE_ATTR(camera_power, 0644, show_ideapad_cam, store_ideapad_cam);
>  
> +static ssize_t show_ideapad_fan(struct device *dev,
> +				struct device_attribute *attr,
> +				char *buf)
> +{
> +	unsigned long result;
> +
> +	if (read_ec_data(ideapad_handle, VPCCMD_R_FAN, &result))
> +		return sprintf(buf, "-1\n");
> +	return sprintf(buf, "%lu\n", result);
> +}
> +
> +static ssize_t store_ideapad_fan(struct device *dev,
> +				 struct device_attribute *attr,
> +				 const char *buf, size_t count)
> +{
> +	int ret, state;
> +
> +	if (!count)
> +		return 0;
> +	if (sscanf(buf, "%i", &state) != 1)
> +		return -EINVAL;
> +	/* WARNING: these fan states are not speed
> +	 * so it isn't cooling_device interface
> +	 * 0 = super silent mode
> +	 * 1 = standard mode
> +	 * 2 = dust cleaning
> +	 * 4 = efficient thermal dissipation mode
> +	 */

I think the file in Documentation is doing good, no need to comment here.

> +	if (state < 0 || state > 4 || state == 3)
> +		return -EINVAL;
> +	ret = write_ec_cmd(ideapad_handle, VPCCMD_W_FAN, state);
> +	if (ret < 0)
> +		return ret;

return -EIO is better, write_ec_cmd only return -1.

> +	return count;
> +}
> +
> +static DEVICE_ATTR(fan_mode, 0644, show_ideapad_fan, store_ideapad_fan);
> +
>  static struct attribute *ideapad_attributes[] = {
>  	&dev_attr_camera_power.attr,
> +	&dev_attr_fan_mode.attr,
>  	NULL
>  };
>  
> @@ -379,6 +422,10 @@ static umode_t ideapad_is_visible(struct
>  	if (attr == &dev_attr_camera_power.attr)
>  		supported = test_bit(CFG_CAMERA_BIT, &(priv->cfg));
>  	else
> +	if (attr == &dev_attr_fan_mode.attr) {
> +		unsigned long value;
> +		supported = !read_ec_data(ideapad_handle, VPCCMD_R_FAN, &value);

I will test this with my ideapads.

> +	} else
>  		supported = true;
>  
>  	return supported ? attr->mode : 0;
> @@ -519,9 +566,15 @@ static void ideapad_platform_exit(struct
>   */
>  static const struct key_entry ideapad_keymap[] = {
>  	{ KE_KEY, 6,  { KEY_SWITCHVIDEOMODE } },
> +	{ KE_KEY, 7,  { KEY_CAMERA } },
> +	{ KE_KEY, 11, { KEY_F16 } },
>  	{ KE_KEY, 13, { KEY_WLAN } },
>  	{ KE_KEY, 16, { KEY_PROG1 } },
>  	{ KE_KEY, 17, { KEY_PROG2 } },
> +	{ KE_KEY, 64, { KEY_PROG3 } },
> +	{ KE_KEY, 65, { KEY_PROG4 } },
> +	{ KE_KEY, 66, { KEY_TOUCHPAD_OFF } },
> +	{ KE_KEY, 67, { KEY_TOUCHPAD_ON } },
>  	{ KE_END, 0 },
>  };
>  
> @@ -692,6 +745,25 @@ static const struct acpi_device_id ideap
>  };
>  MODULE_DEVICE_TABLE(acpi, ideapad_device_ids);
>  
> +static void ideapad_sync_touchpad_state(struct acpi_device *adevice)
> +{
> +	struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
> +	unsigned long value;
> +
> +	/* Without reading from EC touchpad LED doesn't switch state */
> +	if (!read_ec_data(adevice->handle, VPCCMD_R_TOUCHPAD, &value)) {
> +		/* Some IdeaPads don't really turn off touchpad - they only
> +		 * switch the LED state. We (de)activate psmouse to turn
> +		 * touchpad off and on. We send KEY_TOUCHPAD_OFF and
> +		 * KEY_TOUCHPAD_ON to not to get out of sync with LED */
> +		if (value)
> +			psmouse_enable();
> +		else
> +			psmouse_disable();
> +		ideapad_input_report(priv, value ? 67 : 66);
> +	}
> +}
> +
>  static int __devinit ideapad_acpi_add(struct acpi_device *adevice)
>  {
>  	int ret, i;
> @@ -728,6 +800,7 @@ static int __devinit ideapad_acpi_add(st
>  			priv->rfk[i] = NULL;
>  	}
>  	ideapad_sync_rfk_state(priv);
> +	ideapad_sync_touchpad_state(adevice);
>  
>  	if (!acpi_video_backlight_support()) {
>  		ret = ideapad_backlight_init(priv);
> @@ -767,6 +840,26 @@ static int __devexit ideapad_acpi_remove
>  	return 0;
>  }
>  
> +static void ideapad_check_special_buttons(struct ideapad_private *priv,
> +					  unsigned long state)
> +{
> +	unsigned long bit;
> +	for (bit = 0; bit < 16; bit++) {
> +		if (test_bit(bit, &state)) {
> +			switch (bit) {
> +			case 6:
> +				/* Thermal Management button */
> +				ideapad_input_report(priv, 65);
> +				break;
> +			case 1:
> +				/* OneKey Theater button */
> +				ideapad_input_report(priv, 64);
> +				break;
> +			}
> +		}
> +	}
> +}
> +
>  static void ideapad_acpi_notify(struct acpi_device *adevice, u32 event)
>  {
>  	struct ideapad_private *priv = dev_get_drvdata(&adevice->dev);
> @@ -785,6 +878,9 @@ static void ideapad_acpi_notify(struct a
>  			case 9:
>  				ideapad_sync_rfk_state(priv);
>  				break;
> +			case 5:
> +				ideapad_sync_touchpad_state(adevice);
> +				break;
>  			case 4:
>  				ideapad_backlight_notify_brightness(priv);
>  				break;
> @@ -794,6 +890,14 @@ static void ideapad_acpi_notify(struct a
>  			case 2:
>  				ideapad_backlight_notify_power(priv);
>  				break;
> +			case 0:
> +				{
> +				unsigned long value;
> +				read_ec_data(handle, VPCCMD_R_SPECIAL_BUTTONS,
> +					     &value);
> +				ideapad_check_special_buttons(priv, value);
> +				}
> +				break;
>  			default:
>  				ideapad_input_report(priv, vpc_bit);
>  			}
> @@ -801,6 +905,12 @@ static void ideapad_acpi_notify(struct a
>  	}
>  }
>  
> +static int ideapad_acpi_resume(struct acpi_device *adevice)
> +{
> +	ideapad_sync_touchpad_state(adevice);

Good idea, I will see if we need ideapad_sync_rfk_state() also.

> +	return 0;
> +}
> +
>  static struct acpi_driver ideapad_acpi_driver = {
>  	.name = "ideapad_acpi",
>  	.class = "IdeaPad",
> @@ -808,6 +918,7 @@ static struct acpi_driver ideapad_acpi_d
>  	.ops.add = ideapad_acpi_add,
>  	.ops.remove = ideapad_acpi_remove,
>  	.ops.notify = ideapad_acpi_notify,
> +	.ops.resume = ideapad_acpi_resume,
>  	.owner = THIS_MODULE,
>  };
>  
> --- linux/Documentation/ABI/testing/sysfs-platform-ideapad-laptop.orig
> +++ linux/Documentation/ABI/testing/sysfs-platform-ideapad-laptop
> @@ -5,4 +5,14 @@ Contact:	"Ike Panhc <ike.pan@canonical.c
>  Description:
>  		Control the power of camera module. 1 means on, 0 means off.
>  
> -
> +What:		/sys/devices/platform/ideapad/fan_mode
> +Date:		June 2012
> +KernelVersion:	3.5

Shall be 3.6

> +Contact:	"Maxim Mikityanskiy <maxtram95@xxxxxxxxx>"
> +Description:
> +		Change fan mode
> +		There are four available modes:
> +		    * 0 -> Super Silent Mode
> +		    * 1 -> Standard Mode
> +		    * 2 -> Dust Cleaning
> +		    * 4 -> Efficient Thermal Dissipation Mode
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe platform-driver-x86" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-input" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media Devel]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Linux Wireless Networking]     [Linux Omap]

  Powered by Linux