0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/average.h>
0009 #include <linux/bitops.h>
0010 #include <linux/slab.h>
0011 #include <linux/workqueue.h>
0012
0013 #include <drm/drm_atomic.h>
0014 #include <drm/drm_atomic_helper.h>
0015 #include <drm/drm_connector.h>
0016 #include <drm/drm_crtc.h>
0017 #include <drm/drm_device.h>
0018 #include <drm/drm_mode_config.h>
0019 #include <drm/drm_modeset_lock.h>
0020 #include <drm/drm_print.h>
0021 #include <drm/drm_self_refresh_helper.h>
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 #define SELF_REFRESH_AVG_SEED_MS 200
0055
0056 DECLARE_EWMA(psr_time, 4, 4)
0057
0058 struct drm_self_refresh_data {
0059 struct drm_crtc *crtc;
0060 struct delayed_work entry_work;
0061
0062 struct mutex avg_mutex;
0063 struct ewma_psr_time entry_avg_ms;
0064 struct ewma_psr_time exit_avg_ms;
0065 };
0066
0067 static void drm_self_refresh_helper_entry_work(struct work_struct *work)
0068 {
0069 struct drm_self_refresh_data *sr_data = container_of(
0070 to_delayed_work(work),
0071 struct drm_self_refresh_data, entry_work);
0072 struct drm_crtc *crtc = sr_data->crtc;
0073 struct drm_device *dev = crtc->dev;
0074 struct drm_modeset_acquire_ctx ctx;
0075 struct drm_atomic_state *state;
0076 struct drm_connector *conn;
0077 struct drm_connector_state *conn_state;
0078 struct drm_crtc_state *crtc_state;
0079 int i, ret = 0;
0080
0081 drm_modeset_acquire_init(&ctx, 0);
0082
0083 state = drm_atomic_state_alloc(dev);
0084 if (!state) {
0085 ret = -ENOMEM;
0086 goto out_drop_locks;
0087 }
0088
0089 retry:
0090 state->acquire_ctx = &ctx;
0091
0092 crtc_state = drm_atomic_get_crtc_state(state, crtc);
0093 if (IS_ERR(crtc_state)) {
0094 ret = PTR_ERR(crtc_state);
0095 goto out;
0096 }
0097
0098 if (!crtc_state->enable)
0099 goto out;
0100
0101 ret = drm_atomic_add_affected_connectors(state, crtc);
0102 if (ret)
0103 goto out;
0104
0105 for_each_new_connector_in_state(state, conn, conn_state, i) {
0106 if (!conn_state->self_refresh_aware)
0107 goto out;
0108 }
0109
0110 crtc_state->active = false;
0111 crtc_state->self_refresh_active = true;
0112
0113 ret = drm_atomic_commit(state);
0114 if (ret)
0115 goto out;
0116
0117 out:
0118 if (ret == -EDEADLK) {
0119 drm_atomic_state_clear(state);
0120 ret = drm_modeset_backoff(&ctx);
0121 if (!ret)
0122 goto retry;
0123 }
0124
0125 drm_atomic_state_put(state);
0126
0127 out_drop_locks:
0128 drm_modeset_drop_locks(&ctx);
0129 drm_modeset_acquire_fini(&ctx);
0130 }
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144 void
0145 drm_self_refresh_helper_update_avg_times(struct drm_atomic_state *state,
0146 unsigned int commit_time_ms,
0147 unsigned int new_self_refresh_mask)
0148 {
0149 struct drm_crtc *crtc;
0150 struct drm_crtc_state *old_crtc_state;
0151 int i;
0152
0153 for_each_old_crtc_in_state(state, crtc, old_crtc_state, i) {
0154 bool new_self_refresh_active = new_self_refresh_mask & BIT(i);
0155 struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
0156 struct ewma_psr_time *time;
0157
0158 if (old_crtc_state->self_refresh_active ==
0159 new_self_refresh_active)
0160 continue;
0161
0162 if (new_self_refresh_active)
0163 time = &sr_data->entry_avg_ms;
0164 else
0165 time = &sr_data->exit_avg_ms;
0166
0167 mutex_lock(&sr_data->avg_mutex);
0168 ewma_psr_time_add(time, commit_time_ms);
0169 mutex_unlock(&sr_data->avg_mutex);
0170 }
0171 }
0172 EXPORT_SYMBOL(drm_self_refresh_helper_update_avg_times);
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state)
0188 {
0189 struct drm_crtc *crtc;
0190 struct drm_crtc_state *crtc_state;
0191 int i;
0192
0193 if (state->async_update || !state->allow_modeset) {
0194 for_each_old_crtc_in_state(state, crtc, crtc_state, i) {
0195 if (crtc_state->self_refresh_active) {
0196 state->async_update = false;
0197 state->allow_modeset = true;
0198 break;
0199 }
0200 }
0201 }
0202
0203 for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
0204 struct drm_self_refresh_data *sr_data;
0205 unsigned int delay;
0206
0207
0208 if (crtc_state->self_refresh_active)
0209 continue;
0210
0211 sr_data = crtc->self_refresh_data;
0212 if (!sr_data)
0213 continue;
0214
0215 mutex_lock(&sr_data->avg_mutex);
0216 delay = (ewma_psr_time_read(&sr_data->entry_avg_ms) +
0217 ewma_psr_time_read(&sr_data->exit_avg_ms)) * 2;
0218 mutex_unlock(&sr_data->avg_mutex);
0219
0220 mod_delayed_work(system_wq, &sr_data->entry_work,
0221 msecs_to_jiffies(delay));
0222 }
0223 }
0224 EXPORT_SYMBOL(drm_self_refresh_helper_alter_state);
0225
0226
0227
0228
0229
0230
0231
0232 int drm_self_refresh_helper_init(struct drm_crtc *crtc)
0233 {
0234 struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
0235
0236
0237 if (WARN_ON(sr_data))
0238 return -EINVAL;
0239
0240 sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL);
0241 if (!sr_data)
0242 return -ENOMEM;
0243
0244 INIT_DELAYED_WORK(&sr_data->entry_work,
0245 drm_self_refresh_helper_entry_work);
0246 sr_data->crtc = crtc;
0247 mutex_init(&sr_data->avg_mutex);
0248 ewma_psr_time_init(&sr_data->entry_avg_ms);
0249 ewma_psr_time_init(&sr_data->exit_avg_ms);
0250
0251
0252
0253
0254
0255
0256 ewma_psr_time_add(&sr_data->entry_avg_ms, SELF_REFRESH_AVG_SEED_MS);
0257 ewma_psr_time_add(&sr_data->exit_avg_ms, SELF_REFRESH_AVG_SEED_MS);
0258
0259 crtc->self_refresh_data = sr_data;
0260 return 0;
0261 }
0262 EXPORT_SYMBOL(drm_self_refresh_helper_init);
0263
0264
0265
0266
0267
0268 void drm_self_refresh_helper_cleanup(struct drm_crtc *crtc)
0269 {
0270 struct drm_self_refresh_data *sr_data = crtc->self_refresh_data;
0271
0272
0273 if (!sr_data)
0274 return;
0275
0276 crtc->self_refresh_data = NULL;
0277
0278 cancel_delayed_work_sync(&sr_data->entry_work);
0279 kfree(sr_data);
0280 }
0281 EXPORT_SYMBOL(drm_self_refresh_helper_cleanup);