1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2022 Intel Corporation 4 */ 5 6 #include "hsw_ips.h" 7 #include "i915_drv.h" 8 #include "i915_reg.h" 9 #include "intel_de.h" 10 #include "intel_display_types.h" 11 #include "intel_pcode.h" 12 13 static void hsw_ips_enable(const struct intel_crtc_state *crtc_state) 14 { 15 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 16 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 17 18 if (!crtc_state->ips_enabled) 19 return; 20 21 /* 22 * We can only enable IPS after we enable a plane and wait for a vblank 23 * This function is called from post_plane_update, which is run after 24 * a vblank wait. 25 */ 26 drm_WARN_ON(&i915->drm, 27 !(crtc_state->active_planes & ~BIT(PLANE_CURSOR))); 28 29 if (IS_BROADWELL(i915)) { 30 drm_WARN_ON(&i915->drm, 31 snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL, 32 IPS_ENABLE | IPS_PCODE_CONTROL)); 33 /* 34 * Quoting Art Runyan: "its not safe to expect any particular 35 * value in IPS_CTL bit 31 after enabling IPS through the 36 * mailbox." Moreover, the mailbox may return a bogus state, 37 * so we need to just enable it and continue on. 38 */ 39 } else { 40 intel_de_write(i915, IPS_CTL, IPS_ENABLE); 41 /* 42 * The bit only becomes 1 in the next vblank, so this wait here 43 * is essentially intel_wait_for_vblank. If we don't have this 44 * and don't wait for vblanks until the end of crtc_enable, then 45 * the HW state readout code will complain that the expected 46 * IPS_CTL value is not the one we read. 47 */ 48 if (intel_de_wait_for_set(i915, IPS_CTL, IPS_ENABLE, 50)) 49 drm_err(&i915->drm, 50 "Timed out waiting for IPS enable\n"); 51 } 52 } 53 54 bool hsw_ips_disable(const struct intel_crtc_state *crtc_state) 55 { 56 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 57 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 58 bool need_vblank_wait = false; 59 60 if (!crtc_state->ips_enabled) 61 return need_vblank_wait; 62 63 if (IS_BROADWELL(i915)) { 64 drm_WARN_ON(&i915->drm, 65 snb_pcode_write(&i915->uncore, DISPLAY_IPS_CONTROL, 0)); 66 /* 67 * Wait for PCODE to finish disabling IPS. The BSpec specified 68 * 42ms timeout value leads to occasional timeouts so use 100ms 69 * instead. 70 */ 71 if (intel_de_wait_for_clear(i915, IPS_CTL, IPS_ENABLE, 100)) 72 drm_err(&i915->drm, 73 "Timed out waiting for IPS disable\n"); 74 } else { 75 intel_de_write(i915, IPS_CTL, 0); 76 intel_de_posting_read(i915, IPS_CTL); 77 } 78 79 /* We need to wait for a vblank before we can disable the plane. */ 80 need_vblank_wait = true; 81 82 return need_vblank_wait; 83 } 84 85 static bool hsw_ips_need_disable(struct intel_atomic_state *state, 86 struct intel_crtc *crtc) 87 { 88 struct drm_i915_private *i915 = to_i915(state->base.dev); 89 const struct intel_crtc_state *old_crtc_state = 90 intel_atomic_get_old_crtc_state(state, crtc); 91 const struct intel_crtc_state *new_crtc_state = 92 intel_atomic_get_new_crtc_state(state, crtc); 93 94 if (!old_crtc_state->ips_enabled) 95 return false; 96 97 if (intel_crtc_needs_modeset(new_crtc_state)) 98 return true; 99 100 /* 101 * Workaround : Do not read or write the pipe palette/gamma data while 102 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. 103 * 104 * Disable IPS before we program the LUT. 105 */ 106 if (IS_HASWELL(i915) && 107 (new_crtc_state->uapi.color_mgmt_changed || 108 new_crtc_state->update_pipe) && 109 new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) 110 return true; 111 112 return !new_crtc_state->ips_enabled; 113 } 114 115 bool hsw_ips_pre_update(struct intel_atomic_state *state, 116 struct intel_crtc *crtc) 117 { 118 const struct intel_crtc_state *old_crtc_state = 119 intel_atomic_get_old_crtc_state(state, crtc); 120 121 if (!hsw_ips_need_disable(state, crtc)) 122 return false; 123 124 return hsw_ips_disable(old_crtc_state); 125 } 126 127 static bool hsw_ips_need_enable(struct intel_atomic_state *state, 128 struct intel_crtc *crtc) 129 { 130 struct drm_i915_private *i915 = to_i915(state->base.dev); 131 const struct intel_crtc_state *old_crtc_state = 132 intel_atomic_get_old_crtc_state(state, crtc); 133 const struct intel_crtc_state *new_crtc_state = 134 intel_atomic_get_new_crtc_state(state, crtc); 135 136 if (!new_crtc_state->ips_enabled) 137 return false; 138 139 if (intel_crtc_needs_modeset(new_crtc_state)) 140 return true; 141 142 /* 143 * Workaround : Do not read or write the pipe palette/gamma data while 144 * GAMMA_MODE is configured for split gamma and IPS_CTL has IPS enabled. 145 * 146 * Re-enable IPS after the LUT has been programmed. 147 */ 148 if (IS_HASWELL(i915) && 149 (new_crtc_state->uapi.color_mgmt_changed || 150 new_crtc_state->update_pipe) && 151 new_crtc_state->gamma_mode == GAMMA_MODE_MODE_SPLIT) 152 return true; 153 154 /* 155 * We can't read out IPS on broadwell, assume the worst and 156 * forcibly enable IPS on the first fastset. 157 */ 158 if (new_crtc_state->update_pipe && old_crtc_state->inherited) 159 return true; 160 161 return !old_crtc_state->ips_enabled; 162 } 163 164 void hsw_ips_post_update(struct intel_atomic_state *state, 165 struct intel_crtc *crtc) 166 { 167 const struct intel_crtc_state *new_crtc_state = 168 intel_atomic_get_new_crtc_state(state, crtc); 169 170 if (!hsw_ips_need_enable(state, crtc)) 171 return; 172 173 hsw_ips_enable(new_crtc_state); 174 } 175 176 /* IPS only exists on ULT machines and is tied to pipe A. */ 177 bool hsw_crtc_supports_ips(struct intel_crtc *crtc) 178 { 179 return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A; 180 } 181 182 bool hsw_crtc_state_ips_capable(const struct intel_crtc_state *crtc_state) 183 { 184 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 185 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 186 187 /* IPS only exists on ULT machines and is tied to pipe A. */ 188 if (!hsw_crtc_supports_ips(crtc)) 189 return false; 190 191 if (!i915->params.enable_ips) 192 return false; 193 194 if (crtc_state->pipe_bpp > 24) 195 return false; 196 197 /* 198 * We compare against max which means we must take 199 * the increased cdclk requirement into account when 200 * calculating the new cdclk. 201 * 202 * Should measure whether using a lower cdclk w/o IPS 203 */ 204 if (IS_BROADWELL(i915) && 205 crtc_state->pixel_rate > i915->display.cdclk.max_cdclk_freq * 95 / 100) 206 return false; 207 208 return true; 209 } 210 211 int hsw_ips_compute_config(struct intel_atomic_state *state, 212 struct intel_crtc *crtc) 213 { 214 struct drm_i915_private *i915 = to_i915(state->base.dev); 215 struct intel_crtc_state *crtc_state = 216 intel_atomic_get_new_crtc_state(state, crtc); 217 218 crtc_state->ips_enabled = false; 219 220 if (!hsw_crtc_state_ips_capable(crtc_state)) 221 return 0; 222 223 /* 224 * When IPS gets enabled, the pipe CRC changes. Since IPS gets 225 * enabled and disabled dynamically based on package C states, 226 * user space can't make reliable use of the CRCs, so let's just 227 * completely disable it. 228 */ 229 if (crtc_state->crc_enabled) 230 return 0; 231 232 /* IPS should be fine as long as at least one plane is enabled. */ 233 if (!(crtc_state->active_planes & ~BIT(PLANE_CURSOR))) 234 return 0; 235 236 if (IS_BROADWELL(i915)) { 237 const struct intel_cdclk_state *cdclk_state; 238 239 cdclk_state = intel_atomic_get_cdclk_state(state); 240 if (IS_ERR(cdclk_state)) 241 return PTR_ERR(cdclk_state); 242 243 /* pixel rate mustn't exceed 95% of cdclk with IPS on BDW */ 244 if (crtc_state->pixel_rate > cdclk_state->logical.cdclk * 95 / 100) 245 return 0; 246 } 247 248 crtc_state->ips_enabled = true; 249 250 return 0; 251 } 252 253 void hsw_ips_get_config(struct intel_crtc_state *crtc_state) 254 { 255 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); 256 struct drm_i915_private *i915 = to_i915(crtc->base.dev); 257 258 if (!hsw_crtc_supports_ips(crtc)) 259 return; 260 261 if (IS_HASWELL(i915)) { 262 crtc_state->ips_enabled = intel_de_read(i915, IPS_CTL) & IPS_ENABLE; 263 } else { 264 /* 265 * We cannot readout IPS state on broadwell, set to 266 * true so we can set it to a defined state on first 267 * commit. 268 */ 269 crtc_state->ips_enabled = true; 270 } 271 } 272