diff options
author | Midas Chien <midaschieh@google.com> | 2024-01-05 11:40:53 +0000 |
---|---|---|
committer | Midas Chien <midaschieh@google.com> | 2024-01-17 06:23:57 +0000 |
commit | d460f686f4ff55f3cb38a417fa78380c0bee1be7 (patch) | |
tree | 27ff833183d3e6e6c429c09277b06de37a9d90ce | |
parent | a51d2acbe6bd7dc96a3f04b968283a35b02992cc (diff) | |
download | display-android-gs-bluejay-5.10-android14-qpr3-beta.tar.gz |
drm: samsung: support wake up during notify state changeandroid-u-qpr3-beta-2_r0.7android-u-qpr3-beta-2_r0.6android-u-qpr3-beta-2_r0.5android-u-qpr3-beta-2_r0.4android-u-qpr3-beta-2_r0.3android-u-qpr3-beta-2_r0.2android-u-qpr3-beta-2.1_r0.7android-u-qpr3-beta-2.1_r0.5android-u-qpr3-beta-2.1_r0.3android-u-qpr3-beta-2.1_r0.2android-u-qpr3-beta-2.1_r0.1android-15-dp-2_r0.6android-15-dp-2_r0.5android-15-dp-2_r0.4android-15-dp-2_r0.3android-15-dp-2_r0.2android-15-dp-2_r0.1android-gs-tangorpro-5.10-android14-qpr3-betaandroid-gs-raviole-5.10-android14-qpr3-betaandroid-gs-lynx-5.10-android14-qpr3-betaandroid-gs-felix-5.10-android14-qpr3-betaandroid-gs-bluejay-5.10-android14-qpr3-beta
While sysfs_notify initiates updates for state monitors upon state
changes, timely data updates can be hindered if user space processes
are frozen during notification. Support a mechanism to awaken the
system during notification if it need to ensure timely updates.
Bug: 311495944
Test: check refresh rate indicator is correct
Change-Id: I86d1f6e2e72bb54c10d394bd2634ce51147189e4
Signed-off-by: Midas Chien <midaschieh@google.com>
(cherry picked from commit 5cdb5034e2360b17e8cad80e7d5b5902c8ccfba3)
-rw-r--r-- | samsung/panel/Documentation/ABI/testing/sysfs-devices-platform-exynos-drm | 10 | ||||
-rw-r--r-- | samsung/panel/panel-boe-nt37290.c | 4 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-drv.c | 56 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-drv.h | 15 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-s6e3hc3-c10.c | 2 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-s6e3hc3.c | 6 | ||||
-rw-r--r-- | samsung/panel/panel-samsung-s6e3hc4.c | 4 |
7 files changed, 80 insertions, 17 deletions
diff --git a/samsung/panel/Documentation/ABI/testing/sysfs-devices-platform-exynos-drm b/samsung/panel/Documentation/ABI/testing/sysfs-devices-platform-exynos-drm index b9d7b13..3485a4a 100644 --- a/samsung/panel/Documentation/ABI/testing/sysfs-devices-platform-exynos-drm +++ b/samsung/panel/Documentation/ABI/testing/sysfs-devices-platform-exynos-drm @@ -15,3 +15,13 @@ Description: The file provides the available display stats state. Valid panels are 'primary-panel' or 'secondary-panel'. + +What: /sys/class/backlight/<panel>-backlight/allow_wakeup_by_state_change +Date: January 2024 +KernelVersion: 5.10 +Contact: "Midas Chien" <midaschieh@google.com> +Description: + The file specifies whether the system can be awakened to receive + notifications regarding backlight state changes. + + Valid panels are 'panel0' or 'panel1'. diff --git a/samsung/panel/panel-boe-nt37290.c b/samsung/panel/panel-boe-nt37290.c index 17e6b8e..1dfdce5 100644 --- a/samsung/panel/panel-boe-nt37290.c +++ b/samsung/panel/panel-boe-nt37290.c @@ -730,7 +730,7 @@ static bool nt37290_change_frequency(struct exynos_panel *ctx, ctx->panel_idle_vrefresh = ctx->self_refresh_active ? spanel->hw_idle_vrefresh : 0; if (updated) { - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); te2_state_changed(ctx->bl); dev_dbg(ctx->dev, "change to %dHz, idle %s, was_lp_mode %d\n", vrefresh, idle_active ? "active" : "deactive", was_lp_mode); @@ -771,7 +771,7 @@ static bool nt37290_set_self_refresh(struct exynos_panel *ctx, bool enable) if (pmode->exynos_mode.is_lp_mode) { /* set 10Hz while self refresh is active, otherwise clear it */ ctx->panel_idle_vrefresh = enable ? 10 : 0; - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, true); return false; } diff --git a/samsung/panel/panel-samsung-drv.c b/samsung/panel/panel-samsung-drv.c index 60cfaec..968c844 100644 --- a/samsung/panel/panel-samsung-drv.c +++ b/samsung/panel/panel-samsung-drv.c @@ -2024,7 +2024,7 @@ static void exynos_panel_pre_commit_properties( DPU_ATRACE_BEGIN("set_hbm"); mutex_lock(&ctx->mode_lock); exynos_panel_func->set_hbm_mode(ctx, conn_state->global_hbm_mode); - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); mutex_unlock(&ctx->mode_lock); DPU_ATRACE_END("set_hbm"); ghbm_updated = true; @@ -2824,7 +2824,7 @@ static ssize_t hbm_mode_store(struct device *dev, if (hbm_mode != ctx->hbm_mode) { funcs->set_hbm_mode(ctx, hbm_mode); - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); } unlock: @@ -3253,6 +3253,34 @@ static ssize_t als_table_show(struct device *dev, static DEVICE_ATTR_RW(als_table); +static ssize_t allow_wakeup_by_state_change_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct backlight_device *bd = to_backlight_device(dev); + struct exynos_panel *ctx = bl_get_data(bd); + int ret; + + ret = kstrtobool(buf, &ctx->allow_wakeup_by_state_change); + if (ret) { + dev_err(ctx->dev, "invalid allow wakeup by state change value\n"); + return ret; + } + + return count; +} + +static ssize_t allow_wakeup_by_state_change_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct backlight_device *bd = to_backlight_device(dev); + struct exynos_panel *ctx = bl_get_data(bd); + + return sysfs_emit_at(buf, 0, "%d\n", ctx->allow_wakeup_by_state_change); +} + +static DEVICE_ATTR_RW(allow_wakeup_by_state_change); + static struct attribute *bl_device_attrs[] = { &dev_attr_hbm_mode.attr, &dev_attr_dimming_on.attr, @@ -3263,6 +3291,7 @@ static struct attribute *bl_device_attrs[] = { &dev_attr_lp_state.attr, &dev_attr_te2_state.attr, &dev_attr_als_table.attr, + &dev_attr_allow_wakeup_by_state_change.attr, NULL, }; ATTRIBUTE_GROUPS(bl_device); @@ -3331,7 +3360,7 @@ static void exynos_panel_set_backlight_state(struct exynos_panel *ctx, mutex_unlock(&ctx->bl_state_lock); if (state_changed) { - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); dev_info(ctx->dev, "panel: %s | bl: brightness@%u, state@0x%x\n", exynos_panel_get_state_str(panel_state), bl->props.brightness, bl->props.state); @@ -4143,7 +4172,7 @@ static void exynos_panel_bridge_mode_set(struct drm_bridge *bridge, exynos_panel_set_backlight_state( ctx, is_active ? PANEL_STATE_NORMAL : PANEL_STATE_OFF); else if (ctx->bl) - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); if (!is_lp_mode) exynos_panel_update_te2(ctx); @@ -4615,10 +4644,20 @@ static int disp_stats_update_state(struct exynos_panel *ctx) static void notify_panel_mode_changed_worker(struct work_struct *work) { + struct notify_state_change *notify_state_change = + container_of(work, struct notify_state_change, work); struct exynos_panel *ctx = - container_of(work, struct exynos_panel, notify_panel_mode_changed_work); + container_of(notify_state_change, struct exynos_panel, notify_panel_mode_changed); disp_stats_update_state(ctx); + + if (ctx->allow_wakeup_by_state_change && notify_state_change->abort_suspend) { + if (unlikely(!notify_state_change->ws)) + dev_warn(ctx->dev, "wakeup source creation was unsuccessful\n"); + else + pm_wakeup_ws_event(notify_state_change->ws, 0, true); + } + sysfs_notify(&ctx->bl->dev.kobj, NULL, "state"); } @@ -4653,6 +4692,11 @@ int exynos_panel_common_init(struct mipi_dsi_device *dsi, dev_err(ctx->dev, "failed to register backlight device\n"); return PTR_ERR(ctx->bl); } + + ctx->notify_panel_mode_changed.ws = wakeup_source_register(dev, name); + if (!ctx->notify_panel_mode_changed.ws) + dev_warn(ctx->dev, "failed to register `%s` wakeup source\n", name); + ctx->bl->props.max_brightness = ctx->desc->max_brightness; ctx->bl->props.brightness = ctx->desc->dft_brightness; @@ -4688,7 +4732,7 @@ int exynos_panel_common_init(struct mipi_dsi_device *dsi, ctx->panel_idle_enabled = exynos_panel_func && exynos_panel_func->set_self_refresh != NULL; INIT_DELAYED_WORK(&ctx->idle_work, panel_idle_work); - INIT_WORK(&ctx->notify_panel_mode_changed_work, notify_panel_mode_changed_worker); + INIT_WORK(&ctx->notify_panel_mode_changed.work, notify_panel_mode_changed_worker); mutex_init(&ctx->mode_lock); mutex_init(&ctx->bl_state_lock); diff --git a/samsung/panel/panel-samsung-drv.h b/samsung/panel/panel-samsung-drv.h index e10d521..4f29db7 100644 --- a/samsung/panel/panel-samsung-drv.h +++ b/samsung/panel/panel-samsung-drv.h @@ -613,6 +613,12 @@ struct display_stats { bool initialized; }; +struct notify_state_change { + struct work_struct work; + struct wakeup_source *ws; + bool abort_suspend; +}; + struct exynos_panel { struct device *dev; struct drm_panel panel; @@ -705,7 +711,9 @@ struct exynos_panel { enum exynos_cabc_mode current_cabc_mode; /* use for notify state changed */ - struct work_struct notify_panel_mode_changed_work; + bool allow_wakeup_by_state_change; + struct notify_state_change notify_panel_mode_changed; + struct work_struct notify_brightness_changed_work; /* use for display stats residence */ struct display_stats disp_stats; @@ -852,9 +860,10 @@ static inline void te2_state_changed(struct backlight_device *bl) sysfs_notify(&bl->dev.kobj, NULL, "te2_state"); } -static inline void notify_panel_mode_changed(struct exynos_panel *ctx) +static inline void notify_panel_mode_changed(struct exynos_panel *ctx, bool abort_suspend) { - schedule_work(&ctx->notify_panel_mode_changed_work); + ctx->notify_panel_mode_changed.abort_suspend = abort_suspend; + schedule_work(&ctx->notify_panel_mode_changed.work); } static inline u32 get_current_frame_duration_us(struct exynos_panel *ctx) diff --git a/samsung/panel/panel-samsung-s6e3hc3-c10.c b/samsung/panel/panel-samsung-s6e3hc3-c10.c index b0c6ff6..94cc9e1 100644 --- a/samsung/panel/panel-samsung-s6e3hc3-c10.c +++ b/samsung/panel/panel-samsung-s6e3hc3-c10.c @@ -491,7 +491,7 @@ static void s6e3hc3_c10_update_refresh_mode(struct exynos_panel *ctx, ctx->panel_idle_vrefresh = idle_vrefresh; s6e3hc3_c10_update_panel_feat(ctx, pmode, false); te2_state_changed(ctx->bl); - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); } static void s6e3hc3_c10_change_frequency(struct exynos_panel *ctx, diff --git a/samsung/panel/panel-samsung-s6e3hc3.c b/samsung/panel/panel-samsung-s6e3hc3.c index 13c974a..30d8a5f 100644 --- a/samsung/panel/panel-samsung-s6e3hc3.c +++ b/samsung/panel/panel-samsung-s6e3hc3.c @@ -536,7 +536,7 @@ static bool s6e3hc3_set_self_refresh(struct exynos_panel *ctx, bool enable) if (pmode->exynos_mode.is_lp_mode) { /* set 10Hz while self refresh is active, otherwise clear it */ ctx->panel_idle_vrefresh = enable ? 10 : 0; - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, true); return false; } @@ -550,7 +550,7 @@ static bool s6e3hc3_set_self_refresh(struct exynos_panel *ctx, bool enable) if (pmode->idle_mode == IDLE_MODE_ON_INACTIVITY) { /* simply update idle vrefresh follow by self refresh */ ctx->panel_idle_vrefresh = enable ? idle_vrefresh : 0; - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); if (spanel->auto_mode_vrefresh != idle_vrefresh) { dev_dbg(ctx->dev, "early exit update needed for mode: %s (idle_vrefresh: %d)\n", @@ -593,7 +593,7 @@ static bool s6e3hc3_set_self_refresh(struct exynos_panel *ctx, bool enable) } EXYNOS_DCS_WRITE_TABLE(ctx, lock_cmd_f0); - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); DPU_ATRACE_END(__func__); diff --git a/samsung/panel/panel-samsung-s6e3hc4.c b/samsung/panel/panel-samsung-s6e3hc4.c index 4340a89..6c68515 100644 --- a/samsung/panel/panel-samsung-s6e3hc4.c +++ b/samsung/panel/panel-samsung-s6e3hc4.c @@ -549,7 +549,7 @@ static void s6e3hc4_update_refresh_mode(struct exynos_panel *ctx, ctx->panel_idle_vrefresh = idle_vrefresh; s6e3hc4_update_panel_feat(ctx, vrefresh, false); te2_state_changed(ctx->bl); - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, false); } static void s6e3hc4_change_frequency(struct exynos_panel *ctx, @@ -605,7 +605,7 @@ static bool s6e3hc4_set_self_refresh(struct exynos_panel *ctx, bool enable) if (pmode->exynos_mode.is_lp_mode) { /* set 10Hz while self refresh is active, otherwise clear it */ ctx->panel_idle_vrefresh = enable ? 10 : 0; - notify_panel_mode_changed(ctx); + notify_panel_mode_changed(ctx, true); return false; } |