All of lore.kernel.org
 help / color / mirror / Atom feed
From: AceLan Kao <acelan.kao@canonical.com>
To: platform-driver-x86@vger.kernel.org,
	Matthew Garrett <mjg59@srcf.ucam.org>
Subject: [PATCH] dell-laptop: support synaptics touchpad led
Date: Wed,  1 Jun 2011 16:34:48 +0800	[thread overview]
Message-ID: <1306917288-8531-1-git-send-email-acelan.kao@canonical.com> (raw)

The TP-LOCK-LED would bright while TP-disablement.
You can implement 97 command services routing of P/S2 device.
Code like below:
out 0x64,0x97 ;set 0x97 to command port;0x64 is command port
out 0x60,0x01 ;set 0x01 to data port then make LED bright;0x60 is data port
out 0x60,0x02 ;set 0x02 to data port then make LED dark

Before you send the action to the port, you must make sure the Input buffer
is empty (port 0x64).

Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
---
 drivers/platform/x86/dell-laptop.c |  105 +++++++++++++++++++++++++++++++++---
 1 files changed, 98 insertions(+), 7 deletions(-)

diff --git a/drivers/platform/x86/dell-laptop.c b/drivers/platform/x86/dell-laptop.c
index d3841de..65efa74 100644
--- a/drivers/platform/x86/dell-laptop.c
+++ b/drivers/platform/x86/dell-laptop.c
@@ -65,19 +65,14 @@ static int da_command_code;
 static int da_num_tokens;
 static struct calling_interface_token *da_tokens;
 
-static struct platform_driver platform_driver = {
-	.driver = {
-		.name = "dell-laptop",
-		.owner = THIS_MODULE,
-	}
-};
-
 static struct platform_device *platform_device;
 static struct backlight_device *dell_backlight_device;
 static struct rfkill *wifi_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *wwan_rfkill;
 
+static struct delayed_work dell_touchpadled_update_work;
+static int touchpad_led_status;
 static const struct dmi_system_id __initdata dell_device_table[] = {
 	{
 		.ident = "Dell laptop",
@@ -572,6 +567,45 @@ static const struct backlight_ops dell_ops = {
 	.update_status  = dell_send_intensity,
 };
 
+static void dell_touchpadled_on(void)
+{
+	while (inb(0x64) & 0x02)
+		udelay(100);
+	outb(0x97 , 0x64);
+
+	while (inb(0x64) & 0x02)
+		udelay(100);
+	outb(1, 0x60);
+
+	touchpad_led_status = 1;
+}
+
+static void dell_touchpadled_off(void)
+{
+	while (inb(0x64) & 0x02)
+		udelay(100);
+	outb(0x97 , 0x64);
+
+	while (inb(0x64) & 0x02)
+		udelay(100);
+	outb(2, 0x60);
+
+	touchpad_led_status = 0;
+}
+
+/*
+ * Called for each KEY_F22 key press event.
+ */
+static void dell_touchpadled_update(struct work_struct *work)
+{
+	touchpad_led_status = 1 - touchpad_led_status;
+
+	if (touchpad_led_status == 1)
+		dell_touchpadled_on();
+	else
+		dell_touchpadled_off();
+}
+
 static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
 			      struct serio *port)
 {
@@ -589,6 +623,10 @@ static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
 			schedule_delayed_work(&dell_rfkill_work,
 					      round_jiffies_relative(HZ));
 			break;
+		case 0x1E:	/* F22 */
+			schedule_delayed_work(&dell_touchpadled_update_work,
+					      0);
+			break;
 		}
 		extended = false;
 	}
@@ -596,11 +634,64 @@ static bool dell_laptop_i8042_filter(unsigned char data, unsigned char str,
 	return false;
 }
 
+static void restore_touchpad_led(void)
+{
+	/*
+	 * We don't want to change the value of touchpad_led_status while
+	 * resuming, so we modify the value here and it'll be changed back
+	 * in the work queue
+	 */
+	touchpad_led_status = 1 - touchpad_led_status;
+	/* The delay is needed to wait the chip wake up */
+	schedule_delayed_work(&dell_touchpadled_update_work, 1000);
+}
+
+static int __devinit dell_laptop_probe(struct platform_device *device)
+{
+	INIT_DELAYED_WORK(&dell_touchpadled_update_work,
+			  dell_touchpadled_update);
+	return 0;
+}
+
+static int dell_laptop_remove(struct platform_device *device)
+{
+	return 0;
+}
+
+static int dell_laptop_suspend(struct device *dev)
+{
+	return 0;
+}
+
+static int dell_laptop_resume(struct device *dev)
+{
+	restore_touchpad_led();
+	return 0;
+}
+
+static const struct dev_pm_ops dell_laptop_pm_ops = {
+	.suspend = dell_laptop_suspend,
+	.resume  = dell_laptop_resume,
+	.restore = dell_laptop_resume,
+};
+
+static struct platform_driver platform_driver = {
+	.driver = {
+		.name = "dell-laptop",
+		.owner = THIS_MODULE,
+		.pm    = &dell_laptop_pm_ops,
+	},
+	.probe  = dell_laptop_probe,
+	.remove = dell_laptop_remove,
+};
+
 static int __init dell_init(void)
 {
 	int max_intensity = 0;
 	int ret;
 
+	touchpad_led_status = 0;
+
 	if (!dmi_check_system(dell_device_table))
 		return -ENODEV;
 
-- 
1.7.4.1

             reply	other threads:[~2011-06-01  8:34 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-06-01  8:34 AceLan Kao [this message]
2011-06-01 13:31 ` [PATCH] dell-laptop: support synaptics touchpad led Matthew Garrett
2011-06-02  1:30   ` AceLan Kao
2011-06-02  2:05     ` Chris Bagwell
2011-06-02  3:18       ` AceLan Kao
2011-06-02  2:23     ` Matthew Garrett

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1306917288-8531-1-git-send-email-acelan.kao@canonical.com \
    --to=acelan.kao@canonical.com \
    --cc=mjg59@srcf.ucam.org \
    --cc=platform-driver-x86@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.