xref: /linux/drivers/gpu/drm/i915/display/intel_de.c (revision 4a57e0913e8c7fff407e97909f4ae48caa84d612)
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