forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Input: synaptics-rmi4 - add support for 2D sensors and F11
RMI4 currently defines two functions for reporting data for 2D sensors (F11 and F12). This patch adds the common functionality which is shared by devices with 2D reporting along with implementing functionality for F11. Signed-off-by: Andrew Duggan <[email protected]> Signed-off-by: Christopher Heiny <[email protected]> Tested-by: Benjamin Tissoires <[email protected]> Tested-by: Linus Walleij <[email protected]> Tested-by: Bjorn Andersson <[email protected]> Signed-off-by: Dmitry Torokhov <[email protected]>
- Loading branch information
1 parent
d8a8b3e
commit ff8f837
Showing
8 changed files
with
1,724 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,10 @@ | ||
obj-$(CONFIG_RMI4_CORE) += rmi_core.o | ||
rmi_core-y := rmi_bus.o rmi_driver.o rmi_f01.o | ||
|
||
rmi_core-$(CONFIG_RMI4_2D_SENSOR) += rmi_2d_sensor.o | ||
|
||
# Function drivers | ||
rmi_core-$(CONFIG_RMI4_F11) += rmi_f11.o | ||
|
||
# Transports | ||
obj-$(CONFIG_RMI4_I2C) += rmi_i2c.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
/* | ||
* Copyright (c) 2011-2016 Synaptics Incorporated | ||
* Copyright (c) 2011 Unixphere | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 as published by | ||
* the Free Software Foundation. | ||
*/ | ||
|
||
#include <linux/kernel.h> | ||
#include <linux/device.h> | ||
#include <linux/of.h> | ||
#include <linux/input.h> | ||
#include <linux/input/mt.h> | ||
#include <linux/rmi.h> | ||
#include "rmi_driver.h" | ||
#include "rmi_2d_sensor.h" | ||
|
||
#define RMI_2D_REL_POS_MIN -128 | ||
#define RMI_2D_REL_POS_MAX 127 | ||
|
||
/* maximum ABS_MT_POSITION displacement (in mm) */ | ||
#define DMAX 10 | ||
|
||
void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor, | ||
struct rmi_2d_sensor_abs_object *obj, | ||
int slot) | ||
{ | ||
struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; | ||
|
||
/* we keep the previous values if the finger is released */ | ||
if (obj->type == RMI_2D_OBJECT_NONE) | ||
return; | ||
|
||
if (axis_align->swap_axes) | ||
swap(obj->x, obj->y); | ||
|
||
if (axis_align->flip_x) | ||
obj->x = sensor->max_x - obj->x; | ||
|
||
if (axis_align->flip_y) | ||
obj->y = sensor->max_y - obj->y; | ||
|
||
/* | ||
* Here checking if X offset or y offset are specified is | ||
* redundant. We just add the offsets or clip the values. | ||
* | ||
* Note: offsets need to be applied before clipping occurs, | ||
* or we could get funny values that are outside of | ||
* clipping boundaries. | ||
*/ | ||
obj->x += axis_align->offset_x; | ||
obj->y += axis_align->offset_y; | ||
|
||
obj->x = max(axis_align->clip_x_low, obj->x); | ||
obj->y = max(axis_align->clip_y_low, obj->y); | ||
|
||
if (axis_align->clip_x_high) | ||
obj->x = min(sensor->max_x, obj->x); | ||
|
||
if (axis_align->clip_y_high) | ||
obj->y = min(sensor->max_y, obj->y); | ||
|
||
sensor->tracking_pos[slot].x = obj->x; | ||
sensor->tracking_pos[slot].y = obj->y; | ||
} | ||
EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_process); | ||
|
||
void rmi_2d_sensor_abs_report(struct rmi_2d_sensor *sensor, | ||
struct rmi_2d_sensor_abs_object *obj, | ||
int slot) | ||
{ | ||
struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; | ||
struct input_dev *input = sensor->input; | ||
int wide, major, minor; | ||
|
||
if (sensor->kernel_tracking) | ||
input_mt_slot(input, sensor->tracking_slots[slot]); | ||
else | ||
input_mt_slot(input, slot); | ||
|
||
input_mt_report_slot_state(input, obj->mt_tool, | ||
obj->type != RMI_2D_OBJECT_NONE); | ||
|
||
if (obj->type != RMI_2D_OBJECT_NONE) { | ||
obj->x = sensor->tracking_pos[slot].x; | ||
obj->y = sensor->tracking_pos[slot].y; | ||
|
||
if (axis_align->swap_axes) | ||
swap(obj->wx, obj->wy); | ||
|
||
wide = (obj->wx > obj->wy); | ||
major = max(obj->wx, obj->wy); | ||
minor = min(obj->wx, obj->wy); | ||
|
||
if (obj->type == RMI_2D_OBJECT_STYLUS) { | ||
major = max(1, major); | ||
minor = max(1, minor); | ||
} | ||
|
||
input_event(sensor->input, EV_ABS, ABS_MT_POSITION_X, obj->x); | ||
input_event(sensor->input, EV_ABS, ABS_MT_POSITION_Y, obj->y); | ||
input_event(sensor->input, EV_ABS, ABS_MT_ORIENTATION, wide); | ||
input_event(sensor->input, EV_ABS, ABS_MT_PRESSURE, obj->z); | ||
input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MAJOR, major); | ||
input_event(sensor->input, EV_ABS, ABS_MT_TOUCH_MINOR, minor); | ||
|
||
rmi_dbg(RMI_DEBUG_2D_SENSOR, &sensor->input->dev, | ||
"%s: obj[%d]: type: 0x%02x X: %d Y: %d Z: %d WX: %d WY: %d\n", | ||
__func__, slot, obj->type, obj->x, obj->y, obj->z, | ||
obj->wx, obj->wy); | ||
} | ||
} | ||
EXPORT_SYMBOL_GPL(rmi_2d_sensor_abs_report); | ||
|
||
void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y) | ||
{ | ||
struct rmi_2d_axis_alignment *axis_align = &sensor->axis_align; | ||
|
||
x = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)x)); | ||
y = min(RMI_2D_REL_POS_MAX, max(RMI_2D_REL_POS_MIN, (int)y)); | ||
|
||
if (axis_align->swap_axes) | ||
swap(x, y); | ||
|
||
if (axis_align->flip_x) | ||
x = min(RMI_2D_REL_POS_MAX, -x); | ||
|
||
if (axis_align->flip_y) | ||
y = min(RMI_2D_REL_POS_MAX, -y); | ||
|
||
if (x || y) { | ||
input_report_rel(sensor->input, REL_X, x); | ||
input_report_rel(sensor->input, REL_Y, y); | ||
} | ||
} | ||
EXPORT_SYMBOL_GPL(rmi_2d_sensor_rel_report); | ||
|
||
static void rmi_2d_sensor_set_input_params(struct rmi_2d_sensor *sensor) | ||
{ | ||
struct input_dev *input = sensor->input; | ||
int res_x; | ||
int res_y; | ||
int input_flags = 0; | ||
|
||
if (sensor->report_abs) { | ||
if (sensor->axis_align.swap_axes) | ||
swap(sensor->max_x, sensor->max_y); | ||
|
||
sensor->min_x = sensor->axis_align.clip_x_low; | ||
if (sensor->axis_align.clip_x_high) | ||
sensor->max_x = min(sensor->max_x, | ||
sensor->axis_align.clip_x_high); | ||
|
||
sensor->min_y = sensor->axis_align.clip_y_low; | ||
if (sensor->axis_align.clip_y_high) | ||
sensor->max_y = min(sensor->max_y, | ||
sensor->axis_align.clip_y_high); | ||
|
||
set_bit(EV_ABS, input->evbit); | ||
input_set_abs_params(input, ABS_MT_POSITION_X, 0, sensor->max_x, | ||
0, 0); | ||
input_set_abs_params(input, ABS_MT_POSITION_Y, 0, sensor->max_y, | ||
0, 0); | ||
|
||
if (sensor->x_mm && sensor->y_mm) { | ||
res_x = (sensor->max_x - sensor->min_x) / sensor->x_mm; | ||
res_y = (sensor->max_y - sensor->min_y) / sensor->y_mm; | ||
|
||
input_abs_set_res(input, ABS_X, res_x); | ||
input_abs_set_res(input, ABS_Y, res_y); | ||
|
||
input_abs_set_res(input, ABS_MT_POSITION_X, res_x); | ||
input_abs_set_res(input, ABS_MT_POSITION_Y, res_y); | ||
|
||
if (!sensor->dmax) | ||
sensor->dmax = DMAX * res_x; | ||
} | ||
|
||
input_set_abs_params(input, ABS_MT_PRESSURE, 0, 0xff, 0, 0); | ||
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_set_abs_params(input, ABS_MT_ORIENTATION, 0, 1, 0, 0); | ||
|
||
if (sensor->sensor_type == rmi_sensor_touchpad) | ||
input_flags = INPUT_MT_POINTER; | ||
else | ||
input_flags = INPUT_MT_DIRECT; | ||
|
||
if (sensor->kernel_tracking) | ||
input_flags |= INPUT_MT_TRACK; | ||
|
||
input_mt_init_slots(input, sensor->nbr_fingers, input_flags); | ||
} | ||
|
||
if (sensor->report_rel) { | ||
set_bit(EV_REL, input->evbit); | ||
set_bit(REL_X, input->relbit); | ||
set_bit(REL_Y, input->relbit); | ||
} | ||
|
||
if (sensor->topbuttonpad) | ||
set_bit(INPUT_PROP_TOPBUTTONPAD, input->propbit); | ||
} | ||
EXPORT_SYMBOL_GPL(rmi_2d_sensor_set_input_params); | ||
|
||
int rmi_2d_sensor_configure_input(struct rmi_function *fn, | ||
struct rmi_2d_sensor *sensor) | ||
{ | ||
struct rmi_device *rmi_dev = fn->rmi_dev; | ||
struct rmi_driver_data *drv_data = dev_get_drvdata(&rmi_dev->dev); | ||
|
||
if (!drv_data->input) | ||
return -ENODEV; | ||
|
||
sensor->input = drv_data->input; | ||
rmi_2d_sensor_set_input_params(sensor); | ||
|
||
return 0; | ||
} | ||
EXPORT_SYMBOL_GPL(rmi_2d_sensor_configure_input); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
/* | ||
* Copyright (c) 2011-2016 Synaptics Incorporated | ||
* Copyright (c) 2011 Unixphere | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms of the GNU General Public License version 2 as published by | ||
* the Free Software Foundation. | ||
*/ | ||
|
||
#ifndef _RMI_2D_SENSOR_H | ||
#define _RMI_2D_SENSOR_H | ||
|
||
enum rmi_2d_sensor_object_type { | ||
RMI_2D_OBJECT_NONE, | ||
RMI_2D_OBJECT_FINGER, | ||
RMI_2D_OBJECT_STYLUS, | ||
RMI_2D_OBJECT_PALM, | ||
RMI_2D_OBJECT_UNCLASSIFIED, | ||
}; | ||
|
||
struct rmi_2d_sensor_abs_object { | ||
enum rmi_2d_sensor_object_type type; | ||
int mt_tool; | ||
u16 x; | ||
u16 y; | ||
u8 z; | ||
u8 wx; | ||
u8 wy; | ||
}; | ||
|
||
/** | ||
* @axis_align - controls parameters that are useful in system prototyping | ||
* and bring up. | ||
* @max_x - The maximum X coordinate that will be reported by this sensor. | ||
* @max_y - The maximum Y coordinate that will be reported by this sensor. | ||
* @nbr_fingers - How many fingers can this sensor report? | ||
* @data_pkt - buffer for data reported by this sensor. | ||
* @pkt_size - number of bytes in that buffer. | ||
* @attn_size - Size of the HID attention report (only contains abs data). | ||
* position when two fingers are on the device. When this is true, we | ||
* assume we have one of those sensors and report events appropriately. | ||
* @sensor_type - indicates whether we're touchscreen or touchpad. | ||
* @input - input device for absolute pointing stream | ||
* @input_phys - buffer for the absolute phys name for this sensor. | ||
*/ | ||
struct rmi_2d_sensor { | ||
struct rmi_2d_axis_alignment axis_align; | ||
struct input_mt_pos *tracking_pos; | ||
int *tracking_slots; | ||
bool kernel_tracking; | ||
struct rmi_2d_sensor_abs_object *objs; | ||
int dmax; | ||
u16 min_x; | ||
u16 max_x; | ||
u16 min_y; | ||
u16 max_y; | ||
u8 nbr_fingers; | ||
u8 *data_pkt; | ||
int pkt_size; | ||
int attn_size; | ||
bool topbuttonpad; | ||
enum rmi_sensor_type sensor_type; | ||
struct input_dev *input; | ||
struct rmi_function *fn; | ||
char input_phys[32]; | ||
u8 report_abs; | ||
u8 report_rel; | ||
u8 x_mm; | ||
u8 y_mm; | ||
}; | ||
|
||
void rmi_2d_sensor_abs_process(struct rmi_2d_sensor *sensor, | ||
struct rmi_2d_sensor_abs_object *obj, | ||
int slot); | ||
|
||
void rmi_2d_sensor_abs_report(struct rmi_2d_sensor *sensor, | ||
struct rmi_2d_sensor_abs_object *obj, | ||
int slot); | ||
|
||
void rmi_2d_sensor_rel_report(struct rmi_2d_sensor *sensor, int x, int y); | ||
|
||
int rmi_2d_sensor_configure_input(struct rmi_function *fn, | ||
struct rmi_2d_sensor *sensor); | ||
#endif /* _RMI_2D_SENSOR_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.