1 1.4 riastrad /* $NetBSD: drm_self_refresh_helper.c,v 1.4 2021/12/19 10:39:20 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* 5 1.1 riastrad * Copyright (C) 2019 Google, Inc. 6 1.1 riastrad * 7 1.1 riastrad * Authors: 8 1.1 riastrad * Sean Paul <seanpaul (at) chromium.org> 9 1.1 riastrad */ 10 1.1 riastrad #include <sys/cdefs.h> 11 1.4 riastrad __KERNEL_RCSID(0, "$NetBSD: drm_self_refresh_helper.c,v 1.4 2021/12/19 10:39:20 riastradh Exp $"); 12 1.1 riastrad 13 1.1 riastrad #include <linux/average.h> 14 1.1 riastrad #include <linux/bitops.h> 15 1.1 riastrad #include <linux/slab.h> 16 1.1 riastrad #include <linux/workqueue.h> 17 1.1 riastrad 18 1.1 riastrad #include <drm/drm_atomic.h> 19 1.1 riastrad #include <drm/drm_atomic_helper.h> 20 1.1 riastrad #include <drm/drm_connector.h> 21 1.1 riastrad #include <drm/drm_crtc.h> 22 1.1 riastrad #include <drm/drm_device.h> 23 1.1 riastrad #include <drm/drm_mode_config.h> 24 1.1 riastrad #include <drm/drm_modeset_lock.h> 25 1.1 riastrad #include <drm/drm_print.h> 26 1.1 riastrad #include <drm/drm_self_refresh_helper.h> 27 1.1 riastrad 28 1.3 riastrad #include <linux/nbsd-namespace.h> 29 1.3 riastrad 30 1.1 riastrad /** 31 1.1 riastrad * DOC: overview 32 1.1 riastrad * 33 1.1 riastrad * This helper library provides an easy way for drivers to leverage the atomic 34 1.1 riastrad * framework to implement panel self refresh (SR) support. Drivers are 35 1.1 riastrad * responsible for initializing and cleaning up the SR helpers on load/unload 36 1.1 riastrad * (see &drm_self_refresh_helper_init/&drm_self_refresh_helper_cleanup). 37 1.1 riastrad * The connector is responsible for setting 38 1.1 riastrad * &drm_connector_state.self_refresh_aware to true at runtime if it is SR-aware 39 1.1 riastrad * (meaning it knows how to initiate self refresh on the panel). 40 1.1 riastrad * 41 1.1 riastrad * Once a crtc has enabled SR using &drm_self_refresh_helper_init, the 42 1.1 riastrad * helpers will monitor activity and call back into the driver to enable/disable 43 1.1 riastrad * SR as appropriate. The best way to think about this is that it's a DPMS 44 1.1 riastrad * on/off request with &drm_crtc_state.self_refresh_active set in crtc state 45 1.1 riastrad * that tells you to disable/enable SR on the panel instead of power-cycling it. 46 1.1 riastrad * 47 1.1 riastrad * During SR, drivers may choose to fully disable their crtc/encoder/bridge 48 1.1 riastrad * hardware (in which case no driver changes are necessary), or they can inspect 49 1.1 riastrad * &drm_crtc_state.self_refresh_active if they want to enter low power mode 50 1.1 riastrad * without full disable (in case full disable/enable is too slow). 51 1.1 riastrad * 52 1.1 riastrad * SR will be deactivated if there are any atomic updates affecting the 53 1.1 riastrad * pipe that is in SR mode. If a crtc is driving multiple connectors, all 54 1.1 riastrad * connectors must be SR aware and all will enter/exit SR mode at the same time. 55 1.1 riastrad * 56 1.1 riastrad * If the crtc and connector are SR aware, but the panel connected does not 57 1.1 riastrad * support it (or is otherwise unable to enter SR), the driver should fail 58 1.1 riastrad * atomic_check when &drm_crtc_state.self_refresh_active is true. 59 1.1 riastrad */ 60 1.1 riastrad 61 1.1 riastrad #define SELF_REFRESH_AVG_SEED_MS 200 62 1.1 riastrad 63 1.1 riastrad DECLARE_EWMA(psr_time, 4, 4) 64 1.1 riastrad 65 1.1 riastrad struct drm_self_refresh_data { 66 1.1 riastrad struct drm_crtc *crtc; 67 1.1 riastrad struct delayed_work entry_work; 68 1.1 riastrad 69 1.1 riastrad struct mutex avg_mutex; 70 1.1 riastrad struct ewma_psr_time entry_avg_ms; 71 1.1 riastrad struct ewma_psr_time exit_avg_ms; 72 1.1 riastrad }; 73 1.1 riastrad 74 1.1 riastrad static void drm_self_refresh_helper_entry_work(struct work_struct *work) 75 1.1 riastrad { 76 1.1 riastrad struct drm_self_refresh_data *sr_data = container_of( 77 1.1 riastrad to_delayed_work(work), 78 1.1 riastrad struct drm_self_refresh_data, entry_work); 79 1.1 riastrad struct drm_crtc *crtc = sr_data->crtc; 80 1.1 riastrad struct drm_device *dev = crtc->dev; 81 1.1 riastrad struct drm_modeset_acquire_ctx ctx; 82 1.1 riastrad struct drm_atomic_state *state; 83 1.1 riastrad struct drm_connector *conn; 84 1.1 riastrad struct drm_connector_state *conn_state; 85 1.1 riastrad struct drm_crtc_state *crtc_state; 86 1.1 riastrad int i, ret = 0; 87 1.1 riastrad 88 1.1 riastrad drm_modeset_acquire_init(&ctx, 0); 89 1.1 riastrad 90 1.1 riastrad state = drm_atomic_state_alloc(dev); 91 1.1 riastrad if (!state) { 92 1.1 riastrad ret = -ENOMEM; 93 1.1 riastrad goto out_drop_locks; 94 1.1 riastrad } 95 1.1 riastrad 96 1.1 riastrad retry: 97 1.1 riastrad state->acquire_ctx = &ctx; 98 1.1 riastrad 99 1.1 riastrad crtc_state = drm_atomic_get_crtc_state(state, crtc); 100 1.1 riastrad if (IS_ERR(crtc_state)) { 101 1.1 riastrad ret = PTR_ERR(crtc_state); 102 1.1 riastrad goto out; 103 1.1 riastrad } 104 1.1 riastrad 105 1.1 riastrad if (!crtc_state->enable) 106 1.1 riastrad goto out; 107 1.1 riastrad 108 1.1 riastrad ret = drm_atomic_add_affected_connectors(state, crtc); 109 1.1 riastrad if (ret) 110 1.1 riastrad goto out; 111 1.1 riastrad 112 1.1 riastrad for_each_new_connector_in_state(state, conn, conn_state, i) { 113 1.1 riastrad if (!conn_state->self_refresh_aware) 114 1.1 riastrad goto out; 115 1.1 riastrad } 116 1.1 riastrad 117 1.1 riastrad crtc_state->active = false; 118 1.1 riastrad crtc_state->self_refresh_active = true; 119 1.1 riastrad 120 1.1 riastrad ret = drm_atomic_commit(state); 121 1.1 riastrad if (ret) 122 1.1 riastrad goto out; 123 1.1 riastrad 124 1.1 riastrad out: 125 1.1 riastrad if (ret == -EDEADLK) { 126 1.1 riastrad drm_atomic_state_clear(state); 127 1.1 riastrad ret = drm_modeset_backoff(&ctx); 128 1.1 riastrad if (!ret) 129 1.1 riastrad goto retry; 130 1.1 riastrad } 131 1.1 riastrad 132 1.1 riastrad drm_atomic_state_put(state); 133 1.1 riastrad 134 1.1 riastrad out_drop_locks: 135 1.1 riastrad drm_modeset_drop_locks(&ctx); 136 1.1 riastrad drm_modeset_acquire_fini(&ctx); 137 1.1 riastrad } 138 1.1 riastrad 139 1.1 riastrad /** 140 1.1 riastrad * drm_self_refresh_helper_update_avg_times - Updates a crtc's SR time averages 141 1.1 riastrad * @state: the state which has just been applied to hardware 142 1.1 riastrad * @commit_time_ms: the amount of time in ms that this commit took to complete 143 1.1 riastrad * @new_self_refresh_mask: bitmask of crtc's that have self_refresh_active in 144 1.1 riastrad * new state 145 1.1 riastrad * 146 1.1 riastrad * Called after &drm_mode_config_funcs.atomic_commit_tail, this function will 147 1.1 riastrad * update the average entry/exit self refresh times on self refresh transitions. 148 1.1 riastrad * These averages will be used when calculating how long to delay before 149 1.1 riastrad * entering self refresh mode after activity. 150 1.1 riastrad */ 151 1.1 riastrad void 152 1.1 riastrad drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state, 153 1.1 riastrad unsigned int commit_time_ms, 154 1.1 riastrad unsigned int new_self_refresh_mask) 155 1.1 riastrad { 156 1.1 riastrad struct drm_crtc *crtc; 157 1.1 riastrad struct drm_crtc_state *old_crtc_state; 158 1.1 riastrad int i; 159 1.1 riastrad 160 1.1 riastrad for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) { 161 1.1 riastrad bool new_self_refresh_active = new_self_refresh_mask & BIT(i); 162 1.1 riastrad struct drm_self_refresh_data *sr_data = crtc->self_refresh_data; 163 1.1 riastrad struct ewma_psr_time *time; 164 1.1 riastrad 165 1.1 riastrad if (old_crtc_state->self_refresh_active == 166 1.1 riastrad new_self_refresh_active) 167 1.1 riastrad continue; 168 1.1 riastrad 169 1.1 riastrad if (new_self_refresh_active) 170 1.1 riastrad time = &sr_data->entry_avg_ms; 171 1.1 riastrad else 172 1.1 riastrad time = &sr_data->exit_avg_ms; 173 1.1 riastrad 174 1.1 riastrad mutex_lock(&sr_data->avg_mutex); 175 1.1 riastrad ewma_psr_time_add(time, commit_time_ms); 176 1.1 riastrad mutex_unlock(&sr_data->avg_mutex); 177 1.1 riastrad } 178 1.1 riastrad } 179 1.1 riastrad EXPORT_SYMBOL(drm_self_refresh_helper_update_avg_times); 180 1.1 riastrad 181 1.1 riastrad /** 182 1.1 riastrad * drm_self_refresh_helper_alter_state - Alters the atomic state for SR exit 183 1.1 riastrad * @state: the state currently being checked 184 1.1 riastrad * 185 1.1 riastrad * Called at the end of atomic check. This function checks the state for flags 186 1.1 riastrad * incompatible with self refresh exit and changes them. This is a bit 187 1.1 riastrad * disingenuous since userspace is expecting one thing and we're giving it 188 1.1 riastrad * another. However in order to keep self refresh entirely hidden from 189 1.1 riastrad * userspace, this is required. 190 1.1 riastrad * 191 1.1 riastrad * At the end, we queue up the self refresh entry work so we can enter PSR after 192 1.1 riastrad * the desired delay. 193 1.1 riastrad */ 194 1.1 riastrad void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state) 195 1.1 riastrad { 196 1.1 riastrad struct drm_crtc *crtc; 197 1.1 riastrad struct drm_crtc_state *crtc_state; 198 1.1 riastrad int i; 199 1.1 riastrad 200 1.1 riastrad if (state->async_update || !state->allow_modeset) { 201 1.1 riastrad for_each_old_crtc_in_state(state, crtc, crtc_state, i) { 202 1.1 riastrad if (crtc_state->self_refresh_active) { 203 1.1 riastrad state->async_update = false; 204 1.1 riastrad state->allow_modeset = true; 205 1.1 riastrad break; 206 1.1 riastrad } 207 1.1 riastrad } 208 1.1 riastrad } 209 1.1 riastrad 210 1.1 riastrad for_each_new_crtc_in_state(state, crtc, crtc_state, i) { 211 1.1 riastrad struct drm_self_refresh_data *sr_data; 212 1.1 riastrad unsigned int delay; 213 1.1 riastrad 214 1.1 riastrad /* Don't trigger the entry timer when we're already in SR */ 215 1.1 riastrad if (crtc_state->self_refresh_active) 216 1.1 riastrad continue; 217 1.1 riastrad 218 1.1 riastrad sr_data = crtc->self_refresh_data; 219 1.1 riastrad if (!sr_data) 220 1.1 riastrad continue; 221 1.1 riastrad 222 1.1 riastrad mutex_lock(&sr_data->avg_mutex); 223 1.1 riastrad delay = (ewma_psr_time_read(&sr_data->entry_avg_ms) + 224 1.1 riastrad ewma_psr_time_read(&sr_data->exit_avg_ms)) * 2; 225 1.1 riastrad mutex_unlock(&sr_data->avg_mutex); 226 1.1 riastrad 227 1.1 riastrad mod_delayed_work(system_wq, &sr_data->entry_work, 228 1.1 riastrad msecs_to_jiffies(delay)); 229 1.1 riastrad } 230 1.1 riastrad } 231 1.1 riastrad EXPORT_SYMBOL(drm_self_refresh_helper_alter_state); 232 1.1 riastrad 233 1.1 riastrad /** 234 1.1 riastrad * drm_self_refresh_helper_init - Initializes self refresh helpers for a crtc 235 1.1 riastrad * @crtc: the crtc which supports self refresh supported displays 236 1.1 riastrad * 237 1.1 riastrad * Returns zero if successful or -errno on failure 238 1.1 riastrad */ 239 1.1 riastrad int drm_self_refresh_helper_init(struct drm_crtc *crtc) 240 1.1 riastrad { 241 1.1 riastrad struct drm_self_refresh_data *sr_data = crtc->self_refresh_data; 242 1.1 riastrad 243 1.1 riastrad /* Helper is already initialized */ 244 1.1 riastrad if (WARN_ON(sr_data)) 245 1.1 riastrad return -EINVAL; 246 1.1 riastrad 247 1.1 riastrad sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL); 248 1.1 riastrad if (!sr_data) 249 1.1 riastrad return -ENOMEM; 250 1.1 riastrad 251 1.1 riastrad INIT_DELAYED_WORK(&sr_data->entry_work, 252 1.1 riastrad drm_self_refresh_helper_entry_work); 253 1.1 riastrad sr_data->crtc = crtc; 254 1.1 riastrad mutex_init(&sr_data->avg_mutex); 255 1.1 riastrad ewma_psr_time_init(&sr_data->entry_avg_ms); 256 1.1 riastrad ewma_psr_time_init(&sr_data->exit_avg_ms); 257 1.1 riastrad 258 1.1 riastrad /* 259 1.1 riastrad * Seed the averages so they're non-zero (and sufficiently large 260 1.1 riastrad * for even poorly performing panels). As time goes on, this will be 261 1.1 riastrad * averaged out and the values will trend to their true value. 262 1.1 riastrad */ 263 1.1 riastrad ewma_psr_time_add(&sr_data->entry_avg_ms, SELF_REFRESH_AVG_SEED_MS); 264 1.1 riastrad ewma_psr_time_add(&sr_data->exit_avg_ms, SELF_REFRESH_AVG_SEED_MS); 265 1.1 riastrad 266 1.1 riastrad crtc->self_refresh_data = sr_data; 267 1.1 riastrad return 0; 268 1.1 riastrad } 269 1.1 riastrad EXPORT_SYMBOL(drm_self_refresh_helper_init); 270 1.1 riastrad 271 1.1 riastrad /** 272 1.1 riastrad * drm_self_refresh_helper_cleanup - Cleans up self refresh helpers for a crtc 273 1.1 riastrad * @crtc: the crtc to cleanup 274 1.1 riastrad */ 275 1.1 riastrad void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc) 276 1.1 riastrad { 277 1.1 riastrad struct drm_self_refresh_data *sr_data = crtc->self_refresh_data; 278 1.1 riastrad 279 1.1 riastrad /* Helper is already uninitialized */ 280 1.1 riastrad if (!sr_data) 281 1.1 riastrad return; 282 1.1 riastrad 283 1.1 riastrad crtc->self_refresh_data = NULL; 284 1.1 riastrad 285 1.1 riastrad cancel_delayed_work_sync(&sr_data->entry_work); 286 1.4 riastrad mutex_destroy(&sr_data->avg_mutex); 287 1.1 riastrad kfree(sr_data); 288 1.1 riastrad } 289 1.1 riastrad EXPORT_SYMBOL(drm_self_refresh_helper_cleanup); 290