1// SPDX-License-Identifier: MIT
2/*
3 * Copyright © 2021 Intel Corporation
4 */
5
6#include <linux/backlight.h>
7#include <linux/kernel.h>
8#include <linux/pwm.h>
9#include <linux/string_helpers.h>
10#include <acpi/video.h>
11
12#include <drm/drm_file.h>
13#include <drm/drm_print.h>
14
15#include "i915_reg.h"
16#include "i915_utils.h"
17#include "intel_backlight.h"
18#include "intel_backlight_regs.h"
19#include "intel_connector.h"
20#include "intel_de.h"
21#include "intel_display_regs.h"
22#include "intel_display_rpm.h"
23#include "intel_display_types.h"
24#include "intel_dp_aux_backlight.h"
25#include "intel_dsi_dcs_backlight.h"
26#include "intel_panel.h"
27#include "intel_pci_config.h"
28#include "intel_pps.h"
29#include "intel_quirks.h"
30
31/**
32 * scale - scale values from one range to another
33 * @source_val: value in range [@source_min..@source_max]
34 * @source_min: minimum legal value for @source_val
35 * @source_max: maximum legal value for @source_val
36 * @target_min: corresponding target value for @source_min
37 * @target_max: corresponding target value for @source_max
38 *
39 * Return @source_val in range [@source_min..@source_max] scaled to range
40 * [@target_min..@target_max].
41 */
42static u32 scale(u32 source_val,
43 u32 source_min, u32 source_max,
44 u32 target_min, u32 target_max)
45{
46 u64 target_val;
47
48 if (WARN_ON(source_min >= source_max) ||
49 WARN_ON(target_min > target_max))
50 return target_min;
51
52 /* defensive */
53 source_val = clamp(source_val, source_min, source_max);
54
55 /* avoid overflows */
56 target_val = mul_u32_u32(a: source_val - source_min,
57 b: target_max - target_min);
58 target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min);
59 target_val += target_min;
60
61 return target_val;
62}
63
64/*
65 * Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
66 * to [hw_min..hw_max].
67 */
68static u32 clamp_user_to_hw(struct intel_connector *connector,
69 u32 user_level, u32 user_max)
70{
71 struct intel_panel *panel = &connector->panel;
72 u32 hw_level;
73
74 hw_level = scale(source_val: user_level, source_min: 0, source_max: user_max, target_min: 0, target_max: panel->backlight.max);
75 hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
76
77 return hw_level;
78}
79
80/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
81static u32 scale_hw_to_user(struct intel_connector *connector,
82 u32 hw_level, u32 user_max)
83{
84 struct intel_panel *panel = &connector->panel;
85
86 return scale(source_val: hw_level, source_min: panel->backlight.min, source_max: panel->backlight.max,
87 target_min: 0, target_max: user_max);
88}
89
90u32 intel_backlight_invert_pwm_level(struct intel_connector *connector, u32 val)
91{
92 struct intel_display *display = to_intel_display(connector);
93 struct intel_panel *panel = &connector->panel;
94
95 drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0);
96
97 if (display->params.invert_brightness < 0)
98 return val;
99
100 if (display->params.invert_brightness > 0 ||
101 intel_has_quirk(display, quirk: QUIRK_INVERT_BRIGHTNESS)) {
102 return panel->backlight.pwm_level_max - val + panel->backlight.pwm_level_min;
103 }
104
105 return val;
106}
107
108void intel_backlight_set_pwm_level(const struct drm_connector_state *conn_state, u32 val)
109{
110 struct intel_connector *connector = to_intel_connector(conn_state->connector);
111 struct intel_display *display = to_intel_display(connector);
112 struct intel_panel *panel = &connector->panel;
113
114 drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] set backlight PWM = %d\n",
115 connector->base.base.id, connector->base.name, val);
116 panel->backlight.pwm_funcs->set(conn_state, val);
117}
118
119u32 intel_backlight_level_to_pwm(struct intel_connector *connector, u32 val)
120{
121 struct intel_display *display = to_intel_display(connector);
122 struct intel_panel *panel = &connector->panel;
123
124 drm_WARN_ON_ONCE(display->drm,
125 panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0);
126
127 val = scale(source_val: val, source_min: panel->backlight.min, source_max: panel->backlight.max,
128 target_min: panel->backlight.pwm_level_min, target_max: panel->backlight.pwm_level_max);
129
130 return intel_backlight_invert_pwm_level(connector, val);
131}
132
133u32 intel_backlight_level_from_pwm(struct intel_connector *connector, u32 val)
134{
135 struct intel_display *display = to_intel_display(connector);
136 struct intel_panel *panel = &connector->panel;
137
138 drm_WARN_ON_ONCE(display->drm,
139 panel->backlight.max == 0 || panel->backlight.pwm_level_max == 0);
140
141 if (display->params.invert_brightness > 0 ||
142 (display->params.invert_brightness == 0 &&
143 intel_has_quirk(display, quirk: QUIRK_INVERT_BRIGHTNESS)))
144 val = panel->backlight.pwm_level_max - (val - panel->backlight.pwm_level_min);
145
146 return scale(source_val: val, source_min: panel->backlight.pwm_level_min, source_max: panel->backlight.pwm_level_max,
147 target_min: panel->backlight.min, target_max: panel->backlight.max);
148}
149
150static u32 lpt_get_backlight(struct intel_connector *connector, enum pipe unused)
151{
152 struct intel_display *display = to_intel_display(connector);
153
154 return intel_de_read(display, BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
155}
156
157static u32 pch_get_backlight(struct intel_connector *connector, enum pipe unused)
158{
159 struct intel_display *display = to_intel_display(connector);
160
161 return intel_de_read(display, BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
162}
163
164static u32 i9xx_get_backlight(struct intel_connector *connector, enum pipe unused)
165{
166 struct intel_display *display = to_intel_display(connector);
167 struct intel_panel *panel = &connector->panel;
168 u32 val;
169
170 val = intel_de_read(display, BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
171 if (DISPLAY_VER(display) < 4)
172 val >>= 1;
173
174 if (panel->backlight.combination_mode) {
175 struct pci_dev *pdev = to_pci_dev(display->drm->dev);
176 u8 lbpc;
177
178 pci_read_config_byte(dev: pdev, LBPC, val: &lbpc);
179 val *= lbpc;
180 }
181
182 return val;
183}
184
185static u32 vlv_get_backlight(struct intel_connector *connector, enum pipe pipe)
186{
187 struct intel_display *display = to_intel_display(connector);
188
189 if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B))
190 return 0;
191
192 return intel_de_read(display, VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
193}
194
195static u32 bxt_get_backlight(struct intel_connector *connector, enum pipe unused)
196{
197 struct intel_display *display = to_intel_display(connector);
198 struct intel_panel *panel = &connector->panel;
199
200 return intel_de_read(display, BXT_BLC_PWM_DUTY(panel->backlight.controller));
201}
202
203static u32 ext_pwm_get_backlight(struct intel_connector *connector, enum pipe unused)
204{
205 struct intel_panel *panel = &connector->panel;
206 struct pwm_state state;
207
208 pwm_get_state(pwm: panel->backlight.pwm, state: &state);
209 return pwm_get_relative_duty_cycle(state: &state, scale: 100);
210}
211
212static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
213{
214 struct intel_connector *connector = to_intel_connector(conn_state->connector);
215 struct intel_display *display = to_intel_display(connector);
216 u32 val;
217
218 val = intel_de_read(display, BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
219 intel_de_write(display, BLC_PWM_PCH_CTL2, val: val | level);
220}
221
222static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level)
223{
224 struct intel_connector *connector = to_intel_connector(conn_state->connector);
225 struct intel_display *display = to_intel_display(connector);
226 u32 tmp;
227
228 tmp = intel_de_read(display, BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
229 intel_de_write(display, BLC_PWM_CPU_CTL, val: tmp | level);
230}
231
232static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level)
233{
234 struct intel_connector *connector = to_intel_connector(conn_state->connector);
235 struct intel_display *display = to_intel_display(connector);
236 struct intel_panel *panel = &connector->panel;
237 u32 tmp, mask;
238
239 if (drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0))
240 return;
241
242 if (panel->backlight.combination_mode) {
243 struct pci_dev *pdev = to_pci_dev(display->drm->dev);
244 u8 lbpc;
245
246 lbpc = level * 0xfe / panel->backlight.pwm_level_max + 1;
247 level /= lbpc;
248 pci_write_config_byte(dev: pdev, LBPC, val: lbpc);
249 }
250
251 if (DISPLAY_VER(display) == 4) {
252 mask = BACKLIGHT_DUTY_CYCLE_MASK;
253 } else {
254 level <<= 1;
255 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
256 }
257
258 tmp = intel_de_read(display, BLC_PWM_CTL) & ~mask;
259 intel_de_write(display, BLC_PWM_CTL, val: tmp | level);
260}
261
262static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level)
263{
264 struct intel_connector *connector = to_intel_connector(conn_state->connector);
265 struct intel_display *display = to_intel_display(connector);
266 enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe;
267 u32 tmp;
268
269 tmp = intel_de_read(display, VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
270 intel_de_write(display, VLV_BLC_PWM_CTL(pipe), val: tmp | level);
271}
272
273static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
274{
275 struct intel_connector *connector = to_intel_connector(conn_state->connector);
276 struct intel_display *display = to_intel_display(connector);
277 struct intel_panel *panel = &connector->panel;
278
279 intel_de_write(display, BXT_BLC_PWM_DUTY(panel->backlight.controller), val: level);
280}
281
282static void ext_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
283{
284 struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
285
286 pwm_set_relative_duty_cycle(state: &panel->backlight.pwm_state, duty_cycle: level, scale: 100);
287 pwm_apply_might_sleep(pwm: panel->backlight.pwm, state: &panel->backlight.pwm_state);
288}
289
290static void
291intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state, u32 level)
292{
293 struct intel_connector *connector = to_intel_connector(conn_state->connector);
294 struct intel_display *display = to_intel_display(connector);
295 struct intel_panel *panel = &connector->panel;
296
297 drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] set backlight level = %d\n",
298 connector->base.base.id, connector->base.name, level);
299
300 panel->backlight.funcs->set(conn_state, level);
301}
302
303/* set backlight brightness to level in range [0..max], assuming hw min is
304 * respected.
305 */
306void intel_backlight_set_acpi(const struct drm_connector_state *conn_state,
307 u32 user_level, u32 user_max)
308{
309 struct intel_connector *connector = to_intel_connector(conn_state->connector);
310 struct intel_display *display = to_intel_display(connector);
311 struct intel_panel *panel = &connector->panel;
312 u32 hw_level;
313
314 /*
315 * Lack of crtc may occur during driver init because
316 * connection_mutex isn't held across the entire backlight
317 * setup + modeset readout, and the BIOS can issue the
318 * requests at any time.
319 */
320 if (!panel->backlight.present || !conn_state->crtc)
321 return;
322
323 mutex_lock(lock: &display->backlight.lock);
324
325 drm_WARN_ON(display->drm, panel->backlight.max == 0);
326
327 hw_level = clamp_user_to_hw(connector, user_level, user_max);
328 panel->backlight.level = hw_level;
329
330 if (panel->backlight.device)
331 panel->backlight.device->props.brightness =
332 scale_hw_to_user(connector,
333 hw_level: panel->backlight.level,
334 user_max: panel->backlight.device->props.max_brightness);
335
336 if (panel->backlight.enabled)
337 intel_panel_actually_set_backlight(conn_state, level: hw_level);
338
339 mutex_unlock(lock: &display->backlight.lock);
340}
341
342static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
343{
344 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
345 struct intel_display *display = to_intel_display(connector);
346 u32 tmp;
347
348 intel_backlight_set_pwm_level(conn_state: old_conn_state, val: level);
349
350 /*
351 * Although we don't support or enable CPU PWM with LPT/SPT based
352 * systems, it may have been enabled prior to loading the
353 * driver. Disable to avoid warnings on LCPLL disable.
354 *
355 * This needs rework if we need to add support for CPU PWM on PCH split
356 * platforms.
357 */
358 tmp = intel_de_read(display, BLC_PWM_CPU_CTL2);
359 if (tmp & BLM_PWM_ENABLE) {
360 drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] CPU backlight was enabled, disabling\n",
361 connector->base.base.id, connector->base.name);
362 intel_de_write(display, BLC_PWM_CPU_CTL2, val: tmp & ~BLM_PWM_ENABLE);
363 }
364
365 intel_de_rmw(display, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, set: 0);
366}
367
368static void pch_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
369{
370 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
371 struct intel_display *display = to_intel_display(connector);
372
373 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
374
375 intel_de_rmw(display, BLC_PWM_CPU_CTL2, BLM_PWM_ENABLE, set: 0);
376
377 intel_de_rmw(display, BLC_PWM_PCH_CTL1, BLM_PCH_PWM_ENABLE, set: 0);
378}
379
380static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
381{
382 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
383}
384
385static void i965_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
386{
387 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
388 struct intel_display *display = to_intel_display(connector);
389
390 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
391
392 intel_de_rmw(display, BLC_PWM_CTL2, BLM_PWM_ENABLE, set: 0);
393}
394
395static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
396{
397 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
398 struct intel_display *display = to_intel_display(connector);
399 enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe;
400
401 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
402
403 intel_de_rmw(display, VLV_BLC_PWM_CTL2(pipe), BLM_PWM_ENABLE, set: 0);
404}
405
406static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
407{
408 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
409 struct intel_display *display = to_intel_display(connector);
410 struct intel_panel *panel = &connector->panel;
411
412 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
413
414 intel_de_rmw(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
415 BXT_BLC_PWM_ENABLE, set: 0);
416
417 if (panel->backlight.controller == 1)
418 intel_de_rmw(display, UTIL_PIN_CTL, UTIL_PIN_ENABLE, set: 0);
419}
420
421static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state, u32 val)
422{
423 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
424 struct intel_display *display = to_intel_display(connector);
425 struct intel_panel *panel = &connector->panel;
426
427 intel_backlight_set_pwm_level(conn_state: old_conn_state, val);
428
429 intel_de_rmw(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
430 BXT_BLC_PWM_ENABLE, set: 0);
431}
432
433static void ext_pwm_disable_backlight(const struct drm_connector_state *old_conn_state, u32 level)
434{
435 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
436 struct intel_panel *panel = &connector->panel;
437
438 intel_backlight_set_pwm_level(conn_state: old_conn_state, val: level);
439
440 panel->backlight.pwm_state.enabled = false;
441 pwm_apply_might_sleep(pwm: panel->backlight.pwm, state: &panel->backlight.pwm_state);
442}
443
444void intel_backlight_disable(const struct drm_connector_state *old_conn_state)
445{
446 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
447 struct intel_display *display = to_intel_display(connector);
448 struct intel_panel *panel = &connector->panel;
449
450 if (!panel->backlight.present)
451 return;
452
453 /*
454 * Do not disable backlight on the vga_switcheroo path. When switching
455 * away from i915, the other client may depend on i915 to handle the
456 * backlight. This will leave the backlight on unnecessarily when
457 * another client is not activated.
458 */
459 if (display->drm->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
460 drm_dbg_kms(display->drm, "[CONNECTOR:%d:%s] Skipping backlight disable on vga switch\n",
461 connector->base.base.id, connector->base.name);
462 return;
463 }
464
465 mutex_lock(lock: &display->backlight.lock);
466
467 if (panel->backlight.device)
468 panel->backlight.device->props.power = BACKLIGHT_POWER_OFF;
469 panel->backlight.enabled = false;
470 panel->backlight.funcs->disable(old_conn_state, 0);
471
472 mutex_unlock(lock: &display->backlight.lock);
473}
474
475static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
476 const struct drm_connector_state *conn_state, u32 level)
477{
478 struct intel_connector *connector = to_intel_connector(conn_state->connector);
479 struct intel_display *display = to_intel_display(connector);
480 struct intel_panel *panel = &connector->panel;
481 u32 pch_ctl1, pch_ctl2;
482
483 pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1);
484 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
485 drm_dbg_kms(display->drm,
486 "[CONNECTOR:%d:%s] PCH backlight already enabled\n",
487 connector->base.base.id, connector->base.name);
488 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
489 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1);
490 }
491
492 if (HAS_PCH_LPT(display))
493 intel_de_rmw(display, SOUTH_CHICKEN2, LPT_PWM_GRANULARITY,
494 set: panel->backlight.alternate_pwm_increment ?
495 LPT_PWM_GRANULARITY : 0);
496 else
497 intel_de_rmw(display, SOUTH_CHICKEN1, SPT_PWM_GRANULARITY,
498 set: panel->backlight.alternate_pwm_increment ?
499 SPT_PWM_GRANULARITY : 0);
500
501 pch_ctl2 = panel->backlight.pwm_level_max << 16;
502 intel_de_write(display, BLC_PWM_PCH_CTL2, val: pch_ctl2);
503
504 pch_ctl1 = 0;
505 if (panel->backlight.active_low_pwm)
506 pch_ctl1 |= BLM_PCH_POLARITY;
507
508 /* After LPT, override is the default. */
509 if (HAS_PCH_LPT(display))
510 pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
511
512 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1);
513 intel_de_posting_read(display, BLC_PWM_PCH_CTL1);
514 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1 | BLM_PCH_PWM_ENABLE);
515
516 /* This won't stick until the above enable. */
517 intel_backlight_set_pwm_level(conn_state, val: level);
518}
519
520static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
521 const struct drm_connector_state *conn_state, u32 level)
522{
523 struct intel_connector *connector = to_intel_connector(conn_state->connector);
524 struct intel_display *display = to_intel_display(connector);
525 struct intel_panel *panel = &connector->panel;
526 enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
527 u32 cpu_ctl2, pch_ctl1, pch_ctl2;
528
529 cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2);
530 if (cpu_ctl2 & BLM_PWM_ENABLE) {
531 drm_dbg_kms(display->drm,
532 "[CONNECTOR:%d:%s] CPU backlight already enabled\n",
533 connector->base.base.id, connector->base.name);
534 cpu_ctl2 &= ~BLM_PWM_ENABLE;
535 intel_de_write(display, BLC_PWM_CPU_CTL2, val: cpu_ctl2);
536 }
537
538 pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1);
539 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
540 drm_dbg_kms(display->drm,
541 "[CONNECTOR:%d:%s] PCH backlight already enabled\n",
542 connector->base.base.id, connector->base.name);
543 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
544 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1);
545 }
546
547 if (cpu_transcoder == TRANSCODER_EDP)
548 cpu_ctl2 = BLM_TRANSCODER_EDP;
549 else
550 cpu_ctl2 = BLM_PIPE(cpu_transcoder);
551 intel_de_write(display, BLC_PWM_CPU_CTL2, val: cpu_ctl2);
552 intel_de_posting_read(display, BLC_PWM_CPU_CTL2);
553 intel_de_write(display, BLC_PWM_CPU_CTL2, val: cpu_ctl2 | BLM_PWM_ENABLE);
554
555 /* This won't stick until the above enable. */
556 intel_backlight_set_pwm_level(conn_state, val: level);
557
558 pch_ctl2 = panel->backlight.pwm_level_max << 16;
559 intel_de_write(display, BLC_PWM_PCH_CTL2, val: pch_ctl2);
560
561 pch_ctl1 = 0;
562 if (panel->backlight.active_low_pwm)
563 pch_ctl1 |= BLM_PCH_POLARITY;
564
565 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1);
566 intel_de_posting_read(display, BLC_PWM_PCH_CTL1);
567 intel_de_write(display, BLC_PWM_PCH_CTL1, val: pch_ctl1 | BLM_PCH_PWM_ENABLE);
568}
569
570static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
571 const struct drm_connector_state *conn_state, u32 level)
572{
573 struct intel_connector *connector = to_intel_connector(conn_state->connector);
574 struct intel_display *display = to_intel_display(connector);
575 struct intel_panel *panel = &connector->panel;
576 u32 ctl, freq;
577
578 ctl = intel_de_read(display, BLC_PWM_CTL);
579 if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
580 drm_dbg_kms(display->drm,
581 "[CONNECTOR:%d:%s] backlight already enabled\n",
582 connector->base.base.id, connector->base.name);
583 intel_de_write(display, BLC_PWM_CTL, val: 0);
584 }
585
586 freq = panel->backlight.pwm_level_max;
587 if (panel->backlight.combination_mode)
588 freq /= 0xff;
589
590 ctl = freq << 17;
591 if (panel->backlight.combination_mode)
592 ctl |= BLM_LEGACY_MODE;
593 if (display->platform.pineview && panel->backlight.active_low_pwm)
594 ctl |= BLM_POLARITY_PNV;
595
596 intel_de_write(display, BLC_PWM_CTL, val: ctl);
597 intel_de_posting_read(display, BLC_PWM_CTL);
598
599 /* XXX: combine this into above write? */
600 intel_backlight_set_pwm_level(conn_state, val: level);
601
602 /*
603 * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is
604 * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
605 * that has backlight.
606 */
607 if (DISPLAY_VER(display) == 2)
608 intel_de_write(display, BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
609}
610
611static void i965_enable_backlight(const struct intel_crtc_state *crtc_state,
612 const struct drm_connector_state *conn_state, u32 level)
613{
614 struct intel_connector *connector = to_intel_connector(conn_state->connector);
615 struct intel_display *display = to_intel_display(connector);
616 struct intel_panel *panel = &connector->panel;
617 enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe;
618 u32 ctl, ctl2, freq;
619
620 ctl2 = intel_de_read(display, BLC_PWM_CTL2);
621 if (ctl2 & BLM_PWM_ENABLE) {
622 drm_dbg_kms(display->drm,
623 "[CONNECTOR:%d:%s] backlight already enabled\n",
624 connector->base.base.id, connector->base.name);
625 ctl2 &= ~BLM_PWM_ENABLE;
626 intel_de_write(display, BLC_PWM_CTL2, val: ctl2);
627 }
628
629 freq = panel->backlight.pwm_level_max;
630 if (panel->backlight.combination_mode)
631 freq /= 0xff;
632
633 ctl = freq << 16;
634 intel_de_write(display, BLC_PWM_CTL, val: ctl);
635
636 ctl2 = BLM_PIPE(pipe);
637 if (panel->backlight.combination_mode)
638 ctl2 |= BLM_COMBINATION_MODE;
639 if (panel->backlight.active_low_pwm)
640 ctl2 |= BLM_POLARITY_I965;
641 intel_de_write(display, BLC_PWM_CTL2, val: ctl2);
642 intel_de_posting_read(display, BLC_PWM_CTL2);
643 intel_de_write(display, BLC_PWM_CTL2, val: ctl2 | BLM_PWM_ENABLE);
644
645 intel_backlight_set_pwm_level(conn_state, val: level);
646}
647
648static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state,
649 const struct drm_connector_state *conn_state, u32 level)
650{
651 struct intel_connector *connector = to_intel_connector(conn_state->connector);
652 struct intel_display *display = to_intel_display(connector);
653 struct intel_panel *panel = &connector->panel;
654 enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
655 u32 ctl, ctl2;
656
657 ctl2 = intel_de_read(display, VLV_BLC_PWM_CTL2(pipe));
658 if (ctl2 & BLM_PWM_ENABLE) {
659 drm_dbg_kms(display->drm,
660 "[CONNECTOR:%d:%s] backlight already enabled\n",
661 connector->base.base.id, connector->base.name);
662 ctl2 &= ~BLM_PWM_ENABLE;
663 intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), val: ctl2);
664 }
665
666 ctl = panel->backlight.pwm_level_max << 16;
667 intel_de_write(display, VLV_BLC_PWM_CTL(pipe), val: ctl);
668
669 /* XXX: combine this into above write? */
670 intel_backlight_set_pwm_level(conn_state, val: level);
671
672 ctl2 = 0;
673 if (panel->backlight.active_low_pwm)
674 ctl2 |= BLM_POLARITY_I965;
675 intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), val: ctl2);
676 intel_de_posting_read(display, VLV_BLC_PWM_CTL2(pipe));
677 intel_de_write(display, VLV_BLC_PWM_CTL2(pipe), val: ctl2 | BLM_PWM_ENABLE);
678}
679
680static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state,
681 const struct drm_connector_state *conn_state, u32 level)
682{
683 struct intel_connector *connector = to_intel_connector(conn_state->connector);
684 struct intel_display *display = to_intel_display(connector);
685 struct intel_panel *panel = &connector->panel;
686 enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
687 u32 pwm_ctl, val;
688
689 /* Controller 1 uses the utility pin. */
690 if (panel->backlight.controller == 1) {
691 val = intel_de_read(display, UTIL_PIN_CTL);
692 if (val & UTIL_PIN_ENABLE) {
693 drm_dbg_kms(display->drm,
694 "[CONNECTOR:%d:%s] utility pin already enabled\n",
695 connector->base.base.id, connector->base.name);
696 val &= ~UTIL_PIN_ENABLE;
697 intel_de_write(display, UTIL_PIN_CTL, val);
698 }
699
700 val = 0;
701 if (panel->backlight.util_pin_active_low)
702 val |= UTIL_PIN_POLARITY;
703 intel_de_write(display, UTIL_PIN_CTL,
704 val: val | UTIL_PIN_PIPE(pipe) | UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE);
705 }
706
707 pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller));
708 if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
709 drm_dbg_kms(display->drm,
710 "[CONNECTOR:%d:%s] backlight already enabled\n",
711 connector->base.base.id, connector->base.name);
712 pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
713 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
714 val: pwm_ctl);
715 }
716
717 intel_de_write(display, BXT_BLC_PWM_FREQ(panel->backlight.controller),
718 val: panel->backlight.pwm_level_max);
719
720 intel_backlight_set_pwm_level(conn_state, val: level);
721
722 pwm_ctl = 0;
723 if (panel->backlight.active_low_pwm)
724 pwm_ctl |= BXT_BLC_PWM_POLARITY;
725
726 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), val: pwm_ctl);
727 intel_de_posting_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller));
728 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
729 val: pwm_ctl | BXT_BLC_PWM_ENABLE);
730}
731
732static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state,
733 const struct drm_connector_state *conn_state, u32 level)
734{
735 struct intel_connector *connector = to_intel_connector(conn_state->connector);
736 struct intel_display *display = to_intel_display(connector);
737 struct intel_panel *panel = &connector->panel;
738 u32 pwm_ctl;
739
740 pwm_ctl = intel_de_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller));
741 if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
742 drm_dbg_kms(display->drm, "backlight already enabled\n");
743 pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
744 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
745 val: pwm_ctl);
746 }
747
748 intel_de_write(display, BXT_BLC_PWM_FREQ(panel->backlight.controller),
749 val: panel->backlight.pwm_level_max);
750
751 intel_backlight_set_pwm_level(conn_state, val: level);
752
753 pwm_ctl = 0;
754 if (panel->backlight.active_low_pwm)
755 pwm_ctl |= BXT_BLC_PWM_POLARITY;
756
757 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller), val: pwm_ctl);
758 intel_de_posting_read(display, BXT_BLC_PWM_CTL(panel->backlight.controller));
759 intel_de_write(display, BXT_BLC_PWM_CTL(panel->backlight.controller),
760 val: pwm_ctl | BXT_BLC_PWM_ENABLE);
761}
762
763static void ext_pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
764 const struct drm_connector_state *conn_state, u32 level)
765{
766 struct intel_connector *connector = to_intel_connector(conn_state->connector);
767 struct intel_panel *panel = &connector->panel;
768
769 pwm_set_relative_duty_cycle(state: &panel->backlight.pwm_state, duty_cycle: level, scale: 100);
770 panel->backlight.pwm_state.enabled = true;
771 pwm_apply_might_sleep(pwm: panel->backlight.pwm, state: &panel->backlight.pwm_state);
772}
773
774static void __intel_backlight_enable(const struct intel_crtc_state *crtc_state,
775 const struct drm_connector_state *conn_state)
776{
777 struct intel_connector *connector = to_intel_connector(conn_state->connector);
778 struct intel_panel *panel = &connector->panel;
779
780 WARN_ON(panel->backlight.max == 0);
781
782 if (panel->backlight.level < panel->backlight.min) {
783 panel->backlight.level = panel->backlight.min;
784 if (panel->backlight.device)
785 panel->backlight.device->props.brightness =
786 scale_hw_to_user(connector,
787 hw_level: panel->backlight.level,
788 user_max: panel->backlight.device->props.max_brightness);
789 }
790
791 panel->backlight.funcs->enable(crtc_state, conn_state, panel->backlight.level);
792 panel->backlight.enabled = true;
793 if (panel->backlight.device)
794 panel->backlight.device->props.power = BACKLIGHT_POWER_ON;
795}
796
797void intel_backlight_enable(const struct intel_crtc_state *crtc_state,
798 const struct drm_connector_state *conn_state)
799{
800 struct intel_connector *connector = to_intel_connector(conn_state->connector);
801 struct intel_display *display = to_intel_display(connector);
802 struct intel_panel *panel = &connector->panel;
803 enum pipe pipe = to_intel_crtc(crtc_state->uapi.crtc)->pipe;
804
805 if (!panel->backlight.present)
806 return;
807
808 drm_dbg_kms(display->drm, "pipe %c\n", pipe_name(pipe));
809
810 mutex_lock(lock: &display->backlight.lock);
811
812 __intel_backlight_enable(crtc_state, conn_state);
813
814 mutex_unlock(lock: &display->backlight.lock);
815}
816
817#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
818static u32 intel_panel_get_backlight(struct intel_connector *connector)
819{
820 struct intel_display *display = to_intel_display(connector);
821 struct intel_panel *panel = &connector->panel;
822 u32 val = 0;
823
824 mutex_lock(lock: &display->backlight.lock);
825
826 if (panel->backlight.enabled)
827 val = panel->backlight.funcs->get(connector, intel_connector_get_pipe(connector));
828
829 mutex_unlock(lock: &display->backlight.lock);
830
831 drm_dbg_kms(display->drm, "get backlight PWM = %d\n", val);
832 return val;
833}
834
835/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
836static u32 scale_user_to_hw(struct intel_connector *connector,
837 u32 user_level, u32 user_max)
838{
839 struct intel_panel *panel = &connector->panel;
840
841 return scale(source_val: user_level, source_min: 0, source_max: user_max,
842 target_min: panel->backlight.min, target_max: panel->backlight.max);
843}
844
845/* set backlight brightness to level in range [0..max], scaling wrt hw min */
846static void intel_panel_set_backlight(const struct drm_connector_state *conn_state,
847 u32 user_level, u32 user_max)
848{
849 struct intel_connector *connector = to_intel_connector(conn_state->connector);
850 struct intel_display *display = to_intel_display(connector);
851 struct intel_panel *panel = &connector->panel;
852 u32 hw_level;
853
854 if (!panel->backlight.present)
855 return;
856
857 mutex_lock(lock: &display->backlight.lock);
858
859 drm_WARN_ON(display->drm, panel->backlight.max == 0);
860
861 hw_level = scale_user_to_hw(connector, user_level, user_max);
862 panel->backlight.level = hw_level;
863
864 if (panel->backlight.enabled)
865 intel_panel_actually_set_backlight(conn_state, level: hw_level);
866
867 mutex_unlock(lock: &display->backlight.lock);
868}
869
870static int intel_backlight_device_update_status(struct backlight_device *bd)
871{
872 struct intel_connector *connector = bl_get_data(bl_dev: bd);
873 struct intel_display *display = to_intel_display(connector);
874 struct intel_panel *panel = &connector->panel;
875
876 drm_modeset_lock(lock: &display->drm->mode_config.connection_mutex, NULL);
877
878 drm_dbg_kms(display->drm, "updating intel_backlight, brightness=%d/%d\n",
879 bd->props.brightness, bd->props.max_brightness);
880 intel_panel_set_backlight(conn_state: connector->base.state, user_level: bd->props.brightness,
881 user_max: bd->props.max_brightness);
882
883 /*
884 * Allow flipping bl_power as a sub-state of enabled. Sadly the
885 * backlight class device does not make it easy to differentiate
886 * between callbacks for brightness and bl_power, so our backlight_power
887 * callback needs to take this into account.
888 */
889 if (panel->backlight.enabled) {
890 if (panel->backlight.power) {
891 bool enable = bd->props.power == BACKLIGHT_POWER_ON &&
892 bd->props.brightness != 0;
893 panel->backlight.power(connector, enable);
894 }
895 } else {
896 bd->props.power = BACKLIGHT_POWER_OFF;
897 }
898
899 drm_modeset_unlock(lock: &display->drm->mode_config.connection_mutex);
900
901 return 0;
902}
903
904static int intel_backlight_device_get_brightness(struct backlight_device *bd)
905{
906 struct intel_connector *connector = bl_get_data(bl_dev: bd);
907 struct intel_display *display = to_intel_display(connector);
908 int ret = 0;
909
910 with_intel_display_rpm(display) {
911 u32 hw_level;
912
913 drm_modeset_lock(lock: &display->drm->mode_config.connection_mutex, NULL);
914
915 hw_level = intel_panel_get_backlight(connector);
916 ret = scale_hw_to_user(connector,
917 hw_level, user_max: bd->props.max_brightness);
918
919 drm_modeset_unlock(lock: &display->drm->mode_config.connection_mutex);
920 }
921
922 return ret;
923}
924
925static const struct backlight_ops intel_backlight_device_ops = {
926 .update_status = intel_backlight_device_update_status,
927 .get_brightness = intel_backlight_device_get_brightness,
928};
929
930int intel_backlight_device_register(struct intel_connector *connector)
931{
932 struct intel_display *display = to_intel_display(connector);
933 struct intel_panel *panel = &connector->panel;
934 struct backlight_properties props;
935 struct backlight_device *bd;
936 const char *name;
937 int ret = 0;
938
939 if (WARN_ON(panel->backlight.device))
940 return -ENODEV;
941
942 if (!panel->backlight.present)
943 return 0;
944
945 WARN_ON(panel->backlight.max == 0);
946
947 if (!acpi_video_backlight_use_native()) {
948 drm_info(display->drm,
949 "Skipping intel_backlight registration\n");
950 return 0;
951 }
952
953 memset(s: &props, c: 0, n: sizeof(props));
954 props.type = BACKLIGHT_RAW;
955
956 /*
957 * Note: Everything should work even if the backlight device max
958 * presented to the userspace is arbitrarily chosen.
959 */
960 props.max_brightness = panel->backlight.max;
961 props.brightness = scale_hw_to_user(connector,
962 hw_level: panel->backlight.level,
963 user_max: props.max_brightness);
964
965 if (panel->backlight.enabled)
966 props.power = BACKLIGHT_POWER_ON;
967 else
968 props.power = BACKLIGHT_POWER_OFF;
969
970 name = kstrdup(s: "intel_backlight", GFP_KERNEL);
971 if (!name)
972 return -ENOMEM;
973
974 bd = backlight_device_get_by_name(name);
975 if (bd) {
976 put_device(dev: &bd->dev);
977 /*
978 * Using the same name independent of the drm device or connector
979 * prevents registration of multiple backlight devices in the
980 * driver. However, we need to use the default name for backward
981 * compatibility. Use unique names for subsequent backlight devices as a
982 * fallback when the default name already exists.
983 */
984 kfree(objp: name);
985 name = kasprintf(GFP_KERNEL, fmt: "card%d-%s-backlight",
986 display->drm->primary->index,
987 connector->base.name);
988 if (!name)
989 return -ENOMEM;
990 }
991 bd = backlight_device_register(name, dev: connector->base.kdev, devdata: connector,
992 ops: &intel_backlight_device_ops, props: &props);
993
994 if (IS_ERR(ptr: bd)) {
995 drm_err(display->drm,
996 "[CONNECTOR:%d:%s] backlight device %s register failed: %ld\n",
997 connector->base.base.id, connector->base.name, name, PTR_ERR(bd));
998 ret = PTR_ERR(ptr: bd);
999 goto out;
1000 }
1001
1002 panel->backlight.device = bd;
1003
1004 drm_dbg_kms(display->drm,
1005 "[CONNECTOR:%d:%s] backlight device %s registered\n",
1006 connector->base.base.id, connector->base.name, name);
1007
1008out:
1009 kfree(objp: name);
1010
1011 return ret;
1012}
1013
1014void intel_backlight_device_unregister(struct intel_connector *connector)
1015{
1016 struct intel_panel *panel = &connector->panel;
1017
1018 if (panel->backlight.device) {
1019 backlight_device_unregister(bd: panel->backlight.device);
1020 panel->backlight.device = NULL;
1021 }
1022}
1023#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1024
1025/*
1026 * CNP: PWM clock frequency is 19.2 MHz or 24 MHz.
1027 * PWM increment = 1
1028 */
1029static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1030{
1031 struct intel_display *display = to_intel_display(connector);
1032
1033 return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq),
1034 pwm_freq_hz);
1035}
1036
1037/*
1038 * BXT: PWM clock frequency = 19.2 MHz.
1039 */
1040static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1041{
1042 return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz);
1043}
1044
1045/*
1046 * SPT: This value represents the period of the PWM stream in clock periods
1047 * multiplied by 16 (default increment) or 128 (alternate increment selected in
1048 * SCHICKEN_1 bit 0). PWM clock is 24 MHz.
1049 */
1050static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1051{
1052 struct intel_panel *panel = &connector->panel;
1053 u32 mul;
1054
1055 if (panel->backlight.alternate_pwm_increment)
1056 mul = 128;
1057 else
1058 mul = 16;
1059
1060 return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul);
1061}
1062
1063/*
1064 * LPT: This value represents the period of the PWM stream in clock periods
1065 * multiplied by 128 (default increment) or 16 (alternate increment, selected in
1066 * LPT SOUTH_CHICKEN2 register bit 5).
1067 */
1068static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1069{
1070 struct intel_display *display = to_intel_display(connector);
1071 struct intel_panel *panel = &connector->panel;
1072 u32 mul, clock;
1073
1074 if (panel->backlight.alternate_pwm_increment)
1075 mul = 16;
1076 else
1077 mul = 128;
1078
1079 if (HAS_PCH_LPT_H(display))
1080 clock = MHz(135); /* LPT:H */
1081 else
1082 clock = MHz(24); /* LPT:LP */
1083
1084 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
1085}
1086
1087/*
1088 * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH
1089 * display raw clocks multiplied by 128.
1090 */
1091static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1092{
1093 struct intel_display *display = to_intel_display(connector);
1094
1095 return DIV_ROUND_CLOSEST(KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq),
1096 pwm_freq_hz * 128);
1097}
1098
1099/*
1100 * Gen2: This field determines the number of time base events (display core
1101 * clock frequency/32) in total for a complete cycle of modulated backlight
1102 * control.
1103 *
1104 * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock)
1105 * divided by 32.
1106 */
1107static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1108{
1109 struct intel_display *display = to_intel_display(connector);
1110 int clock;
1111
1112 if (display->platform.pineview)
1113 clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq);
1114 else
1115 clock = KHz(display->cdclk.hw.cdclk);
1116
1117 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
1118}
1119
1120/*
1121 * Gen4: This value represents the period of the PWM stream in display core
1122 * clocks ([DevCTG] HRAW clocks) multiplied by 128.
1123 *
1124 */
1125static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1126{
1127 struct intel_display *display = to_intel_display(connector);
1128 int clock;
1129
1130 if (display->platform.g4x)
1131 clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq);
1132 else
1133 clock = KHz(display->cdclk.hw.cdclk);
1134
1135 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
1136}
1137
1138/*
1139 * VLV: This value represents the period of the PWM stream in display core
1140 * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
1141 * multiplied by 16. CHV uses a 19.2MHz S0IX clock.
1142 */
1143static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1144{
1145 struct intel_display *display = to_intel_display(connector);
1146 int mul, clock;
1147
1148 if ((intel_de_read(display, CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
1149 if (display->platform.cherryview)
1150 clock = KHz(19200);
1151 else
1152 clock = MHz(25);
1153 mul = 16;
1154 } else {
1155 clock = KHz(DISPLAY_RUNTIME_INFO(display)->rawclk_freq);
1156 mul = 128;
1157 }
1158
1159 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
1160}
1161
1162static u16 get_vbt_pwm_freq(struct intel_connector *connector)
1163{
1164 struct intel_display *display = to_intel_display(connector);
1165 u16 pwm_freq_hz = connector->panel.vbt.backlight.pwm_freq_hz;
1166
1167 if (pwm_freq_hz) {
1168 drm_dbg_kms(display->drm,
1169 "VBT defined backlight frequency %u Hz\n",
1170 pwm_freq_hz);
1171 } else {
1172 pwm_freq_hz = 200;
1173 drm_dbg_kms(display->drm,
1174 "default backlight frequency %u Hz\n",
1175 pwm_freq_hz);
1176 }
1177
1178 return pwm_freq_hz;
1179}
1180
1181static u32 get_backlight_max_vbt(struct intel_connector *connector)
1182{
1183 struct intel_display *display = to_intel_display(connector);
1184 struct intel_panel *panel = &connector->panel;
1185 u16 pwm_freq_hz = get_vbt_pwm_freq(connector);
1186 u32 pwm;
1187
1188 if (!panel->backlight.pwm_funcs->hz_to_pwm) {
1189 drm_dbg_kms(display->drm,
1190 "backlight frequency conversion not supported\n");
1191 return 0;
1192 }
1193
1194 pwm = panel->backlight.pwm_funcs->hz_to_pwm(connector, pwm_freq_hz);
1195 if (!pwm) {
1196 drm_dbg_kms(display->drm,
1197 "backlight frequency conversion failed\n");
1198 return 0;
1199 }
1200
1201 return pwm;
1202}
1203
1204/*
1205 * Note: The setup hooks can't assume pipe is set!
1206 */
1207static u32 get_backlight_min_vbt(struct intel_connector *connector)
1208{
1209 struct intel_display *display = to_intel_display(connector);
1210 struct intel_panel *panel = &connector->panel;
1211 int min;
1212
1213 drm_WARN_ON(display->drm, panel->backlight.pwm_level_max == 0);
1214
1215 /*
1216 * XXX: If the vbt value is 255, it makes min equal to max, which leads
1217 * to problems. There are such machines out there. Either our
1218 * interpretation is wrong or the vbt has bogus data. Or both. Safeguard
1219 * against this by letting the minimum be at most (arbitrarily chosen)
1220 * 25% of the max.
1221 */
1222 min = clamp_t(int, connector->panel.vbt.backlight.min_brightness, 0, 64);
1223 if (min != connector->panel.vbt.backlight.min_brightness) {
1224 drm_dbg_kms(display->drm,
1225 "clamping VBT min backlight %d/255 to %d/255\n",
1226 connector->panel.vbt.backlight.min_brightness, min);
1227 }
1228
1229 /* vbt value is a coefficient in range [0..255] */
1230 return scale(source_val: min, source_min: 0, source_max: 255, target_min: 0, target_max: panel->backlight.pwm_level_max);
1231}
1232
1233static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
1234{
1235 struct intel_display *display = to_intel_display(connector);
1236 struct intel_panel *panel = &connector->panel;
1237 u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
1238 bool alt, cpu_mode;
1239
1240 if (HAS_PCH_LPT(display))
1241 alt = intel_de_read(display, SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY;
1242 else
1243 alt = intel_de_read(display, SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY;
1244 panel->backlight.alternate_pwm_increment = alt;
1245
1246 pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1);
1247 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1248
1249 pch_ctl2 = intel_de_read(display, BLC_PWM_PCH_CTL2);
1250 panel->backlight.pwm_level_max = pch_ctl2 >> 16;
1251
1252 cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2);
1253
1254 if (!panel->backlight.pwm_level_max)
1255 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1256
1257 if (!panel->backlight.pwm_level_max)
1258 return -ENODEV;
1259
1260 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1261
1262 panel->backlight.pwm_enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE;
1263
1264 cpu_mode = panel->backlight.pwm_enabled && HAS_PCH_LPT(display) &&
1265 !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) &&
1266 (cpu_ctl2 & BLM_PWM_ENABLE);
1267
1268 if (cpu_mode) {
1269 val = pch_get_backlight(connector, unused);
1270
1271 drm_dbg_kms(display->drm,
1272 "CPU backlight register was enabled, switching to PCH override\n");
1273
1274 /* Write converted CPU PWM value to PCH override register */
1275 lpt_set_backlight(conn_state: connector->base.state, level: val);
1276 intel_de_write(display, BLC_PWM_PCH_CTL1,
1277 val: pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE);
1278
1279 intel_de_write(display, BLC_PWM_CPU_CTL2,
1280 val: cpu_ctl2 & ~BLM_PWM_ENABLE);
1281 }
1282
1283 drm_dbg_kms(display->drm,
1284 "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control\n",
1285 connector->base.base.id, connector->base.name);
1286
1287 return 0;
1288}
1289
1290static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused)
1291{
1292 struct intel_display *display = to_intel_display(connector);
1293 struct intel_panel *panel = &connector->panel;
1294 u32 cpu_ctl2, pch_ctl1, pch_ctl2;
1295
1296 pch_ctl1 = intel_de_read(display, BLC_PWM_PCH_CTL1);
1297 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1298
1299 pch_ctl2 = intel_de_read(display, BLC_PWM_PCH_CTL2);
1300 panel->backlight.pwm_level_max = pch_ctl2 >> 16;
1301
1302 if (!panel->backlight.pwm_level_max)
1303 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1304
1305 if (!panel->backlight.pwm_level_max)
1306 return -ENODEV;
1307
1308 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1309
1310 cpu_ctl2 = intel_de_read(display, BLC_PWM_CPU_CTL2);
1311 panel->backlight.pwm_enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
1312 (pch_ctl1 & BLM_PCH_PWM_ENABLE);
1313
1314 drm_dbg_kms(display->drm,
1315 "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control\n",
1316 connector->base.base.id, connector->base.name);
1317
1318 return 0;
1319}
1320
1321static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused)
1322{
1323 struct intel_display *display = to_intel_display(connector);
1324 struct intel_panel *panel = &connector->panel;
1325 u32 ctl, val;
1326
1327 ctl = intel_de_read(display, BLC_PWM_CTL);
1328
1329 if (DISPLAY_VER(display) == 2 || display->platform.i915gm || display->platform.i945gm)
1330 panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
1331
1332 if (display->platform.pineview)
1333 panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
1334
1335 panel->backlight.pwm_level_max = ctl >> 17;
1336
1337 if (!panel->backlight.pwm_level_max) {
1338 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1339 panel->backlight.pwm_level_max >>= 1;
1340 }
1341
1342 if (!panel->backlight.pwm_level_max)
1343 return -ENODEV;
1344
1345 if (panel->backlight.combination_mode)
1346 panel->backlight.pwm_level_max *= 0xff;
1347
1348 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1349
1350 val = i9xx_get_backlight(connector, unused);
1351 val = intel_backlight_invert_pwm_level(connector, val);
1352 val = clamp(val, panel->backlight.pwm_level_min, panel->backlight.pwm_level_max);
1353
1354 panel->backlight.pwm_enabled = val != 0;
1355
1356 drm_dbg_kms(display->drm,
1357 "[CONNECTOR:%d:%s] Using native PWM for backlight control\n",
1358 connector->base.base.id, connector->base.name);
1359
1360 return 0;
1361}
1362
1363static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused)
1364{
1365 struct intel_display *display = to_intel_display(connector);
1366 struct intel_panel *panel = &connector->panel;
1367 u32 ctl, ctl2;
1368
1369 ctl2 = intel_de_read(display, BLC_PWM_CTL2);
1370 panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1371 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1372
1373 ctl = intel_de_read(display, BLC_PWM_CTL);
1374 panel->backlight.pwm_level_max = ctl >> 16;
1375
1376 if (!panel->backlight.pwm_level_max)
1377 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1378
1379 if (!panel->backlight.pwm_level_max)
1380 return -ENODEV;
1381
1382 if (panel->backlight.combination_mode)
1383 panel->backlight.pwm_level_max *= 0xff;
1384
1385 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1386
1387 panel->backlight.pwm_enabled = ctl2 & BLM_PWM_ENABLE;
1388
1389 drm_dbg_kms(display->drm,
1390 "[CONNECTOR:%d:%s] Using native PWM for backlight control\n",
1391 connector->base.base.id, connector->base.name);
1392
1393 return 0;
1394}
1395
1396static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe)
1397{
1398 struct intel_display *display = to_intel_display(connector);
1399 struct intel_panel *panel = &connector->panel;
1400 u32 ctl, ctl2;
1401
1402 if (drm_WARN_ON(display->drm, pipe != PIPE_A && pipe != PIPE_B))
1403 return -ENODEV;
1404
1405 ctl2 = intel_de_read(display, VLV_BLC_PWM_CTL2(pipe));
1406 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1407
1408 ctl = intel_de_read(display, VLV_BLC_PWM_CTL(pipe));
1409 panel->backlight.pwm_level_max = ctl >> 16;
1410
1411 if (!panel->backlight.pwm_level_max)
1412 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1413
1414 if (!panel->backlight.pwm_level_max)
1415 return -ENODEV;
1416
1417 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1418
1419 panel->backlight.pwm_enabled = ctl2 & BLM_PWM_ENABLE;
1420
1421 drm_dbg_kms(display->drm,
1422 "[CONNECTOR:%d:%s] Using native PWM for backlight control (on pipe %c)\n",
1423 connector->base.base.id, connector->base.name, pipe_name(pipe));
1424
1425 return 0;
1426}
1427
1428static int
1429bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
1430{
1431 struct intel_display *display = to_intel_display(connector);
1432 struct intel_panel *panel = &connector->panel;
1433 u32 pwm_ctl, val;
1434
1435 panel->backlight.controller = connector->panel.vbt.backlight.controller;
1436
1437 pwm_ctl = intel_de_read(display,
1438 BXT_BLC_PWM_CTL(panel->backlight.controller));
1439
1440 /* Controller 1 uses the utility pin. */
1441 if (panel->backlight.controller == 1) {
1442 val = intel_de_read(display, UTIL_PIN_CTL);
1443 panel->backlight.util_pin_active_low =
1444 val & UTIL_PIN_POLARITY;
1445 }
1446
1447 panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
1448 panel->backlight.pwm_level_max =
1449 intel_de_read(display, BXT_BLC_PWM_FREQ(panel->backlight.controller));
1450
1451 if (!panel->backlight.pwm_level_max)
1452 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1453
1454 if (!panel->backlight.pwm_level_max)
1455 return -ENODEV;
1456
1457 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1458
1459 panel->backlight.pwm_enabled = pwm_ctl & BXT_BLC_PWM_ENABLE;
1460
1461 drm_dbg_kms(display->drm,
1462 "[CONNECTOR:%d:%s] Using native PWM for backlight control (controller=%d)\n",
1463 connector->base.base.id, connector->base.name,
1464 panel->backlight.controller);
1465
1466 return 0;
1467}
1468
1469static int cnp_num_backlight_controllers(struct intel_display *display)
1470{
1471 if (INTEL_PCH_TYPE(display) >= PCH_MTL)
1472 return 2;
1473
1474 if (INTEL_PCH_TYPE(display) >= PCH_DG1)
1475 return 1;
1476
1477 if (INTEL_PCH_TYPE(display) >= PCH_ICP)
1478 return 2;
1479
1480 return 1;
1481}
1482
1483static bool cnp_backlight_controller_is_valid(struct intel_display *display, int controller)
1484{
1485 if (controller < 0 || controller >= cnp_num_backlight_controllers(display))
1486 return false;
1487
1488 if (controller == 1 &&
1489 INTEL_PCH_TYPE(display) >= PCH_ICP &&
1490 INTEL_PCH_TYPE(display) <= PCH_ADP)
1491 return intel_de_read(display, SOUTH_CHICKEN1) & ICP_SECOND_PPS_IO_SELECT;
1492
1493 return true;
1494}
1495
1496static int
1497cnp_setup_backlight(struct intel_connector *connector, enum pipe unused)
1498{
1499 struct intel_display *display = to_intel_display(connector);
1500 struct intel_panel *panel = &connector->panel;
1501 u32 pwm_ctl;
1502
1503 /*
1504 * CNP has the BXT implementation of backlight, but with only one
1505 * controller. ICP+ can have two controllers, depending on pin muxing.
1506 */
1507 panel->backlight.controller = connector->panel.vbt.backlight.controller;
1508 if (!cnp_backlight_controller_is_valid(display, controller: panel->backlight.controller)) {
1509 drm_dbg_kms(display->drm,
1510 "[CONNECTOR:%d:%s] Invalid backlight controller %d, assuming 0\n",
1511 connector->base.base.id, connector->base.name,
1512 panel->backlight.controller);
1513 panel->backlight.controller = 0;
1514 }
1515
1516 pwm_ctl = intel_de_read(display,
1517 BXT_BLC_PWM_CTL(panel->backlight.controller));
1518
1519 panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
1520 panel->backlight.pwm_level_max =
1521 intel_de_read(display, BXT_BLC_PWM_FREQ(panel->backlight.controller));
1522
1523 if (!panel->backlight.pwm_level_max)
1524 panel->backlight.pwm_level_max = get_backlight_max_vbt(connector);
1525
1526 if (!panel->backlight.pwm_level_max)
1527 return -ENODEV;
1528
1529 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1530
1531 panel->backlight.pwm_enabled = pwm_ctl & BXT_BLC_PWM_ENABLE;
1532
1533 drm_dbg_kms(display->drm,
1534 "[CONNECTOR:%d:%s] Using native PCH PWM for backlight control (controller=%d)\n",
1535 connector->base.base.id, connector->base.name,
1536 panel->backlight.controller);
1537
1538 return 0;
1539}
1540
1541static int ext_pwm_setup_backlight(struct intel_connector *connector,
1542 enum pipe pipe)
1543{
1544 struct intel_display *display = to_intel_display(connector);
1545 struct intel_panel *panel = &connector->panel;
1546 const char *desc;
1547 u32 level;
1548
1549 /* Get the right PWM chip for DSI backlight according to VBT */
1550 if (connector->panel.vbt.dsi.config->pwm_blc == PPS_BLC_PMIC) {
1551 panel->backlight.pwm = pwm_get(dev: display->drm->dev,
1552 consumer: "pwm_pmic_backlight");
1553 desc = "PMIC";
1554 } else {
1555 panel->backlight.pwm = pwm_get(dev: display->drm->dev,
1556 consumer: "pwm_soc_backlight");
1557 desc = "SoC";
1558 }
1559
1560 if (IS_ERR(ptr: panel->backlight.pwm)) {
1561 drm_err(display->drm,
1562 "[CONNECTOR:%d:%s] Failed to get the %s PWM chip\n",
1563 connector->base.base.id, connector->base.name, desc);
1564 panel->backlight.pwm = NULL;
1565 return -ENODEV;
1566 }
1567
1568 panel->backlight.pwm_level_max = 100; /* 100% */
1569 panel->backlight.pwm_level_min = get_backlight_min_vbt(connector);
1570
1571 if (pwm_is_enabled(pwm: panel->backlight.pwm)) {
1572 /* PWM is already enabled, use existing settings */
1573 pwm_get_state(pwm: panel->backlight.pwm, state: &panel->backlight.pwm_state);
1574
1575 level = pwm_get_relative_duty_cycle(state: &panel->backlight.pwm_state,
1576 scale: 100);
1577 level = intel_backlight_invert_pwm_level(connector, val: level);
1578 panel->backlight.pwm_enabled = true;
1579
1580 drm_dbg_kms(display->drm,
1581 "[CONNECTOR:%d:%s] PWM already enabled at freq %ld, VBT freq %d, level %d\n",
1582 connector->base.base.id, connector->base.name,
1583 NSEC_PER_SEC / (unsigned long)panel->backlight.pwm_state.period,
1584 get_vbt_pwm_freq(connector), level);
1585 } else {
1586 /* Set period from VBT frequency, leave other settings at 0. */
1587 panel->backlight.pwm_state.period =
1588 NSEC_PER_SEC / get_vbt_pwm_freq(connector);
1589 }
1590
1591 drm_dbg_kms(display->drm,
1592 "[CONNECTOR:%d:%s] Using %s PWM for backlight control\n",
1593 connector->base.base.id, connector->base.name, desc);
1594
1595 return 0;
1596}
1597
1598static void intel_pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
1599{
1600 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1601 struct intel_panel *panel = &connector->panel;
1602
1603 panel->backlight.pwm_funcs->set(conn_state,
1604 intel_backlight_invert_pwm_level(connector, val: level));
1605}
1606
1607static u32 intel_pwm_get_backlight(struct intel_connector *connector, enum pipe pipe)
1608{
1609 struct intel_panel *panel = &connector->panel;
1610
1611 return intel_backlight_invert_pwm_level(connector,
1612 val: panel->backlight.pwm_funcs->get(connector, pipe));
1613}
1614
1615static void intel_pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
1616 const struct drm_connector_state *conn_state, u32 level)
1617{
1618 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1619 struct intel_panel *panel = &connector->panel;
1620
1621 panel->backlight.pwm_funcs->enable(crtc_state, conn_state,
1622 intel_backlight_invert_pwm_level(connector, val: level));
1623}
1624
1625static void intel_pwm_disable_backlight(const struct drm_connector_state *conn_state, u32 level)
1626{
1627 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1628 struct intel_panel *panel = &connector->panel;
1629
1630 panel->backlight.pwm_funcs->disable(conn_state,
1631 intel_backlight_invert_pwm_level(connector, val: level));
1632}
1633
1634static int intel_pwm_setup_backlight(struct intel_connector *connector, enum pipe pipe)
1635{
1636 struct intel_panel *panel = &connector->panel;
1637 int ret;
1638
1639 ret = panel->backlight.pwm_funcs->setup(connector, pipe);
1640 if (ret < 0)
1641 return ret;
1642
1643 panel->backlight.min = panel->backlight.pwm_level_min;
1644 panel->backlight.max = panel->backlight.pwm_level_max;
1645 panel->backlight.level = intel_pwm_get_backlight(connector, pipe);
1646 panel->backlight.enabled = panel->backlight.pwm_enabled;
1647
1648 return 0;
1649}
1650
1651void intel_backlight_update(struct intel_atomic_state *state,
1652 struct intel_encoder *encoder,
1653 const struct intel_crtc_state *crtc_state,
1654 const struct drm_connector_state *conn_state)
1655{
1656 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1657 struct intel_display *display = to_intel_display(connector);
1658 struct intel_panel *panel = &connector->panel;
1659
1660 if (!panel->backlight.present)
1661 return;
1662
1663 mutex_lock(lock: &display->backlight.lock);
1664 if (!panel->backlight.enabled)
1665 __intel_backlight_enable(crtc_state, conn_state);
1666
1667 mutex_unlock(lock: &display->backlight.lock);
1668}
1669
1670int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe)
1671{
1672 struct intel_display *display = to_intel_display(connector);
1673 struct intel_panel *panel = &connector->panel;
1674 int ret;
1675
1676 if (!connector->panel.vbt.backlight.present) {
1677 if (intel_has_quirk(display, quirk: QUIRK_BACKLIGHT_PRESENT)) {
1678 drm_dbg_kms(display->drm,
1679 "[CONNECTOR:%d:%s] no backlight present per VBT, but present per quirk\n",
1680 connector->base.base.id, connector->base.name);
1681 } else {
1682 drm_dbg_kms(display->drm,
1683 "[CONNECTOR:%d:%s] no backlight present per VBT\n",
1684 connector->base.base.id, connector->base.name);
1685 return 0;
1686 }
1687 }
1688
1689 /* ensure intel_panel has been initialized first */
1690 if (drm_WARN_ON(display->drm, !panel->backlight.funcs))
1691 return -ENODEV;
1692
1693 /* set level and max in panel struct */
1694 mutex_lock(lock: &display->backlight.lock);
1695 ret = panel->backlight.funcs->setup(connector, pipe);
1696 mutex_unlock(lock: &display->backlight.lock);
1697
1698 if (ret) {
1699 drm_dbg_kms(display->drm,
1700 "[CONNECTOR:%d:%s] failed to setup backlight\n",
1701 connector->base.base.id, connector->base.name);
1702 return ret;
1703 }
1704
1705 panel->backlight.present = true;
1706
1707 drm_dbg_kms(display->drm,
1708 "[CONNECTOR:%d:%s] backlight initialized, %s, brightness %u/%u\n",
1709 connector->base.base.id, connector->base.name,
1710 str_enabled_disabled(panel->backlight.enabled),
1711 panel->backlight.level, panel->backlight.max);
1712
1713 return 0;
1714}
1715
1716void intel_backlight_destroy(struct intel_panel *panel)
1717{
1718 /* dispose of the pwm */
1719 if (panel->backlight.pwm)
1720 pwm_put(pwm: panel->backlight.pwm);
1721
1722 panel->backlight.present = false;
1723}
1724
1725static const struct intel_panel_bl_funcs bxt_pwm_funcs = {
1726 .setup = bxt_setup_backlight,
1727 .enable = bxt_enable_backlight,
1728 .disable = bxt_disable_backlight,
1729 .set = bxt_set_backlight,
1730 .get = bxt_get_backlight,
1731 .hz_to_pwm = bxt_hz_to_pwm,
1732};
1733
1734static const struct intel_panel_bl_funcs cnp_pwm_funcs = {
1735 .setup = cnp_setup_backlight,
1736 .enable = cnp_enable_backlight,
1737 .disable = cnp_disable_backlight,
1738 .set = bxt_set_backlight,
1739 .get = bxt_get_backlight,
1740 .hz_to_pwm = cnp_hz_to_pwm,
1741};
1742
1743static const struct intel_panel_bl_funcs lpt_pwm_funcs = {
1744 .setup = lpt_setup_backlight,
1745 .enable = lpt_enable_backlight,
1746 .disable = lpt_disable_backlight,
1747 .set = lpt_set_backlight,
1748 .get = lpt_get_backlight,
1749 .hz_to_pwm = lpt_hz_to_pwm,
1750};
1751
1752static const struct intel_panel_bl_funcs spt_pwm_funcs = {
1753 .setup = lpt_setup_backlight,
1754 .enable = lpt_enable_backlight,
1755 .disable = lpt_disable_backlight,
1756 .set = lpt_set_backlight,
1757 .get = lpt_get_backlight,
1758 .hz_to_pwm = spt_hz_to_pwm,
1759};
1760
1761static const struct intel_panel_bl_funcs pch_pwm_funcs = {
1762 .setup = pch_setup_backlight,
1763 .enable = pch_enable_backlight,
1764 .disable = pch_disable_backlight,
1765 .set = pch_set_backlight,
1766 .get = pch_get_backlight,
1767 .hz_to_pwm = pch_hz_to_pwm,
1768};
1769
1770static const struct intel_panel_bl_funcs ext_pwm_funcs = {
1771 .setup = ext_pwm_setup_backlight,
1772 .enable = ext_pwm_enable_backlight,
1773 .disable = ext_pwm_disable_backlight,
1774 .set = ext_pwm_set_backlight,
1775 .get = ext_pwm_get_backlight,
1776};
1777
1778static const struct intel_panel_bl_funcs vlv_pwm_funcs = {
1779 .setup = vlv_setup_backlight,
1780 .enable = vlv_enable_backlight,
1781 .disable = vlv_disable_backlight,
1782 .set = vlv_set_backlight,
1783 .get = vlv_get_backlight,
1784 .hz_to_pwm = vlv_hz_to_pwm,
1785};
1786
1787static const struct intel_panel_bl_funcs i965_pwm_funcs = {
1788 .setup = i965_setup_backlight,
1789 .enable = i965_enable_backlight,
1790 .disable = i965_disable_backlight,
1791 .set = i9xx_set_backlight,
1792 .get = i9xx_get_backlight,
1793 .hz_to_pwm = i965_hz_to_pwm,
1794};
1795
1796static const struct intel_panel_bl_funcs i9xx_pwm_funcs = {
1797 .setup = i9xx_setup_backlight,
1798 .enable = i9xx_enable_backlight,
1799 .disable = i9xx_disable_backlight,
1800 .set = i9xx_set_backlight,
1801 .get = i9xx_get_backlight,
1802 .hz_to_pwm = i9xx_hz_to_pwm,
1803};
1804
1805static const struct intel_panel_bl_funcs pwm_bl_funcs = {
1806 .setup = intel_pwm_setup_backlight,
1807 .enable = intel_pwm_enable_backlight,
1808 .disable = intel_pwm_disable_backlight,
1809 .set = intel_pwm_set_backlight,
1810 .get = intel_pwm_get_backlight,
1811};
1812
1813/* Set up chip specific backlight functions */
1814void intel_backlight_init_funcs(struct intel_panel *panel)
1815{
1816 struct intel_connector *connector =
1817 container_of(panel, struct intel_connector, panel);
1818 struct intel_display *display = to_intel_display(connector);
1819
1820 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI &&
1821 intel_dsi_dcs_init_backlight_funcs(intel_connector: connector) == 0)
1822 return;
1823
1824 if (display->platform.geminilake || display->platform.broxton) {
1825 panel->backlight.pwm_funcs = &bxt_pwm_funcs;
1826 } else if (INTEL_PCH_TYPE(display) >= PCH_CNP) {
1827 panel->backlight.pwm_funcs = &cnp_pwm_funcs;
1828 } else if (INTEL_PCH_TYPE(display) >= PCH_LPT_H) {
1829 if (HAS_PCH_LPT(display))
1830 panel->backlight.pwm_funcs = &lpt_pwm_funcs;
1831 else
1832 panel->backlight.pwm_funcs = &spt_pwm_funcs;
1833 } else if (HAS_PCH_SPLIT(display)) {
1834 panel->backlight.pwm_funcs = &pch_pwm_funcs;
1835 } else if (display->platform.valleyview || display->platform.cherryview) {
1836 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
1837 panel->backlight.pwm_funcs = &ext_pwm_funcs;
1838 } else {
1839 panel->backlight.pwm_funcs = &vlv_pwm_funcs;
1840 }
1841 } else if (DISPLAY_VER(display) == 4) {
1842 panel->backlight.pwm_funcs = &i965_pwm_funcs;
1843 } else {
1844 panel->backlight.pwm_funcs = &i9xx_pwm_funcs;
1845 }
1846
1847 if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) {
1848 if (intel_dp_aux_init_backlight_funcs(intel_connector: connector) == 0)
1849 return;
1850
1851 if (!intel_has_quirk(display, quirk: QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK))
1852 connector->panel.backlight.power = intel_pps_backlight_power;
1853 }
1854
1855 /* We're using a standard PWM backlight interface */
1856 panel->backlight.funcs = &pwm_bl_funcs;
1857}
1858