| 1 | // SPDX-License-Identifier: MIT | 
|---|
| 2 | /* | 
|---|
| 3 | * Copyright © 2022 Intel Corporation | 
|---|
| 4 | * | 
|---|
| 5 | * Read out the current hardware modeset state, and sanitize it to the current | 
|---|
| 6 | * state. | 
|---|
| 7 | */ | 
|---|
| 8 |  | 
|---|
| 9 | #include <drm/drm_atomic_state_helper.h> | 
|---|
| 10 | #include <drm/drm_atomic_uapi.h> | 
|---|
| 11 | #include <drm/drm_print.h> | 
|---|
| 12 | #include <drm/drm_vblank.h> | 
|---|
| 13 |  | 
|---|
| 14 | #include "i915_reg.h" | 
|---|
| 15 | #include "i9xx_wm.h" | 
|---|
| 16 | #include "intel_atomic.h" | 
|---|
| 17 | #include "intel_bw.h" | 
|---|
| 18 | #include "intel_cmtg.h" | 
|---|
| 19 | #include "intel_color.h" | 
|---|
| 20 | #include "intel_crtc.h" | 
|---|
| 21 | #include "intel_crtc_state_dump.h" | 
|---|
| 22 | #include "intel_ddi.h" | 
|---|
| 23 | #include "intel_de.h" | 
|---|
| 24 | #include "intel_display.h" | 
|---|
| 25 | #include "intel_display_power.h" | 
|---|
| 26 | #include "intel_display_regs.h" | 
|---|
| 27 | #include "intel_display_types.h" | 
|---|
| 28 | #include "intel_dmc.h" | 
|---|
| 29 | #include "intel_fifo_underrun.h" | 
|---|
| 30 | #include "intel_modeset_setup.h" | 
|---|
| 31 | #include "intel_pch_display.h" | 
|---|
| 32 | #include "intel_pmdemand.h" | 
|---|
| 33 | #include "intel_tc.h" | 
|---|
| 34 | #include "intel_vblank.h" | 
|---|
| 35 | #include "intel_vga.h" | 
|---|
| 36 | #include "intel_wm.h" | 
|---|
| 37 | #include "skl_watermark.h" | 
|---|
| 38 |  | 
|---|
| 39 | static void intel_crtc_disable_noatomic_begin(struct intel_crtc *crtc, | 
|---|
| 40 | struct drm_modeset_acquire_ctx *ctx) | 
|---|
| 41 | { | 
|---|
| 42 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 43 | struct intel_crtc_state *crtc_state = | 
|---|
| 44 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 45 | struct intel_plane *plane; | 
|---|
| 46 | struct drm_atomic_state *state; | 
|---|
| 47 | struct intel_crtc *temp_crtc; | 
|---|
| 48 | enum pipe pipe = crtc->pipe; | 
|---|
| 49 |  | 
|---|
| 50 | if (!crtc_state->hw.active) | 
|---|
| 51 | return; | 
|---|
| 52 |  | 
|---|
| 53 | for_each_intel_plane_on_crtc(display->drm, crtc, plane) { | 
|---|
| 54 | const struct intel_plane_state *plane_state = | 
|---|
| 55 | to_intel_plane_state(plane->base.state); | 
|---|
| 56 |  | 
|---|
| 57 | if (plane_state->uapi.visible) | 
|---|
| 58 | intel_plane_disable_noatomic(crtc, plane); | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | state = drm_atomic_state_alloc(dev: display->drm); | 
|---|
| 62 | if (!state) { | 
|---|
| 63 | drm_dbg_kms(display->drm, | 
|---|
| 64 | "failed to disable [CRTC:%d:%s], out of memory", | 
|---|
| 65 | crtc->base.base.id, crtc->base.name); | 
|---|
| 66 | return; | 
|---|
| 67 | } | 
|---|
| 68 |  | 
|---|
| 69 | state->acquire_ctx = ctx; | 
|---|
| 70 | to_intel_atomic_state(state)->internal = true; | 
|---|
| 71 |  | 
|---|
| 72 | /* Everything's already locked, -EDEADLK can't happen. */ | 
|---|
| 73 | for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, | 
|---|
| 74 | BIT(pipe) | | 
|---|
| 75 | intel_crtc_joiner_secondary_pipes(crtc_state)) { | 
|---|
| 76 | struct intel_crtc_state *temp_crtc_state = | 
|---|
| 77 | intel_atomic_get_crtc_state(state, crtc: temp_crtc); | 
|---|
| 78 | int ret; | 
|---|
| 79 |  | 
|---|
| 80 | ret = drm_atomic_add_affected_connectors(state, crtc: &temp_crtc->base); | 
|---|
| 81 |  | 
|---|
| 82 | drm_WARN_ON(display->drm, IS_ERR(temp_crtc_state) || ret); | 
|---|
| 83 | } | 
|---|
| 84 |  | 
|---|
| 85 | display->funcs.display->crtc_disable(to_intel_atomic_state(state), crtc); | 
|---|
| 86 |  | 
|---|
| 87 | drm_atomic_state_put(state); | 
|---|
| 88 |  | 
|---|
| 89 | drm_dbg_kms(display->drm, | 
|---|
| 90 | "[CRTC:%d:%s] hw state adjusted, was enabled, now disabled\n", | 
|---|
| 91 | crtc->base.base.id, crtc->base.name); | 
|---|
| 92 |  | 
|---|
| 93 | crtc->active = false; | 
|---|
| 94 | crtc->base.enabled = false; | 
|---|
| 95 |  | 
|---|
| 96 | if (crtc_state->intel_dpll) | 
|---|
| 97 | intel_dpll_crtc_put(crtc, | 
|---|
| 98 | pll: crtc_state->intel_dpll, | 
|---|
| 99 | shared_dpll_state: &crtc_state->intel_dpll->state); | 
|---|
| 100 | } | 
|---|
| 101 |  | 
|---|
| 102 | static void set_encoder_for_connector(struct intel_connector *connector, | 
|---|
| 103 | struct intel_encoder *encoder) | 
|---|
| 104 | { | 
|---|
| 105 | struct drm_connector_state *conn_state = connector->base.state; | 
|---|
| 106 |  | 
|---|
| 107 | if (conn_state->crtc) | 
|---|
| 108 | drm_connector_put(connector: &connector->base); | 
|---|
| 109 |  | 
|---|
| 110 | if (encoder) { | 
|---|
| 111 | conn_state->best_encoder = &encoder->base; | 
|---|
| 112 | conn_state->crtc = encoder->base.crtc; | 
|---|
| 113 | drm_connector_get(connector: &connector->base); | 
|---|
| 114 | } else { | 
|---|
| 115 | conn_state->best_encoder = NULL; | 
|---|
| 116 | conn_state->crtc = NULL; | 
|---|
| 117 | } | 
|---|
| 118 | } | 
|---|
| 119 |  | 
|---|
| 120 | static void reset_encoder_connector_state(struct intel_encoder *encoder) | 
|---|
| 121 | { | 
|---|
| 122 | struct intel_display *display = to_intel_display(encoder); | 
|---|
| 123 | struct intel_pmdemand_state *pmdemand_state = | 
|---|
| 124 | to_intel_pmdemand_state(obj_state: display->pmdemand.obj.state); | 
|---|
| 125 | struct intel_connector *connector; | 
|---|
| 126 | struct drm_connector_list_iter conn_iter; | 
|---|
| 127 |  | 
|---|
| 128 | drm_connector_list_iter_begin(dev: display->drm, iter: &conn_iter); | 
|---|
| 129 | for_each_intel_connector_iter(connector, &conn_iter) { | 
|---|
| 130 | if (connector->base.encoder != &encoder->base) | 
|---|
| 131 | continue; | 
|---|
| 132 |  | 
|---|
| 133 | /* Clear the corresponding bit in pmdemand active phys mask */ | 
|---|
| 134 | intel_pmdemand_update_phys_mask(display, encoder, | 
|---|
| 135 | pmdemand_state, clear_bit: false); | 
|---|
| 136 |  | 
|---|
| 137 | set_encoder_for_connector(connector, NULL); | 
|---|
| 138 |  | 
|---|
| 139 | connector->base.dpms = DRM_MODE_DPMS_OFF; | 
|---|
| 140 | connector->base.encoder = NULL; | 
|---|
| 141 | } | 
|---|
| 142 | drm_connector_list_iter_end(iter: &conn_iter); | 
|---|
| 143 | } | 
|---|
| 144 |  | 
|---|
| 145 | static void reset_crtc_encoder_state(struct intel_crtc *crtc) | 
|---|
| 146 | { | 
|---|
| 147 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 148 | struct intel_encoder *encoder; | 
|---|
| 149 |  | 
|---|
| 150 | for_each_encoder_on_crtc(display->drm, &crtc->base, encoder) { | 
|---|
| 151 | reset_encoder_connector_state(encoder); | 
|---|
| 152 | encoder->base.crtc = NULL; | 
|---|
| 153 | } | 
|---|
| 154 | } | 
|---|
| 155 |  | 
|---|
| 156 | static void intel_crtc_disable_noatomic_complete(struct intel_crtc *crtc) | 
|---|
| 157 | { | 
|---|
| 158 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 159 | struct intel_pmdemand_state *pmdemand_state = | 
|---|
| 160 | to_intel_pmdemand_state(obj_state: display->pmdemand.obj.state); | 
|---|
| 161 | struct intel_crtc_state *crtc_state = | 
|---|
| 162 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 163 | enum pipe pipe = crtc->pipe; | 
|---|
| 164 |  | 
|---|
| 165 | __drm_atomic_helper_crtc_destroy_state(state: &crtc_state->uapi); | 
|---|
| 166 | intel_crtc_free_hw_state(crtc_state); | 
|---|
| 167 | intel_crtc_state_reset(crtc_state, crtc); | 
|---|
| 168 |  | 
|---|
| 169 | reset_crtc_encoder_state(crtc); | 
|---|
| 170 |  | 
|---|
| 171 | intel_fbc_disable(crtc); | 
|---|
| 172 | intel_update_watermarks(display); | 
|---|
| 173 |  | 
|---|
| 174 | intel_display_power_put_all_in_set(display, power_domain_set: &crtc->enabled_power_domains); | 
|---|
| 175 |  | 
|---|
| 176 | intel_cdclk_crtc_disable_noatomic(crtc); | 
|---|
| 177 | skl_wm_crtc_disable_noatomic(crtc); | 
|---|
| 178 | intel_bw_crtc_disable_noatomic(crtc); | 
|---|
| 179 |  | 
|---|
| 180 | intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, port_clock: 0); | 
|---|
| 181 | } | 
|---|
| 182 |  | 
|---|
| 183 | /* | 
|---|
| 184 | * Return all the pipes using a transcoder in @transcoder_mask. | 
|---|
| 185 | * For joiner configs return only the joiner primary. | 
|---|
| 186 | */ | 
|---|
| 187 | static u8 get_transcoder_pipes(struct intel_display *display, | 
|---|
| 188 | u8 transcoder_mask) | 
|---|
| 189 | { | 
|---|
| 190 | struct intel_crtc *temp_crtc; | 
|---|
| 191 | u8 pipes = 0; | 
|---|
| 192 |  | 
|---|
| 193 | for_each_intel_crtc(display->drm, temp_crtc) { | 
|---|
| 194 | struct intel_crtc_state *temp_crtc_state = | 
|---|
| 195 | to_intel_crtc_state(temp_crtc->base.state); | 
|---|
| 196 |  | 
|---|
| 197 | if (temp_crtc_state->cpu_transcoder == INVALID_TRANSCODER) | 
|---|
| 198 | continue; | 
|---|
| 199 |  | 
|---|
| 200 | if (intel_crtc_is_joiner_secondary(crtc_state: temp_crtc_state)) | 
|---|
| 201 | continue; | 
|---|
| 202 |  | 
|---|
| 203 | if (transcoder_mask & BIT(temp_crtc_state->cpu_transcoder)) | 
|---|
| 204 | pipes |= BIT(temp_crtc->pipe); | 
|---|
| 205 | } | 
|---|
| 206 |  | 
|---|
| 207 | return pipes; | 
|---|
| 208 | } | 
|---|
| 209 |  | 
|---|
| 210 | /* | 
|---|
| 211 | * Return the port sync master and slave pipes linked to @crtc. | 
|---|
| 212 | * For joiner configs return only the joiner primary pipes. | 
|---|
| 213 | */ | 
|---|
| 214 | static void get_portsync_pipes(struct intel_crtc *crtc, | 
|---|
| 215 | u8 *master_pipe_mask, u8 *slave_pipes_mask) | 
|---|
| 216 | { | 
|---|
| 217 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 218 | struct intel_crtc_state *crtc_state = | 
|---|
| 219 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 220 | struct intel_crtc *master_crtc; | 
|---|
| 221 | struct intel_crtc_state *master_crtc_state; | 
|---|
| 222 | enum transcoder master_transcoder; | 
|---|
| 223 |  | 
|---|
| 224 | if (!is_trans_port_sync_mode(state: crtc_state)) { | 
|---|
| 225 | *master_pipe_mask = BIT(crtc->pipe); | 
|---|
| 226 | *slave_pipes_mask = 0; | 
|---|
| 227 |  | 
|---|
| 228 | return; | 
|---|
| 229 | } | 
|---|
| 230 |  | 
|---|
| 231 | if (is_trans_port_sync_master(state: crtc_state)) | 
|---|
| 232 | master_transcoder = crtc_state->cpu_transcoder; | 
|---|
| 233 | else | 
|---|
| 234 | master_transcoder = crtc_state->master_transcoder; | 
|---|
| 235 |  | 
|---|
| 236 | *master_pipe_mask = get_transcoder_pipes(display, BIT(master_transcoder)); | 
|---|
| 237 | drm_WARN_ON(display->drm, !is_power_of_2(*master_pipe_mask)); | 
|---|
| 238 |  | 
|---|
| 239 | master_crtc = intel_crtc_for_pipe(display, ffs(*master_pipe_mask) - 1); | 
|---|
| 240 | master_crtc_state = to_intel_crtc_state(master_crtc->base.state); | 
|---|
| 241 | *slave_pipes_mask = get_transcoder_pipes(display, transcoder_mask: master_crtc_state->sync_mode_slaves_mask); | 
|---|
| 242 | } | 
|---|
| 243 |  | 
|---|
| 244 | static u8 get_joiner_secondary_pipes(struct intel_display *display, u8 primary_pipes_mask) | 
|---|
| 245 | { | 
|---|
| 246 | struct intel_crtc *primary_crtc; | 
|---|
| 247 | u8 pipes = 0; | 
|---|
| 248 |  | 
|---|
| 249 | for_each_intel_crtc_in_pipe_mask(display->drm, primary_crtc, primary_pipes_mask) { | 
|---|
| 250 | struct intel_crtc_state *primary_crtc_state = | 
|---|
| 251 | to_intel_crtc_state(primary_crtc->base.state); | 
|---|
| 252 |  | 
|---|
| 253 | pipes |= intel_crtc_joiner_secondary_pipes(crtc_state: primary_crtc_state); | 
|---|
| 254 | } | 
|---|
| 255 |  | 
|---|
| 256 | return pipes; | 
|---|
| 257 | } | 
|---|
| 258 |  | 
|---|
| 259 | static void intel_crtc_disable_noatomic(struct intel_crtc *crtc, | 
|---|
| 260 | struct drm_modeset_acquire_ctx *ctx) | 
|---|
| 261 | { | 
|---|
| 262 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 263 | struct intel_crtc *temp_crtc; | 
|---|
| 264 | u8 portsync_master_mask; | 
|---|
| 265 | u8 portsync_slaves_mask; | 
|---|
| 266 | u8 joiner_secondaries_mask; | 
|---|
| 267 |  | 
|---|
| 268 | /* TODO: Add support for MST */ | 
|---|
| 269 | get_portsync_pipes(crtc, master_pipe_mask: &portsync_master_mask, slave_pipes_mask: &portsync_slaves_mask); | 
|---|
| 270 | joiner_secondaries_mask = get_joiner_secondary_pipes(display, | 
|---|
| 271 | primary_pipes_mask: portsync_master_mask | | 
|---|
| 272 | portsync_slaves_mask); | 
|---|
| 273 |  | 
|---|
| 274 | drm_WARN_ON(display->drm, | 
|---|
| 275 | portsync_master_mask & portsync_slaves_mask || | 
|---|
| 276 | portsync_master_mask & joiner_secondaries_mask || | 
|---|
| 277 | portsync_slaves_mask & joiner_secondaries_mask); | 
|---|
| 278 |  | 
|---|
| 279 | for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, joiner_secondaries_mask) | 
|---|
| 280 | intel_crtc_disable_noatomic_begin(crtc: temp_crtc, ctx); | 
|---|
| 281 |  | 
|---|
| 282 | for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_slaves_mask) | 
|---|
| 283 | intel_crtc_disable_noatomic_begin(crtc: temp_crtc, ctx); | 
|---|
| 284 |  | 
|---|
| 285 | for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, portsync_master_mask) | 
|---|
| 286 | intel_crtc_disable_noatomic_begin(crtc: temp_crtc, ctx); | 
|---|
| 287 |  | 
|---|
| 288 | for_each_intel_crtc_in_pipe_mask(display->drm, temp_crtc, | 
|---|
| 289 | joiner_secondaries_mask | | 
|---|
| 290 | portsync_slaves_mask | | 
|---|
| 291 | portsync_master_mask) | 
|---|
| 292 | intel_crtc_disable_noatomic_complete(crtc: temp_crtc); | 
|---|
| 293 | } | 
|---|
| 294 |  | 
|---|
| 295 | static void intel_modeset_update_connector_atomic_state(struct intel_display *display) | 
|---|
| 296 | { | 
|---|
| 297 | struct intel_connector *connector; | 
|---|
| 298 | struct drm_connector_list_iter conn_iter; | 
|---|
| 299 |  | 
|---|
| 300 | drm_connector_list_iter_begin(dev: display->drm, iter: &conn_iter); | 
|---|
| 301 | for_each_intel_connector_iter(connector, &conn_iter) { | 
|---|
| 302 | struct drm_connector_state *conn_state = connector->base.state; | 
|---|
| 303 | struct intel_encoder *encoder = | 
|---|
| 304 | to_intel_encoder(connector->base.encoder); | 
|---|
| 305 |  | 
|---|
| 306 | set_encoder_for_connector(connector, encoder); | 
|---|
| 307 |  | 
|---|
| 308 | if (encoder) { | 
|---|
| 309 | struct intel_crtc *crtc = | 
|---|
| 310 | to_intel_crtc(encoder->base.crtc); | 
|---|
| 311 | const struct intel_crtc_state *crtc_state = | 
|---|
| 312 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 313 |  | 
|---|
| 314 | conn_state->max_bpc = (crtc_state->pipe_bpp ?: 24) / 3; | 
|---|
| 315 | } | 
|---|
| 316 | } | 
|---|
| 317 | drm_connector_list_iter_end(iter: &conn_iter); | 
|---|
| 318 | } | 
|---|
| 319 |  | 
|---|
| 320 | static void intel_crtc_copy_hw_to_uapi_state(struct intel_crtc_state *crtc_state) | 
|---|
| 321 | { | 
|---|
| 322 | struct intel_display *display = to_intel_display(crtc_state); | 
|---|
| 323 |  | 
|---|
| 324 | if (intel_crtc_is_joiner_secondary(crtc_state)) | 
|---|
| 325 | return; | 
|---|
| 326 |  | 
|---|
| 327 | crtc_state->uapi.enable = crtc_state->hw.enable; | 
|---|
| 328 | crtc_state->uapi.active = crtc_state->hw.active; | 
|---|
| 329 | drm_WARN_ON(crtc_state->uapi.crtc->dev, | 
|---|
| 330 | drm_atomic_set_mode_for_crtc(&crtc_state->uapi, &crtc_state->hw.mode) < 0); | 
|---|
| 331 |  | 
|---|
| 332 | crtc_state->uapi.adjusted_mode = crtc_state->hw.adjusted_mode; | 
|---|
| 333 | crtc_state->uapi.scaling_filter = crtc_state->hw.scaling_filter; | 
|---|
| 334 |  | 
|---|
| 335 | if (DISPLAY_INFO(display)->color.degamma_lut_size) { | 
|---|
| 336 | /* assume 1:1 mapping */ | 
|---|
| 337 | drm_property_replace_blob(blob: &crtc_state->hw.degamma_lut, | 
|---|
| 338 | new_blob: crtc_state->pre_csc_lut); | 
|---|
| 339 | drm_property_replace_blob(blob: &crtc_state->hw.gamma_lut, | 
|---|
| 340 | new_blob: crtc_state->post_csc_lut); | 
|---|
| 341 | } else { | 
|---|
| 342 | /* | 
|---|
| 343 | * ilk/snb hw may be configured for either pre_csc_lut | 
|---|
| 344 | * or post_csc_lut, but we don't advertise degamma_lut as | 
|---|
| 345 | * being available in the uapi since there is only one | 
|---|
| 346 | * hardware LUT. Always assign the result of the readout | 
|---|
| 347 | * to gamma_lut as that is the only valid source of LUTs | 
|---|
| 348 | * in the uapi. | 
|---|
| 349 | */ | 
|---|
| 350 | drm_WARN_ON(display->drm, crtc_state->post_csc_lut && | 
|---|
| 351 | crtc_state->pre_csc_lut); | 
|---|
| 352 |  | 
|---|
| 353 | drm_property_replace_blob(blob: &crtc_state->hw.degamma_lut, | 
|---|
| 354 | NULL); | 
|---|
| 355 | drm_property_replace_blob(blob: &crtc_state->hw.gamma_lut, | 
|---|
| 356 | new_blob: crtc_state->post_csc_lut ?: | 
|---|
| 357 | crtc_state->pre_csc_lut); | 
|---|
| 358 | } | 
|---|
| 359 |  | 
|---|
| 360 | drm_property_replace_blob(blob: &crtc_state->uapi.degamma_lut, | 
|---|
| 361 | new_blob: crtc_state->hw.degamma_lut); | 
|---|
| 362 | drm_property_replace_blob(blob: &crtc_state->uapi.gamma_lut, | 
|---|
| 363 | new_blob: crtc_state->hw.gamma_lut); | 
|---|
| 364 | drm_property_replace_blob(blob: &crtc_state->uapi.ctm, | 
|---|
| 365 | new_blob: crtc_state->hw.ctm); | 
|---|
| 366 | } | 
|---|
| 367 |  | 
|---|
| 368 | static void | 
|---|
| 369 | intel_sanitize_plane_mapping(struct intel_display *display) | 
|---|
| 370 | { | 
|---|
| 371 | struct intel_crtc *crtc; | 
|---|
| 372 |  | 
|---|
| 373 | if (DISPLAY_VER(display) >= 4) | 
|---|
| 374 | return; | 
|---|
| 375 |  | 
|---|
| 376 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 377 | struct intel_plane *plane = | 
|---|
| 378 | to_intel_plane(crtc->base.primary); | 
|---|
| 379 | struct intel_crtc *plane_crtc; | 
|---|
| 380 | enum pipe pipe; | 
|---|
| 381 |  | 
|---|
| 382 | if (!plane->get_hw_state(plane, &pipe)) | 
|---|
| 383 | continue; | 
|---|
| 384 |  | 
|---|
| 385 | if (pipe == crtc->pipe) | 
|---|
| 386 | continue; | 
|---|
| 387 |  | 
|---|
| 388 | drm_dbg_kms(display->drm, | 
|---|
| 389 | "[PLANE:%d:%s] attached to the wrong pipe, disabling plane\n", | 
|---|
| 390 | plane->base.base.id, plane->base.name); | 
|---|
| 391 |  | 
|---|
| 392 | plane_crtc = intel_crtc_for_pipe(display, pipe); | 
|---|
| 393 | intel_plane_disable_noatomic(crtc: plane_crtc, plane); | 
|---|
| 394 | } | 
|---|
| 395 | } | 
|---|
| 396 |  | 
|---|
| 397 | static bool intel_crtc_has_encoders(struct intel_crtc *crtc) | 
|---|
| 398 | { | 
|---|
| 399 | struct drm_device *dev = crtc->base.dev; | 
|---|
| 400 | struct intel_encoder *encoder; | 
|---|
| 401 |  | 
|---|
| 402 | for_each_encoder_on_crtc(dev, &crtc->base, encoder) | 
|---|
| 403 | return true; | 
|---|
| 404 |  | 
|---|
| 405 | return false; | 
|---|
| 406 | } | 
|---|
| 407 |  | 
|---|
| 408 | static bool intel_crtc_needs_link_reset(struct intel_crtc *crtc) | 
|---|
| 409 | { | 
|---|
| 410 | struct drm_device *dev = crtc->base.dev; | 
|---|
| 411 | struct intel_encoder *encoder; | 
|---|
| 412 |  | 
|---|
| 413 | for_each_encoder_on_crtc(dev, &crtc->base, encoder) { | 
|---|
| 414 | struct intel_digital_port *dig_port = enc_to_dig_port(encoder); | 
|---|
| 415 |  | 
|---|
| 416 | if (dig_port && intel_tc_port_link_needs_reset(dig_port)) | 
|---|
| 417 | return true; | 
|---|
| 418 | } | 
|---|
| 419 |  | 
|---|
| 420 | return false; | 
|---|
| 421 | } | 
|---|
| 422 |  | 
|---|
| 423 | static struct intel_connector *intel_encoder_find_connector(struct intel_encoder *encoder) | 
|---|
| 424 | { | 
|---|
| 425 | struct intel_display *display = to_intel_display(encoder); | 
|---|
| 426 | struct drm_connector_list_iter conn_iter; | 
|---|
| 427 | struct intel_connector *connector; | 
|---|
| 428 | struct intel_connector *found_connector = NULL; | 
|---|
| 429 |  | 
|---|
| 430 | drm_connector_list_iter_begin(dev: display->drm, iter: &conn_iter); | 
|---|
| 431 | for_each_intel_connector_iter(connector, &conn_iter) { | 
|---|
| 432 | if (&encoder->base == connector->base.encoder) { | 
|---|
| 433 | found_connector = connector; | 
|---|
| 434 | break; | 
|---|
| 435 | } | 
|---|
| 436 | } | 
|---|
| 437 | drm_connector_list_iter_end(iter: &conn_iter); | 
|---|
| 438 |  | 
|---|
| 439 | return found_connector; | 
|---|
| 440 | } | 
|---|
| 441 |  | 
|---|
| 442 | static void intel_sanitize_fifo_underrun_reporting(const struct intel_crtc_state *crtc_state) | 
|---|
| 443 | { | 
|---|
| 444 | struct intel_display *display = to_intel_display(crtc_state); | 
|---|
| 445 | struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); | 
|---|
| 446 |  | 
|---|
| 447 | /* | 
|---|
| 448 | * We start out with underrun reporting disabled on active | 
|---|
| 449 | * pipes to avoid races. | 
|---|
| 450 | * | 
|---|
| 451 | * Also on gmch platforms we dont have any hardware bits to | 
|---|
| 452 | * disable the underrun reporting. Which means we need to start | 
|---|
| 453 | * out with underrun reporting disabled also on inactive pipes, | 
|---|
| 454 | * since otherwise we'll complain about the garbage we read when | 
|---|
| 455 | * e.g. coming up after runtime pm. | 
|---|
| 456 | * | 
|---|
| 457 | * No protection against concurrent access is required - at | 
|---|
| 458 | * worst a fifo underrun happens which also sets this to false. | 
|---|
| 459 | */ | 
|---|
| 460 | intel_init_fifo_underrun_reporting(display, crtc, | 
|---|
| 461 | enable: !crtc_state->hw.active && | 
|---|
| 462 | !HAS_GMCH(display)); | 
|---|
| 463 | } | 
|---|
| 464 |  | 
|---|
| 465 | static bool intel_sanitize_crtc(struct intel_crtc *crtc, | 
|---|
| 466 | struct drm_modeset_acquire_ctx *ctx) | 
|---|
| 467 | { | 
|---|
| 468 | struct intel_display *display = to_intel_display(crtc); | 
|---|
| 469 | struct intel_crtc_state *crtc_state = to_intel_crtc_state(crtc->base.state); | 
|---|
| 470 | bool needs_link_reset; | 
|---|
| 471 |  | 
|---|
| 472 | if (crtc_state->hw.active) { | 
|---|
| 473 | struct intel_plane *plane; | 
|---|
| 474 |  | 
|---|
| 475 | /* Disable everything but the primary plane */ | 
|---|
| 476 | for_each_intel_plane_on_crtc(display->drm, crtc, plane) { | 
|---|
| 477 | const struct intel_plane_state *plane_state = | 
|---|
| 478 | to_intel_plane_state(plane->base.state); | 
|---|
| 479 |  | 
|---|
| 480 | if (plane_state->uapi.visible && | 
|---|
| 481 | plane->base.type != DRM_PLANE_TYPE_PRIMARY) | 
|---|
| 482 | intel_plane_disable_noatomic(crtc, plane); | 
|---|
| 483 | } | 
|---|
| 484 |  | 
|---|
| 485 | /* Disable any background color/etc. set by the BIOS */ | 
|---|
| 486 | intel_color_commit_noarm(NULL, crtc_state); | 
|---|
| 487 | intel_color_commit_arm(NULL, crtc_state); | 
|---|
| 488 | } | 
|---|
| 489 |  | 
|---|
| 490 | if (!crtc_state->hw.active || | 
|---|
| 491 | intel_crtc_is_joiner_secondary(crtc_state)) | 
|---|
| 492 | return false; | 
|---|
| 493 |  | 
|---|
| 494 | needs_link_reset = intel_crtc_needs_link_reset(crtc); | 
|---|
| 495 |  | 
|---|
| 496 | /* | 
|---|
| 497 | * Adjust the state of the output pipe according to whether we have | 
|---|
| 498 | * active connectors/encoders. | 
|---|
| 499 | */ | 
|---|
| 500 | if (!needs_link_reset && intel_crtc_has_encoders(crtc)) | 
|---|
| 501 | return false; | 
|---|
| 502 |  | 
|---|
| 503 | intel_crtc_disable_noatomic(crtc, ctx); | 
|---|
| 504 |  | 
|---|
| 505 | /* | 
|---|
| 506 | * The HPD state on other active/disconnected TC ports may be stuck in | 
|---|
| 507 | * the connected state until this port is disabled and a ~10ms delay has | 
|---|
| 508 | * passed, wait here for that so that sanitizing other CRTCs will see the | 
|---|
| 509 | * up-to-date HPD state. | 
|---|
| 510 | */ | 
|---|
| 511 | if (needs_link_reset) | 
|---|
| 512 | msleep(msecs: 20); | 
|---|
| 513 |  | 
|---|
| 514 | return true; | 
|---|
| 515 | } | 
|---|
| 516 |  | 
|---|
| 517 | static void intel_sanitize_all_crtcs(struct intel_display *display, | 
|---|
| 518 | struct drm_modeset_acquire_ctx *ctx) | 
|---|
| 519 | { | 
|---|
| 520 | struct intel_crtc *crtc; | 
|---|
| 521 | u32 crtcs_forced_off = 0; | 
|---|
| 522 |  | 
|---|
| 523 | /* | 
|---|
| 524 | * An active and disconnected TypeC port prevents the HPD live state | 
|---|
| 525 | * to get updated on other active/disconnected TypeC ports, so after | 
|---|
| 526 | * a port gets disabled the CRTCs using other TypeC ports must be | 
|---|
| 527 | * rechecked wrt. their link status. | 
|---|
| 528 | */ | 
|---|
| 529 | for (;;) { | 
|---|
| 530 | u32 old_mask = crtcs_forced_off; | 
|---|
| 531 |  | 
|---|
| 532 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 533 | u32 crtc_mask = drm_crtc_mask(crtc: &crtc->base); | 
|---|
| 534 |  | 
|---|
| 535 | if (crtcs_forced_off & crtc_mask) | 
|---|
| 536 | continue; | 
|---|
| 537 |  | 
|---|
| 538 | if (intel_sanitize_crtc(crtc, ctx)) | 
|---|
| 539 | crtcs_forced_off |= crtc_mask; | 
|---|
| 540 | } | 
|---|
| 541 | if (crtcs_forced_off == old_mask) | 
|---|
| 542 | break; | 
|---|
| 543 | } | 
|---|
| 544 |  | 
|---|
| 545 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 546 | struct intel_crtc_state *crtc_state = | 
|---|
| 547 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 548 |  | 
|---|
| 549 | intel_crtc_state_dump(crtc_state, NULL, context: "setup_hw_state"); | 
|---|
| 550 | } | 
|---|
| 551 | } | 
|---|
| 552 |  | 
|---|
| 553 | static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state) | 
|---|
| 554 | { | 
|---|
| 555 | struct intel_display *display = to_intel_display(crtc_state); | 
|---|
| 556 |  | 
|---|
| 557 | /* | 
|---|
| 558 | * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram | 
|---|
| 559 | * the hardware when a high res displays plugged in. DPLL P | 
|---|
| 560 | * divider is zero, and the pipe timings are bonkers. We'll | 
|---|
| 561 | * try to disable everything in that case. | 
|---|
| 562 | * | 
|---|
| 563 | * FIXME would be nice to be able to sanitize this state | 
|---|
| 564 | * without several WARNs, but for now let's take the easy | 
|---|
| 565 | * road. | 
|---|
| 566 | */ | 
|---|
| 567 | return display->platform.sandybridge && | 
|---|
| 568 | crtc_state->hw.active && | 
|---|
| 569 | crtc_state->intel_dpll && | 
|---|
| 570 | crtc_state->port_clock == 0; | 
|---|
| 571 | } | 
|---|
| 572 |  | 
|---|
| 573 | static void intel_sanitize_encoder(struct intel_encoder *encoder) | 
|---|
| 574 | { | 
|---|
| 575 | struct intel_display *display = to_intel_display(encoder); | 
|---|
| 576 | struct intel_connector *connector; | 
|---|
| 577 | struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc); | 
|---|
| 578 | struct intel_crtc_state *crtc_state = crtc ? | 
|---|
| 579 | to_intel_crtc_state(crtc->base.state) : NULL; | 
|---|
| 580 | struct intel_pmdemand_state *pmdemand_state = | 
|---|
| 581 | to_intel_pmdemand_state(obj_state: display->pmdemand.obj.state); | 
|---|
| 582 |  | 
|---|
| 583 | /* | 
|---|
| 584 | * We need to check both for a crtc link (meaning that the encoder is | 
|---|
| 585 | * active and trying to read from a pipe) and the pipe itself being | 
|---|
| 586 | * active. | 
|---|
| 587 | */ | 
|---|
| 588 | bool has_active_crtc = crtc_state && | 
|---|
| 589 | crtc_state->hw.active; | 
|---|
| 590 |  | 
|---|
| 591 | if (crtc_state && has_bogus_dpll_config(crtc_state)) { | 
|---|
| 592 | drm_dbg_kms(display->drm, | 
|---|
| 593 | "BIOS has misprogrammed the hardware. Disabling pipe %c\n", | 
|---|
| 594 | pipe_name(crtc->pipe)); | 
|---|
| 595 | has_active_crtc = false; | 
|---|
| 596 | } | 
|---|
| 597 |  | 
|---|
| 598 | connector = intel_encoder_find_connector(encoder); | 
|---|
| 599 | if (connector && !has_active_crtc) { | 
|---|
| 600 | drm_dbg_kms(display->drm, | 
|---|
| 601 | "[ENCODER:%d:%s] has active connectors but no active pipe!\n", | 
|---|
| 602 | encoder->base.base.id, | 
|---|
| 603 | encoder->base.name); | 
|---|
| 604 |  | 
|---|
| 605 | /* Clear the corresponding bit in pmdemand active phys mask */ | 
|---|
| 606 | intel_pmdemand_update_phys_mask(display, encoder, | 
|---|
| 607 | pmdemand_state, clear_bit: false); | 
|---|
| 608 |  | 
|---|
| 609 | /* | 
|---|
| 610 | * Connector is active, but has no active pipe. This is fallout | 
|---|
| 611 | * from our resume register restoring. Disable the encoder | 
|---|
| 612 | * manually again. | 
|---|
| 613 | */ | 
|---|
| 614 | if (crtc_state) { | 
|---|
| 615 | struct drm_encoder *best_encoder; | 
|---|
| 616 |  | 
|---|
| 617 | drm_dbg_kms(display->drm, | 
|---|
| 618 | "[ENCODER:%d:%s] manually disabled\n", | 
|---|
| 619 | encoder->base.base.id, | 
|---|
| 620 | encoder->base.name); | 
|---|
| 621 |  | 
|---|
| 622 | /* avoid oopsing in case the hooks consult best_encoder */ | 
|---|
| 623 | best_encoder = connector->base.state->best_encoder; | 
|---|
| 624 | connector->base.state->best_encoder = &encoder->base; | 
|---|
| 625 |  | 
|---|
| 626 | /* FIXME NULL atomic state passed! */ | 
|---|
| 627 | if (encoder->disable) | 
|---|
| 628 | encoder->disable(NULL, encoder, crtc_state, | 
|---|
| 629 | connector->base.state); | 
|---|
| 630 | if (encoder->post_disable) | 
|---|
| 631 | encoder->post_disable(NULL, encoder, crtc_state, | 
|---|
| 632 | connector->base.state); | 
|---|
| 633 |  | 
|---|
| 634 | connector->base.state->best_encoder = best_encoder; | 
|---|
| 635 | } | 
|---|
| 636 | encoder->base.crtc = NULL; | 
|---|
| 637 |  | 
|---|
| 638 | /* | 
|---|
| 639 | * Inconsistent output/port/pipe state happens presumably due to | 
|---|
| 640 | * a bug in one of the get_hw_state functions. Or someplace else | 
|---|
| 641 | * in our code, like the register restore mess on resume. Clamp | 
|---|
| 642 | * things to off as a safer default. | 
|---|
| 643 | */ | 
|---|
| 644 | connector->base.dpms = DRM_MODE_DPMS_OFF; | 
|---|
| 645 | connector->base.encoder = NULL; | 
|---|
| 646 | } | 
|---|
| 647 |  | 
|---|
| 648 | /* notify opregion of the sanitized encoder state */ | 
|---|
| 649 | intel_opregion_notify_encoder(encoder, enable: connector && has_active_crtc); | 
|---|
| 650 |  | 
|---|
| 651 | if (HAS_DDI(display)) | 
|---|
| 652 | intel_ddi_sanitize_encoder_pll_mapping(encoder); | 
|---|
| 653 | } | 
|---|
| 654 |  | 
|---|
| 655 | /* FIXME read out full plane state for all planes */ | 
|---|
| 656 | static void readout_plane_state(struct intel_display *display) | 
|---|
| 657 | { | 
|---|
| 658 | struct intel_plane *plane; | 
|---|
| 659 | struct intel_crtc *crtc; | 
|---|
| 660 |  | 
|---|
| 661 | for_each_intel_plane(display->drm, plane) { | 
|---|
| 662 | struct intel_plane_state *plane_state = | 
|---|
| 663 | to_intel_plane_state(plane->base.state); | 
|---|
| 664 | struct intel_crtc_state *crtc_state; | 
|---|
| 665 | enum pipe pipe = PIPE_A; | 
|---|
| 666 | bool visible; | 
|---|
| 667 |  | 
|---|
| 668 | visible = plane->get_hw_state(plane, &pipe); | 
|---|
| 669 |  | 
|---|
| 670 | crtc = intel_crtc_for_pipe(display, pipe); | 
|---|
| 671 | crtc_state = to_intel_crtc_state(crtc->base.state); | 
|---|
| 672 |  | 
|---|
| 673 | intel_set_plane_visible(crtc_state, plane_state, visible); | 
|---|
| 674 |  | 
|---|
| 675 | drm_dbg_kms(display->drm, | 
|---|
| 676 | "[PLANE:%d:%s] hw state readout: %s, pipe %c\n", | 
|---|
| 677 | plane->base.base.id, plane->base.name, | 
|---|
| 678 | str_enabled_disabled(visible), pipe_name(pipe)); | 
|---|
| 679 | } | 
|---|
| 680 |  | 
|---|
| 681 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 682 | struct intel_crtc_state *crtc_state = | 
|---|
| 683 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 684 |  | 
|---|
| 685 | intel_plane_fixup_bitmasks(crtc_state); | 
|---|
| 686 | } | 
|---|
| 687 | } | 
|---|
| 688 |  | 
|---|
| 689 | static void intel_modeset_readout_hw_state(struct intel_display *display) | 
|---|
| 690 | { | 
|---|
| 691 | struct intel_pmdemand_state *pmdemand_state = | 
|---|
| 692 | to_intel_pmdemand_state(obj_state: display->pmdemand.obj.state); | 
|---|
| 693 | enum pipe pipe; | 
|---|
| 694 | struct intel_crtc *crtc; | 
|---|
| 695 | struct intel_encoder *encoder; | 
|---|
| 696 | struct intel_connector *connector; | 
|---|
| 697 | struct drm_connector_list_iter conn_iter; | 
|---|
| 698 |  | 
|---|
| 699 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 700 | struct intel_crtc_state *crtc_state = | 
|---|
| 701 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 702 |  | 
|---|
| 703 | __drm_atomic_helper_crtc_destroy_state(state: &crtc_state->uapi); | 
|---|
| 704 | intel_crtc_free_hw_state(crtc_state); | 
|---|
| 705 | intel_crtc_state_reset(crtc_state, crtc); | 
|---|
| 706 |  | 
|---|
| 707 | intel_crtc_get_pipe_config(crtc_state); | 
|---|
| 708 |  | 
|---|
| 709 | crtc_state->hw.enable = crtc_state->hw.active; | 
|---|
| 710 |  | 
|---|
| 711 | crtc->base.enabled = crtc_state->hw.enable; | 
|---|
| 712 | crtc->active = crtc_state->hw.active; | 
|---|
| 713 |  | 
|---|
| 714 | drm_dbg_kms(display->drm, | 
|---|
| 715 | "[CRTC:%d:%s] hw state readout: %s\n", | 
|---|
| 716 | crtc->base.base.id, crtc->base.name, | 
|---|
| 717 | str_enabled_disabled(crtc_state->hw.active)); | 
|---|
| 718 | } | 
|---|
| 719 |  | 
|---|
| 720 | readout_plane_state(display); | 
|---|
| 721 |  | 
|---|
| 722 | for_each_intel_encoder(display->drm, encoder) { | 
|---|
| 723 | struct intel_crtc_state *crtc_state = NULL; | 
|---|
| 724 |  | 
|---|
| 725 | pipe = 0; | 
|---|
| 726 |  | 
|---|
| 727 | if (encoder->get_hw_state(encoder, &pipe)) { | 
|---|
| 728 | crtc = intel_crtc_for_pipe(display, pipe); | 
|---|
| 729 | crtc_state = to_intel_crtc_state(crtc->base.state); | 
|---|
| 730 |  | 
|---|
| 731 | encoder->base.crtc = &crtc->base; | 
|---|
| 732 | intel_encoder_get_config(encoder, crtc_state); | 
|---|
| 733 |  | 
|---|
| 734 | /* read out to secondary crtc as well for joiner */ | 
|---|
| 735 | if (crtc_state->joiner_pipes) { | 
|---|
| 736 | struct intel_crtc *secondary_crtc; | 
|---|
| 737 |  | 
|---|
| 738 | /* encoder should read be linked to joiner primary */ | 
|---|
| 739 | WARN_ON(intel_crtc_is_joiner_secondary(crtc_state)); | 
|---|
| 740 |  | 
|---|
| 741 | for_each_intel_crtc_in_pipe_mask(display->drm, secondary_crtc, | 
|---|
| 742 | intel_crtc_joiner_secondary_pipes(crtc_state)) { | 
|---|
| 743 | struct intel_crtc_state *secondary_crtc_state; | 
|---|
| 744 |  | 
|---|
| 745 | secondary_crtc_state = to_intel_crtc_state(secondary_crtc->base.state); | 
|---|
| 746 | intel_encoder_get_config(encoder, crtc_state: secondary_crtc_state); | 
|---|
| 747 | } | 
|---|
| 748 | } | 
|---|
| 749 |  | 
|---|
| 750 | intel_pmdemand_update_phys_mask(display, encoder, | 
|---|
| 751 | pmdemand_state, | 
|---|
| 752 | clear_bit: true); | 
|---|
| 753 | } else { | 
|---|
| 754 | intel_pmdemand_update_phys_mask(display, encoder, | 
|---|
| 755 | pmdemand_state, | 
|---|
| 756 | clear_bit: false); | 
|---|
| 757 |  | 
|---|
| 758 | encoder->base.crtc = NULL; | 
|---|
| 759 | } | 
|---|
| 760 |  | 
|---|
| 761 | if (encoder->sync_state) | 
|---|
| 762 | encoder->sync_state(encoder, crtc_state); | 
|---|
| 763 |  | 
|---|
| 764 | drm_dbg_kms(display->drm, | 
|---|
| 765 | "[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", | 
|---|
| 766 | encoder->base.base.id, encoder->base.name, | 
|---|
| 767 | str_enabled_disabled(encoder->base.crtc), | 
|---|
| 768 | pipe_name(pipe)); | 
|---|
| 769 | } | 
|---|
| 770 |  | 
|---|
| 771 | intel_dpll_readout_hw_state(display); | 
|---|
| 772 |  | 
|---|
| 773 | drm_connector_list_iter_begin(dev: display->drm, iter: &conn_iter); | 
|---|
| 774 | for_each_intel_connector_iter(connector, &conn_iter) { | 
|---|
| 775 | struct intel_crtc_state *crtc_state = NULL; | 
|---|
| 776 |  | 
|---|
| 777 | if (connector->get_hw_state(connector)) { | 
|---|
| 778 | struct intel_crtc *crtc; | 
|---|
| 779 |  | 
|---|
| 780 | connector->base.dpms = DRM_MODE_DPMS_ON; | 
|---|
| 781 |  | 
|---|
| 782 | encoder = intel_attached_encoder(connector); | 
|---|
| 783 | connector->base.encoder = &encoder->base; | 
|---|
| 784 |  | 
|---|
| 785 | crtc = to_intel_crtc(encoder->base.crtc); | 
|---|
| 786 | crtc_state = crtc ? to_intel_crtc_state(crtc->base.state) : NULL; | 
|---|
| 787 |  | 
|---|
| 788 | if (crtc_state && crtc_state->hw.active) { | 
|---|
| 789 | /* | 
|---|
| 790 | * This has to be done during hardware readout | 
|---|
| 791 | * because anything calling .crtc_disable may | 
|---|
| 792 | * rely on the connector_mask being accurate. | 
|---|
| 793 | */ | 
|---|
| 794 | crtc_state->uapi.connector_mask |= | 
|---|
| 795 | drm_connector_mask(connector: &connector->base); | 
|---|
| 796 | crtc_state->uapi.encoder_mask |= | 
|---|
| 797 | drm_encoder_mask(encoder: &encoder->base); | 
|---|
| 798 | } | 
|---|
| 799 | } else { | 
|---|
| 800 | connector->base.dpms = DRM_MODE_DPMS_OFF; | 
|---|
| 801 | connector->base.encoder = NULL; | 
|---|
| 802 | } | 
|---|
| 803 |  | 
|---|
| 804 | if (connector->sync_state) | 
|---|
| 805 | connector->sync_state(connector, crtc_state); | 
|---|
| 806 |  | 
|---|
| 807 | drm_dbg_kms(display->drm, | 
|---|
| 808 | "[CONNECTOR:%d:%s] hw state readout: %s\n", | 
|---|
| 809 | connector->base.base.id, connector->base.name, | 
|---|
| 810 | str_enabled_disabled(connector->base.encoder)); | 
|---|
| 811 | } | 
|---|
| 812 | drm_connector_list_iter_end(iter: &conn_iter); | 
|---|
| 813 |  | 
|---|
| 814 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 815 | struct intel_crtc_state *crtc_state = | 
|---|
| 816 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 817 | struct intel_plane *plane; | 
|---|
| 818 |  | 
|---|
| 819 | /* | 
|---|
| 820 | * The initial mode needs to be set in order to keep | 
|---|
| 821 | * the atomic core happy. It wants a valid mode if the | 
|---|
| 822 | * crtc's enabled, so we do the above call. | 
|---|
| 823 | * | 
|---|
| 824 | * But we don't set all the derived state fully, hence | 
|---|
| 825 | * set a flag to indicate that a full recalculation is | 
|---|
| 826 | * needed on the next commit. | 
|---|
| 827 | */ | 
|---|
| 828 | crtc_state->inherited = true; | 
|---|
| 829 |  | 
|---|
| 830 | if (crtc_state->hw.active) { | 
|---|
| 831 | intel_crtc_update_active_timings(crtc_state, | 
|---|
| 832 | vrr_enable: crtc_state->vrr.enable); | 
|---|
| 833 |  | 
|---|
| 834 | intel_crtc_copy_hw_to_uapi_state(crtc_state); | 
|---|
| 835 | } | 
|---|
| 836 |  | 
|---|
| 837 | for_each_intel_plane_on_crtc(display->drm, crtc, plane) { | 
|---|
| 838 | const struct intel_plane_state *plane_state = | 
|---|
| 839 | to_intel_plane_state(plane->base.state); | 
|---|
| 840 |  | 
|---|
| 841 | /* | 
|---|
| 842 | * FIXME don't have the fb yet, so can't | 
|---|
| 843 | * use intel_plane_data_rate() :( | 
|---|
| 844 | */ | 
|---|
| 845 | if (plane_state->uapi.visible) | 
|---|
| 846 | crtc_state->data_rate[plane->id] = | 
|---|
| 847 | 4 * crtc_state->pixel_rate; | 
|---|
| 848 | /* | 
|---|
| 849 | * FIXME don't have the fb yet, so can't | 
|---|
| 850 | * use plane->min_cdclk() :( | 
|---|
| 851 | */ | 
|---|
| 852 | if (plane_state->uapi.visible && plane->min_cdclk) { | 
|---|
| 853 | if (crtc_state->double_wide || DISPLAY_VER(display) >= 10) | 
|---|
| 854 | crtc_state->min_cdclk[plane->id] = | 
|---|
| 855 | DIV_ROUND_UP(crtc_state->pixel_rate, 2); | 
|---|
| 856 | else | 
|---|
| 857 | crtc_state->min_cdclk[plane->id] = | 
|---|
| 858 | crtc_state->pixel_rate; | 
|---|
| 859 | } | 
|---|
| 860 | drm_dbg_kms(display->drm, | 
|---|
| 861 | "[PLANE:%d:%s] min_cdclk %d kHz\n", | 
|---|
| 862 | plane->base.base.id, plane->base.name, | 
|---|
| 863 | crtc_state->min_cdclk[plane->id]); | 
|---|
| 864 | } | 
|---|
| 865 |  | 
|---|
| 866 | intel_pmdemand_update_port_clock(display, pmdemand_state, pipe, | 
|---|
| 867 | port_clock: crtc_state->port_clock); | 
|---|
| 868 | } | 
|---|
| 869 |  | 
|---|
| 870 | /* TODO move here (or even earlier?) on all platforms */ | 
|---|
| 871 | if (DISPLAY_VER(display) >= 9) | 
|---|
| 872 | intel_wm_get_hw_state(display); | 
|---|
| 873 |  | 
|---|
| 874 | intel_bw_update_hw_state(display); | 
|---|
| 875 | intel_cdclk_update_hw_state(display); | 
|---|
| 876 |  | 
|---|
| 877 | intel_pmdemand_init_pmdemand_params(display, pmdemand_state); | 
|---|
| 878 | } | 
|---|
| 879 |  | 
|---|
| 880 | static void | 
|---|
| 881 | get_encoder_power_domains(struct intel_display *display) | 
|---|
| 882 | { | 
|---|
| 883 | struct intel_encoder *encoder; | 
|---|
| 884 |  | 
|---|
| 885 | for_each_intel_encoder(display->drm, encoder) { | 
|---|
| 886 | struct intel_crtc_state *crtc_state; | 
|---|
| 887 |  | 
|---|
| 888 | if (!encoder->get_power_domains) | 
|---|
| 889 | continue; | 
|---|
| 890 |  | 
|---|
| 891 | /* | 
|---|
| 892 | * MST-primary and inactive encoders don't have a crtc state | 
|---|
| 893 | * and neither of these require any power domain references. | 
|---|
| 894 | */ | 
|---|
| 895 | if (!encoder->base.crtc) | 
|---|
| 896 | continue; | 
|---|
| 897 |  | 
|---|
| 898 | crtc_state = to_intel_crtc_state(encoder->base.crtc->state); | 
|---|
| 899 | encoder->get_power_domains(encoder, crtc_state); | 
|---|
| 900 | } | 
|---|
| 901 | } | 
|---|
| 902 |  | 
|---|
| 903 | static void intel_early_display_was(struct intel_display *display) | 
|---|
| 904 | { | 
|---|
| 905 | /* | 
|---|
| 906 | * Display WA #1185 WaDisableDARBFClkGating:glk,icl,ehl,tgl | 
|---|
| 907 | * Also known as Wa_14010480278. | 
|---|
| 908 | */ | 
|---|
| 909 | if (IS_DISPLAY_VER(display, 10, 12)) | 
|---|
| 910 | intel_de_rmw(display, GEN9_CLKGATE_DIS_0, clear: 0, DARBF_GATING_DIS); | 
|---|
| 911 |  | 
|---|
| 912 | /* | 
|---|
| 913 | * WaRsPkgCStateDisplayPMReq:hsw | 
|---|
| 914 | * System hang if this isn't done before disabling all planes! | 
|---|
| 915 | */ | 
|---|
| 916 | if (display->platform.haswell) | 
|---|
| 917 | intel_de_rmw(display, CHICKEN_PAR1_1, clear: 0, FORCE_ARB_IDLE_PLANES); | 
|---|
| 918 |  | 
|---|
| 919 | if (display->platform.kabylake || display->platform.coffeelake || | 
|---|
| 920 | display->platform.cometlake) { | 
|---|
| 921 | /* Display WA #1142:kbl,cfl,cml */ | 
|---|
| 922 | intel_de_rmw(display, CHICKEN_PAR1_1, | 
|---|
| 923 | KBL_ARB_FILL_SPARE_22, KBL_ARB_FILL_SPARE_22); | 
|---|
| 924 | intel_de_rmw(display, CHICKEN_MISC_2, | 
|---|
| 925 | KBL_ARB_FILL_SPARE_13 | KBL_ARB_FILL_SPARE_14, | 
|---|
| 926 | KBL_ARB_FILL_SPARE_14); | 
|---|
| 927 | } | 
|---|
| 928 | } | 
|---|
| 929 |  | 
|---|
| 930 | void intel_modeset_setup_hw_state(struct intel_display *display, | 
|---|
| 931 | struct drm_modeset_acquire_ctx *ctx) | 
|---|
| 932 | { | 
|---|
| 933 | struct intel_encoder *encoder; | 
|---|
| 934 | struct intel_crtc *crtc; | 
|---|
| 935 | intel_wakeref_t wakeref; | 
|---|
| 936 |  | 
|---|
| 937 | wakeref = intel_display_power_get(display, domain: POWER_DOMAIN_INIT); | 
|---|
| 938 |  | 
|---|
| 939 | intel_early_display_was(display); | 
|---|
| 940 | intel_vga_disable(display); | 
|---|
| 941 |  | 
|---|
| 942 | intel_modeset_readout_hw_state(display); | 
|---|
| 943 |  | 
|---|
| 944 | /* HW state is read out, now we need to sanitize this mess. */ | 
|---|
| 945 | get_encoder_power_domains(display); | 
|---|
| 946 |  | 
|---|
| 947 | intel_pch_sanitize(display); | 
|---|
| 948 |  | 
|---|
| 949 | intel_cmtg_sanitize(display); | 
|---|
| 950 |  | 
|---|
| 951 | /* | 
|---|
| 952 | * intel_sanitize_plane_mapping() may need to do vblank | 
|---|
| 953 | * waits, so we need vblank interrupts restored beforehand. | 
|---|
| 954 | */ | 
|---|
| 955 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 956 | struct intel_crtc_state *crtc_state = | 
|---|
| 957 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 958 |  | 
|---|
| 959 | intel_sanitize_fifo_underrun_reporting(crtc_state); | 
|---|
| 960 |  | 
|---|
| 961 | drm_crtc_vblank_reset(crtc: &crtc->base); | 
|---|
| 962 |  | 
|---|
| 963 | if (crtc_state->hw.active) { | 
|---|
| 964 | intel_dmc_enable_pipe(crtc_state); | 
|---|
| 965 | intel_crtc_vblank_on(crtc_state); | 
|---|
| 966 | } | 
|---|
| 967 | } | 
|---|
| 968 |  | 
|---|
| 969 | intel_fbc_sanitize(display); | 
|---|
| 970 |  | 
|---|
| 971 | intel_sanitize_plane_mapping(display); | 
|---|
| 972 |  | 
|---|
| 973 | for_each_intel_encoder(display->drm, encoder) | 
|---|
| 974 | intel_sanitize_encoder(encoder); | 
|---|
| 975 |  | 
|---|
| 976 | /* | 
|---|
| 977 | * Sanitizing CRTCs needs their connector atomic state to be | 
|---|
| 978 | * up-to-date, so ensure that already here. | 
|---|
| 979 | */ | 
|---|
| 980 | intel_modeset_update_connector_atomic_state(display); | 
|---|
| 981 |  | 
|---|
| 982 | intel_sanitize_all_crtcs(display, ctx); | 
|---|
| 983 |  | 
|---|
| 984 | intel_dpll_sanitize_state(display); | 
|---|
| 985 |  | 
|---|
| 986 | /* TODO move earlier on all platforms */ | 
|---|
| 987 | if (DISPLAY_VER(display) < 9) | 
|---|
| 988 | intel_wm_get_hw_state(display); | 
|---|
| 989 | intel_wm_sanitize(display); | 
|---|
| 990 |  | 
|---|
| 991 | for_each_intel_crtc(display->drm, crtc) { | 
|---|
| 992 | struct intel_crtc_state *crtc_state = | 
|---|
| 993 | to_intel_crtc_state(crtc->base.state); | 
|---|
| 994 | struct intel_power_domain_mask put_domains; | 
|---|
| 995 |  | 
|---|
| 996 | intel_modeset_get_crtc_power_domains(crtc_state, old_domains: &put_domains); | 
|---|
| 997 | if (drm_WARN_ON(display->drm, !bitmap_empty(put_domains.bits, POWER_DOMAIN_NUM))) | 
|---|
| 998 | intel_modeset_put_crtc_power_domains(crtc, domains: &put_domains); | 
|---|
| 999 | } | 
|---|
| 1000 |  | 
|---|
| 1001 | intel_display_power_put(display, domain: POWER_DOMAIN_INIT, wakeref); | 
|---|
| 1002 |  | 
|---|
| 1003 | intel_power_domains_sanitize_state(display); | 
|---|
| 1004 | } | 
|---|
| 1005 |  | 
|---|