1 |
commit: b75b7e6a336c28fa493be98a01eef5ce375e020b |
2 |
Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
3 |
AuthorDate: Mon Nov 29 23:34:54 2021 +0000 |
4 |
Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> |
5 |
CommitDate: Mon Nov 29 23:34:54 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=b75b7e6a |
7 |
|
8 |
Add suprt for panels w. VESA backlights with PWM enable/disable |
9 |
|
10 |
Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> |
11 |
|
12 |
0000_README | 4 + |
13 |
...15-PWM-support-for-VESA-backlight-helpers.patch | 618 +++++++++++++++++++++ |
14 |
2 files changed, 622 insertions(+) |
15 |
|
16 |
diff --git a/0000_README b/0000_README |
17 |
index 68d0c0db..0923a646 100644 |
18 |
--- a/0000_README |
19 |
+++ b/0000_README |
20 |
@@ -75,6 +75,10 @@ Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch |
21 |
From: https://lore.kernel.org/linux-bluetooth/20190522070540.48895-1-marcel@××××××××.org/raw |
22 |
Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758 |
23 |
|
24 |
+Patch: 2800_drm-i915-PWM-support-for-VESA-backlight-helpers.patch |
25 |
+From: https://patchwork.freedesktop.org/series/95127/ |
26 |
+Desc: drm/i915: Add support for panels with VESA backlights with PWM enable/disable |
27 |
+ |
28 |
Patch: 2900_tmp513-Fix-build-issue-by-selecting-CONFIG_REG.patch |
29 |
From: https://bugs.gentoo.org/710790 |
30 |
Desc: tmp513 requies REGMAP_I2C to build. Select it by default in Kconfig. See bug #710790. Thanks to Phil Stracchino |
31 |
|
32 |
diff --git a/2800_drm-i915-PWM-support-for-VESA-backlight-helpers.patch b/2800_drm-i915-PWM-support-for-VESA-backlight-helpers.patch |
33 |
new file mode 100644 |
34 |
index 00000000..45969bce |
35 |
--- /dev/null |
36 |
+++ b/2800_drm-i915-PWM-support-for-VESA-backlight-helpers.patch |
37 |
@@ -0,0 +1,618 @@ |
38 |
+From patchwork Fri Nov 5 18:33:38 2021 |
39 |
+Content-Type: text/plain; charset="utf-8" |
40 |
+MIME-Version: 1.0 |
41 |
+Content-Transfer-Encoding: 8bit |
42 |
+Subject: [v5,1/5] drm/i915: Add support for panels with VESA backlights with |
43 |
+ PWM enable/disable |
44 |
+From: Lyude Paul <lyude@××××××.com> |
45 |
+X-Patchwork-Id: 462369 |
46 |
+Message-Id: <20211105183342.130810-2-lyude@××××××.com> |
47 |
+To: dri-devel@×××××××××××××××××.org, nouveau@×××××××××××××××××.org, |
48 |
+ intel-gfx@×××××××××××××××××.org |
49 |
+Cc: David Airlie <airlied@×××××.ie>, open list <linux-kernel@×××××××××××.org>, |
50 |
+ stable@×××××××××××.org |
51 |
+Date: Fri, 5 Nov 2021 14:33:38 -0400 |
52 |
+ |
53 |
+This simply adds proper support for panel backlights that can be controlled |
54 |
+via VESA's backlight control protocol, but which also require that we |
55 |
+enable and disable the backlight via PWM instead of via the DPCD interface. |
56 |
+We also enable this by default, in order to fix some people's backlights |
57 |
+that were broken by not having this enabled. |
58 |
+ |
59 |
+For reference, backlights that require this and use VESA's backlight |
60 |
+interface tend to be laptops with hybrid GPUs, but this very well may |
61 |
+change in the future. |
62 |
+ |
63 |
+v4: |
64 |
+* Make sure that we call intel_backlight_level_to_pwm() in |
65 |
+ intel_dp_aux_vesa_enable_backlight() - vsyrjala |
66 |
+ |
67 |
+Signed-off-by: Lyude Paul <lyude@××××××.com> |
68 |
+Link: https://gitlab.freedesktop.org/drm/intel/-/issues/3680 |
69 |
+Fixes: fe7d52bccab6 ("drm/i915/dp: Don't use DPCD backlights that need PWM enable/disable") |
70 |
+Reviewed-by: Ville Syrjälä <ville.syrjala@×××××××××××.com> |
71 |
+Cc: <stable@×××××××××××.org> # v5.12+ |
72 |
+--- |
73 |
+ .../drm/i915/display/intel_dp_aux_backlight.c | 27 ++++++++++++++----- |
74 |
+ 1 file changed, 21 insertions(+), 6 deletions(-) |
75 |
+ |
76 |
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
77 |
+index 569d17b4d00f..f05b71c01b8e 100644 |
78 |
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
79 |
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
80 |
+@@ -293,6 +293,13 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, |
81 |
+ struct intel_panel *panel = &connector->panel; |
82 |
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
83 |
+ |
84 |
++ if (!panel->backlight.edp.vesa.info.aux_enable) { |
85 |
++ u32 pwm_level = intel_backlight_invert_pwm_level(connector, |
86 |
++ panel->backlight.pwm_level_max); |
87 |
++ |
88 |
++ panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level); |
89 |
++ } |
90 |
++ |
91 |
+ drm_edp_backlight_enable(&intel_dp->aux, &panel->backlight.edp.vesa.info, level); |
92 |
+ } |
93 |
+ |
94 |
+@@ -304,6 +311,10 @@ static void intel_dp_aux_vesa_disable_backlight(const struct drm_connector_state |
95 |
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
96 |
+ |
97 |
+ drm_edp_backlight_disable(&intel_dp->aux, &panel->backlight.edp.vesa.info); |
98 |
++ |
99 |
++ if (!panel->backlight.edp.vesa.info.aux_enable) |
100 |
++ panel->backlight.pwm_funcs->disable(old_conn_state, |
101 |
++ intel_backlight_invert_pwm_level(connector, 0)); |
102 |
+ } |
103 |
+ |
104 |
+ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, enum pipe pipe) |
105 |
+@@ -321,6 +332,15 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, |
106 |
+ if (ret < 0) |
107 |
+ return ret; |
108 |
+ |
109 |
++ if (!panel->backlight.edp.vesa.info.aux_enable) { |
110 |
++ ret = panel->backlight.pwm_funcs->setup(connector, pipe); |
111 |
++ if (ret < 0) { |
112 |
++ drm_err(&i915->drm, |
113 |
++ "Failed to setup PWM backlight controls for eDP backlight: %d\n", |
114 |
++ ret); |
115 |
++ return ret; |
116 |
++ } |
117 |
++ } |
118 |
+ panel->backlight.max = panel->backlight.edp.vesa.info.max; |
119 |
+ panel->backlight.min = 0; |
120 |
+ if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
121 |
+@@ -340,12 +360,7 @@ intel_dp_aux_supports_vesa_backlight(struct intel_connector *connector) |
122 |
+ struct intel_dp *intel_dp = intel_attached_dp(connector); |
123 |
+ struct drm_i915_private *i915 = dp_to_i915(intel_dp); |
124 |
+ |
125 |
+- /* TODO: We currently only support AUX only backlight configurations, not backlights which |
126 |
+- * require a mix of PWM and AUX controls to work. In the mean time, these machines typically |
127 |
+- * work just fine using normal PWM controls anyway. |
128 |
+- */ |
129 |
+- if ((intel_dp->edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && |
130 |
+- drm_edp_backlight_supported(intel_dp->edp_dpcd)) { |
131 |
++ if (drm_edp_backlight_supported(intel_dp->edp_dpcd)) { |
132 |
+ drm_dbg_kms(&i915->drm, "AUX Backlight Control Supported!\n"); |
133 |
+ return true; |
134 |
+ } |
135 |
+ |
136 |
+From patchwork Fri Nov 5 18:33:39 2021 |
137 |
+Content-Type: text/plain; charset="utf-8" |
138 |
+MIME-Version: 1.0 |
139 |
+Content-Transfer-Encoding: 7bit |
140 |
+Subject: [v5,2/5] drm/nouveau/kms/nv50-: Explicitly check DPCD backlights for |
141 |
+ aux enable/brightness |
142 |
+From: Lyude Paul <lyude@××××××.com> |
143 |
+X-Patchwork-Id: 462371 |
144 |
+Message-Id: <20211105183342.130810-3-lyude@××××××.com> |
145 |
+To: dri-devel@×××××××××××××××××.org, nouveau@×××××××××××××××××.org, |
146 |
+ intel-gfx@×××××××××××××××××.org |
147 |
+Cc: David Airlie <airlied@×××××.ie>, Ben Skeggs <bskeggs@××××××.com>, |
148 |
+ Karol Herbst <kherbst@××××××.com>, open list <linux-kernel@×××××××××××.org> |
149 |
+Date: Fri, 5 Nov 2021 14:33:39 -0400 |
150 |
+ |
151 |
+Since we don't support hybrid AUX/PWM backlights in nouveau right now, |
152 |
+let's add some explicit checks so that we don't break nouveau once we |
153 |
+enable support for these backlights in other drivers. |
154 |
+ |
155 |
+Reviewed-by: Karol Herbst <kherbst@××××××.com> |
156 |
+Signed-off-by: Lyude Paul <lyude@××××××.com> |
157 |
+--- |
158 |
+ drivers/gpu/drm/nouveau/nouveau_backlight.c | 5 ++++- |
159 |
+ 1 file changed, 4 insertions(+), 1 deletion(-) |
160 |
+ |
161 |
+diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c |
162 |
+index 1cbd71abc80a..ae2f2abc8f5a 100644 |
163 |
+--- a/drivers/gpu/drm/nouveau/nouveau_backlight.c |
164 |
++++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c |
165 |
+@@ -308,7 +308,10 @@ nv50_backlight_init(struct nouveau_backlight *bl, |
166 |
+ if (ret < 0) |
167 |
+ return ret; |
168 |
+ |
169 |
+- if (drm_edp_backlight_supported(edp_dpcd)) { |
170 |
++ /* TODO: Add support for hybrid PWM/DPCD panels */ |
171 |
++ if (drm_edp_backlight_supported(edp_dpcd) && |
172 |
++ (edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) && |
173 |
++ (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP)) { |
174 |
+ NV_DEBUG(drm, "DPCD backlight controls supported on %s\n", |
175 |
+ nv_conn->base.name); |
176 |
+ |
177 |
+ |
178 |
+From patchwork Fri Nov 5 18:33:40 2021 |
179 |
+Content-Type: text/plain; charset="utf-8" |
180 |
+MIME-Version: 1.0 |
181 |
+Content-Transfer-Encoding: 7bit |
182 |
+Subject: [v5,3/5] drm/dp: Don't read back backlight mode in |
183 |
+ drm_edp_backlight_enable() |
184 |
+From: Lyude Paul <lyude@××××××.com> |
185 |
+X-Patchwork-Id: 462376 |
186 |
+Message-Id: <20211105183342.130810-4-lyude@××××××.com> |
187 |
+To: dri-devel@×××××××××××××××××.org, nouveau@×××××××××××××××××.org, |
188 |
+ intel-gfx@×××××××××××××××××.org |
189 |
+Cc: Thomas Zimmermann <tzimmermann@××××.de>, David Airlie <airlied@×××××.ie>, |
190 |
+ open list <linux-kernel@×××××××××××.org>, Maxime Ripard <mripard@××××××.org> |
191 |
+Date: Fri, 5 Nov 2021 14:33:40 -0400 |
192 |
+ |
193 |
+As it turns out, apparently some machines will actually leave additional |
194 |
+backlight functionality like dynamic backlight control on before the OS |
195 |
+loads. Currently we don't take care to disable unsupported features when |
196 |
+writing back the backlight mode, which can lead to some rather strange |
197 |
+looking behavior when adjusting the backlight. |
198 |
+ |
199 |
+So, let's fix this by just not reading back the current backlight mode on |
200 |
+initial enable. I don't think there should really be any downsides to this, |
201 |
+and this will ensure we don't leave any unsupported functionality enabled. |
202 |
+ |
203 |
+This should fix at least one (but not all) of the issues seen with DPCD |
204 |
+backlight support on fi-bdw-samus |
205 |
+ |
206 |
+v5: |
207 |
+* Just avoid reading back DPCD register - Doug Anderson |
208 |
+ |
209 |
+Signed-off-by: Lyude Paul <lyude@××××××.com> |
210 |
+Fixes: 867cf9cd73c3 ("drm/dp: Extract i915's eDP backlight code into DRM helpers") |
211 |
+Reviewed-by: Douglas Anderson <dianders@××××××××.org> |
212 |
+--- |
213 |
+ drivers/gpu/drm/drm_dp_helper.c | 40 ++++++++++----------------------- |
214 |
+ 1 file changed, 12 insertions(+), 28 deletions(-) |
215 |
+ |
216 |
+diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c |
217 |
+index ada0a1ff262d..af2aad2f4725 100644 |
218 |
+--- a/drivers/gpu/drm/drm_dp_helper.c |
219 |
++++ b/drivers/gpu/drm/drm_dp_helper.c |
220 |
+@@ -3363,27 +3363,13 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli |
221 |
+ const u16 level) |
222 |
+ { |
223 |
+ int ret; |
224 |
+- u8 dpcd_buf, new_dpcd_buf; |
225 |
++ u8 dpcd_buf = DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; |
226 |
+ |
227 |
+- ret = drm_dp_dpcd_readb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, &dpcd_buf); |
228 |
+- if (ret != 1) { |
229 |
+- drm_dbg_kms(aux->drm_dev, |
230 |
+- "%s: Failed to read backlight mode: %d\n", aux->name, ret); |
231 |
+- return ret < 0 ? ret : -EIO; |
232 |
+- } |
233 |
+- |
234 |
+- new_dpcd_buf = dpcd_buf; |
235 |
+- |
236 |
+- if ((dpcd_buf & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK) != DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
237 |
+- new_dpcd_buf &= ~DP_EDP_BACKLIGHT_CONTROL_MODE_MASK; |
238 |
+- new_dpcd_buf |= DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; |
239 |
+- |
240 |
+- if (bl->pwmgen_bit_count) { |
241 |
+- ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); |
242 |
+- if (ret != 1) |
243 |
+- drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", |
244 |
+- aux->name, ret); |
245 |
+- } |
246 |
++ if (bl->pwmgen_bit_count) { |
247 |
++ ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); |
248 |
++ if (ret != 1) |
249 |
++ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux pwmgen bit count: %d\n", |
250 |
++ aux->name, ret); |
251 |
+ } |
252 |
+ |
253 |
+ if (bl->pwm_freq_pre_divider) { |
254 |
+@@ -3393,16 +3379,14 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli |
255 |
+ "%s: Failed to write aux backlight frequency: %d\n", |
256 |
+ aux->name, ret); |
257 |
+ else |
258 |
+- new_dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; |
259 |
++ dpcd_buf |= DP_EDP_BACKLIGHT_FREQ_AUX_SET_ENABLE; |
260 |
+ } |
261 |
+ |
262 |
+- if (new_dpcd_buf != dpcd_buf) { |
263 |
+- ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, new_dpcd_buf); |
264 |
+- if (ret != 1) { |
265 |
+- drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux backlight mode: %d\n", |
266 |
+- aux->name, ret); |
267 |
+- return ret < 0 ? ret : -EIO; |
268 |
+- } |
269 |
++ ret = drm_dp_dpcd_writeb(aux, DP_EDP_BACKLIGHT_MODE_SET_REGISTER, dpcd_buf); |
270 |
++ if (ret != 1) { |
271 |
++ drm_dbg_kms(aux->drm_dev, "%s: Failed to write aux backlight mode: %d\n", |
272 |
++ aux->name, ret); |
273 |
++ return ret < 0 ? ret : -EIO; |
274 |
+ } |
275 |
+ |
276 |
+ ret = drm_edp_backlight_set_level(aux, bl, level); |
277 |
+ |
278 |
+From patchwork Fri Nov 5 18:33:41 2021 |
279 |
+Content-Type: text/plain; charset="utf-8" |
280 |
+MIME-Version: 1.0 |
281 |
+Content-Transfer-Encoding: 7bit |
282 |
+Subject: [v5,4/5] drm/dp, |
283 |
+ drm/i915: Add support for VESA backlights using PWM for brightness control |
284 |
+From: Lyude Paul <lyude@××××××.com> |
285 |
+X-Patchwork-Id: 462379 |
286 |
+Message-Id: <20211105183342.130810-5-lyude@××××××.com> |
287 |
+To: dri-devel@×××××××××××××××××.org, nouveau@×××××××××××××××××.org, |
288 |
+ intel-gfx@×××××××××××××××××.org |
289 |
+Cc: Rajeev Nandan <rajeevny@××××××××××.org>, David Airlie <airlied@×××××.ie>, |
290 |
+ Doug Anderson <dianders@××××××××.org>, Maxime Ripard <mripard@××××××.org>, |
291 |
+ open list <linux-kernel@×××××××××××.org>, |
292 |
+ Thomas Zimmermann <tzimmermann@××××.de> |
293 |
+Date: Fri, 5 Nov 2021 14:33:41 -0400 |
294 |
+ |
295 |
+Now that we've added support to i915 for controlling panel backlights that |
296 |
+need PWM to be enabled/disabled, let's finalize this and add support for |
297 |
+controlling brightness levels via PWM as well. This should hopefully put us |
298 |
+towards the path of supporting _ALL_ backlights via VESA's DPCD interface |
299 |
+which would allow us to finally start trusting the DPCD again. |
300 |
+ |
301 |
+Note however that we still don't enable using this by default on i915 when |
302 |
+it's not needed, primarily because I haven't yet had a chance to confirm if |
303 |
+it's safe to do this on the one machine in Intel's CI that had an issue |
304 |
+with this: samus-fi-bdw. I have done basic testing of this on other |
305 |
+machines though, by manually patching i915 to force it into PWM-only mode |
306 |
+on some of my laptops. |
307 |
+ |
308 |
+v2: |
309 |
+* Correct documentation (thanks Doug!) |
310 |
+* Get rid of backlight caps |
311 |
+ |
312 |
+Signed-off-by: Lyude Paul <lyude@××××××.com> |
313 |
+Reviewed-by: Doug Anderson <dianders@××××××××.org> |
314 |
+Cc: Rajeev Nandan <rajeevny@××××××××××.org> |
315 |
+Cc: Satadru Pramanik <satadru@×××××.com> |
316 |
+--- |
317 |
+ drivers/gpu/drm/drm_dp_helper.c | 72 +++++++++++++------ |
318 |
+ .../drm/i915/display/intel_dp_aux_backlight.c | 44 +++++++++--- |
319 |
+ include/drm/drm_dp_helper.h | 7 +- |
320 |
+ 3 files changed, 89 insertions(+), 34 deletions(-) |
321 |
+ |
322 |
+diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c |
323 |
+index af2aad2f4725..23f9073bc473 100644 |
324 |
+--- a/drivers/gpu/drm/drm_dp_helper.c |
325 |
++++ b/drivers/gpu/drm/drm_dp_helper.c |
326 |
+@@ -3290,6 +3290,10 @@ int drm_edp_backlight_set_level(struct drm_dp_aux *aux, const struct drm_edp_bac |
327 |
+ int ret; |
328 |
+ u8 buf[2] = { 0 }; |
329 |
+ |
330 |
++ /* The panel uses the PWM for controlling brightness levels */ |
331 |
++ if (!bl->aux_set) |
332 |
++ return 0; |
333 |
++ |
334 |
+ if (bl->lsb_reg_used) { |
335 |
+ buf[0] = (level & 0xff00) >> 8; |
336 |
+ buf[1] = (level & 0x00ff); |
337 |
+@@ -3316,7 +3320,7 @@ drm_edp_backlight_set_enable(struct drm_dp_aux *aux, const struct drm_edp_backli |
338 |
+ int ret; |
339 |
+ u8 buf; |
340 |
+ |
341 |
+- /* The panel uses something other then DPCD for enabling its backlight */ |
342 |
++ /* This panel uses the EDP_BL_PWR GPIO for enablement */ |
343 |
+ if (!bl->aux_enable) |
344 |
+ return 0; |
345 |
+ |
346 |
+@@ -3351,11 +3355,11 @@ drm_edp_backlight_set_enable(struct drm_dp_aux *aux, const struct drm_edp_backli |
347 |
+ * restoring any important backlight state such as the given backlight level, the brightness byte |
348 |
+ * count, backlight frequency, etc. |
349 |
+ * |
350 |
+- * Note that certain panels, while supporting brightness level controls over DPCD, may not support |
351 |
+- * having their backlights enabled via the standard %DP_EDP_DISPLAY_CONTROL_REGISTER. On such panels |
352 |
+- * &drm_edp_backlight_info.aux_enable will be set to %false, this function will skip the step of |
353 |
+- * programming the %DP_EDP_DISPLAY_CONTROL_REGISTER, and the driver must perform the required |
354 |
+- * implementation specific step for enabling the backlight after calling this function. |
355 |
++ * Note that certain panels do not support being enabled or disabled via DPCD, but instead require |
356 |
++ * that the driver handle enabling/disabling the panel through implementation-specific means using |
357 |
++ * the EDP_BL_PWR GPIO. For such panels, &drm_edp_backlight_info.aux_enable will be set to %false, |
358 |
++ * this function becomes a no-op, and the driver is expected to handle powering the panel on using |
359 |
++ * the EDP_BL_PWR GPIO. |
360 |
+ * |
361 |
+ * Returns: %0 on success, negative error code on failure. |
362 |
+ */ |
363 |
+@@ -3363,7 +3367,12 @@ int drm_edp_backlight_enable(struct drm_dp_aux *aux, const struct drm_edp_backli |
364 |
+ const u16 level) |
365 |
+ { |
366 |
+ int ret; |
367 |
+- u8 dpcd_buf = DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; |
368 |
++ u8 dpcd_buf; |
369 |
++ |
370 |
++ if (bl->aux_set) |
371 |
++ dpcd_buf = DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD; |
372 |
++ else |
373 |
++ dpcd_buf = DP_EDP_BACKLIGHT_CONTROL_MODE_PWM; |
374 |
+ |
375 |
+ if (bl->pwmgen_bit_count) { |
376 |
+ ret = drm_dp_dpcd_writeb(aux, DP_EDP_PWMGEN_BIT_COUNT, bl->pwmgen_bit_count); |
377 |
+@@ -3405,12 +3414,13 @@ EXPORT_SYMBOL(drm_edp_backlight_enable); |
378 |
+ * @aux: The DP AUX channel to use |
379 |
+ * @bl: Backlight capability info from drm_edp_backlight_init() |
380 |
+ * |
381 |
+- * This function handles disabling DPCD backlight controls on a panel over AUX. Note that some |
382 |
+- * panels have backlights that are enabled/disabled by other means, despite having their brightness |
383 |
+- * values controlled through DPCD. On such panels &drm_edp_backlight_info.aux_enable will be set to |
384 |
+- * %false, this function will become a no-op (and we will skip updating |
385 |
+- * %DP_EDP_DISPLAY_CONTROL_REGISTER), and the driver must take care to perform it's own |
386 |
+- * implementation specific step for disabling the backlight. |
387 |
++ * This function handles disabling DPCD backlight controls on a panel over AUX. |
388 |
++ * |
389 |
++ * Note that certain panels do not support being enabled or disabled via DPCD, but instead require |
390 |
++ * that the driver handle enabling/disabling the panel through implementation-specific means using |
391 |
++ * the EDP_BL_PWR GPIO. For such panels, &drm_edp_backlight_info.aux_enable will be set to %false, |
392 |
++ * this function becomes a no-op, and the driver is expected to handle powering the panel off using |
393 |
++ * the EDP_BL_PWR GPIO. |
394 |
+ * |
395 |
+ * Returns: %0 on success or no-op, negative error code on failure. |
396 |
+ */ |
397 |
+@@ -3434,6 +3444,9 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf |
398 |
+ int ret; |
399 |
+ u8 pn, pn_min, pn_max; |
400 |
+ |
401 |
++ if (!bl->aux_set) |
402 |
++ return 0; |
403 |
++ |
404 |
+ ret = drm_dp_dpcd_readb(aux, DP_EDP_PWMGEN_BIT_COUNT, &pn); |
405 |
+ if (ret != 1) { |
406 |
+ drm_dbg_kms(aux->drm_dev, "%s: Failed to read pwmgen bit count cap: %d\n", |
407 |
+@@ -3519,7 +3532,7 @@ drm_edp_backlight_probe_max(struct drm_dp_aux *aux, struct drm_edp_backlight_inf |
408 |
+ } |
409 |
+ |
410 |
+ static inline int |
411 |
+-drm_edp_backlight_probe_level(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl, |
412 |
++drm_edp_backlight_probe_state(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl, |
413 |
+ u8 *current_mode) |
414 |
+ { |
415 |
+ int ret; |
416 |
+@@ -3534,6 +3547,9 @@ drm_edp_backlight_probe_level(struct drm_dp_aux *aux, struct drm_edp_backlight_i |
417 |
+ } |
418 |
+ |
419 |
+ *current_mode = (mode_reg & DP_EDP_BACKLIGHT_CONTROL_MODE_MASK); |
420 |
++ if (!bl->aux_set) |
421 |
++ return 0; |
422 |
++ |
423 |
+ if (*current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
424 |
+ int size = 1 + bl->lsb_reg_used; |
425 |
+ |
426 |
+@@ -3564,7 +3580,7 @@ drm_edp_backlight_probe_level(struct drm_dp_aux *aux, struct drm_edp_backlight_i |
427 |
+ * @bl: The &drm_edp_backlight_info struct to fill out with information on the backlight |
428 |
+ * @driver_pwm_freq_hz: Optional PWM frequency from the driver in hz |
429 |
+ * @edp_dpcd: A cached copy of the eDP DPCD |
430 |
+- * @current_level: Where to store the probed brightness level |
431 |
++ * @current_level: Where to store the probed brightness level, if any |
432 |
+ * @current_mode: Where to store the currently set backlight control mode |
433 |
+ * |
434 |
+ * Initializes a &drm_edp_backlight_info struct by probing @aux for it's backlight capabilities, |
435 |
+@@ -3584,24 +3600,38 @@ drm_edp_backlight_init(struct drm_dp_aux *aux, struct drm_edp_backlight_info *bl |
436 |
+ |
437 |
+ if (edp_dpcd[1] & DP_EDP_BACKLIGHT_AUX_ENABLE_CAP) |
438 |
+ bl->aux_enable = true; |
439 |
++ if (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP) |
440 |
++ bl->aux_set = true; |
441 |
+ if (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_BYTE_COUNT) |
442 |
+ bl->lsb_reg_used = true; |
443 |
+ |
444 |
++ /* Sanity check caps */ |
445 |
++ if (!bl->aux_set && !(edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_PWM_PIN_CAP)) { |
446 |
++ drm_dbg_kms(aux->drm_dev, |
447 |
++ "%s: Panel supports neither AUX or PWM brightness control? Aborting\n", |
448 |
++ aux->name); |
449 |
++ return -EINVAL; |
450 |
++ } |
451 |
++ |
452 |
+ ret = drm_edp_backlight_probe_max(aux, bl, driver_pwm_freq_hz, edp_dpcd); |
453 |
+ if (ret < 0) |
454 |
+ return ret; |
455 |
+ |
456 |
+- ret = drm_edp_backlight_probe_level(aux, bl, current_mode); |
457 |
++ ret = drm_edp_backlight_probe_state(aux, bl, current_mode); |
458 |
+ if (ret < 0) |
459 |
+ return ret; |
460 |
+ *current_level = ret; |
461 |
+ |
462 |
+ drm_dbg_kms(aux->drm_dev, |
463 |
+- "%s: Found backlight level=%d/%d pwm_freq_pre_divider=%d mode=%x\n", |
464 |
+- aux->name, *current_level, bl->max, bl->pwm_freq_pre_divider, *current_mode); |
465 |
+- drm_dbg_kms(aux->drm_dev, |
466 |
+- "%s: Backlight caps: pwmgen_bit_count=%d lsb_reg_used=%d aux_enable=%d\n", |
467 |
+- aux->name, bl->pwmgen_bit_count, bl->lsb_reg_used, bl->aux_enable); |
468 |
++ "%s: Found backlight: aux_set=%d aux_enable=%d mode=%d\n", |
469 |
++ aux->name, bl->aux_set, bl->aux_enable, *current_mode); |
470 |
++ if (bl->aux_set) { |
471 |
++ drm_dbg_kms(aux->drm_dev, |
472 |
++ "%s: Backlight caps: level=%d/%d pwm_freq_pre_divider=%d lsb_reg_used=%d\n", |
473 |
++ aux->name, *current_level, bl->max, bl->pwm_freq_pre_divider, |
474 |
++ bl->lsb_reg_used); |
475 |
++ } |
476 |
++ |
477 |
+ return 0; |
478 |
+ } |
479 |
+ EXPORT_SYMBOL(drm_edp_backlight_init); |
480 |
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
481 |
+index f05b71c01b8e..96fe3eaba44a 100644 |
482 |
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
483 |
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
484 |
+@@ -282,6 +282,12 @@ intel_dp_aux_vesa_set_backlight(const struct drm_connector_state *conn_state, u3 |
485 |
+ struct intel_panel *panel = &connector->panel; |
486 |
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
487 |
+ |
488 |
++ if (!panel->backlight.edp.vesa.info.aux_set) { |
489 |
++ const u32 pwm_level = intel_backlight_level_to_pwm(connector, level); |
490 |
++ |
491 |
++ intel_backlight_set_pwm_level(conn_state, pwm_level); |
492 |
++ } |
493 |
++ |
494 |
+ drm_edp_backlight_set_level(&intel_dp->aux, &panel->backlight.edp.vesa.info, level); |
495 |
+ } |
496 |
+ |
497 |
+@@ -294,8 +300,13 @@ intel_dp_aux_vesa_enable_backlight(const struct intel_crtc_state *crtc_state, |
498 |
+ struct intel_dp *intel_dp = enc_to_intel_dp(connector->encoder); |
499 |
+ |
500 |
+ if (!panel->backlight.edp.vesa.info.aux_enable) { |
501 |
+- u32 pwm_level = intel_backlight_invert_pwm_level(connector, |
502 |
+- panel->backlight.pwm_level_max); |
503 |
++ u32 pwm_level; |
504 |
++ |
505 |
++ if (!panel->backlight.edp.vesa.info.aux_set) |
506 |
++ pwm_level = intel_backlight_level_to_pwm(connector, level); |
507 |
++ else |
508 |
++ pwm_level = intel_backlight_invert_pwm_level(connector, |
509 |
++ panel->backlight.pwm_level_max); |
510 |
+ |
511 |
+ panel->backlight.pwm_funcs->enable(crtc_state, conn_state, pwm_level); |
512 |
+ } |
513 |
+@@ -332,7 +343,7 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, |
514 |
+ if (ret < 0) |
515 |
+ return ret; |
516 |
+ |
517 |
+- if (!panel->backlight.edp.vesa.info.aux_enable) { |
518 |
++ if (!panel->backlight.edp.vesa.info.aux_set || !panel->backlight.edp.vesa.info.aux_enable) { |
519 |
+ ret = panel->backlight.pwm_funcs->setup(connector, pipe); |
520 |
+ if (ret < 0) { |
521 |
+ drm_err(&i915->drm, |
522 |
+@@ -341,14 +352,27 @@ static int intel_dp_aux_vesa_setup_backlight(struct intel_connector *connector, |
523 |
+ return ret; |
524 |
+ } |
525 |
+ } |
526 |
+- panel->backlight.max = panel->backlight.edp.vesa.info.max; |
527 |
+- panel->backlight.min = 0; |
528 |
+- if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
529 |
+- panel->backlight.level = current_level; |
530 |
+- panel->backlight.enabled = panel->backlight.level != 0; |
531 |
++ |
532 |
++ if (panel->backlight.edp.vesa.info.aux_set) { |
533 |
++ panel->backlight.max = panel->backlight.edp.vesa.info.max; |
534 |
++ panel->backlight.min = 0; |
535 |
++ if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_DPCD) { |
536 |
++ panel->backlight.level = current_level; |
537 |
++ panel->backlight.enabled = panel->backlight.level != 0; |
538 |
++ } else { |
539 |
++ panel->backlight.level = panel->backlight.max; |
540 |
++ panel->backlight.enabled = false; |
541 |
++ } |
542 |
+ } else { |
543 |
+- panel->backlight.level = panel->backlight.max; |
544 |
+- panel->backlight.enabled = false; |
545 |
++ panel->backlight.max = panel->backlight.pwm_level_max; |
546 |
++ panel->backlight.min = panel->backlight.pwm_level_min; |
547 |
++ if (current_mode == DP_EDP_BACKLIGHT_CONTROL_MODE_PWM) { |
548 |
++ panel->backlight.level = panel->backlight.pwm_funcs->get(connector, pipe); |
549 |
++ panel->backlight.enabled = panel->backlight.pwm_enabled; |
550 |
++ } else { |
551 |
++ panel->backlight.level = panel->backlight.max; |
552 |
++ panel->backlight.enabled = false; |
553 |
++ } |
554 |
+ } |
555 |
+ |
556 |
+ return 0; |
557 |
+diff --git a/include/drm/drm_dp_helper.h b/include/drm/drm_dp_helper.h |
558 |
+index afdf7f4183f9..8b2ed4199284 100644 |
559 |
+--- a/include/drm/drm_dp_helper.h |
560 |
++++ b/include/drm/drm_dp_helper.h |
561 |
+@@ -1868,7 +1868,7 @@ drm_dp_sink_can_do_video_without_timing_msa(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) |
562 |
+ * |
563 |
+ * Note that currently this function will return %false for panels which support various DPCD |
564 |
+ * backlight features but which require the brightness be set through PWM, and don't support setting |
565 |
+- * the brightness level via the DPCD. This is a TODO. |
566 |
++ * the brightness level via the DPCD. |
567 |
+ * |
568 |
+ * Returns: %True if @edp_dpcd indicates that VESA backlight controls are supported, %false |
569 |
+ * otherwise |
570 |
+@@ -1876,8 +1876,7 @@ drm_dp_sink_can_do_video_without_timing_msa(const u8 dpcd[DP_RECEIVER_CAP_SIZE]) |
571 |
+ static inline bool |
572 |
+ drm_edp_backlight_supported(const u8 edp_dpcd[EDP_DISPLAY_CTL_CAP_SIZE]) |
573 |
+ { |
574 |
+- return (edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP) && |
575 |
+- (edp_dpcd[2] & DP_EDP_BACKLIGHT_BRIGHTNESS_AUX_SET_CAP); |
576 |
++ return !!(edp_dpcd[1] & DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP); |
577 |
+ } |
578 |
+ |
579 |
+ /* |
580 |
+@@ -2238,6 +2237,7 @@ drm_dp_has_quirk(const struct drm_dp_desc *desc, enum drm_dp_quirk quirk) |
581 |
+ * @max: The maximum backlight level that may be set |
582 |
+ * @lsb_reg_used: Do we also write values to the DP_EDP_BACKLIGHT_BRIGHTNESS_LSB register? |
583 |
+ * @aux_enable: Does the panel support the AUX enable cap? |
584 |
++ * @aux_set: Does the panel support setting the brightness through AUX? |
585 |
+ * |
586 |
+ * This structure contains various data about an eDP backlight, which can be populated by using |
587 |
+ * drm_edp_backlight_init(). |
588 |
+@@ -2249,6 +2249,7 @@ struct drm_edp_backlight_info { |
589 |
+ |
590 |
+ bool lsb_reg_used : 1; |
591 |
+ bool aux_enable : 1; |
592 |
++ bool aux_set : 1; |
593 |
+ }; |
594 |
+ |
595 |
+ int |
596 |
+ |
597 |
+From patchwork Fri Nov 5 18:33:42 2021 |
598 |
+Content-Type: text/plain; charset="utf-8" |
599 |
+MIME-Version: 1.0 |
600 |
+Content-Transfer-Encoding: 8bit |
601 |
+Subject: [v5,5/5] drm/i915: Clarify probing order in |
602 |
+ intel_dp_aux_init_backlight_funcs() |
603 |
+From: Lyude Paul <lyude@××××××.com> |
604 |
+X-Patchwork-Id: 462382 |
605 |
+Message-Id: <20211105183342.130810-6-lyude@××××××.com> |
606 |
+To: dri-devel@×××××××××××××××××.org, nouveau@×××××××××××××××××.org, |
607 |
+ intel-gfx@×××××××××××××××××.org |
608 |
+Cc: David Airlie <airlied@×××××.ie>, open list <linux-kernel@×××××××××××.org> |
609 |
+Date: Fri, 5 Nov 2021 14:33:42 -0400 |
610 |
+ |
611 |
+Hooray! We've managed to hit enough bugs upstream that I've been able to |
612 |
+come up with a pretty solid explanation for how backlight controls are |
613 |
+actually supposed to be detected and used these days. As well, having the |
614 |
+rest of the PWM bits in VESA's backlight interface implemented seems to |
615 |
+have fixed all of the problematic brightness controls laptop panels that |
616 |
+we've hit so far. |
617 |
+ |
618 |
+So, let's actually document this instead of just calling the laptop panels |
619 |
+liars. As well, I would like to formally apologize to all of the laptop |
620 |
+panels I called liars. I'm sorry laptop panels, hopefully you can all |
621 |
+forgive me and we can move past this~ |
622 |
+ |
623 |
+Signed-off-by: Lyude Paul <lyude@××××××.com> |
624 |
+Acked-by: Ville Syrjälä <ville.syrjala@×××××××××××.com> |
625 |
+--- |
626 |
+ .../drm/i915/display/intel_dp_aux_backlight.c | 16 +++++++++++----- |
627 |
+ 1 file changed, 11 insertions(+), 5 deletions(-) |
628 |
+ |
629 |
+diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
630 |
+index 96fe3eaba44a..8b9c925c4c16 100644 |
631 |
+--- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
632 |
++++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c |
633 |
+@@ -456,11 +456,17 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) |
634 |
+ } |
635 |
+ |
636 |
+ /* |
637 |
+- * A lot of eDP panels in the wild will report supporting both the |
638 |
+- * Intel proprietary backlight control interface, and the VESA |
639 |
+- * backlight control interface. Many of these panels are liars though, |
640 |
+- * and will only work with the Intel interface. So, always probe for |
641 |
+- * that first. |
642 |
++ * Since Intel has their own backlight control interface, the majority of machines out there |
643 |
++ * using DPCD backlight controls with Intel GPUs will be using this interface as opposed to |
644 |
++ * the VESA interface. However, other GPUs (such as Nvidia's) will always use the VESA |
645 |
++ * interface. This means that there's quite a number of panels out there that will advertise |
646 |
++ * support for both interfaces, primarily systems with Intel/Nvidia hybrid GPU setups. |
647 |
++ * |
648 |
++ * There's a catch to this though: on many panels that advertise support for both |
649 |
++ * interfaces, the VESA backlight interface will stop working once we've programmed the |
650 |
++ * panel with Intel's OUI - which is also required for us to be able to detect Intel's |
651 |
++ * backlight interface at all. This means that the only sensible way for us to detect both |
652 |
++ * interfaces is to probe for Intel's first, and VESA's second. |
653 |
+ */ |
654 |
+ if (try_intel_interface && intel_dp_aux_supports_hdr_backlight(connector)) { |
655 |
+ drm_dbg_kms(dev, "Using Intel proprietary eDP backlight controls\n"); |