@@ -89,6 +89,47 @@ static int elantech_ps2_command(struct psmouse *psmouse,
8989 return rc ;
9090}
9191
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+
92133/*
93134 * Send an Elantech style special command to read a value from a register
94135 */
@@ -1529,19 +1570,35 @@ static const struct dmi_system_id no_hw_res_dmi_table[] = {
15291570 { }
15301571};
15311572
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+ }
15321589/*
15331590 * determine hardware version and set some properties according to it.
15341591 */
15351592static int elantech_set_properties (struct elantech_device_info * info )
15361593{
15371594 /* This represents the version of IC body. */
1538- int ver = (info -> fw_version & 0x0f0000 ) >> 16 ;
1595+ info -> ic_version = (info -> fw_version & 0x0f0000 ) >> 16 ;
15391596
15401597 /* Early version of Elan touchpads doesn't obey the rule. */
15411598 if (info -> fw_version < 0x020030 || info -> fw_version == 0x020600 )
15421599 info -> hw_version = 1 ;
15431600 else {
1544- switch (ver ) {
1601+ switch (info -> ic_version ) {
15451602 case 2 :
15461603 case 4 :
15471604 info -> hw_version = 2 ;
@@ -1557,6 +1614,11 @@ static int elantech_set_properties(struct elantech_device_info *info)
15571614 }
15581615 }
15591616
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+
15601622 /* decide which send_cmd we're gonna use early */
15611623 info -> send_cmd = info -> hw_version >= 3 ? elantech_send_cmd :
15621624 synaptics_send_cmd ;
@@ -1598,6 +1660,7 @@ static int elantech_query_info(struct psmouse *psmouse,
15981660{
15991661 unsigned char param [3 ];
16001662 unsigned char traces ;
1663+ unsigned char ic_body [3 ];
16011664
16021665 memset (info , 0 , sizeof (* info ));
16031666
@@ -1640,6 +1703,21 @@ static int elantech_query_info(struct psmouse *psmouse,
16401703 info -> samples [2 ]);
16411704 }
16421705
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+
16431721 if (info -> samples [1 ] == 0x74 && info -> hw_version == 0x03 ) {
16441722 /*
16451723 * This module has a bug which makes absolute mode
@@ -1654,6 +1732,23 @@ static int elantech_query_info(struct psmouse *psmouse,
16541732 /* The MSB indicates the presence of the trackpoint */
16551733 info -> has_trackpoint = (info -> capabilities [0 ] & 0x80 ) == 0x80 ;
16561734
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+
16571752 info -> x_res = 31 ;
16581753 info -> y_res = 31 ;
16591754 if (info -> hw_version == 4 ) {
0 commit comments