diff options
author | Wei-Han Chen <stimim@google.com> | 2018-05-24 19:59:58 +0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2018-05-29 06:02:11 -0700 |
commit | ffcf7cf3fbb1456eaf7129a3632ea2758154e204 (patch) | |
tree | e195b1e9fbf64c3adae2b389751ae7816ad32a2a /driver | |
parent | b73431f6733225799d0519966dc79fdf226f61a8 (diff) | |
download | chrome-ec-ffcf7cf3fbb1456eaf7129a3632ea2758154e204.tar.gz |
driver/touchpad_st.c: wait for event "controller ready" after reset
After resetting touchpad, we should wait for "controller ready" event
before sending any commands to touchpad.
BRANCH=none
BUG=b:70482333
BUG=b:78483107
TEST=manual
Signed-off-by: Wei-Han Chen <stimim@chromium.org>
Change-Id: I7049579db23c083e518137055a8243fee400e924
Reviewed-on: https://chromium-review.googlesource.com/1071313
Commit-Ready: Wei-Han Chen <stimim@chromium.org>
Tested-by: Wei-Han Chen <stimim@chromium.org>
Reviewed-by: Nicolas Boichat <drinkcat@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/touchpad_st.c | 103 | ||||
-rw-r--r-- | driver/touchpad_st.h | 4 |
2 files changed, 83 insertions, 24 deletions
diff --git a/driver/touchpad_st.c b/driver/touchpad_st.c index 340923e587..a2559f51a9 100644 --- a/driver/touchpad_st.c +++ b/driver/touchpad_st.c @@ -34,10 +34,11 @@ BUILD_ASSERT(sizeof(struct st_tp_event_t) == 8); static struct st_tp_system_info_t system_info; static int st_tp_read_all_events(void); +static int st_tp_read_host_buffer_header(void); static int st_tp_send_ack(void); static int st_tp_start_scan(void); static int st_tp_stop_scan(void); -static int st_tp_read_host_buffer_header(void); +static int st_tp_update_system_state(int new_state, int mask); /* * Current system state, meaning of each bit is defined below. @@ -121,9 +122,8 @@ static int st_tp_parse_finger(struct usb_hid_touchpad_report *report, static int st_tp_write_hid_report(void) { - int ret, i, num_finger; + int ret, i, num_finger, num_events; struct usb_hid_touchpad_report report; - struct st_tp_event_t *event; ret = st_tp_read_host_buffer_header(); if (ret) @@ -140,31 +140,22 @@ static int st_tp_write_hid_report(void) SYSTEM_STATE_DOME_SWITCH_LEVEL); } - ret = st_tp_read_all_events(); - if (ret) - return ret; + num_events = st_tp_read_all_events(); + if (num_events < 0) + return -num_events; memset(&report, 0, sizeof(report)); report.id = 0x1; num_finger = 0; - for (i = 0; i < ARRAY_SIZE(rx_buf.events); i++) { - event = &rx_buf.events[i]; + for (i = 0; i < num_events; i++) { + struct st_tp_event_t *e = &rx_buf.events[i]; - /* - * this is not a valid event, and assume all following - * events are invalid too - */ - if (event->magic != 0x3) - break; - - switch (event->evt_id) { + switch (e->evt_id) { case ST_TP_EVENT_ID_ENTER_POINTER: case ST_TP_EVENT_ID_MOTION_POINTER: case ST_TP_EVENT_ID_LEAVE_POINTER: - num_finger = st_tp_parse_finger(&report, - event, - num_finger); + num_finger = st_tp_parse_finger(&report, e, num_finger); break; default: break; @@ -176,7 +167,7 @@ static int st_tp_write_hid_report(void) report.timestamp = irq_ts / USB_HID_TOUCHPAD_TIMESTAMP_UNIT; set_touchpad_report(&report); - return ret; + return 0; } static int st_tp_read_report(void) @@ -275,7 +266,8 @@ static int st_tp_start_scan(void) return ret; } -static int st_tp_read_host_data_memory(uint16_t addr, void *rx_buf, int len) { +static int st_tp_read_host_data_memory(uint16_t addr, void *rx_buf, int len) +{ uint8_t tx_buf[] = { ST_TP_CMD_READ_HOST_DATA_MEMORY, addr >> 8, addr & 0xFF }; @@ -372,18 +364,83 @@ static int st_tp_read_system_info(int reload) return ret; } +/* + * Handles error reports. + * + * @return 0 for minor errors, non-zero for major errors (must halt). + * TODO(stimim): check for major errors. + */ +static int st_tp_handle_error_report(struct st_tp_event_t *e) +{ + if (e->magic != ST_TP_EVENT_MAGIC || + e->evt_id != ST_TP_EVENT_ID_ERROR_REPORT) + return 0; + + CPRINTS("Touchpad error: %x %x", e->report.report_type, + ((e->report.info[0] << 24) | (e->report.info[1] << 16) | + (e->report.info[2] << 8) | (e->report.info[3] << 0))); + + return 0; +} + +/* + * Read all events, and handle errors. + * + * @return number of events available on success, or negative error code on + * failure. + */ static int st_tp_read_all_events(void) { uint8_t cmd = ST_TP_CMD_READ_ALL_EVENTS; int rx_len = sizeof(rx_buf.events) + ST_TP_DUMMY_BYTE; + int ret; + int i; + + ret = spi_transaction(SPI, &cmd, 1, (uint8_t *)&rx_buf, rx_len); + if (ret) + return -ret; + + for (i = 0; i < ARRAY_SIZE(rx_buf.events); i++) { + struct st_tp_event_t *e = &rx_buf.events[i]; - return spi_transaction(SPI, &cmd, 1, (uint8_t *)&rx_buf, rx_len); + if (e->magic != ST_TP_EVENT_MAGIC) + break; + + if (e->evt_id == ST_TP_EVENT_ID_ERROR_REPORT) { + ret = st_tp_handle_error_report(e); + if (ret) + return -ret; + } + } + return i; } +/* + * Reset touchpad. This function will wait for "controller ready" event after + * the touchpad is reset. + */ static int st_tp_reset(void) { + int i, num_events; + board_touchpad_reset(); - return st_tp_read_all_events(); + + while (1) { + num_events = st_tp_read_all_events(); + if (num_events < 0) + return -num_events; + + for (i = 0; i < num_events; i++) { + struct st_tp_event_t *e = &rx_buf.events[i]; + + if (e->evt_id == ST_TP_EVENT_ID_CONTROLLER_READY) + break; + } + + msleep(10); + } + CPRINTS("Touchpad ready"); + return 0; } /* Initialize the controller ICs after reset */ diff --git a/driver/touchpad_st.h b/driver/touchpad_st.h index 23bb404d36..db4a8f4bc1 100644 --- a/driver/touchpad_st.h +++ b/driver/touchpad_st.h @@ -197,8 +197,10 @@ struct st_tp_host_buffer_heat_map_t { } __packed; struct st_tp_event_t { +#define ST_TP_EVENT_MAGIC 0x3 unsigned magic:2; /* should always be 0x3 */ unsigned major_high:2; +#define ST_TP_EVENT_ID_CONTROLLER_READY 0x0 #define ST_TP_EVENT_ID_ENTER_POINTER 0x1 #define ST_TP_EVENT_ID_MOTION_POINTER 0x2 #define ST_TP_EVENT_ID_LEAVE_POINTER 0x3 @@ -226,7 +228,7 @@ struct st_tp_event_t { struct { uint8_t report_type; - uint32_t info; + uint8_t info[4]; uint8_t reserved; } __packed report; } __packed ; /* anonymous */ |