Commit c2c06c41 authored by Dudley Du's avatar Dudley Du Committed by Dmitry Torokhov

Input: cyapa - add gen6 device module support

Based on the cyapa core, add support for basic functionality of the gen6
trackpad devices. The driver can automatically determine what protocol
(gen3, gen5, or gen6) should be used with the attached trackpad device.
Signed-off-by: default avatarDudley Du <dudl@cypress.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 94897619
......@@ -24,7 +24,7 @@ obj-$(CONFIG_MOUSE_SYNAPTICS_I2C) += synaptics_i2c.o
obj-$(CONFIG_MOUSE_SYNAPTICS_USB) += synaptics_usb.o
obj-$(CONFIG_MOUSE_VSXXXAA) += vsxxxaa.o
cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o
cyapatp-objs := cyapa.o cyapa_gen3.o cyapa_gen5.o cyapa_gen6.o
psmouse-objs := psmouse-base.o synaptics.o focaltech.o
psmouse-$(CONFIG_MOUSE_PS2_ALPS) += alps.o
......
......@@ -41,6 +41,9 @@ static int cyapa_reinitialize(struct cyapa *cyapa);
bool cyapa_is_pip_bl_mode(struct cyapa *cyapa)
{
if (cyapa->gen == CYAPA_GEN6 && cyapa->state == CYAPA_STATE_GEN6_BL)
return true;
if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_BL)
return true;
......@@ -49,6 +52,9 @@ bool cyapa_is_pip_bl_mode(struct cyapa *cyapa)
bool cyapa_is_pip_app_mode(struct cyapa *cyapa)
{
if (cyapa->gen == CYAPA_GEN6 && cyapa->state == CYAPA_STATE_GEN6_APP)
return true;
if (cyapa->gen == CYAPA_GEN5 && cyapa->state == CYAPA_STATE_GEN5_APP)
return true;
......@@ -204,6 +210,15 @@ static int cyapa_get_state(struct cyapa *cyapa)
if (!error)
goto out_detected;
}
if (cyapa->gen == CYAPA_GEN_UNKNOWN ||
cyapa->gen == CYAPA_GEN6 ||
cyapa->gen == CYAPA_GEN5) {
error = cyapa_pip_state_parse(cyapa,
status, BL_STATUS_SIZE);
if (!error)
goto out_detected;
}
/* For old Gen5 trackpads detecting. */
if ((cyapa->gen == CYAPA_GEN_UNKNOWN ||
cyapa->gen == CYAPA_GEN5) &&
!smbus && even_addr) {
......@@ -300,6 +315,9 @@ static int cyapa_check_is_operational(struct cyapa *cyapa)
return error;
switch (cyapa->gen) {
case CYAPA_GEN6:
cyapa->ops = &cyapa_gen6_ops;
break;
case CYAPA_GEN5:
cyapa->ops = &cyapa_gen5_ops;
break;
......@@ -579,6 +597,8 @@ static int cyapa_initialize(struct cyapa *cyapa)
error = cyapa_gen3_ops.initialize(cyapa);
if (!error)
error = cyapa_gen5_ops.initialize(cyapa);
if (!error)
error = cyapa_gen6_ops.initialize(cyapa);
if (error)
return error;
......@@ -1136,9 +1156,11 @@ static char *cyapa_state_to_string(struct cyapa *cyapa)
case CYAPA_STATE_BL_ACTIVE:
return "bootloader active";
case CYAPA_STATE_GEN5_BL:
case CYAPA_STATE_GEN6_BL:
return "bootloader";
case CYAPA_STATE_OP:
case CYAPA_STATE_GEN5_APP:
case CYAPA_STATE_GEN6_APP:
return "operational"; /* Normal valid state. */
default:
return "invalid mode";
......
......@@ -19,6 +19,7 @@
#define CYAPA_GEN_UNKNOWN 0x00 /* unknown protocol. */
#define CYAPA_GEN3 0x03 /* support MT-protocol B with tracking ID. */
#define CYAPA_GEN5 0x05 /* support TrueTouch GEN5 trackpad device. */
#define CYAPA_GEN6 0x06 /* support TrueTouch GEN6 trackpad device. */
#define CYAPA_NAME "Cypress APA Trackpad (cyapa)"
......@@ -198,6 +199,9 @@
#define PIP_BL_APP_INFO_RESP_LENGTH 30
#define PIP_BL_GET_INFO_RESP_LENGTH 19
#define PIP_BL_PLATFORM_VER_SHIFT 4
#define PIP_BL_PLATFORM_VER_MASK 0x0f
#define PIP_PRODUCT_FAMILY_MASK 0xf000
#define PIP_PRODUCT_FAMILY_TRACKPAD 0x1000
......@@ -299,6 +303,14 @@ enum cyapa_state {
CYAPA_STATE_OP,
CYAPA_STATE_GEN5_BL,
CYAPA_STATE_GEN5_APP,
CYAPA_STATE_GEN6_BL,
CYAPA_STATE_GEN6_APP,
};
struct gen6_interval_setting {
u16 active_interval;
u16 lp1_interval;
u16 lp2_interval;
};
/* The main device structure */
......@@ -320,9 +332,11 @@ struct cyapa {
u16 runtime_suspend_sleep_time;
u8 dev_pwr_mode;
u16 dev_sleep_time;
struct gen6_interval_setting gen6_interval_setting;
/* Read from query data region. */
char product_id[16];
u8 platform_ver; /* Platform version. */
u8 fw_maj_ver; /* Firmware major version. */
u8 fw_min_ver; /* Firmware minor version. */
u8 btn_capability;
......@@ -411,5 +425,6 @@ extern u8 pip_bl_read_app_info[];
extern const char product_id[];
extern const struct cyapa_dev_ops cyapa_gen3_ops;
extern const struct cyapa_dev_ops cyapa_gen5_ops;
extern const struct cyapa_dev_ops cyapa_gen6_ops;
#endif
......@@ -133,7 +133,9 @@ struct cyapa_pip_touch_record {
* Bit 7 - 3: reserved
* Bit 2 - 0: touch type;
* 0 : standard finger;
* 1 - 15 : reserved.
* 1 : proximity (Start supported in Gen5 TP).
* 2 : finger hover (defined, but not used yet.)
* 3 - 15 : reserved.
*/
u8 touch_type;
......@@ -167,6 +169,9 @@ struct cyapa_pip_touch_record {
* The meaning of this value is different when touch_type is different.
* For standard finger type:
* Touch intensity in counts, pressure value.
* For proximity type (Start supported in Gen5 TP):
* The distance, in surface units, between the contact and
* the surface.
**/
u8 z;
......@@ -218,6 +223,12 @@ struct cyapa_tsg_bin_image_head {
u8 fw_major_version;
u8 fw_minor_version;
u8 fw_revision_control_number[8];
u8 silicon_id_hi;
u8 silicon_id_lo;
u8 chip_revision;
u8 family_id;
u8 bl_ver_maj;
u8 bl_ver_min;
} __packed;
struct cyapa_tsg_bin_image_data_record {
......@@ -1134,6 +1145,39 @@ int cyapa_pip_bl_enter(struct cyapa *cyapa)
cyapa->operational = false;
if (cyapa->gen == CYAPA_GEN5)
cyapa->state = CYAPA_STATE_GEN5_BL;
else if (cyapa->gen == CYAPA_GEN6)
cyapa->state = CYAPA_STATE_GEN6_BL;
return 0;
}
static int cyapa_pip_fw_head_check(struct cyapa *cyapa,
struct cyapa_tsg_bin_image_head *image_head)
{
if (image_head->head_size != 0x0C && image_head->head_size != 0x12)
return -EINVAL;
switch (cyapa->gen) {
case CYAPA_GEN6:
if (image_head->family_id != 0x9B ||
image_head->silicon_id_hi != 0x0B)
return -EINVAL;
break;
case CYAPA_GEN5:
/* Gen5 without proximity support. */
if (cyapa->platform_ver < 2) {
if (image_head->head_size == 0x0C)
break;
return -EINVAL;
}
if (image_head->family_id != 0x91 ||
image_head->silicon_id_hi != 0x02)
return -EINVAL;
break;
default:
return -EINVAL;
}
return 0;
}
......@@ -1150,6 +1194,14 @@ int cyapa_pip_check_fw(struct cyapa *cyapa, const struct firmware *fw)
u16 app_integrity_crc;
int i;
/* Verify the firmware image not miss-used for Gen5 and Gen6. */
if (cyapa_pip_fw_head_check(cyapa,
(struct cyapa_tsg_bin_image_head *)fw->data)) {
dev_err(dev, "%s: firmware image not match TP device.\n",
__func__);
return -EINVAL;
}
image_records =
cyapa_get_image_record_data_num(fw, &flash_records_count);
......@@ -2339,6 +2391,9 @@ static int cyapa_gen5_bl_query_data(struct cyapa *cyapa)
cyapa->fw_maj_ver = resp_data[22];
cyapa->fw_min_ver = resp_data[23];
cyapa->platform_ver = (resp_data[26] >> PIP_BL_PLATFORM_VER_SHIFT) &
PIP_BL_PLATFORM_VER_MASK;
return 0;
}
......@@ -2362,8 +2417,16 @@ static int cyapa_gen5_get_query_data(struct cyapa *cyapa)
PIP_PRODUCT_FAMILY_TRACKPAD)
return -EINVAL;
cyapa->platform_ver = (resp_data[49] >> PIP_BL_PLATFORM_VER_SHIFT) &
PIP_BL_PLATFORM_VER_MASK;
if (cyapa->gen == CYAPA_GEN5 && cyapa->platform_ver < 2) {
/* Gen5 firmware that does not support proximity. */
cyapa->fw_maj_ver = resp_data[15];
cyapa->fw_min_ver = resp_data[16];
} else {
cyapa->fw_maj_ver = resp_data[9];
cyapa->fw_min_ver = resp_data[10];
}
cyapa->electrodes_x = resp_data[52];
cyapa->electrodes_y = resp_data[53];
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment