diff mbox

[v2,8/14] input: cyapa: add gen3 trackpad device baseline and calibrate functions supported

Message ID 77BC725C9062764F874D79F51E1F1A8F4406C8DB@S04-MBX01-01.s04.local (mailing list archive)
State New, archived
Headers show

Commit Message

Dudley Du June 6, 2014, 7:29 a.m. UTC
Add report baseline and force calibrate functions supported for gen3
trackpad device, which these functions are supplied through
cyapa core baseline and calibrate interfaces.
TEST=test on Chomebooks.

Signed-off-by: Du, Dudley <dudl@cypress.com>
---
This message and any attachments may contain Cypress (or its subsidiaries) confidential information. If it has been received in error, please advise the sender and immediately delete this message.
diff mbox

Patch

diff --git a/drivers/input/mouse/cyapa_gen3.c b/drivers/input/mouse/cyapa_gen3.c
index a3e1e72..9ffdbc1 100644
--- a/drivers/input/mouse/cyapa_gen3.c
+++ b/drivers/input/mouse/cyapa_gen3.c
@@ -724,6 +724,138 @@  static int cyapa_gen3_do_fw_update(struct cyapa *cyapa,
        return 0;
 }

+static ssize_t cyapa_gen3_do_calibrate(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;
+
+       cyapa_disable_irq(cyapa);
+
+       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:
+       cyapa_enable_irq(cyapa);
+       return ret < 0 ? ret : count;
+}
+
+static ssize_t cyapa_gen3_show_baseline(struct device *dev,
+                                  struct device_attribute *attr, char *buf)
+{
+       struct cyapa *cyapa = dev_get_drvdata(dev);
+       int max_baseline, min_baseline;
+       int tries = 3;
+       int ret;
+
+       cyapa_disable_irq(cyapa);
+
+       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_REPORT_BASELINE_MASK);
+       if (ret < 0) {
+               dev_err(dev, "Failed to send report baseline command. %d\n",
+                       ret);
+               goto out;
+       }
+
+       do {
+               usleep_range(10000, 20000);
+
+               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, "Device timed out going to Normal state.\n");
+               ret = -ETIMEDOUT;
+               goto out;
+       }
+
+       ret = cyapa_read_byte(cyapa, CYAPA_CMD_MAX_BASELINE);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read max baseline. err = %d\n", ret);
+               goto out;
+       }
+       max_baseline = ret;
+
+       ret = cyapa_read_byte(cyapa, CYAPA_CMD_MIN_BASELINE);
+       if (ret < 0) {
+               dev_err(dev, "Failed to read min baseline. err = %d\n", ret);
+               goto out;
+       }
+       min_baseline = ret;
+
+       dev_dbg(dev, "Baseline report successful. Max: %d Min: %d\n",
+               max_baseline, min_baseline);
+       ret = scnprintf(buf, PAGE_SIZE, "%d %d\n", max_baseline, min_baseline);
+
+out:
+       cyapa_enable_irq(cyapa);
+       return ret;
+}
+
 /*
  * cyapa_get_wait_time_for_pwr_cmd
  *
@@ -987,8 +1119,8 @@  const struct cyapa_dev_ops cyapa_gen3_ops = {
        NULL,
        cyapa_gen3_bl_deactivate,

-       NULL,
-       NULL,
+       cyapa_gen3_show_baseline,
+       cyapa_gen3_do_calibrate,

        NULL,
        NULL,