@@ -89,6 +89,47 @@ static int elantech_ps2_command(struct psmouse *psmouse,
89
89
return rc ;
90
90
}
91
91
92
+ /*
93
+ * Send an Elantech style special command to read 3 bytes from a register
94
+ */
95
+ static int elantech_read_reg_params (struct psmouse * psmouse , u8 reg , u8 * param )
96
+ {
97
+ if (elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
98
+ elantech_ps2_command (psmouse , NULL , ETP_REGISTER_READWRITE ) ||
99
+ elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
100
+ elantech_ps2_command (psmouse , NULL , reg ) ||
101
+ elantech_ps2_command (psmouse , param , PSMOUSE_CMD_GETINFO )) {
102
+ psmouse_err (psmouse ,
103
+ "failed to read register %#02x\n" , reg );
104
+ return - EIO ;
105
+ }
106
+
107
+ return 0 ;
108
+ }
109
+
110
+ /*
111
+ * Send an Elantech style special command to write a register with a parameter
112
+ */
113
+ static int elantech_write_reg_params (struct psmouse * psmouse , u8 reg , u8 * param )
114
+ {
115
+ if (elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
116
+ elantech_ps2_command (psmouse , NULL , ETP_REGISTER_READWRITE ) ||
117
+ elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
118
+ elantech_ps2_command (psmouse , NULL , reg ) ||
119
+ elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
120
+ elantech_ps2_command (psmouse , NULL , param [0 ]) ||
121
+ elantech_ps2_command (psmouse , NULL , ETP_PS2_CUSTOM_COMMAND ) ||
122
+ elantech_ps2_command (psmouse , NULL , param [1 ]) ||
123
+ elantech_ps2_command (psmouse , NULL , PSMOUSE_CMD_SETSCALE11 )) {
124
+ psmouse_err (psmouse ,
125
+ "failed to write register %#02x with value %#02x%#02x\n" ,
126
+ reg , param [0 ], param [1 ]);
127
+ return - EIO ;
128
+ }
129
+
130
+ return 0 ;
131
+ }
132
+
92
133
/*
93
134
* Send an Elantech style special command to read a value from a register
94
135
*/
@@ -1529,19 +1570,35 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = {
1529
1570
{ }
1530
1571
};
1531
1572
1573
+ /*
1574
+ * Change Report id 0x5E to 0x5F.
1575
+ */
1576
+ static int elantech_change_report_id (struct psmouse * psmouse )
1577
+ {
1578
+ unsigned char param [2 ] = { 0x10 , 0x03 };
1579
+
1580
+ if (elantech_write_reg_params (psmouse , 0x7 , param ) ||
1581
+ elantech_read_reg_params (psmouse , 0x7 , param ) ||
1582
+ param [0 ] != 0x10 || param [1 ] != 0x03 ) {
1583
+ psmouse_err (psmouse , "Unable to change report ID to 0x5f.\n" );
1584
+ return - EIO ;
1585
+ }
1586
+
1587
+ return 0 ;
1588
+ }
1532
1589
/*
1533
1590
* determine hardware version and set some properties according to it.
1534
1591
*/
1535
1592
static int elantech_set_properties (struct elantech_device_info * info )
1536
1593
{
1537
1594
/* This represents the version of IC body. */
1538
- int ver = (info -> fw_version & 0x0f0000 ) >> 16 ;
1595
+ info -> ic_version = (info -> fw_version & 0x0f0000 ) >> 16 ;
1539
1596
1540
1597
/* Early version of Elan touchpads doesn't obey the rule. */
1541
1598
if (info -> fw_version < 0x020030 || info -> fw_version == 0x020600 )
1542
1599
info -> hw_version = 1 ;
1543
1600
else {
1544
- switch (ver ) {
1601
+ switch (info -> ic_version ) {
1545
1602
case 2 :
1546
1603
case 4 :
1547
1604
info -> hw_version = 2 ;
@@ -1557,6 +1614,11 @@ static int elantech_set_properties(struct elantech_device_info *info)
1557
1614
}
1558
1615
}
1559
1616
1617
+ /* Get information pattern for hw_version 4 */
1618
+ info -> pattern = 0x00 ;
1619
+ if (info -> ic_version == 0x0f && (info -> fw_version & 0xff ) <= 0x02 )
1620
+ info -> pattern = info -> fw_version & 0xff ;
1621
+
1560
1622
/* decide which send_cmd we're gonna use early */
1561
1623
info -> send_cmd = info -> hw_version >= 3 ? elantech_send_cmd :
1562
1624
synaptics_send_cmd ;
@@ -1598,6 +1660,7 @@ static int elantech_query_info(struct psmouse *psmouse,
1598
1660
{
1599
1661
unsigned char param [3 ];
1600
1662
unsigned char traces ;
1663
+ unsigned char ic_body [3 ];
1601
1664
1602
1665
memset (info , 0 , sizeof (* info ));
1603
1666
@@ -1640,6 +1703,21 @@ static int elantech_query_info(struct psmouse *psmouse,
1640
1703
info -> samples [2 ]);
1641
1704
}
1642
1705
1706
+ if (info -> pattern > 0x00 && info -> ic_version == 0xf ) {
1707
+ if (info -> send_cmd (psmouse , ETP_ICBODY_QUERY , ic_body )) {
1708
+ psmouse_err (psmouse , "failed to query ic body\n" );
1709
+ return - EINVAL ;
1710
+ }
1711
+ info -> ic_version = be16_to_cpup ((__be16 * )ic_body );
1712
+ psmouse_info (psmouse ,
1713
+ "Elan ic body: %#04x, current fw version: %#02x\n" ,
1714
+ info -> ic_version , ic_body [2 ]);
1715
+ }
1716
+
1717
+ info -> product_id = be16_to_cpup ((__be16 * )info -> samples );
1718
+ if (info -> pattern == 0x00 )
1719
+ info -> product_id &= 0xff ;
1720
+
1643
1721
if (info -> samples [1 ] == 0x74 && info -> hw_version == 0x03 ) {
1644
1722
/*
1645
1723
* This module has a bug which makes absolute mode
@@ -1654,6 +1732,23 @@ static int elantech_query_info(struct psmouse *psmouse,
1654
1732
/* The MSB indicates the presence of the trackpoint */
1655
1733
info -> has_trackpoint = (info -> capabilities [0 ] & 0x80 ) == 0x80 ;
1656
1734
1735
+ if (info -> has_trackpoint && info -> ic_version == 0x0011 &&
1736
+ (info -> product_id == 0x08 || info -> product_id == 0x09 ||
1737
+ info -> product_id == 0x0d || info -> product_id == 0x0e )) {
1738
+ /*
1739
+ * This module has a bug which makes trackpoint in SMBus
1740
+ * mode return invalid data unless trackpoint is switched
1741
+ * from using 0x5e reports to 0x5f. If we are not able to
1742
+ * make the switch, let's abort initialization so we'll be
1743
+ * using standard PS/2 protocol.
1744
+ */
1745
+ if (elantech_change_report_id (psmouse )) {
1746
+ psmouse_info (psmouse ,
1747
+ "Trackpoint report is broken, forcing standard PS/2 protocol\n" );
1748
+ return - ENODEV ;
1749
+ }
1750
+ }
1751
+
1657
1752
info -> x_res = 31 ;
1658
1753
info -> y_res = 31 ;
1659
1754
if (info -> hw_version == 4 ) {
0 commit comments