diff options
Diffstat (limited to 'drivers/hid/i2c-hid/i2c-hid-core.c')
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid-core.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index d3912e3f2f13..30ebde1273be 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -112,9 +112,9 @@ struct i2c_hid { struct i2chid_ops *ops; struct drm_panel_follower panel_follower; - struct work_struct panel_follower_prepare_work; + struct work_struct panel_follower_work; bool is_panel_follower; - bool prepare_work_finished; + bool panel_follower_work_finished; }; static const struct i2c_hid_quirks { @@ -1110,10 +1110,10 @@ err_power_down: return ret; } -static void ihid_core_panel_prepare_work(struct work_struct *work) +static void ihid_core_panel_follower_work(struct work_struct *work) { struct i2c_hid *ihid = container_of(work, struct i2c_hid, - panel_follower_prepare_work); + panel_follower_work); struct hid_device *hid = ihid->hid; int ret; @@ -1130,7 +1130,7 @@ static void ihid_core_panel_prepare_work(struct work_struct *work) if (ret) dev_warn(&ihid->client->dev, "Power on failed: %d\n", ret); else - WRITE_ONCE(ihid->prepare_work_finished, true); + WRITE_ONCE(ihid->panel_follower_work_finished, true); /* * The work APIs provide a number of memory ordering guarantees @@ -1139,12 +1139,12 @@ static void ihid_core_panel_prepare_work(struct work_struct *work) * guarantee that a write that happened in the work is visible after * cancel_work_sync(). We'll add a write memory barrier here to match * with i2c_hid_core_panel_unpreparing() to ensure that our write to - * prepare_work_finished is visible there. + * panel_follower_work_finished is visible there. */ smp_wmb(); } -static int i2c_hid_core_panel_prepared(struct drm_panel_follower *follower) +static int i2c_hid_core_panel_follower_resume(struct drm_panel_follower *follower) { struct i2c_hid *ihid = container_of(follower, struct i2c_hid, panel_follower); @@ -1152,29 +1152,36 @@ static int i2c_hid_core_panel_prepared(struct drm_panel_follower *follower) * Powering on a touchscreen can be a slow process. Queue the work to * the system workqueue so we don't block the panel's power up. */ - WRITE_ONCE(ihid->prepare_work_finished, false); - schedule_work(&ihid->panel_follower_prepare_work); + WRITE_ONCE(ihid->panel_follower_work_finished, false); + schedule_work(&ihid->panel_follower_work); return 0; } -static int i2c_hid_core_panel_unpreparing(struct drm_panel_follower *follower) +static int i2c_hid_core_panel_follower_suspend(struct drm_panel_follower *follower) { struct i2c_hid *ihid = container_of(follower, struct i2c_hid, panel_follower); - cancel_work_sync(&ihid->panel_follower_prepare_work); + cancel_work_sync(&ihid->panel_follower_work); - /* Match with ihid_core_panel_prepare_work() */ + /* Match with ihid_core_panel_follower_work() */ smp_rmb(); - if (!READ_ONCE(ihid->prepare_work_finished)) + if (!READ_ONCE(ihid->panel_follower_work_finished)) return 0; return i2c_hid_core_suspend(ihid, true); } -static const struct drm_panel_follower_funcs i2c_hid_core_panel_follower_funcs = { - .panel_prepared = i2c_hid_core_panel_prepared, - .panel_unpreparing = i2c_hid_core_panel_unpreparing, +static const struct drm_panel_follower_funcs + i2c_hid_core_panel_follower_prepare_funcs = { + .panel_prepared = i2c_hid_core_panel_follower_resume, + .panel_unpreparing = i2c_hid_core_panel_follower_suspend, +}; + +static const struct drm_panel_follower_funcs + i2c_hid_core_panel_follower_enable_funcs = { + .panel_enabled = i2c_hid_core_panel_follower_resume, + .panel_disabling = i2c_hid_core_panel_follower_suspend, }; static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid) @@ -1182,7 +1189,10 @@ static int i2c_hid_core_register_panel_follower(struct i2c_hid *ihid) struct device *dev = &ihid->client->dev; int ret; - ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_funcs; + if (ihid->hid->initial_quirks & HID_QUIRK_POWER_ON_AFTER_BACKLIGHT) + ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_enable_funcs; + else + ihid->panel_follower.funcs = &i2c_hid_core_panel_follower_prepare_funcs; /* * If we're not in control of our own power up/power down then we can't @@ -1237,7 +1247,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, init_waitqueue_head(&ihid->wait); mutex_init(&ihid->cmd_lock); mutex_init(&ihid->reset_lock); - INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work); + INIT_WORK(&ihid->panel_follower_work, ihid_core_panel_follower_work); /* we need to allocate the command buffer without knowing the maximum * size of the reports. Let's use HID_MIN_BUFFER_SIZE, then we do the |