| 1 | /* SPDX-License-Identifier: MIT */ | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright © 2019 Intel Corporation | 
|---|
| 4 | */ | 
|---|
| 5 |  | 
|---|
| 6 | #ifndef __INTEL_DISPLAY_POWER_H__ | 
|---|
| 7 | #define __INTEL_DISPLAY_POWER_H__ | 
|---|
| 8 |  | 
|---|
| 9 | #include <linux/mutex.h> | 
|---|
| 10 | #include <linux/workqueue.h> | 
|---|
| 11 |  | 
|---|
| 12 | #include "intel_wakeref.h" | 
|---|
| 13 |  | 
|---|
| 14 | enum aux_ch; | 
|---|
| 15 | enum port; | 
|---|
| 16 | struct i915_power_well; | 
|---|
| 17 | struct intel_display; | 
|---|
| 18 | struct intel_encoder; | 
|---|
| 19 | struct seq_file; | 
|---|
| 20 |  | 
|---|
| 21 | /* | 
|---|
| 22 | * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances | 
|---|
| 23 | * consecutive, so that the pipe,transcoder,port -> power domain macros | 
|---|
| 24 | * work correctly. | 
|---|
| 25 | */ | 
|---|
| 26 | enum intel_display_power_domain { | 
|---|
| 27 | POWER_DOMAIN_DISPLAY_CORE, | 
|---|
| 28 | POWER_DOMAIN_PIPE_A, | 
|---|
| 29 | POWER_DOMAIN_PIPE_B, | 
|---|
| 30 | POWER_DOMAIN_PIPE_C, | 
|---|
| 31 | POWER_DOMAIN_PIPE_D, | 
|---|
| 32 | POWER_DOMAIN_PIPE_PANEL_FITTER_A, | 
|---|
| 33 | POWER_DOMAIN_PIPE_PANEL_FITTER_B, | 
|---|
| 34 | POWER_DOMAIN_PIPE_PANEL_FITTER_C, | 
|---|
| 35 | POWER_DOMAIN_PIPE_PANEL_FITTER_D, | 
|---|
| 36 | POWER_DOMAIN_TRANSCODER_A, | 
|---|
| 37 | POWER_DOMAIN_TRANSCODER_B, | 
|---|
| 38 | POWER_DOMAIN_TRANSCODER_C, | 
|---|
| 39 | POWER_DOMAIN_TRANSCODER_D, | 
|---|
| 40 | POWER_DOMAIN_TRANSCODER_EDP, | 
|---|
| 41 | POWER_DOMAIN_TRANSCODER_DSI_A, | 
|---|
| 42 | POWER_DOMAIN_TRANSCODER_DSI_C, | 
|---|
| 43 |  | 
|---|
| 44 | /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ | 
|---|
| 45 | POWER_DOMAIN_TRANSCODER_VDSC_PW2, | 
|---|
| 46 |  | 
|---|
| 47 | POWER_DOMAIN_PORT_DDI_LANES_A, | 
|---|
| 48 | POWER_DOMAIN_PORT_DDI_LANES_B, | 
|---|
| 49 | POWER_DOMAIN_PORT_DDI_LANES_C, | 
|---|
| 50 | POWER_DOMAIN_PORT_DDI_LANES_D, | 
|---|
| 51 | POWER_DOMAIN_PORT_DDI_LANES_E, | 
|---|
| 52 | POWER_DOMAIN_PORT_DDI_LANES_F, | 
|---|
| 53 |  | 
|---|
| 54 | POWER_DOMAIN_PORT_DDI_LANES_TC1, | 
|---|
| 55 | POWER_DOMAIN_PORT_DDI_LANES_TC2, | 
|---|
| 56 | POWER_DOMAIN_PORT_DDI_LANES_TC3, | 
|---|
| 57 | POWER_DOMAIN_PORT_DDI_LANES_TC4, | 
|---|
| 58 | POWER_DOMAIN_PORT_DDI_LANES_TC5, | 
|---|
| 59 | POWER_DOMAIN_PORT_DDI_LANES_TC6, | 
|---|
| 60 |  | 
|---|
| 61 | POWER_DOMAIN_PORT_DDI_IO_A, | 
|---|
| 62 | POWER_DOMAIN_PORT_DDI_IO_B, | 
|---|
| 63 | POWER_DOMAIN_PORT_DDI_IO_C, | 
|---|
| 64 | POWER_DOMAIN_PORT_DDI_IO_D, | 
|---|
| 65 | POWER_DOMAIN_PORT_DDI_IO_E, | 
|---|
| 66 | POWER_DOMAIN_PORT_DDI_IO_F, | 
|---|
| 67 |  | 
|---|
| 68 | POWER_DOMAIN_PORT_DDI_IO_TC1, | 
|---|
| 69 | POWER_DOMAIN_PORT_DDI_IO_TC2, | 
|---|
| 70 | POWER_DOMAIN_PORT_DDI_IO_TC3, | 
|---|
| 71 | POWER_DOMAIN_PORT_DDI_IO_TC4, | 
|---|
| 72 | POWER_DOMAIN_PORT_DDI_IO_TC5, | 
|---|
| 73 | POWER_DOMAIN_PORT_DDI_IO_TC6, | 
|---|
| 74 |  | 
|---|
| 75 | POWER_DOMAIN_PORT_DSI, | 
|---|
| 76 | POWER_DOMAIN_PORT_CRT, | 
|---|
| 77 | POWER_DOMAIN_PORT_OTHER, | 
|---|
| 78 | POWER_DOMAIN_VGA, | 
|---|
| 79 | POWER_DOMAIN_AUDIO_MMIO, | 
|---|
| 80 | POWER_DOMAIN_AUDIO_PLAYBACK, | 
|---|
| 81 |  | 
|---|
| 82 | POWER_DOMAIN_AUX_IO_A, | 
|---|
| 83 | POWER_DOMAIN_AUX_IO_B, | 
|---|
| 84 | POWER_DOMAIN_AUX_IO_C, | 
|---|
| 85 | POWER_DOMAIN_AUX_IO_D, | 
|---|
| 86 | POWER_DOMAIN_AUX_IO_E, | 
|---|
| 87 | POWER_DOMAIN_AUX_IO_F, | 
|---|
| 88 |  | 
|---|
| 89 | POWER_DOMAIN_AUX_A, | 
|---|
| 90 | POWER_DOMAIN_AUX_B, | 
|---|
| 91 | POWER_DOMAIN_AUX_C, | 
|---|
| 92 | POWER_DOMAIN_AUX_D, | 
|---|
| 93 | POWER_DOMAIN_AUX_E, | 
|---|
| 94 | POWER_DOMAIN_AUX_F, | 
|---|
| 95 |  | 
|---|
| 96 | POWER_DOMAIN_AUX_USBC1, | 
|---|
| 97 | POWER_DOMAIN_AUX_USBC2, | 
|---|
| 98 | POWER_DOMAIN_AUX_USBC3, | 
|---|
| 99 | POWER_DOMAIN_AUX_USBC4, | 
|---|
| 100 | POWER_DOMAIN_AUX_USBC5, | 
|---|
| 101 | POWER_DOMAIN_AUX_USBC6, | 
|---|
| 102 |  | 
|---|
| 103 | POWER_DOMAIN_AUX_TBT1, | 
|---|
| 104 | POWER_DOMAIN_AUX_TBT2, | 
|---|
| 105 | POWER_DOMAIN_AUX_TBT3, | 
|---|
| 106 | POWER_DOMAIN_AUX_TBT4, | 
|---|
| 107 | POWER_DOMAIN_AUX_TBT5, | 
|---|
| 108 | POWER_DOMAIN_AUX_TBT6, | 
|---|
| 109 |  | 
|---|
| 110 | POWER_DOMAIN_GMBUS, | 
|---|
| 111 | POWER_DOMAIN_GT_IRQ, | 
|---|
| 112 | POWER_DOMAIN_DC_OFF, | 
|---|
| 113 | POWER_DOMAIN_TC_COLD_OFF, | 
|---|
| 114 | POWER_DOMAIN_INIT, | 
|---|
| 115 |  | 
|---|
| 116 | POWER_DOMAIN_NUM, | 
|---|
| 117 | POWER_DOMAIN_INVALID = POWER_DOMAIN_NUM, | 
|---|
| 118 | }; | 
|---|
| 119 |  | 
|---|
| 120 | #define POWER_DOMAIN_PIPE(pipe) \ | 
|---|
| 121 | ((enum intel_display_power_domain)((pipe) - PIPE_A + POWER_DOMAIN_PIPE_A)) | 
|---|
| 122 | #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ | 
|---|
| 123 | ((enum intel_display_power_domain)((pipe) - PIPE_A + POWER_DOMAIN_PIPE_PANEL_FITTER_A)) | 
|---|
| 124 | #define POWER_DOMAIN_TRANSCODER(tran) \ | 
|---|
| 125 | ((tran) == TRANSCODER_EDP ? POWER_DOMAIN_TRANSCODER_EDP : \ | 
|---|
| 126 | (enum intel_display_power_domain)((tran) - TRANSCODER_A + POWER_DOMAIN_TRANSCODER_A)) | 
|---|
| 127 |  | 
|---|
| 128 | struct intel_power_domain_mask { | 
|---|
| 129 | DECLARE_BITMAP(bits, POWER_DOMAIN_NUM); | 
|---|
| 130 | }; | 
|---|
| 131 |  | 
|---|
| 132 | struct i915_power_domains { | 
|---|
| 133 | /* | 
|---|
| 134 | * Power wells needed for initialization at driver init and suspend | 
|---|
| 135 | * time are on. They are kept on until after the first modeset. | 
|---|
| 136 | */ | 
|---|
| 137 | bool initializing; | 
|---|
| 138 | bool display_core_suspended; | 
|---|
| 139 | int power_well_count; | 
|---|
| 140 |  | 
|---|
| 141 | u32 dc_state; | 
|---|
| 142 | u32 target_dc_state; | 
|---|
| 143 | u32 allowed_dc_mask; | 
|---|
| 144 |  | 
|---|
| 145 | intel_wakeref_t init_wakeref; | 
|---|
| 146 | intel_wakeref_t disable_wakeref; | 
|---|
| 147 |  | 
|---|
| 148 | struct mutex lock; | 
|---|
| 149 | int domain_use_count[POWER_DOMAIN_NUM]; | 
|---|
| 150 |  | 
|---|
| 151 | struct delayed_work async_put_work; | 
|---|
| 152 | intel_wakeref_t async_put_wakeref; | 
|---|
| 153 | struct intel_power_domain_mask async_put_domains[2]; | 
|---|
| 154 | int async_put_next_delay; | 
|---|
| 155 |  | 
|---|
| 156 | struct i915_power_well *power_wells; | 
|---|
| 157 | }; | 
|---|
| 158 |  | 
|---|
| 159 | struct intel_display_power_domain_set { | 
|---|
| 160 | struct intel_power_domain_mask mask; | 
|---|
| 161 | #ifdef CONFIG_DRM_I915_DEBUG_RUNTIME_PM | 
|---|
| 162 | intel_wakeref_t wakerefs[POWER_DOMAIN_NUM]; | 
|---|
| 163 | #endif | 
|---|
| 164 | }; | 
|---|
| 165 |  | 
|---|
| 166 | #define for_each_power_domain(__domain, __mask)				\ | 
|---|
| 167 | for ((__domain) = 0; (__domain) < POWER_DOMAIN_NUM; (__domain)++)	\ | 
|---|
| 168 | for_each_if(test_bit((__domain), (__mask)->bits)) | 
|---|
| 169 |  | 
|---|
| 170 | int intel_power_domains_init(struct intel_display *display); | 
|---|
| 171 | void intel_power_domains_cleanup(struct intel_display *display); | 
|---|
| 172 | void intel_power_domains_init_hw(struct intel_display *display, bool resume); | 
|---|
| 173 | void intel_power_domains_driver_remove(struct intel_display *display); | 
|---|
| 174 | void intel_power_domains_enable(struct intel_display *display); | 
|---|
| 175 | void intel_power_domains_disable(struct intel_display *display); | 
|---|
| 176 | void intel_power_domains_suspend(struct intel_display *display, bool s2idle); | 
|---|
| 177 | void intel_power_domains_resume(struct intel_display *display); | 
|---|
| 178 | void intel_power_domains_sanitize_state(struct intel_display *display); | 
|---|
| 179 |  | 
|---|
| 180 | void intel_display_power_suspend_late(struct intel_display *display, bool s2idle); | 
|---|
| 181 | void intel_display_power_resume_early(struct intel_display *display); | 
|---|
| 182 | void intel_display_power_suspend(struct intel_display *display); | 
|---|
| 183 | void intel_display_power_resume(struct intel_display *display); | 
|---|
| 184 | void intel_display_power_set_target_dc_state(struct intel_display *display, | 
|---|
| 185 | u32 state); | 
|---|
| 186 | u32 intel_display_power_get_current_dc_state(struct intel_display *display); | 
|---|
| 187 |  | 
|---|
| 188 | bool intel_display_power_is_enabled(struct intel_display *display, | 
|---|
| 189 | enum intel_display_power_domain domain); | 
|---|
| 190 | intel_wakeref_t intel_display_power_get(struct intel_display *display, | 
|---|
| 191 | enum intel_display_power_domain domain); | 
|---|
| 192 | intel_wakeref_t | 
|---|
| 193 | intel_display_power_get_if_enabled(struct intel_display *display, | 
|---|
| 194 | enum intel_display_power_domain domain); | 
|---|
| 195 | void __intel_display_power_put_async(struct intel_display *display, | 
|---|
| 196 | enum intel_display_power_domain domain, | 
|---|
| 197 | intel_wakeref_t wakeref, | 
|---|
| 198 | int delay_ms); | 
|---|
| 199 | void intel_display_power_flush_work(struct intel_display *display); | 
|---|
| 200 | #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) | 
|---|
| 201 | void intel_display_power_put(struct intel_display *display, | 
|---|
| 202 | enum intel_display_power_domain domain, | 
|---|
| 203 | intel_wakeref_t wakeref); | 
|---|
| 204 | static inline void | 
|---|
| 205 | intel_display_power_put_async(struct intel_display *display, | 
|---|
| 206 | enum intel_display_power_domain domain, | 
|---|
| 207 | intel_wakeref_t wakeref) | 
|---|
| 208 | { | 
|---|
| 209 | __intel_display_power_put_async(display, domain, wakeref, -1); | 
|---|
| 210 | } | 
|---|
| 211 |  | 
|---|
| 212 | static inline void | 
|---|
| 213 | intel_display_power_put_async_delay(struct intel_display *display, | 
|---|
| 214 | enum intel_display_power_domain domain, | 
|---|
| 215 | intel_wakeref_t wakeref, | 
|---|
| 216 | int delay_ms) | 
|---|
| 217 | { | 
|---|
| 218 | __intel_display_power_put_async(display, domain, wakeref, delay_ms); | 
|---|
| 219 | } | 
|---|
| 220 | #else | 
|---|
| 221 | void intel_display_power_put_unchecked(struct intel_display *display, | 
|---|
| 222 | enum intel_display_power_domain domain); | 
|---|
| 223 |  | 
|---|
| 224 | static inline void | 
|---|
| 225 | intel_display_power_put(struct intel_display *display, | 
|---|
| 226 | enum intel_display_power_domain domain, | 
|---|
| 227 | intel_wakeref_t wakeref) | 
|---|
| 228 | { | 
|---|
| 229 | intel_display_power_put_unchecked(display, domain); | 
|---|
| 230 | } | 
|---|
| 231 |  | 
|---|
| 232 | static inline void | 
|---|
| 233 | intel_display_power_put_async(struct intel_display *display, | 
|---|
| 234 | enum intel_display_power_domain domain, | 
|---|
| 235 | intel_wakeref_t wakeref) | 
|---|
| 236 | { | 
|---|
| 237 | __intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, delay_ms: -1); | 
|---|
| 238 | } | 
|---|
| 239 |  | 
|---|
| 240 | static inline void | 
|---|
| 241 | intel_display_power_put_async_delay(struct intel_display *display, | 
|---|
| 242 | enum intel_display_power_domain domain, | 
|---|
| 243 | intel_wakeref_t wakeref, | 
|---|
| 244 | int delay_ms) | 
|---|
| 245 | { | 
|---|
| 246 | __intel_display_power_put_async(display, domain, INTEL_WAKEREF_DEF, delay_ms); | 
|---|
| 247 | } | 
|---|
| 248 | #endif | 
|---|
| 249 |  | 
|---|
| 250 | void | 
|---|
| 251 | intel_display_power_get_in_set(struct intel_display *display, | 
|---|
| 252 | struct intel_display_power_domain_set *power_domain_set, | 
|---|
| 253 | enum intel_display_power_domain domain); | 
|---|
| 254 |  | 
|---|
| 255 | bool | 
|---|
| 256 | intel_display_power_get_in_set_if_enabled(struct intel_display *display, | 
|---|
| 257 | struct intel_display_power_domain_set *power_domain_set, | 
|---|
| 258 | enum intel_display_power_domain domain); | 
|---|
| 259 |  | 
|---|
| 260 | void | 
|---|
| 261 | intel_display_power_put_mask_in_set(struct intel_display *display, | 
|---|
| 262 | struct intel_display_power_domain_set *power_domain_set, | 
|---|
| 263 | struct intel_power_domain_mask *mask); | 
|---|
| 264 |  | 
|---|
| 265 | static inline void | 
|---|
| 266 | intel_display_power_put_all_in_set(struct intel_display *display, | 
|---|
| 267 | struct intel_display_power_domain_set *power_domain_set) | 
|---|
| 268 | { | 
|---|
| 269 | intel_display_power_put_mask_in_set(display, power_domain_set, mask: &power_domain_set->mask); | 
|---|
| 270 | } | 
|---|
| 271 |  | 
|---|
| 272 | void intel_display_power_debug(struct intel_display *display, struct seq_file *m); | 
|---|
| 273 |  | 
|---|
| 274 | enum intel_display_power_domain | 
|---|
| 275 | intel_display_power_ddi_lanes_domain(struct intel_display *display, enum port port); | 
|---|
| 276 | enum intel_display_power_domain | 
|---|
| 277 | intel_display_power_ddi_io_domain(struct intel_display *display, enum port port); | 
|---|
| 278 | enum intel_display_power_domain | 
|---|
| 279 | intel_display_power_aux_io_domain(struct intel_display *display, enum aux_ch aux_ch); | 
|---|
| 280 | enum intel_display_power_domain | 
|---|
| 281 | intel_display_power_legacy_aux_domain(struct intel_display *display, enum aux_ch aux_ch); | 
|---|
| 282 | enum intel_display_power_domain | 
|---|
| 283 | intel_display_power_tbt_aux_domain(struct intel_display *display, enum aux_ch aux_ch); | 
|---|
| 284 |  | 
|---|
| 285 | /* | 
|---|
| 286 | * FIXME: We should probably switch this to a 0-based scheme to be consistent | 
|---|
| 287 | * with how we now name/number DBUF_CTL instances. | 
|---|
| 288 | */ | 
|---|
| 289 | enum dbuf_slice { | 
|---|
| 290 | DBUF_S1, | 
|---|
| 291 | DBUF_S2, | 
|---|
| 292 | DBUF_S3, | 
|---|
| 293 | DBUF_S4, | 
|---|
| 294 | I915_MAX_DBUF_SLICES | 
|---|
| 295 | }; | 
|---|
| 296 |  | 
|---|
| 297 | void gen9_dbuf_slices_update(struct intel_display *display, | 
|---|
| 298 | u8 req_slices); | 
|---|
| 299 |  | 
|---|
| 300 | #define with_intel_display_power(display, domain, wf) \ | 
|---|
| 301 | for ((wf) = intel_display_power_get((display), (domain)); (wf); \ | 
|---|
| 302 | intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL) | 
|---|
| 303 |  | 
|---|
| 304 | #define with_intel_display_power_if_enabled(display, domain, wf) \ | 
|---|
| 305 | for ((wf) = intel_display_power_get_if_enabled((display), (domain)); (wf); \ | 
|---|
| 306 | intel_display_power_put_async((display), (domain), (wf)), (wf) = NULL) | 
|---|
| 307 |  | 
|---|
| 308 | #endif /* __INTEL_DISPLAY_POWER_H__ */ | 
|---|
| 309 |  | 
|---|