diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c index 3075bbb90903..fdbff7ac64cd 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_control_access_block.c @@ -419,7 +419,7 @@ static int __init synaptics_control_access_block_module_init(void) synaptics_rmi4_new_function(RMI_CTRL_ACCESS_BLK, true, synaptics_control_access_block_init, synaptics_control_access_block_remove, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); return 0; } @@ -429,7 +429,7 @@ static void __exit synaptics_control_access_block_module_exit(void) synaptics_rmi4_new_function(RMI_CTRL_ACCESS_BLK, false, synaptics_control_access_block_init, synaptics_control_access_block_remove, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); wait_for_completion(&remove_complete); return; } diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c index 5cfa5c7dcc15..a1c17dfdaad7 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.c @@ -2653,7 +2653,7 @@ static void synaptics_dsx_enable_wakeup_source( static const char * const synaptics_state_names[] = {"UNKNOWN", "ACTIVE", "SUSPEND", "UNUSED", "STANDBY", "BL", "INIT", - "FLASH", "QUERY", "INVALID" }; + "FLASH", "QUERY", "LOADING", "INVALID" }; static const char *synaptics_dsx_state_name(int state) { @@ -2766,6 +2766,7 @@ static int synaptics_dsx_wait_for_idle(struct synaptics_rmi4_data *rmi4_data) current_state = synaptics_dsx_get_state_safe(rmi4_data); if (!(current_state == STATE_INIT || current_state == STATE_FLASH || + current_state == STATE_LOADING || current_state == STATE_UNKNOWN)) break; @@ -2884,6 +2885,7 @@ static void synaptics_dsx_sensor_state(struct synaptics_rmi4_data *rmi4_data, case STATE_UNKNOWN: rmi4_data->in_bootloader = false; case STATE_FLASH: + case STATE_LOADING: /* no special handling for these states */ break; @@ -6745,10 +6747,20 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) if (exp_fhandler->mode == IC_MODE_UI) { if (rmi4_data->in_bootloader) { - dev_err(dev, "%s: handler %d requires UI mode\n", + dev_warn(dev, "%s: handler %d requires UI mode\n", __func__, exp_fhandler->fn_type); continue; } + /* UI mode requires IC powered on */ + if (state == STATE_SUSPEND) { + dev_warn(dev, "%s: handler %d cannot operate while suspended\n", + __func__, exp_fhandler->fn_type); + scheduled_delay = 500; + continue; + } + /* postpone suspend for loading RMI_F54 and */ + if (exp_fhandler->fn_type == RMI_F54) + synaptics_dsx_sensor_state(rmi4_data, STATE_LOADING); } exp_fhandler->func_init(rmi4_data); @@ -6762,7 +6774,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_ctrl_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6771,7 +6783,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | COMMAND_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_cmd_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6780,7 +6792,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | DATA_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_data_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6790,7 +6802,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) regs = find_function(rmi4_data, SYNAPTICS_RMI4_F54 | QUERY_TYPE); if (!regs) - continue; + goto restore_state; error = rmi4_data->scan_f54_query_regs(rmi4_data, regs); if (error) { regs->nr_regs = 0; @@ -6813,11 +6825,9 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) control_access_block_update_dynamic(rmi4_data); } - if (exp_fhandler->fn_type == RMI_FW_UPDATER) { + if (exp_fhandler->fn_type == RMI_FW_UPDATER && exp_fhandler->func_status) { int status; - if (!exp_fhandler->func_status) - continue; status = exp_fhandler->func_status(rmi4_data); /* consider changing to */ /* if (status == 1) */ @@ -6827,7 +6837,7 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) rmi = &(rmi4_data->rmi4_mod_info); rmi4_data->in_bootloader = true; - synaptics_dsx_set_state_safe(rmi4_data, STATE_BL); + synaptics_dsx_sensor_state(rmi4_data, STATE_BL); state = synaptics_dsx_get_state_safe(rmi4_data); dev_dbg(dev, "%s: current state %s\n", @@ -6855,11 +6865,17 @@ static void synaptics_rmi4_detection_work(struct work_struct *work) /* allowing sufficient time for F34 to complete */ scheduled_delay = 3000; } + +restore_state: + if (STATE_LOADING == synaptics_dsx_get_state_safe(rmi4_data)) + synaptics_dsx_sensor_state(rmi4_data, state); } - if (scheduled_delay) + if (scheduled_delay) { queue_delayed_work(det_workqueue, &exp_fn_ctrl->det_work, msecs_to_jiffies(scheduled_delay)); + dev_dbg(dev, "%s: re-scheduled %d\n", __func__, scheduled_delay); + } release_mutex: mutex_unlock(&exp_fn_ctrl->list_mutex); @@ -6936,12 +6952,18 @@ void synaptics_rmi4_new_function( list_add_tail(&exp_fhandler->link, &rmi4_data->exp_fn_ctrl.fn_list); } else { list_for_each_entry(exp_fhandler, &rmi4_data->exp_fn_ctrl.fn_list, link) { - if (exp_fhandler->func_init == func_init) { - /* leave inserted flag ON to run */ - /* remove function in detection work */ - exp_fhandler->func_init = NULL; - goto exit; + if (exp_fhandler->func_init != func_init) + continue; + /* insert flag needed to run remove function in detection */ + /* work even though function was never properly inserted */ + if (!exp_fhandler->inserted) { + exp_fhandler->inserted = true; + dev_info(&rmi4_data->i2c_client->dev, + "removing not inserted handler %d\n", + exp_fhandler->fn_type); } + exp_fhandler->func_init = NULL; + goto exit; } } diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h index 592aee7e762c..af11b0835388 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_i2c.h @@ -335,6 +335,7 @@ enum { STATE_INIT, STATE_FLASH, STATE_QUERY, + STATE_LOADING, STATE_INVALID }; diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c index 4eb87605a5b6..13b4a07c12f9 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_rmi_dev.c @@ -850,7 +850,7 @@ static int __init rmidev_module_init(void) synaptics_rmi4_new_function(next, RMI_DEV, true, rmidev_init_device, rmidev_remove_device, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); } return 0; @@ -869,7 +869,7 @@ static void __exit rmidev_module_exit(void) synaptics_rmi4_new_function(next, RMI_DEV, false, rmidev_init_device, rmidev_remove_device, - NULL, NULL, IC_MODE_ANY); + NULL, NULL, IC_MODE_UI); wait_for_completion(&rmidev->remove_complete); kfree(rmidev); next->rmidev_data = NULL; diff --git a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c index 40359ea42d3b..0527a84e6ff1 100644 --- a/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c +++ b/drivers/input/touchscreen/synaptics_mmi/synaptics_dsx_test_reporting.c @@ -2304,6 +2304,7 @@ struct f54_kobj_data { #define to_f54_attr(x) container_of(x, struct f54_attribute, attr) struct synaptics_rmi4_f54_handle { + bool init_done; bool no_auto_cal; int status; unsigned char intr_mask; @@ -3453,92 +3454,92 @@ static void print_image_report(struct synaptics_rmi4_f54_handle *f54) static void free_control_mem(struct synaptics_rmi4_f54_handle *f54) { - struct f54_control control = f54->control; + struct f54_control *control = &f54->control; - kfree(control.reg_0); - kfree(control.reg_1); - kfree(control.reg_2); - kfree(control.reg_3); - kfree(control.reg_4__6); - kfree(control.reg_7); - kfree(control.reg_8__9); - kfree(control.reg_10); - kfree(control.reg_11); - kfree(control.reg_12__13); - kfree(control.reg_14); - if (control.reg_15) - kfree(control.reg_15->data); - kfree(control.reg_15); - if (control.reg_16) - kfree(control.reg_16->data); - kfree(control.reg_16); - if (control.reg_17) - kfree(control.reg_17->data); - kfree(control.reg_17); - if (control.reg_18) - kfree(control.reg_18->data); - kfree(control.reg_18); - if (control.reg_19) - kfree(control.reg_19->data); - kfree(control.reg_19); - kfree(control.reg_20); - kfree(control.reg_21); - kfree(control.reg_22__26); - kfree(control.reg_27); - kfree(control.reg_28); - kfree(control.reg_29); - kfree(control.reg_30); - kfree(control.reg_31); - kfree(control.reg_32__35); - if (control.reg_36) - kfree(control.reg_36->data); - kfree(control.reg_36); - if (control.reg_37) - kfree(control.reg_37->data); - kfree(control.reg_37); - if (control.reg_38) - kfree(control.reg_38->data); - kfree(control.reg_38); - if (control.reg_39) - kfree(control.reg_39->data); - kfree(control.reg_39); - if (control.reg_40) - kfree(control.reg_40->data); - kfree(control.reg_40); - if (control.reg_89) - kfree(control.reg_89->data); - kfree(control.reg_89); - kfree(control.reg_93); - if (control.reg_95) - kfree(control.reg_95->data); - kfree(control.reg_95); - kfree(control.reg_99); - kfree(control.reg_107); - kfree(control.reg_113); - kfree(control.reg_116); - kfree(control.reg_137); - kfree(control.reg_145); - kfree(control.reg_146); - kfree(control.reg_242); - kfree(control.reg_269); + kfree(control->reg_0); + kfree(control->reg_1); + kfree(control->reg_2); + kfree(control->reg_3); + kfree(control->reg_4__6); + kfree(control->reg_7); + kfree(control->reg_8__9); + kfree(control->reg_10); + kfree(control->reg_11); + kfree(control->reg_12__13); + kfree(control->reg_14); + if (control->reg_15) + kfree(control->reg_15->data); + kfree(control->reg_15); + if (control->reg_16) + kfree(control->reg_16->data); + kfree(control->reg_16); + if (control->reg_17) + kfree(control->reg_17->data); + kfree(control->reg_17); + if (control->reg_18) + kfree(control->reg_18->data); + kfree(control->reg_18); + if (control->reg_19) + kfree(control->reg_19->data); + kfree(control->reg_19); + kfree(control->reg_20); + kfree(control->reg_21); + kfree(control->reg_22__26); + kfree(control->reg_27); + kfree(control->reg_28); + kfree(control->reg_29); + kfree(control->reg_30); + kfree(control->reg_31); + kfree(control->reg_32__35); + if (control->reg_36) + kfree(control->reg_36->data); + kfree(control->reg_36); + if (control->reg_37) + kfree(control->reg_37->data); + kfree(control->reg_37); + if (control->reg_38) + kfree(control->reg_38->data); + kfree(control->reg_38); + if (control->reg_39) + kfree(control->reg_39->data); + kfree(control->reg_39); + if (control->reg_40) + kfree(control->reg_40->data); + kfree(control->reg_40); + if (control->reg_89) + kfree(control->reg_89->data); + kfree(control->reg_89); + kfree(control->reg_93); + if (control->reg_95) + kfree(control->reg_95->data); + kfree(control->reg_95); + kfree(control->reg_99); + kfree(control->reg_107); + kfree(control->reg_113); + kfree(control->reg_116); + kfree(control->reg_137); + kfree(control->reg_145); + kfree(control->reg_146); + kfree(control->reg_242); + kfree(control->reg_269); return; } static void free_data_mem(struct synaptics_rmi4_f54_handle *f54) { - struct f54_data data = f54->data; + struct f54_data *data = &f54->data; - kfree(data.reg_4); - kfree(data.reg_6); - kfree(data.reg_7_0); - kfree(data.reg_7_1); - kfree(data.reg_8); - kfree(data.reg_9); - kfree(data.reg_10); - kfree(data.reg_14); - kfree(data.reg_16); - kfree(data.reg_17); + kfree(data->reg_4); + kfree(data->reg_6); + kfree(data->reg_7_0); + kfree(data->reg_7_1); + kfree(data->reg_8); + kfree(data->reg_9); + kfree(data->reg_10); + kfree(data->reg_14); + kfree(data->reg_16); + kfree(data->reg_17); } static void remove_sysfs(struct synaptics_rmi4_f54_handle *f54) @@ -5868,6 +5869,8 @@ found: INIT_WORK(&f54->timeout_work, timeout_set_status); #endif + f54->init_done = true; + return 0; exit_sysfs: @@ -5891,6 +5894,12 @@ static void synaptics_rmi4_f54_remove(struct synaptics_rmi4_data *rmi4_data) { struct synaptics_rmi4_f54_handle *f54 = (struct synaptics_rmi4_f54_handle *)rmi4_data->f54_data; + + if (!f54->init_done) { + dev_dbg(&rmi4_data->i2c_client->dev, "%s: no cleanup necessary!!!\n", __func__); + goto exit_and_complete; + } + #ifdef WATCHDOG_HRTIMER hrtimer_cancel(&f54->watchdog); #endif @@ -5902,11 +5911,12 @@ static void synaptics_rmi4_f54_remove(struct synaptics_rmi4_data *rmi4_data) kfree(f54->report_data); kfree(f54->fn55); + /* cancel delayed work first then free fn_ptr!!! */ + cancel_delayed_work_sync(&f54->status_work); kfree(f54->fn_ptr); - cancel_delayed_work(&f54->status_work); wakeup_source_trash(&f54->test_wake_lock); - +exit_and_complete: complete(&f54->remove_complete); return;