]> xenbits.xensource.com Git - people/aperard/linux-chromebook.git/commitdiff
CHROMIUM: Input: cyapa - calibrate command
authorBenson Leung <bleung@chromium.org>
Fri, 25 Jan 2013 03:49:38 +0000 (19:49 -0800)
committerChromeBot <chrome-bot@google.com>
Wed, 30 Jan 2013 20:29:20 +0000 (12:29 -0800)
Add a sysfs property that allows userspace to trigger
a recalibration of the trackpad.

Signed-off-by: Benson Leung <bleung@chromium.org>
BUG=chrome-os-partner:17441
TEST=echo 1 > calibrate
After about a second, the command should return.
Check that the trackpad is responsive.

Change-Id: I17ef8b7960406f9c3230918a18cdf25a0cd84b72
Reviewed-on: https://gerrit.chromium.org/gerrit/41980
Reviewed-by: Benson Leung <bleung@chromium.org>
Tested-by: Benson Leung <bleung@chromium.org>
Commit-Queue: Benson Leung <bleung@chromium.org>

drivers/input/mouse/cyapa.c

index e4b0f4e6020ed396874d063c22d9d65c96097e36..ee9e0c6462066bdaf0d753b749a0734c7d922e85 100644 (file)
                              CAPABILITY_MIDDLE_BTN_MASK)
 
 #define CYAPA_OFFSET_SOFT_RESET  REG_OFFSET_COMMAND_BASE
+#define OP_RECALIBRATION_MASK    0x80
 #define OP_REPORT_BASELINE_MASK  0x40
 #define REG_OFFSET_MAX_BASELINE  0x0026
 #define REG_OFFSET_MIN_BASELINE  0x0027
@@ -1373,6 +1374,66 @@ static ssize_t cyapa_update_fw_store(struct device *dev,
        return ret ? ret : count;
 }
 
+static ssize_t cyapa_calibrate_store(struct device *dev,
+                                    struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       struct cyapa *cyapa = dev_get_drvdata(dev);
+       int tries = 20;  /* max recalibration timeout 2s. */
+       int ret;
+
+       disable_irq(cyapa->irq);
+
+       ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
+       if (ret < 0) {
+               dev_err(dev, "Error reading dev status. err = %d\n", ret);
+               goto out;
+       }
+       if ((ret & CYAPA_DEV_NORMAL) != CYAPA_DEV_NORMAL) {
+               dev_warn(dev, "Trackpad device is busy. device state = 0x%x\n",
+                        ret);
+               ret = -EAGAIN;
+               goto out;
+       }
+
+       ret = cyapa_write_byte(cyapa, CYAPA_CMD_SOFT_RESET,
+                              OP_RECALIBRATION_MASK);
+       if (ret < 0) {
+               dev_err(dev, "Failed to send calibrate command. ret = %d\n",
+                       ret);
+               goto out;
+       }
+
+       do {
+               /*
+                * For this recalibration, the max time will not exceed 2s.
+                * The average time is approximately 500 - 700 ms, and we
+                * will check the status every 100 - 200ms.
+                */
+               usleep_range(100000, 200000);
+
+               ret = cyapa_read_byte(cyapa, CYAPA_CMD_DEV_STATUS);
+               if (ret < 0) {
+                       dev_err(dev, "Error reading dev status. err = %d\n",
+                               ret);
+                       goto out;
+               }
+               if ((ret & CYAPA_DEV_NORMAL) == CYAPA_DEV_NORMAL)
+                       break;
+       } while (--tries);
+
+       if (tries == 0) {
+               dev_err(dev, "Failed to calibrate. Timeout.\n");
+               ret = -ETIMEDOUT;
+               goto out;
+       }
+       dev_dbg(dev, "Calibration successful.\n");
+
+out:
+       enable_irq(cyapa->irq);
+       return ret < 0 ? ret : count;
+}
+
 static ssize_t cyapa_show_baseline(struct device *dev,
                                   struct device_attribute *attr, char *buf)
 {
@@ -1594,6 +1655,7 @@ static DEVICE_ATTR(protocol_version, S_IRUGO, cyapa_show_protocol_version,
                   NULL);
 static DEVICE_ATTR(update_fw, S_IWUSR, NULL, cyapa_update_fw_store);
 static DEVICE_ATTR(baseline, S_IRUGO, cyapa_show_baseline, NULL);
+static DEVICE_ATTR(calibrate, S_IWUSR, NULL, cyapa_calibrate_store);
 
 static struct attribute *cyapa_sysfs_entries[] = {
        &dev_attr_firmware_version.attr,
@@ -1602,6 +1664,7 @@ static struct attribute *cyapa_sysfs_entries[] = {
        &dev_attr_protocol_version.attr,
        &dev_attr_update_fw.attr,
        &dev_attr_baseline.attr,
+       &dev_attr_calibrate.attr,
        NULL,
 };