summaryrefslogtreecommitdiffstats
path: root/kernel/drivers/hid/hid-rmi.c
diff options
context:
space:
mode:
authorJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-11 10:41:07 +0300
committerJosé Pekkarinen <jose.pekkarinen@nokia.com>2016-04-13 08:17:18 +0300
commite09b41010ba33a20a87472ee821fa407a5b8da36 (patch)
treed10dc367189862e7ca5c592f033dc3726e1df4e3 /kernel/drivers/hid/hid-rmi.c
parentf93b97fd65072de626c074dbe099a1fff05ce060 (diff)
These changes are the raw update to linux-4.4.6-rt14. Kernel sources
are taken from kernel.org, and rt patch from the rt wiki download page. During the rebasing, the following patch collided: Force tick interrupt and get rid of softirq magic(I70131fb85). Collisions have been removed because its logic was found on the source already. Change-Id: I7f57a4081d9deaa0d9ccfc41a6c8daccdee3b769 Signed-off-by: José Pekkarinen <jose.pekkarinen@nokia.com>
Diffstat (limited to 'kernel/drivers/hid/hid-rmi.c')
-rw-r--r--kernel/drivers/hid/hid-rmi.c189
1 files changed, 163 insertions, 26 deletions
diff --git a/kernel/drivers/hid/hid-rmi.c b/kernel/drivers/hid/hid-rmi.c
index 368ffdf2c..67cd059a8 100644
--- a/kernel/drivers/hid/hid-rmi.c
+++ b/kernel/drivers/hid/hid-rmi.c
@@ -29,14 +29,25 @@
#define RMI_SET_RMI_MODE_REPORT_ID 0x0f /* Feature Report */
/* flags */
-#define RMI_READ_REQUEST_PENDING BIT(0)
-#define RMI_READ_DATA_PENDING BIT(1)
-#define RMI_STARTED BIT(2)
+#define RMI_READ_REQUEST_PENDING 0
+#define RMI_READ_DATA_PENDING 1
+#define RMI_STARTED 2
+
+#define RMI_SLEEP_NORMAL 0x0
+#define RMI_SLEEP_DEEP_SLEEP 0x1
/* device flags */
#define RMI_DEVICE BIT(0)
#define RMI_DEVICE_HAS_PHYS_BUTTONS BIT(1)
+/*
+ * retrieve the ctrl registers
+ * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
+ * and there is no way to know if the first 20 bytes are here or not.
+ * We use only the first 12 bytes, so get only them.
+ */
+#define RMI_F11_CTRL_REG_COUNT 12
+
enum rmi_mode_type {
RMI_MODE_OFF = 0,
RMI_MODE_ATTN_REPORTS = 1,
@@ -113,6 +124,8 @@ struct rmi_data {
unsigned int max_y;
unsigned int x_size_mm;
unsigned int y_size_mm;
+ bool read_f11_ctrl_regs;
+ u8 f11_ctrl_regs[RMI_F11_CTRL_REG_COUNT];
unsigned int gpio_led_count;
unsigned int button_count;
@@ -126,6 +139,10 @@ struct rmi_data {
unsigned long device_flags;
unsigned long firmware_id;
+
+ u8 f01_ctrl0;
+ u8 interrupt_enable_mask;
+ bool restore_interrupt_mask;
};
#define RMI_PAGE(addr) (((addr) >> 8) & 0xff)
@@ -346,13 +363,34 @@ static void rmi_f11_process_touch(struct rmi_data *hdata, int slot,
}
}
+static int rmi_reset_attn_mode(struct hid_device *hdev)
+{
+ struct rmi_data *data = hid_get_drvdata(hdev);
+ int ret;
+
+ ret = rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+ if (ret)
+ return ret;
+
+ if (data->restore_interrupt_mask) {
+ ret = rmi_write(hdev, data->f01.control_base_addr + 1,
+ &data->interrupt_enable_mask);
+ if (ret) {
+ hid_err(hdev, "can not write F01 control register\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void rmi_reset_work(struct work_struct *work)
{
struct rmi_data *hdata = container_of(work, struct rmi_data,
reset_work);
/* switch the device to RMI if we receive a generic mouse report */
- rmi_set_mode(hdata->hdev, RMI_MODE_ATTN_REPORTS);
+ rmi_reset_attn_mode(hdata->hdev);
}
static inline int rmi_schedule_reset(struct hid_device *hdev)
@@ -532,14 +570,77 @@ static int rmi_event(struct hid_device *hdev, struct hid_field *field,
}
#ifdef CONFIG_PM
+static int rmi_set_sleep_mode(struct hid_device *hdev, int sleep_mode)
+{
+ struct rmi_data *data = hid_get_drvdata(hdev);
+ int ret;
+ u8 f01_ctrl0;
+
+ f01_ctrl0 = (data->f01_ctrl0 & ~0x3) | sleep_mode;
+
+ ret = rmi_write(hdev, data->f01.control_base_addr,
+ &f01_ctrl0);
+ if (ret) {
+ hid_err(hdev, "can not write sleep mode\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rmi_suspend(struct hid_device *hdev, pm_message_t message)
+{
+ struct rmi_data *data = hid_get_drvdata(hdev);
+ int ret;
+ u8 buf[RMI_F11_CTRL_REG_COUNT];
+
+ ret = rmi_read_block(hdev, data->f11.control_base_addr, buf,
+ RMI_F11_CTRL_REG_COUNT);
+ if (ret)
+ hid_warn(hdev, "can not read F11 control registers\n");
+ else
+ memcpy(data->f11_ctrl_regs, buf, RMI_F11_CTRL_REG_COUNT);
+
+
+ if (!device_may_wakeup(hdev->dev.parent))
+ return rmi_set_sleep_mode(hdev, RMI_SLEEP_DEEP_SLEEP);
+
+ return 0;
+}
+
static int rmi_post_reset(struct hid_device *hdev)
{
- return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+ struct rmi_data *data = hid_get_drvdata(hdev);
+ int ret;
+
+ ret = rmi_reset_attn_mode(hdev);
+ if (ret) {
+ hid_err(hdev, "can not set rmi mode\n");
+ return ret;
+ }
+
+ if (data->read_f11_ctrl_regs) {
+ ret = rmi_write_block(hdev, data->f11.control_base_addr,
+ data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
+ if (ret)
+ hid_warn(hdev,
+ "can not write F11 control registers after reset\n");
+ }
+
+ if (!device_may_wakeup(hdev->dev.parent)) {
+ ret = rmi_set_sleep_mode(hdev, RMI_SLEEP_NORMAL);
+ if (ret) {
+ hid_err(hdev, "can not write sleep mode\n");
+ return ret;
+ }
+ }
+
+ return ret;
}
static int rmi_post_resume(struct hid_device *hdev)
{
- return rmi_set_mode(hdev, RMI_MODE_ATTN_REPORTS);
+ return rmi_reset_attn_mode(hdev);
}
#endif /* CONFIG_PM */
@@ -595,6 +696,7 @@ static void rmi_register_function(struct rmi_data *data,
f->interrupt_count = pdt_entry->interrupt_source_count;
f->irq_mask = rmi_gen_mask(f->interrupt_base,
f->interrupt_count);
+ data->interrupt_enable_mask |= f->irq_mask;
}
}
@@ -732,6 +834,35 @@ static int rmi_populate_f01(struct hid_device *hdev)
data->firmware_id += info[2] * 65536;
}
+ ret = rmi_read_block(hdev, data->f01.control_base_addr, info,
+ 2);
+
+ if (ret) {
+ hid_err(hdev, "can not read f01 ctrl registers\n");
+ return ret;
+ }
+
+ data->f01_ctrl0 = info[0];
+
+ if (!info[1]) {
+ /*
+ * Do to a firmware bug in some touchpads the F01 interrupt
+ * enable control register will be cleared on reset.
+ * This will stop the touchpad from reporting data, so
+ * if F01 CTRL1 is 0 then we need to explicitly enable
+ * interrupts for the functions we want data for.
+ */
+ data->restore_interrupt_mask = true;
+
+ ret = rmi_write(hdev, data->f01.control_base_addr + 1,
+ &data->interrupt_enable_mask);
+ if (ret) {
+ hid_err(hdev, "can not write to control reg 1: %d.\n",
+ ret);
+ return ret;
+ }
+ }
+
return 0;
}
@@ -904,24 +1035,23 @@ static int rmi_populate_f11(struct hid_device *hdev)
if (has_data40)
data->f11.report_size += data->max_fingers * 2;
- /*
- * retrieve the ctrl registers
- * the ctrl register has a size of 20 but a fw bug split it into 16 + 4,
- * and there is no way to know if the first 20 bytes are here or not.
- * We use only the first 12 bytes, so get only them.
- */
- ret = rmi_read_block(hdev, data->f11.control_base_addr, buf, 12);
+ ret = rmi_read_block(hdev, data->f11.control_base_addr,
+ data->f11_ctrl_regs, RMI_F11_CTRL_REG_COUNT);
if (ret) {
hid_err(hdev, "can not read ctrl block of size 11: %d.\n", ret);
return ret;
}
- data->max_x = buf[6] | (buf[7] << 8);
- data->max_y = buf[8] | (buf[9] << 8);
+ /* data->f11_ctrl_regs now contains valid register data */
+ data->read_f11_ctrl_regs = true;
+
+ data->max_x = data->f11_ctrl_regs[6] | (data->f11_ctrl_regs[7] << 8);
+ data->max_y = data->f11_ctrl_regs[8] | (data->f11_ctrl_regs[9] << 8);
if (has_dribble) {
- buf[0] = buf[0] & ~BIT(6);
- ret = rmi_write(hdev, data->f11.control_base_addr, buf);
+ data->f11_ctrl_regs[0] = data->f11_ctrl_regs[0] & ~BIT(6);
+ ret = rmi_write(hdev, data->f11.control_base_addr,
+ data->f11_ctrl_regs);
if (ret) {
hid_err(hdev, "can not write to control reg 0: %d.\n",
ret);
@@ -930,9 +1060,9 @@ static int rmi_populate_f11(struct hid_device *hdev)
}
if (has_palm_detect) {
- buf[11] = buf[11] & ~BIT(0);
+ data->f11_ctrl_regs[11] = data->f11_ctrl_regs[11] & ~BIT(0);
ret = rmi_write(hdev, data->f11.control_base_addr + 11,
- &buf[11]);
+ &data->f11_ctrl_regs[11]);
if (ret) {
hid_err(hdev, "can not write to control reg 11: %d.\n",
ret);
@@ -1013,6 +1143,7 @@ static int rmi_populate_f30(struct hid_device *hdev)
static int rmi_populate(struct hid_device *hdev)
{
+ struct rmi_data *data = hid_get_drvdata(hdev);
int ret;
ret = rmi_scan_pdt(hdev);
@@ -1033,14 +1164,16 @@ static int rmi_populate(struct hid_device *hdev)
return ret;
}
- ret = rmi_populate_f30(hdev);
- if (ret)
- hid_warn(hdev, "Error while initializing F30 (%d).\n", ret);
+ if (!(data->device_flags & RMI_DEVICE_HAS_PHYS_BUTTONS)) {
+ ret = rmi_populate_f30(hdev);
+ if (ret)
+ hid_warn(hdev, "Error while initializing F30 (%d).\n", ret);
+ }
return 0;
}
-static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
+static int rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
{
struct rmi_data *data = hid_get_drvdata(hdev);
struct input_dev *input = hi->input;
@@ -1052,10 +1185,10 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
hid_dbg(hdev, "Opening low level driver\n");
ret = hid_hw_open(hdev);
if (ret)
- return;
+ return ret;
if (!(data->device_flags & RMI_DEVICE))
- return;
+ return 0;
/* Allow incoming hid reports */
hid_device_io_start(hdev);
@@ -1095,7 +1228,9 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 0x0f, 0, 0);
input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 0x0f, 0, 0);
- input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+ ret = input_mt_init_slots(input, data->max_fingers, INPUT_MT_POINTER);
+ if (ret < 0)
+ goto exit;
if (data->button_count) {
__set_bit(EV_KEY, input->evbit);
@@ -1111,6 +1246,7 @@ static void rmi_input_configured(struct hid_device *hdev, struct hid_input *hi)
exit:
hid_device_io_stop(hdev);
hid_hw_close(hdev);
+ return ret;
}
static int rmi_input_mapping(struct hid_device *hdev,
@@ -1270,6 +1406,7 @@ static struct hid_driver rmi_driver = {
.input_mapping = rmi_input_mapping,
.input_configured = rmi_input_configured,
#ifdef CONFIG_PM
+ .suspend = rmi_suspend,
.resume = rmi_post_resume,
.reset_resume = rmi_post_reset,
#endif