1 // SPDX-License-Identifier: MIT 2 /* 3 * Copyright © 2026 Intel Corporation 4 */ 5 6 #include <linux/delay.h> 7 8 #include <drm/drm_print.h> 9 10 #include "intel_de.h" 11 12 static int __intel_de_wait_for_register(struct intel_display *display, 13 i915_reg_t reg, u32 mask, u32 value, 14 unsigned int timeout_us, 15 u32 (*read)(struct intel_display *display, i915_reg_t reg), 16 u32 *out_val, bool is_atomic) 17 { 18 const ktime_t end = ktime_add_us(ktime_get_raw(), timeout_us); 19 int wait_max = 1000; 20 int wait = 10; 21 u32 reg_value; 22 int ret; 23 24 might_sleep_if(!is_atomic); 25 26 if (timeout_us <= 10) { 27 is_atomic = true; 28 wait = 1; 29 } 30 31 for (;;) { 32 bool expired = ktime_after(ktime_get_raw(), end); 33 34 /* guarantee the condition is evaluated after timeout expired */ 35 barrier(); 36 37 reg_value = read(display, reg); 38 if ((reg_value & mask) == value) { 39 ret = 0; 40 break; 41 } 42 43 if (expired) { 44 ret = -ETIMEDOUT; 45 break; 46 } 47 48 if (is_atomic) 49 udelay(wait); 50 else 51 usleep_range(wait, wait << 1); 52 53 if (wait < wait_max) 54 wait <<= 1; 55 } 56 57 if (out_val) 58 *out_val = reg_value; 59 60 return ret; 61 } 62 63 static int intel_de_wait_for_register(struct intel_display *display, 64 i915_reg_t reg, u32 mask, u32 value, 65 unsigned int fast_timeout_us, 66 unsigned int slow_timeout_us, 67 u32 (*read)(struct intel_display *display, i915_reg_t reg), 68 u32 *out_value, bool is_atomic) 69 { 70 int ret = -EINVAL; 71 72 if (fast_timeout_us) 73 ret = __intel_de_wait_for_register(display, reg, mask, value, 74 fast_timeout_us, read, 75 out_value, is_atomic); 76 77 if (ret && slow_timeout_us) 78 ret = __intel_de_wait_for_register(display, reg, mask, value, 79 slow_timeout_us, read, 80 out_value, is_atomic); 81 82 return ret; 83 } 84 85 int intel_de_wait_us(struct intel_display *display, i915_reg_t reg, 86 u32 mask, u32 value, unsigned int timeout_us, 87 u32 *out_value) 88 { 89 int ret; 90 91 intel_dmc_wl_get(display, reg); 92 93 ret = intel_de_wait_for_register(display, reg, mask, value, 94 timeout_us, 0, 95 intel_de_read, 96 out_value, false); 97 98 intel_dmc_wl_put(display, reg); 99 100 return ret; 101 } 102 103 int intel_de_wait_ms(struct intel_display *display, i915_reg_t reg, 104 u32 mask, u32 value, unsigned int timeout_ms, 105 u32 *out_value) 106 { 107 int ret; 108 109 intel_dmc_wl_get(display, reg); 110 111 ret = intel_de_wait_for_register(display, reg, mask, value, 112 2, timeout_ms * 1000, 113 intel_de_read, 114 out_value, false); 115 116 intel_dmc_wl_put(display, reg); 117 118 return ret; 119 } 120 121 int intel_de_wait_fw_ms(struct intel_display *display, i915_reg_t reg, 122 u32 mask, u32 value, unsigned int timeout_ms, 123 u32 *out_value) 124 { 125 return intel_de_wait_for_register(display, reg, mask, value, 126 2, timeout_ms * 1000, 127 intel_de_read_fw, 128 out_value, false); 129 } 130 131 int intel_de_wait_fw_us_atomic(struct intel_display *display, i915_reg_t reg, 132 u32 mask, u32 value, unsigned int timeout_us, 133 u32 *out_value) 134 { 135 return intel_de_wait_for_register(display, reg, mask, value, 136 timeout_us, 0, 137 intel_de_read_fw, 138 out_value, true); 139 } 140 141 int intel_de_wait_for_set_us(struct intel_display *display, i915_reg_t reg, 142 u32 mask, unsigned int timeout_us) 143 { 144 return intel_de_wait_us(display, reg, mask, mask, timeout_us, NULL); 145 } 146 147 int intel_de_wait_for_clear_us(struct intel_display *display, i915_reg_t reg, 148 u32 mask, unsigned int timeout_us) 149 { 150 return intel_de_wait_us(display, reg, mask, 0, timeout_us, NULL); 151 } 152 153 int intel_de_wait_for_set_ms(struct intel_display *display, i915_reg_t reg, 154 u32 mask, unsigned int timeout_ms) 155 { 156 return intel_de_wait_ms(display, reg, mask, mask, timeout_ms, NULL); 157 } 158 159 int intel_de_wait_for_clear_ms(struct intel_display *display, i915_reg_t reg, 160 u32 mask, unsigned int timeout_ms) 161 { 162 return intel_de_wait_ms(display, reg, mask, 0, timeout_ms, NULL); 163 } 164 165 u8 intel_de_read8(struct intel_display *display, i915_reg_t reg) 166 { 167 /* this is only used on VGA registers (possible on pre-g4x) */ 168 drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x); 169 170 return intel_uncore_read8(__to_uncore(display), reg); 171 } 172 173 void intel_de_write8(struct intel_display *display, i915_reg_t reg, u8 val) 174 { 175 drm_WARN_ON(display->drm, DISPLAY_VER(display) >= 5 || display->platform.g4x); 176 177 intel_uncore_write8(__to_uncore(display), reg, val); 178 } 179