Merge branch 'next' into for-linus
Prepare first round of input updates for 4.2 merge window.
This commit is contained in:
@@ -159,8 +159,8 @@ static const struct alps_protocol_info alps_v8_protocol_data = {
|
||||
|
||||
static void alps_set_abs_params_st(struct alps_data *priv,
|
||||
struct input_dev *dev1);
|
||||
static void alps_set_abs_params_mt(struct alps_data *priv,
|
||||
struct input_dev *dev1);
|
||||
static void alps_set_abs_params_semi_mt(struct alps_data *priv,
|
||||
struct input_dev *dev1);
|
||||
static void alps_set_abs_params_v7(struct alps_data *priv,
|
||||
struct input_dev *dev1);
|
||||
static void alps_set_abs_params_ss4_v2(struct alps_data *priv,
|
||||
@@ -310,53 +310,6 @@ static void alps_process_packet_v1_v2(struct psmouse *psmouse)
|
||||
input_sync(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process bitmap data for V5 protocols. Return value is null.
|
||||
*
|
||||
* The bitmaps don't have enough data to track fingers, so this function
|
||||
* only generates points representing a bounding box of at most two contacts.
|
||||
* These two points are returned in fields->mt.
|
||||
*/
|
||||
static void alps_process_bitmap_dolphin(struct alps_data *priv,
|
||||
struct alps_fields *fields)
|
||||
{
|
||||
int box_middle_x, box_middle_y;
|
||||
unsigned int x_map, y_map;
|
||||
unsigned char start_bit, end_bit;
|
||||
unsigned char x_msb, x_lsb, y_msb, y_lsb;
|
||||
|
||||
x_map = fields->x_map;
|
||||
y_map = fields->y_map;
|
||||
|
||||
if (!x_map || !y_map)
|
||||
return;
|
||||
|
||||
/* Get Most-significant and Least-significant bit */
|
||||
x_msb = fls(x_map);
|
||||
x_lsb = ffs(x_map);
|
||||
y_msb = fls(y_map);
|
||||
y_lsb = ffs(y_map);
|
||||
|
||||
/* Most-significant bit should never exceed max sensor line number */
|
||||
if (x_msb > priv->x_bits || y_msb > priv->y_bits)
|
||||
return;
|
||||
|
||||
if (fields->fingers > 1) {
|
||||
start_bit = priv->x_bits - x_msb;
|
||||
end_bit = priv->x_bits - x_lsb;
|
||||
box_middle_x = (priv->x_max * (start_bit + end_bit)) /
|
||||
(2 * (priv->x_bits - 1));
|
||||
|
||||
start_bit = y_lsb - 1;
|
||||
end_bit = y_msb - 1;
|
||||
box_middle_y = (priv->y_max * (start_bit + end_bit)) /
|
||||
(2 * (priv->y_bits - 1));
|
||||
fields->mt[0] = fields->st;
|
||||
fields->mt[1].x = 2 * box_middle_x - fields->mt[0].x;
|
||||
fields->mt[1].y = 2 * box_middle_y - fields->mt[0].y;
|
||||
}
|
||||
}
|
||||
|
||||
static void alps_get_bitmap_points(unsigned int map,
|
||||
struct alps_bitmap_point *low,
|
||||
struct alps_bitmap_point *high,
|
||||
@@ -384,7 +337,7 @@ static void alps_get_bitmap_points(unsigned int map,
|
||||
}
|
||||
|
||||
/*
|
||||
* Process bitmap data from v3 and v4 protocols. Returns the number of
|
||||
* Process bitmap data from semi-mt protocols. Returns the number of
|
||||
* fingers detected. A return value of 0 means at least one of the
|
||||
* bitmaps was empty.
|
||||
*
|
||||
@@ -396,9 +349,10 @@ static void alps_get_bitmap_points(unsigned int map,
|
||||
static int alps_process_bitmap(struct alps_data *priv,
|
||||
struct alps_fields *fields)
|
||||
{
|
||||
int i, fingers_x = 0, fingers_y = 0, fingers;
|
||||
int i, fingers_x = 0, fingers_y = 0, fingers, closest;
|
||||
struct alps_bitmap_point x_low = {0,}, x_high = {0,};
|
||||
struct alps_bitmap_point y_low = {0,}, y_high = {0,};
|
||||
struct input_mt_pos corner[4];
|
||||
|
||||
if (!fields->x_map || !fields->y_map)
|
||||
return 0;
|
||||
@@ -429,26 +383,76 @@ static int alps_process_bitmap(struct alps_data *priv,
|
||||
y_high.num_bits = max(i, 1);
|
||||
}
|
||||
|
||||
fields->mt[0].x =
|
||||
/* top-left corner */
|
||||
corner[0].x =
|
||||
(priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
|
||||
(2 * (priv->x_bits - 1));
|
||||
fields->mt[0].y =
|
||||
corner[0].y =
|
||||
(priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
|
||||
(2 * (priv->y_bits - 1));
|
||||
|
||||
fields->mt[1].x =
|
||||
/* top-right corner */
|
||||
corner[1].x =
|
||||
(priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
|
||||
(2 * (priv->x_bits - 1));
|
||||
fields->mt[1].y =
|
||||
corner[1].y =
|
||||
(priv->y_max * (2 * y_low.start_bit + y_low.num_bits - 1)) /
|
||||
(2 * (priv->y_bits - 1));
|
||||
|
||||
/* bottom-right corner */
|
||||
corner[2].x =
|
||||
(priv->x_max * (2 * x_high.start_bit + x_high.num_bits - 1)) /
|
||||
(2 * (priv->x_bits - 1));
|
||||
corner[2].y =
|
||||
(priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
|
||||
(2 * (priv->y_bits - 1));
|
||||
|
||||
/* y-bitmap order is reversed, except on rushmore */
|
||||
if (priv->proto_version != ALPS_PROTO_V3_RUSHMORE) {
|
||||
fields->mt[0].y = priv->y_max - fields->mt[0].y;
|
||||
fields->mt[1].y = priv->y_max - fields->mt[1].y;
|
||||
/* bottom-left corner */
|
||||
corner[3].x =
|
||||
(priv->x_max * (2 * x_low.start_bit + x_low.num_bits - 1)) /
|
||||
(2 * (priv->x_bits - 1));
|
||||
corner[3].y =
|
||||
(priv->y_max * (2 * y_high.start_bit + y_high.num_bits - 1)) /
|
||||
(2 * (priv->y_bits - 1));
|
||||
|
||||
/* x-bitmap order is reversed on v5 touchpads */
|
||||
if (priv->proto_version == ALPS_PROTO_V5) {
|
||||
for (i = 0; i < 4; i++)
|
||||
corner[i].x = priv->x_max - corner[i].x;
|
||||
}
|
||||
|
||||
/* y-bitmap order is reversed on v3 and v4 touchpads */
|
||||
if (priv->proto_version == ALPS_PROTO_V3 ||
|
||||
priv->proto_version == ALPS_PROTO_V4) {
|
||||
for (i = 0; i < 4; i++)
|
||||
corner[i].y = priv->y_max - corner[i].y;
|
||||
}
|
||||
|
||||
/*
|
||||
* We only select a corner for the second touch once per 2 finger
|
||||
* touch sequence to avoid the chosen corner (and thus the coordinates)
|
||||
* jumping around when the first touch is in the middle.
|
||||
*/
|
||||
if (priv->second_touch == -1) {
|
||||
/* Find corner closest to our st coordinates */
|
||||
closest = 0x7fffffff;
|
||||
for (i = 0; i < 4; i++) {
|
||||
int dx = fields->st.x - corner[i].x;
|
||||
int dy = fields->st.y - corner[i].y;
|
||||
int distance = dx * dx + dy * dy;
|
||||
|
||||
if (distance < closest) {
|
||||
priv->second_touch = i;
|
||||
closest = distance;
|
||||
}
|
||||
}
|
||||
/* And select the opposite corner to use for the 2nd touch */
|
||||
priv->second_touch = (priv->second_touch + 2) % 4;
|
||||
}
|
||||
|
||||
fields->mt[0] = fields->st;
|
||||
fields->mt[1] = corner[priv->second_touch];
|
||||
|
||||
return fingers;
|
||||
}
|
||||
|
||||
@@ -485,9 +489,14 @@ static void alps_report_semi_mt_data(struct psmouse *psmouse, int fingers)
|
||||
f->mt[0].x = f->st.x;
|
||||
f->mt[0].y = f->st.y;
|
||||
fingers = f->pressure > 0 ? 1 : 0;
|
||||
priv->second_touch = -1;
|
||||
}
|
||||
|
||||
alps_report_mt_data(psmouse, (fingers <= 2) ? fingers : 2);
|
||||
if (fingers >= 1)
|
||||
alps_set_slot(dev, 0, f->mt[0].x, f->mt[0].y);
|
||||
if (fingers >= 2)
|
||||
alps_set_slot(dev, 1, f->mt[1].x, f->mt[1].y);
|
||||
input_mt_sync_frame(dev);
|
||||
|
||||
input_mt_report_finger_count(dev, fingers);
|
||||
|
||||
@@ -584,20 +593,22 @@ static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
|
||||
f->first_mp = !!(p[4] & 0x40);
|
||||
f->is_mp = !!(p[0] & 0x40);
|
||||
|
||||
f->fingers = (p[5] & 0x3) + 1;
|
||||
f->x_map = ((p[4] & 0x7e) << 8) |
|
||||
((p[1] & 0x7f) << 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->y_map = ((p[3] & 0x70) << 4) |
|
||||
((p[2] & 0x7f) << 1) |
|
||||
(p[4] & 0x01);
|
||||
if (f->is_mp) {
|
||||
f->fingers = (p[5] & 0x3) + 1;
|
||||
f->x_map = ((p[4] & 0x7e) << 8) |
|
||||
((p[1] & 0x7f) << 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->y_map = ((p[3] & 0x70) << 4) |
|
||||
((p[2] & 0x7f) << 1) |
|
||||
(p[4] & 0x01);
|
||||
} else {
|
||||
f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
|
||||
f->pressure = p[5] & 0x7f;
|
||||
|
||||
f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
|
||||
f->pressure = p[5] & 0x7f;
|
||||
|
||||
alps_decode_buttons_v3(f, p);
|
||||
alps_decode_buttons_v3(f, p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -605,13 +616,27 @@ static int alps_decode_pinnacle(struct alps_fields *f, unsigned char *p,
|
||||
static int alps_decode_rushmore(struct alps_fields *f, unsigned char *p,
|
||||
struct psmouse *psmouse)
|
||||
{
|
||||
alps_decode_pinnacle(f, p, psmouse);
|
||||
|
||||
/* Rushmore's packet decode has a bit difference with Pinnacle's */
|
||||
f->first_mp = !!(p[4] & 0x40);
|
||||
f->is_mp = !!(p[5] & 0x40);
|
||||
f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
|
||||
f->x_map |= (p[5] & 0x10) << 11;
|
||||
f->y_map |= (p[5] & 0x20) << 6;
|
||||
|
||||
if (f->is_mp) {
|
||||
f->fingers = max((p[5] & 0x3), ((p[5] >> 2) & 0x3)) + 1;
|
||||
f->x_map = ((p[5] & 0x10) << 11) |
|
||||
((p[4] & 0x7e) << 8) |
|
||||
((p[1] & 0x7f) << 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->y_map = ((p[5] & 0x20) << 6) |
|
||||
((p[3] & 0x70) << 4) |
|
||||
((p[2] & 0x7f) << 1) |
|
||||
(p[4] & 0x01);
|
||||
} else {
|
||||
f->st.x = ((p[1] & 0x7f) << 4) | ((p[4] & 0x30) >> 2) |
|
||||
((p[0] & 0x30) >> 4);
|
||||
f->st.y = ((p[2] & 0x7f) << 4) | (p[4] & 0x0f);
|
||||
f->pressure = p[5] & 0x7f;
|
||||
|
||||
alps_decode_buttons_v3(f, p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -680,30 +705,13 @@ static void alps_process_touchpad_packet_v3_v5(struct psmouse *psmouse)
|
||||
*/
|
||||
if (f->is_mp) {
|
||||
fingers = f->fingers;
|
||||
if (priv->proto_version == ALPS_PROTO_V3 ||
|
||||
priv->proto_version == ALPS_PROTO_V3_RUSHMORE) {
|
||||
if (alps_process_bitmap(priv, f) == 0)
|
||||
fingers = 0; /* Use st data */
|
||||
|
||||
/* Now process position packet */
|
||||
priv->decode_fields(f, priv->multi_data,
|
||||
psmouse);
|
||||
} else {
|
||||
/*
|
||||
* Because Dolphin uses position packet's
|
||||
* coordinate data as Pt1 and uses it to
|
||||
* calculate Pt2, so we need to do position
|
||||
* packet decode first.
|
||||
*/
|
||||
priv->decode_fields(f, priv->multi_data,
|
||||
psmouse);
|
||||
|
||||
/*
|
||||
* Since Dolphin's finger number is reliable,
|
||||
* there is no need to compare with bmap_fn.
|
||||
*/
|
||||
alps_process_bitmap_dolphin(priv, f);
|
||||
}
|
||||
/*
|
||||
* Bitmap processing uses position packet's coordinate
|
||||
* data, so we need to do decode it first.
|
||||
*/
|
||||
priv->decode_fields(f, priv->multi_data, psmouse);
|
||||
if (alps_process_bitmap(priv, f) == 0)
|
||||
fingers = 0; /* Use st data */
|
||||
} else {
|
||||
priv->multi_packet = 0;
|
||||
}
|
||||
@@ -865,6 +873,14 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
|
||||
priv->multi_data[offset] = packet[6];
|
||||
priv->multi_data[offset + 1] = packet[7];
|
||||
|
||||
f->left = !!(packet[4] & 0x01);
|
||||
f->right = !!(packet[4] & 0x02);
|
||||
|
||||
f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
|
||||
((packet[0] & 0x30) >> 4);
|
||||
f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
|
||||
f->pressure = packet[5] & 0x7f;
|
||||
|
||||
if (++priv->multi_packet > 2) {
|
||||
priv->multi_packet = 0;
|
||||
|
||||
@@ -879,14 +895,6 @@ static void alps_process_packet_v4(struct psmouse *psmouse)
|
||||
f->fingers = alps_process_bitmap(priv, f);
|
||||
}
|
||||
|
||||
f->left = !!(packet[4] & 0x01);
|
||||
f->right = !!(packet[4] & 0x02);
|
||||
|
||||
f->st.x = ((packet[1] & 0x7f) << 4) | ((packet[3] & 0x30) >> 2) |
|
||||
((packet[0] & 0x30) >> 4);
|
||||
f->st.y = ((packet[2] & 0x7f) << 4) | (packet[3] & 0x0f);
|
||||
f->pressure = packet[5] & 0x7f;
|
||||
|
||||
alps_report_semi_mt_data(psmouse, f->fingers);
|
||||
}
|
||||
|
||||
@@ -2561,7 +2569,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
|
||||
case ALPS_PROTO_V3:
|
||||
priv->hw_init = alps_hw_init_v3;
|
||||
priv->process_packet = alps_process_packet_v3;
|
||||
priv->set_abs_params = alps_set_abs_params_mt;
|
||||
priv->set_abs_params = alps_set_abs_params_semi_mt;
|
||||
priv->decode_fields = alps_decode_pinnacle;
|
||||
priv->nibble_commands = alps_v3_nibble_commands;
|
||||
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
|
||||
@@ -2570,7 +2578,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
|
||||
case ALPS_PROTO_V3_RUSHMORE:
|
||||
priv->hw_init = alps_hw_init_rushmore_v3;
|
||||
priv->process_packet = alps_process_packet_v3;
|
||||
priv->set_abs_params = alps_set_abs_params_mt;
|
||||
priv->set_abs_params = alps_set_abs_params_semi_mt;
|
||||
priv->decode_fields = alps_decode_rushmore;
|
||||
priv->nibble_commands = alps_v3_nibble_commands;
|
||||
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
|
||||
@@ -2586,7 +2594,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
|
||||
case ALPS_PROTO_V4:
|
||||
priv->hw_init = alps_hw_init_v4;
|
||||
priv->process_packet = alps_process_packet_v4;
|
||||
priv->set_abs_params = alps_set_abs_params_mt;
|
||||
priv->set_abs_params = alps_set_abs_params_semi_mt;
|
||||
priv->nibble_commands = alps_v4_nibble_commands;
|
||||
priv->addr_command = PSMOUSE_CMD_DISABLE;
|
||||
break;
|
||||
@@ -2595,7 +2603,7 @@ static int alps_set_protocol(struct psmouse *psmouse,
|
||||
priv->hw_init = alps_hw_init_dolphin_v1;
|
||||
priv->process_packet = alps_process_touchpad_packet_v3_v5;
|
||||
priv->decode_fields = alps_decode_dolphin;
|
||||
priv->set_abs_params = alps_set_abs_params_mt;
|
||||
priv->set_abs_params = alps_set_abs_params_semi_mt;
|
||||
priv->nibble_commands = alps_v3_nibble_commands;
|
||||
priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
|
||||
priv->x_bits = 23;
|
||||
@@ -2777,15 +2785,15 @@ static void alps_set_abs_params_mt_common(struct alps_data *priv,
|
||||
set_bit(BTN_TOOL_QUADTAP, dev1->keybit);
|
||||
}
|
||||
|
||||
static void alps_set_abs_params_mt(struct alps_data *priv,
|
||||
struct input_dev *dev1)
|
||||
static void alps_set_abs_params_semi_mt(struct alps_data *priv,
|
||||
struct input_dev *dev1)
|
||||
{
|
||||
alps_set_abs_params_mt_common(priv, dev1);
|
||||
input_set_abs_params(dev1, ABS_PRESSURE, 0, 127, 0, 0);
|
||||
|
||||
input_mt_init_slots(dev1, MAX_TOUCHES,
|
||||
INPUT_MT_POINTER | INPUT_MT_DROP_UNUSED |
|
||||
INPUT_MT_TRACK | INPUT_MT_SEMI_MT);
|
||||
INPUT_MT_SEMI_MT);
|
||||
}
|
||||
|
||||
static void alps_set_abs_params_v7(struct alps_data *priv,
|
||||
|
@@ -278,6 +278,7 @@ struct alps_data {
|
||||
|
||||
int prev_fin;
|
||||
int multi_packet;
|
||||
int second_touch;
|
||||
unsigned char multi_data[6];
|
||||
struct alps_fields f;
|
||||
u8 quirks;
|
||||
|
@@ -950,14 +950,13 @@ static u16 cyapa_get_wait_time_for_pwr_cmd(u8 pwr_mode)
|
||||
* Device power mode can only be set when device is in operational mode.
|
||||
*/
|
||||
static int cyapa_gen3_set_power_mode(struct cyapa *cyapa, u8 power_mode,
|
||||
u16 always_unused)
|
||||
u16 always_unused)
|
||||
{
|
||||
int ret;
|
||||
u8 power;
|
||||
int tries;
|
||||
u16 sleep_time;
|
||||
|
||||
always_unused = 0;
|
||||
if (cyapa->state != CYAPA_STATE_OP)
|
||||
return 0;
|
||||
|
||||
|
@@ -352,7 +352,7 @@ struct gen5_app_cmd_head {
|
||||
u8 parameter_data[0]; /* Parameter data variable based on cmd_code */
|
||||
} __packed;
|
||||
|
||||
/* Applicaton get/set parameter command data structure */
|
||||
/* Application get/set parameter command data structure */
|
||||
struct gen5_app_set_parameter_data {
|
||||
u8 parameter_id;
|
||||
u8 parameter_size;
|
||||
@@ -832,7 +832,7 @@ static int gen5_hid_description_header_parse(struct cyapa *cyapa, u8 *reg_data)
|
||||
int ret;
|
||||
|
||||
/* 0x20 0x00 0xF7 is Gen5 Application HID Description Header;
|
||||
* 0x20 0x00 0xFF is Gen5 Booloader HID Description Header.
|
||||
* 0x20 0x00 0xFF is Gen5 Bootloader HID Description Header.
|
||||
*
|
||||
* Must read HID Description content through out,
|
||||
* otherwise Gen5 trackpad cannot response next command
|
||||
@@ -1654,8 +1654,8 @@ static int cyapa_gen5_set_power_mode(struct cyapa *cyapa,
|
||||
* that trackpad unable to report signal to wake system up
|
||||
* in the special situation that system is in suspending, and
|
||||
* at the same time, user touch trackpad to wake system up.
|
||||
* This function can avoid the data to be buffured when system
|
||||
* is suspending which may cause interrput line unable to be
|
||||
* This function can avoid the data to be buffered when system
|
||||
* is suspending which may cause interrupt line unable to be
|
||||
* asserted again.
|
||||
*/
|
||||
cyapa_empty_pip_output_data(cyapa, NULL, NULL, NULL);
|
||||
@@ -2546,16 +2546,11 @@ static bool cyapa_gen5_irq_cmd_handler(struct cyapa *cyapa)
|
||||
gen5_pip->resp_sort_func(cyapa,
|
||||
gen5_pip->irq_cmd_buf, length))) {
|
||||
/*
|
||||
* Cover the Gen5 V1 firmware issue.
|
||||
* The issue is there is no interrut will be
|
||||
* asserted to notityf host to read a command
|
||||
* data out when always has finger touch on
|
||||
* trackpad during the command is issued to
|
||||
* trackad device.
|
||||
* This issue has the scenario is that,
|
||||
* user always has his fingers touched on
|
||||
* trackpad device when booting/rebooting
|
||||
* their chrome book.
|
||||
* Work around the Gen5 V1 firmware
|
||||
* that does not assert interrupt signalling
|
||||
* that command response is ready if user
|
||||
* keeps touching the trackpad while command
|
||||
* is sent to the device.
|
||||
*/
|
||||
length = 0;
|
||||
if (gen5_pip->resp_len)
|
||||
|
@@ -28,14 +28,13 @@
|
||||
#define ETP_PRESSURE_OFFSET 25
|
||||
|
||||
/* IAP Firmware handling */
|
||||
#define ETP_FW_NAME "elan_i2c.bin"
|
||||
#define ETP_PRODUCT_ID_FORMAT_STRING "%d.0"
|
||||
#define ETP_FW_NAME "elan_i2c_" ETP_PRODUCT_ID_FORMAT_STRING ".bin"
|
||||
#define ETP_IAP_START_ADDR 0x0083
|
||||
#define ETP_FW_IAP_PAGE_ERR (1 << 5)
|
||||
#define ETP_FW_IAP_INTF_ERR (1 << 4)
|
||||
#define ETP_FW_PAGE_SIZE 64
|
||||
#define ETP_FW_VAILDPAGE_COUNT 768
|
||||
#define ETP_FW_SIGNATURE_SIZE 6
|
||||
#define ETP_FW_SIGNATURE_ADDRESS 0xBFFA
|
||||
|
||||
struct i2c_client;
|
||||
struct completion;
|
||||
@@ -58,7 +57,8 @@ struct elan_transport_ops {
|
||||
bool max_baseliune, u8 *value);
|
||||
|
||||
int (*get_version)(struct i2c_client *client, bool iap, u8 *version);
|
||||
int (*get_sm_version)(struct i2c_client *client, u8 *version);
|
||||
int (*get_sm_version)(struct i2c_client *client,
|
||||
u8* ic_type, u8 *version);
|
||||
int (*get_checksum)(struct i2c_client *client, bool iap, u16 *csum);
|
||||
int (*get_product_id)(struct i2c_client *client, u8 *id);
|
||||
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* Copyright (c) 2013 ELAN Microelectronics Corp.
|
||||
*
|
||||
* Author: 林政維 (Duson Lin) <dusonlin@emc.com.tw>
|
||||
* Version: 1.5.7
|
||||
* Version: 1.5.9
|
||||
*
|
||||
* Based on cyapa driver:
|
||||
* copyright (c) 2011-2012 Cypress Semiconductor, Inc.
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "elan_i2c.h"
|
||||
|
||||
#define DRIVER_NAME "elan_i2c"
|
||||
#define ELAN_DRIVER_VERSION "1.5.7"
|
||||
#define ELAN_DRIVER_VERSION "1.5.9"
|
||||
#define ETP_MAX_PRESSURE 255
|
||||
#define ETP_FWIDTH_REDUCE 90
|
||||
#define ETP_FINGER_WIDTH 15
|
||||
@@ -83,6 +83,9 @@ struct elan_tp_data {
|
||||
u16 fw_checksum;
|
||||
int pressure_adjustment;
|
||||
u8 mode;
|
||||
u8 ic_type;
|
||||
u16 fw_vaildpage_count;
|
||||
u16 fw_signature_address;
|
||||
|
||||
bool irq_wake;
|
||||
|
||||
@@ -91,6 +94,29 @@ struct elan_tp_data {
|
||||
bool baseline_ready;
|
||||
};
|
||||
|
||||
static int elan_get_fwinfo(u8 ic_type, u16 *vaildpage_count,
|
||||
u16 *signature_address)
|
||||
{
|
||||
switch(ic_type) {
|
||||
case 0x09:
|
||||
*vaildpage_count = 768;
|
||||
break;
|
||||
case 0x0D:
|
||||
*vaildpage_count = 896;
|
||||
break;
|
||||
default:
|
||||
/* unknown ic type clear value */
|
||||
*vaildpage_count = 0;
|
||||
*signature_address = 0;
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
*signature_address =
|
||||
(*vaildpage_count * ETP_FW_PAGE_SIZE) - ETP_FW_SIGNATURE_SIZE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_enable_power(struct elan_tp_data *data)
|
||||
{
|
||||
int repeat = ETP_RETRY_COUNT;
|
||||
@@ -221,7 +247,8 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = data->ops->get_sm_version(data->client, &data->sm_version);
|
||||
error = data->ops->get_sm_version(data->client, &data->ic_type,
|
||||
&data->sm_version);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -234,6 +261,14 @@ static int elan_query_device_info(struct elan_tp_data *data)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = elan_get_fwinfo(data->ic_type, &data->fw_vaildpage_count,
|
||||
&data->fw_signature_address);
|
||||
if (error) {
|
||||
dev_err(&data->client->dev,
|
||||
"unknown ic type %d\n", data->ic_type);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -318,7 +353,7 @@ static int __elan_update_firmware(struct elan_tp_data *data,
|
||||
iap_start_addr = get_unaligned_le16(&fw->data[ETP_IAP_START_ADDR * 2]);
|
||||
|
||||
boot_page_count = (iap_start_addr * 2) / ETP_FW_PAGE_SIZE;
|
||||
for (i = boot_page_count; i < ETP_FW_VAILDPAGE_COUNT; i++) {
|
||||
for (i = boot_page_count; i < data->fw_vaildpage_count; i++) {
|
||||
u16 checksum = 0;
|
||||
const u8 *page = &fw->data[i * ETP_FW_PAGE_SIZE];
|
||||
|
||||
@@ -403,7 +438,8 @@ static ssize_t elan_sysfs_read_product_id(struct device *dev,
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
|
||||
return sprintf(buf, "%d.0\n", data->product_id);
|
||||
return sprintf(buf, ETP_PRODUCT_ID_FORMAT_STRING "\n",
|
||||
data->product_id);
|
||||
}
|
||||
|
||||
static ssize_t elan_sysfs_read_fw_ver(struct device *dev,
|
||||
@@ -442,19 +478,28 @@ static ssize_t elan_sysfs_update_fw(struct device *dev,
|
||||
{
|
||||
struct elan_tp_data *data = dev_get_drvdata(dev);
|
||||
const struct firmware *fw;
|
||||
char *fw_name;
|
||||
int error;
|
||||
const u8 *fw_signature;
|
||||
static const u8 signature[] = {0xAA, 0x55, 0xCC, 0x33, 0xFF, 0xFF};
|
||||
|
||||
error = request_firmware(&fw, ETP_FW_NAME, dev);
|
||||
/* Look for a firmware with the product id appended. */
|
||||
fw_name = kasprintf(GFP_KERNEL, ETP_FW_NAME, data->product_id);
|
||||
if (!fw_name) {
|
||||
dev_err(dev, "failed to allocate memory for firmware name\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dev_info(dev, "requesting fw '%s'\n", fw_name);
|
||||
error = request_firmware(&fw, fw_name, dev);
|
||||
kfree(fw_name);
|
||||
if (error) {
|
||||
dev_err(dev, "cannot load firmware %s: %d\n",
|
||||
ETP_FW_NAME, error);
|
||||
dev_err(dev, "failed to request firmware: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Firmware file must match signature data */
|
||||
fw_signature = &fw->data[ETP_FW_SIGNATURE_ADDRESS];
|
||||
fw_signature = &fw->data[data->fw_signature_address];
|
||||
if (memcmp(fw_signature, signature, sizeof(signature)) != 0) {
|
||||
dev_err(dev, "signature mismatch (expected %*ph, got %*ph)\n",
|
||||
(int)sizeof(signature), signature,
|
||||
|
@@ -259,7 +259,8 @@ static int elan_i2c_get_version(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
|
||||
static int elan_i2c_get_sm_version(struct i2c_client *client,
|
||||
u8 *ic_type, u8 *version)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
@@ -271,6 +272,7 @@ static int elan_i2c_get_sm_version(struct i2c_client *client, u8 *version)
|
||||
}
|
||||
|
||||
*version = val[0];
|
||||
*ic_type = val[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -165,7 +165,8 @@ static int elan_smbus_get_version(struct i2c_client *client,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
|
||||
static int elan_smbus_get_sm_version(struct i2c_client *client,
|
||||
u8 *ic_type, u8 *version)
|
||||
{
|
||||
int error;
|
||||
u8 val[3];
|
||||
@@ -177,7 +178,8 @@ static int elan_smbus_get_sm_version(struct i2c_client *client, u8 *version)
|
||||
return error;
|
||||
}
|
||||
|
||||
*version = val[0]; /* XXX Why 0 and not 2 as in IAP/FW versions? */
|
||||
*version = val[0];
|
||||
*ic_type = val[1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -103,6 +103,16 @@ struct focaltech_hw_state {
|
||||
*/
|
||||
struct focaltech_finger_state fingers[FOC_MAX_FINGERS];
|
||||
|
||||
/*
|
||||
* Finger width 0-7 and 15 for a very big contact area.
|
||||
* 15 value stays until the finger is released.
|
||||
* Width is reported only in absolute packets.
|
||||
* Since hardware reports width only for last touching finger,
|
||||
* there is no need to store width for every specific finger,
|
||||
* so we keep only last value reported.
|
||||
*/
|
||||
unsigned int width;
|
||||
|
||||
/* True if the clickpad has been pressed. */
|
||||
bool pressed;
|
||||
};
|
||||
@@ -137,6 +147,7 @@ static void focaltech_report_state(struct psmouse *psmouse)
|
||||
input_report_abs(dev, ABS_MT_POSITION_X, clamped_x);
|
||||
input_report_abs(dev, ABS_MT_POSITION_Y,
|
||||
priv->y_max - clamped_y);
|
||||
input_report_abs(dev, ABS_TOOL_WIDTH, state->width);
|
||||
}
|
||||
}
|
||||
input_mt_report_pointer_emulation(dev, true);
|
||||
@@ -187,6 +198,7 @@ static void focaltech_process_abs_packet(struct psmouse *psmouse,
|
||||
|
||||
state->fingers[finger].x = ((packet[1] & 0xf) << 8) | packet[2];
|
||||
state->fingers[finger].y = (packet[3] << 8) | packet[4];
|
||||
state->width = packet[5] >> 4;
|
||||
state->fingers[finger].valid = true;
|
||||
}
|
||||
|
||||
@@ -331,6 +343,7 @@ static void focaltech_set_input_params(struct psmouse *psmouse)
|
||||
__set_bit(EV_ABS, dev->evbit);
|
||||
input_set_abs_params(dev, ABS_MT_POSITION_X, 0, priv->x_max, 0, 0);
|
||||
input_set_abs_params(dev, ABS_MT_POSITION_Y, 0, priv->y_max, 0, 0);
|
||||
input_set_abs_params(dev, ABS_TOOL_WIDTH, 0, 15, 0, 0);
|
||||
input_mt_init_slots(dev, 5, INPUT_MT_POINTER);
|
||||
__set_bit(INPUT_PROP_BUTTONPAD, dev->propbit);
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ static unsigned int psmouse_rate = 100;
|
||||
module_param_named(rate, psmouse_rate, uint, 0644);
|
||||
MODULE_PARM_DESC(rate, "Report rate, in reports per second.");
|
||||
|
||||
static bool psmouse_smartscroll = 1;
|
||||
static bool psmouse_smartscroll = true;
|
||||
module_param_named(smartscroll, psmouse_smartscroll, bool, 0644);
|
||||
MODULE_PARM_DESC(smartscroll, "Logitech Smartscroll autorepeat, 1 = enabled (default), 0 = disabled.");
|
||||
|
||||
|
@@ -123,11 +123,11 @@ struct fsp_data {
|
||||
extern int fsp_detect(struct psmouse *psmouse, bool set_properties);
|
||||
extern int fsp_init(struct psmouse *psmouse);
|
||||
#else
|
||||
inline int fsp_detect(struct psmouse *psmouse, bool set_properties)
|
||||
static inline int fsp_detect(struct psmouse *psmouse, bool set_properties)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
inline int fsp_init(struct psmouse *psmouse)
|
||||
static inline int fsp_init(struct psmouse *psmouse)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
@@ -185,7 +185,7 @@
|
||||
#define NO_DATA_SLEEP_MSECS (MSEC_PER_SEC / 4)
|
||||
|
||||
/* Control touchpad's No Deceleration option */
|
||||
static bool no_decel = 1;
|
||||
static bool no_decel = true;
|
||||
module_param(no_decel, bool, 0644);
|
||||
MODULE_PARM_DESC(no_decel, "No Deceleration. Default = 1 (on)");
|
||||
|
||||
@@ -340,9 +340,9 @@ static bool synaptics_i2c_get_input(struct synaptics_i2c *touch)
|
||||
s32 data;
|
||||
s8 x_delta, y_delta;
|
||||
|
||||
/* Deal with spontanious resets and errors */
|
||||
/* Deal with spontaneous resets and errors */
|
||||
if (synaptics_i2c_check_error(touch->client))
|
||||
return 0;
|
||||
return false;
|
||||
|
||||
/* Get Gesture Bit */
|
||||
data = synaptics_i2c_reg_get(touch->client, DATA_REG0);
|
||||
|
Reference in New Issue
Block a user