]> git.ipfire.org Git - thirdparty/kernel/stable.git/blame - drivers/gpu/drm/i915/intel_panel.c
drm/i915: extract intel_connector.h from intel_drv.h
[thirdparty/kernel/stable.git] / drivers / gpu / drm / i915 / intel_panel.c
CommitLineData
1d8e1c75
CW
1/*
2 * Copyright © 2006-2010 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
28 * Chris Wilson <chris@chris-wilson.co.uk>
29 */
30
a70491cc
JP
31#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
32
f766093e 33#include <linux/kernel.h>
7bd90909 34#include <linux/moduleparam.h>
b029e66f 35#include <linux/pwm.h>
ec7f29ff
JN
36
37#include "intel_connector.h"
1d8e1c75
CW
38#include "intel_drv.h"
39
b029e66f
SK
40#define CRC_PMIC_PWM_PERIOD_NS 21333
41
1d8e1c75 42void
4c6df4b4 43intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
1d8e1c75
CW
44 struct drm_display_mode *adjusted_mode)
45{
4c6df4b4 46 drm_mode_copy(adjusted_mode, fixed_mode);
a52690e4
ID
47
48 drm_mode_set_crtcinfo(adjusted_mode, 0);
1d8e1c75
CW
49}
50
9f6fbe22
VS
51static bool is_downclock_mode(const struct drm_display_mode *downclock_mode,
52 const struct drm_display_mode *fixed_mode)
53{
54 return drm_mode_match(downclock_mode, fixed_mode,
55 DRM_MODE_MATCH_TIMINGS |
56 DRM_MODE_MATCH_FLAGS |
57 DRM_MODE_MATCH_3D_FLAGS) &&
58 downclock_mode->clock < fixed_mode->clock;
59}
60
525997e0 61struct drm_display_mode *
abf1aae8
VS
62intel_panel_edid_downclock_mode(struct intel_connector *connector,
63 const struct drm_display_mode *fixed_mode)
525997e0 64{
abf1aae8 65 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
9f6fbe22 66 const struct drm_display_mode *scan, *best_mode = NULL;
abf1aae8 67 struct drm_display_mode *downclock_mode;
9f6fbe22 68 int best_clock = fixed_mode->clock;
525997e0 69
abf1aae8 70 list_for_each_entry(scan, &connector->base.probed_modes, head) {
525997e0
JN
71 /*
72 * If one mode has the same resolution with the fixed_panel
73 * mode while they have the different refresh rate, it means
74 * that the reduced downclock is found. In such
75 * case we can set the different FPx0/1 to dynamically select
76 * between low and high frequency.
77 */
9f6fbe22
VS
78 if (is_downclock_mode(scan, fixed_mode) &&
79 scan->clock < best_clock) {
80 /*
81 * The downclock is already found. But we
82 * expect to find the lower downclock.
83 */
84 best_clock = scan->clock;
85 best_mode = scan;
525997e0
JN
86 }
87 }
88
abf1aae8
VS
89 if (!best_mode)
90 return NULL;
91
92 downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode);
93 if (!downclock_mode)
94 return NULL;
95
96 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using downclock mode from EDID: ",
97 connector->base.base.id, connector->base.name);
98 drm_mode_debug_printmodeline(downclock_mode);
9f6fbe22 99
abf1aae8 100 return downclock_mode;
525997e0
JN
101}
102
0dc927eb
VS
103struct drm_display_mode *
104intel_panel_edid_fixed_mode(struct intel_connector *connector)
105{
106 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
107 const struct drm_display_mode *scan;
8f49673e
VS
108 struct drm_display_mode *fixed_mode;
109
110 if (list_empty(&connector->base.probed_modes))
111 return NULL;
0dc927eb
VS
112
113 /* prefer fixed mode from EDID if available */
114 list_for_each_entry(scan, &connector->base.probed_modes, head) {
0dc927eb
VS
115 if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0)
116 continue;
117
118 fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
119 if (!fixed_mode)
120 return NULL;
121
122 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using preferred mode from EDID: ",
123 connector->base.base.id, connector->base.name);
124 drm_mode_debug_printmodeline(fixed_mode);
125
126 return fixed_mode;
127 }
128
8f49673e
VS
129 scan = list_first_entry(&connector->base.probed_modes,
130 typeof(*scan), head);
131
132 fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan);
133 if (!fixed_mode)
134 return NULL;
135
136 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
137
138 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using first mode from EDID: ",
139 connector->base.base.id, connector->base.name);
140 drm_mode_debug_printmodeline(fixed_mode);
141
142 return fixed_mode;
0dc927eb
VS
143}
144
325710d3
VS
145struct drm_display_mode *
146intel_panel_vbt_fixed_mode(struct intel_connector *connector)
147{
148 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
149 struct drm_display_info *info = &connector->base.display_info;
150 struct drm_display_mode *fixed_mode;
151
152 if (!dev_priv->vbt.lfp_lvds_vbt_mode)
153 return NULL;
154
155 fixed_mode = drm_mode_duplicate(&dev_priv->drm,
156 dev_priv->vbt.lfp_lvds_vbt_mode);
157 if (!fixed_mode)
158 return NULL;
159
160 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
161
162 DRM_DEBUG_KMS("[CONNECTOR:%d:%s] using mode from VBT: ",
163 connector->base.base.id, connector->base.name);
164 drm_mode_debug_printmodeline(fixed_mode);
165
166 info->width_mm = fixed_mode->width_mm;
167 info->height_mm = fixed_mode->height_mm;
168
169 return fixed_mode;
170}
171
1d8e1c75
CW
172/* adjusted_mode has been preset to be the panel's fixed mode */
173void
b074cec8 174intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
5cec258b 175 struct intel_crtc_state *pipe_config,
b074cec8 176 int fitting_mode)
1d8e1c75 177{
7c5f93b0
VS
178 const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
179 int x = 0, y = 0, width = 0, height = 0;
1d8e1c75
CW
180
181 /* Native modes don't need fitting */
aad941d5 182 if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
e5c05931 183 adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h &&
33b7f3ee 184 pipe_config->output_format != INTEL_OUTPUT_FORMAT_YCBCR420)
1d8e1c75
CW
185 goto done;
186
187 switch (fitting_mode) {
188 case DRM_MODE_SCALE_CENTER:
37327abd
VS
189 width = pipe_config->pipe_src_w;
190 height = pipe_config->pipe_src_h;
aad941d5
VS
191 x = (adjusted_mode->crtc_hdisplay - width + 1)/2;
192 y = (adjusted_mode->crtc_vdisplay - height + 1)/2;
1d8e1c75
CW
193 break;
194
195 case DRM_MODE_SCALE_ASPECT:
196 /* Scale but preserve the aspect ratio */
197 {
aad941d5 198 u32 scaled_width = adjusted_mode->crtc_hdisplay
9084e7d2
SV
199 * pipe_config->pipe_src_h;
200 u32 scaled_height = pipe_config->pipe_src_w
aad941d5 201 * adjusted_mode->crtc_vdisplay;
1d8e1c75 202 if (scaled_width > scaled_height) { /* pillar */
37327abd 203 width = scaled_height / pipe_config->pipe_src_h;
302983e9 204 if (width & 1)
0206e353 205 width++;
aad941d5 206 x = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
1d8e1c75 207 y = 0;
aad941d5 208 height = adjusted_mode->crtc_vdisplay;
1d8e1c75 209 } else if (scaled_width < scaled_height) { /* letter */
37327abd 210 height = scaled_width / pipe_config->pipe_src_w;
302983e9
AJ
211 if (height & 1)
212 height++;
aad941d5 213 y = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
1d8e1c75 214 x = 0;
aad941d5 215 width = adjusted_mode->crtc_hdisplay;
1d8e1c75
CW
216 } else {
217 x = y = 0;
aad941d5
VS
218 width = adjusted_mode->crtc_hdisplay;
219 height = adjusted_mode->crtc_vdisplay;
1d8e1c75
CW
220 }
221 }
222 break;
223
1d8e1c75
CW
224 case DRM_MODE_SCALE_FULLSCREEN:
225 x = y = 0;
aad941d5
VS
226 width = adjusted_mode->crtc_hdisplay;
227 height = adjusted_mode->crtc_vdisplay;
1d8e1c75 228 break;
ab3e67f4
JB
229
230 default:
231 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
232 return;
1d8e1c75
CW
233 }
234
235done:
b074cec8
JB
236 pipe_config->pch_pfit.pos = (x << 16) | y;
237 pipe_config->pch_pfit.size = (width << 16) | height;
fd4daa9c 238 pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
1d8e1c75 239}
a9573556 240
2dd24552 241static void
5e7234c9 242centre_horizontally(struct drm_display_mode *adjusted_mode,
2dd24552
JB
243 int width)
244{
245 u32 border, sync_pos, blank_width, sync_width;
246
247 /* keep the hsync and hblank widths constant */
5e7234c9
VS
248 sync_width = adjusted_mode->crtc_hsync_end - adjusted_mode->crtc_hsync_start;
249 blank_width = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
2dd24552
JB
250 sync_pos = (blank_width - sync_width + 1) / 2;
251
aad941d5 252 border = (adjusted_mode->crtc_hdisplay - width + 1) / 2;
2dd24552
JB
253 border += border & 1; /* make the border even */
254
5e7234c9
VS
255 adjusted_mode->crtc_hdisplay = width;
256 adjusted_mode->crtc_hblank_start = width + border;
257 adjusted_mode->crtc_hblank_end = adjusted_mode->crtc_hblank_start + blank_width;
2dd24552 258
5e7234c9
VS
259 adjusted_mode->crtc_hsync_start = adjusted_mode->crtc_hblank_start + sync_pos;
260 adjusted_mode->crtc_hsync_end = adjusted_mode->crtc_hsync_start + sync_width;
2dd24552
JB
261}
262
263static void
5e7234c9 264centre_vertically(struct drm_display_mode *adjusted_mode,
2dd24552
JB
265 int height)
266{
267 u32 border, sync_pos, blank_width, sync_width;
268
269 /* keep the vsync and vblank widths constant */
5e7234c9
VS
270 sync_width = adjusted_mode->crtc_vsync_end - adjusted_mode->crtc_vsync_start;
271 blank_width = adjusted_mode->crtc_vblank_end - adjusted_mode->crtc_vblank_start;
2dd24552
JB
272 sync_pos = (blank_width - sync_width + 1) / 2;
273
aad941d5 274 border = (adjusted_mode->crtc_vdisplay - height + 1) / 2;
2dd24552 275
5e7234c9
VS
276 adjusted_mode->crtc_vdisplay = height;
277 adjusted_mode->crtc_vblank_start = height + border;
278 adjusted_mode->crtc_vblank_end = adjusted_mode->crtc_vblank_start + blank_width;
2dd24552 279
5e7234c9
VS
280 adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vblank_start + sync_pos;
281 adjusted_mode->crtc_vsync_end = adjusted_mode->crtc_vsync_start + sync_width;
2dd24552
JB
282}
283
284static inline u32 panel_fitter_scaling(u32 source, u32 target)
285{
286 /*
287 * Floating point operation is not supported. So the FACTOR
288 * is defined, which can avoid the floating point computation
289 * when calculating the panel ratio.
290 */
291#define ACCURACY 12
292#define FACTOR (1 << ACCURACY)
293 u32 ratio = source * FACTOR / target;
294 return (FACTOR * ratio + FACTOR/2) / FACTOR;
295}
296
5cec258b 297static void i965_scale_aspect(struct intel_crtc_state *pipe_config,
9084e7d2
SV
298 u32 *pfit_control)
299{
7c5f93b0 300 const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
aad941d5 301 u32 scaled_width = adjusted_mode->crtc_hdisplay *
9084e7d2
SV
302 pipe_config->pipe_src_h;
303 u32 scaled_height = pipe_config->pipe_src_w *
aad941d5 304 adjusted_mode->crtc_vdisplay;
9084e7d2
SV
305
306 /* 965+ is easy, it does everything in hw */
307 if (scaled_width > scaled_height)
308 *pfit_control |= PFIT_ENABLE |
309 PFIT_SCALING_PILLAR;
310 else if (scaled_width < scaled_height)
311 *pfit_control |= PFIT_ENABLE |
312 PFIT_SCALING_LETTER;
aad941d5 313 else if (adjusted_mode->crtc_hdisplay != pipe_config->pipe_src_w)
9084e7d2
SV
314 *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
315}
316
5cec258b 317static void i9xx_scale_aspect(struct intel_crtc_state *pipe_config,
9084e7d2
SV
318 u32 *pfit_control, u32 *pfit_pgm_ratios,
319 u32 *border)
320{
2d112de7 321 struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
aad941d5 322 u32 scaled_width = adjusted_mode->crtc_hdisplay *
9084e7d2
SV
323 pipe_config->pipe_src_h;
324 u32 scaled_height = pipe_config->pipe_src_w *
aad941d5 325 adjusted_mode->crtc_vdisplay;
9084e7d2
SV
326 u32 bits;
327
328 /*
329 * For earlier chips we have to calculate the scaling
330 * ratio by hand and program it into the
331 * PFIT_PGM_RATIO register
332 */
333 if (scaled_width > scaled_height) { /* pillar */
334 centre_horizontally(adjusted_mode,
335 scaled_height /
336 pipe_config->pipe_src_h);
337
338 *border = LVDS_BORDER_ENABLE;
aad941d5 339 if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay) {
9084e7d2 340 bits = panel_fitter_scaling(pipe_config->pipe_src_h,
aad941d5 341 adjusted_mode->crtc_vdisplay);
9084e7d2
SV
342
343 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
344 bits << PFIT_VERT_SCALE_SHIFT);
345 *pfit_control |= (PFIT_ENABLE |
346 VERT_INTERP_BILINEAR |
347 HORIZ_INTERP_BILINEAR);
348 }
349 } else if (scaled_width < scaled_height) { /* letter */
350 centre_vertically(adjusted_mode,
351 scaled_width /
352 pipe_config->pipe_src_w);
353
354 *border = LVDS_BORDER_ENABLE;
aad941d5 355 if (pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
9084e7d2 356 bits = panel_fitter_scaling(pipe_config->pipe_src_w,
aad941d5 357 adjusted_mode->crtc_hdisplay);
9084e7d2
SV
358
359 *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
360 bits << PFIT_VERT_SCALE_SHIFT);
361 *pfit_control |= (PFIT_ENABLE |
362 VERT_INTERP_BILINEAR |
363 HORIZ_INTERP_BILINEAR);
364 }
365 } else {
366 /* Aspects match, Let hw scale both directions */
367 *pfit_control |= (PFIT_ENABLE |
368 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
369 VERT_INTERP_BILINEAR |
370 HORIZ_INTERP_BILINEAR);
371 }
372}
373
2dd24552 374void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
5cec258b 375 struct intel_crtc_state *pipe_config,
2dd24552
JB
376 int fitting_mode)
377{
66478475 378 struct drm_i915_private *dev_priv = to_i915(intel_crtc->base.dev);
2dd24552 379 u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
7c5f93b0 380 struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
2dd24552
JB
381
382 /* Native modes don't need fitting */
aad941d5
VS
383 if (adjusted_mode->crtc_hdisplay == pipe_config->pipe_src_w &&
384 adjusted_mode->crtc_vdisplay == pipe_config->pipe_src_h)
2dd24552
JB
385 goto out;
386
387 switch (fitting_mode) {
388 case DRM_MODE_SCALE_CENTER:
389 /*
390 * For centered modes, we have to calculate border widths &
391 * heights and modify the values programmed into the CRTC.
392 */
37327abd
VS
393 centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
394 centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
2dd24552
JB
395 border = LVDS_BORDER_ENABLE;
396 break;
397 case DRM_MODE_SCALE_ASPECT:
398 /* Scale but preserve the aspect ratio */
66478475 399 if (INTEL_GEN(dev_priv) >= 4)
9084e7d2
SV
400 i965_scale_aspect(pipe_config, &pfit_control);
401 else
402 i9xx_scale_aspect(pipe_config, &pfit_control,
403 &pfit_pgm_ratios, &border);
2dd24552 404 break;
2dd24552
JB
405 case DRM_MODE_SCALE_FULLSCREEN:
406 /*
407 * Full scaling, even if it changes the aspect ratio.
408 * Fortunately this is all done for us in hw.
409 */
aad941d5
VS
410 if (pipe_config->pipe_src_h != adjusted_mode->crtc_vdisplay ||
411 pipe_config->pipe_src_w != adjusted_mode->crtc_hdisplay) {
2dd24552 412 pfit_control |= PFIT_ENABLE;
66478475 413 if (INTEL_GEN(dev_priv) >= 4)
2dd24552
JB
414 pfit_control |= PFIT_SCALING_AUTO;
415 else
416 pfit_control |= (VERT_AUTO_SCALE |
417 VERT_INTERP_BILINEAR |
418 HORIZ_AUTO_SCALE |
419 HORIZ_INTERP_BILINEAR);
420 }
421 break;
ab3e67f4
JB
422 default:
423 WARN(1, "bad panel fit mode: %d\n", fitting_mode);
424 return;
2dd24552
JB
425 }
426
427 /* 965+ wants fuzzy fitting */
428 /* FIXME: handle multiple panels by failing gracefully */
66478475 429 if (INTEL_GEN(dev_priv) >= 4)
2dd24552
JB
430 pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
431 PFIT_FILTER_FUZZY);
432
433out:
434 if ((pfit_control & PFIT_ENABLE) == 0) {
435 pfit_control = 0;
436 pfit_pgm_ratios = 0;
437 }
438
6b89cdde 439 /* Make sure pre-965 set dither correctly for 18bpp panels. */
66478475 440 if (INTEL_GEN(dev_priv) < 4 && pipe_config->pipe_bpp == 18)
6b89cdde
SV
441 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
442
2deefda5
SV
443 pipe_config->gmch_pfit.control = pfit_control;
444 pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
68fc8742 445 pipe_config->gmch_pfit.lvds_border_bits = border;
2dd24552
JB
446}
447
6dda730e
JN
448/**
449 * scale - scale values from one range to another
6dda730e 450 * @source_val: value in range [@source_min..@source_max]
e9a744fa
CW
451 * @source_min: minimum legal value for @source_val
452 * @source_max: maximum legal value for @source_val
453 * @target_min: corresponding target value for @source_min
454 * @target_max: corresponding target value for @source_max
6dda730e
JN
455 *
456 * Return @source_val in range [@source_min..@source_max] scaled to range
457 * [@target_min..@target_max].
458 */
fd620bf9
JN
459static u32 scale(u32 source_val,
460 u32 source_min, u32 source_max,
461 u32 target_min, u32 target_max)
6dda730e 462{
fd620bf9 463 u64 target_val;
6dda730e
JN
464
465 WARN_ON(source_min > source_max);
466 WARN_ON(target_min > target_max);
467
468 /* defensive */
469 source_val = clamp(source_val, source_min, source_max);
470
471 /* avoid overflows */
5af4ce7d
CW
472 target_val = mul_u32_u32(source_val - source_min,
473 target_max - target_min);
474 target_val = DIV_ROUND_CLOSEST_ULL(target_val, source_max - source_min);
6dda730e
JN
475 target_val += target_min;
476
477 return target_val;
478}
479
480/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
481static inline u32 scale_user_to_hw(struct intel_connector *connector,
482 u32 user_level, u32 user_max)
483{
484 struct intel_panel *panel = &connector->panel;
485
486 return scale(user_level, 0, user_max,
487 panel->backlight.min, panel->backlight.max);
488}
489
490/* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
491 * to [hw_min..hw_max]. */
492static inline u32 clamp_user_to_hw(struct intel_connector *connector,
493 u32 user_level, u32 user_max)
494{
495 struct intel_panel *panel = &connector->panel;
496 u32 hw_level;
497
498 hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
499 hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);
500
501 return hw_level;
502}
503
504/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
505static inline u32 scale_hw_to_user(struct intel_connector *connector,
506 u32 hw_level, u32 user_max)
507{
508 struct intel_panel *panel = &connector->panel;
509
510 return scale(hw_level, panel->backlight.min, panel->backlight.max,
511 0, user_max);
512}
513
7bd688cd
JN
514static u32 intel_panel_compute_brightness(struct intel_connector *connector,
515 u32 val)
7bd90909 516{
e6cb3727 517 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
f91c15e0
JN
518 struct intel_panel *panel = &connector->panel;
519
520 WARN_ON(panel->backlight.max == 0);
4dca20ef 521
4f044a88 522 if (i915_modparams.invert_brightness < 0)
4dca20ef
CE
523 return val;
524
4f044a88 525 if (i915_modparams.invert_brightness > 0 ||
d6540632 526 dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
e9d7486e 527 return panel->backlight.max - val + panel->backlight.min;
d6540632 528 }
7bd90909
CE
529
530 return val;
531}
532
437b15b8 533static u32 lpt_get_backlight(struct intel_connector *connector)
0b0b053a 534{
e6cb3727 535 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
0b0b053a 536
96ab4c70
SV
537 return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
538}
07bf139b 539
7bd688cd 540static u32 pch_get_backlight(struct intel_connector *connector)
a9573556 541{
e6cb3727 542 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
8ba2d185 543
7bd688cd
JN
544 return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
545}
a9573556 546
7bd688cd
JN
547static u32 i9xx_get_backlight(struct intel_connector *connector)
548{
e6cb3727 549 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
636baebf 550 struct intel_panel *panel = &connector->panel;
7bd688cd 551 u32 val;
07bf139b 552
7bd688cd 553 val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
c56b89f1 554 if (INTEL_GEN(dev_priv) < 4)
7bd688cd 555 val >>= 1;
ba3820ad 556
636baebf 557 if (panel->backlight.combination_mode) {
7bd688cd 558 u8 lbpc;
ba3820ad 559
91c8a326 560 pci_read_config_byte(dev_priv->drm.pdev, LBPC, &lbpc);
7bd688cd 561 val *= lbpc;
a9573556
CW
562 }
563
7bd688cd
JN
564 return val;
565}
566
e6cb3727 567static u32 _vlv_get_backlight(struct drm_i915_private *dev_priv, enum pipe pipe)
7bd688cd 568{
23ec0a88
VS
569 if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
570 return 0;
571
7bd688cd
JN
572 return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
573}
574
575static u32 vlv_get_backlight(struct intel_connector *connector)
576{
e6cb3727 577 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
046c9bca 578 enum pipe pipe = intel_connector_get_pipe(connector);
7bd688cd 579
e6cb3727 580 return _vlv_get_backlight(dev_priv, pipe);
7bd688cd
JN
581}
582
0fb890c0
VK
583static u32 bxt_get_backlight(struct intel_connector *connector)
584{
e6cb3727 585 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
022e4e52 586 struct intel_panel *panel = &connector->panel;
0fb890c0 587
022e4e52 588 return I915_READ(BXT_BLC_PWM_DUTY(panel->backlight.controller));
0fb890c0
VK
589}
590
b029e66f
SK
591static u32 pwm_get_backlight(struct intel_connector *connector)
592{
593 struct intel_panel *panel = &connector->panel;
594 int duty_ns;
595
596 duty_ns = pwm_get_duty_cycle(panel->backlight.pwm);
597 return DIV_ROUND_UP(duty_ns * 100, CRC_PMIC_PWM_PERIOD_NS);
598}
599
7d025e08 600static void lpt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
f8e10062 601{
7d025e08 602 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 603 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7d025e08 604
f8e10062
BW
605 u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
606 I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
607}
608
7d025e08 609static void pch_set_backlight(const struct drm_connector_state *conn_state, u32 level)
a9573556 610{
7d025e08 611 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 612 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd
JN
613 u32 tmp;
614
615 tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
616 I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
a9573556
CW
617}
618
7d025e08 619static void i9xx_set_backlight(const struct drm_connector_state *conn_state, u32 level)
a9573556 620{
7d025e08 621 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 622 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
f91c15e0 623 struct intel_panel *panel = &connector->panel;
b329b328 624 u32 tmp, mask;
ba3820ad 625
f91c15e0
JN
626 WARN_ON(panel->backlight.max == 0);
627
636baebf 628 if (panel->backlight.combination_mode) {
ba3820ad
TI
629 u8 lbpc;
630
f91c15e0 631 lbpc = level * 0xfe / panel->backlight.max + 1;
ba3820ad 632 level /= lbpc;
91c8a326 633 pci_write_config_byte(dev_priv->drm.pdev, LBPC, lbpc);
ba3820ad
TI
634 }
635
cf819eff 636 if (IS_GEN(dev_priv, 4)) {
b329b328
JN
637 mask = BACKLIGHT_DUTY_CYCLE_MASK;
638 } else {
a9573556 639 level <<= 1;
b329b328
JN
640 mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
641 }
7bd688cd 642
b329b328 643 tmp = I915_READ(BLC_PWM_CTL) & ~mask;
7bd688cd
JN
644 I915_WRITE(BLC_PWM_CTL, tmp | level);
645}
646
7d025e08 647static void vlv_set_backlight(const struct drm_connector_state *conn_state, u32 level)
7bd688cd 648{
7d025e08 649 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 650 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7d025e08 651 enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe;
7bd688cd
JN
652 u32 tmp;
653
654 tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
655 I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
656}
657
7d025e08 658static void bxt_set_backlight(const struct drm_connector_state *conn_state, u32 level)
0fb890c0 659{
7d025e08 660 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 661 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
022e4e52 662 struct intel_panel *panel = &connector->panel;
0fb890c0 663
022e4e52 664 I915_WRITE(BXT_BLC_PWM_DUTY(panel->backlight.controller), level);
0fb890c0
VK
665}
666
7d025e08 667static void pwm_set_backlight(const struct drm_connector_state *conn_state, u32 level)
b029e66f 668{
7d025e08 669 struct intel_panel *panel = &to_intel_connector(conn_state->connector)->panel;
b029e66f
SK
670 int duty_ns = DIV_ROUND_UP(level * CRC_PMIC_PWM_PERIOD_NS, 100);
671
672 pwm_config(panel->backlight.pwm, duty_ns, CRC_PMIC_PWM_PERIOD_NS);
673}
674
7bd688cd 675static void
7d025e08 676intel_panel_actually_set_backlight(const struct drm_connector_state *conn_state, u32 level)
7bd688cd 677{
7d025e08 678 struct intel_connector *connector = to_intel_connector(conn_state->connector);
5507faeb 679 struct intel_panel *panel = &connector->panel;
7bd688cd
JN
680
681 DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
682
683 level = intel_panel_compute_brightness(connector, level);
7d025e08 684 panel->backlight.set(conn_state, level);
a9573556 685}
47356eb6 686
6dda730e
JN
687/* set backlight brightness to level in range [0..max], assuming hw min is
688 * respected.
689 */
90d7cd24 690void intel_panel_set_backlight_acpi(const struct drm_connector_state *conn_state,
6dda730e
JN
691 u32 user_level, u32 user_max)
692{
90d7cd24 693 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 694 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
6dda730e 695 struct intel_panel *panel = &connector->panel;
6dda730e 696 u32 hw_level;
6dda730e 697
260d8f98 698 /*
90d7cd24 699 * Lack of crtc may occur during driver init because
260d8f98
VS
700 * connection_mutex isn't held across the entire backlight
701 * setup + modeset readout, and the BIOS can issue the
702 * requests at any time.
703 */
90d7cd24 704 if (!panel->backlight.present || !conn_state->crtc)
6dda730e
JN
705 return;
706
07f11d49 707 mutex_lock(&dev_priv->backlight_lock);
6dda730e
JN
708
709 WARN_ON(panel->backlight.max == 0);
710
711 hw_level = clamp_user_to_hw(connector, user_level, user_max);
712 panel->backlight.level = hw_level;
47356eb6 713
58c68779 714 if (panel->backlight.device)
6dda730e
JN
715 panel->backlight.device->props.brightness =
716 scale_hw_to_user(connector,
717 panel->backlight.level,
718 panel->backlight.device->props.max_brightness);
b6b3ba5b 719
58c68779 720 if (panel->backlight.enabled)
7d025e08 721 intel_panel_actually_set_backlight(conn_state, hw_level);
f91c15e0 722
07f11d49 723 mutex_unlock(&dev_priv->backlight_lock);
f52c619a
TI
724}
725
7d025e08 726static void lpt_disable_backlight(const struct drm_connector_state *old_conn_state)
437b15b8 727{
7d025e08 728 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
e6cb3727 729 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
437b15b8
JN
730 u32 tmp;
731
7d025e08 732 intel_panel_actually_set_backlight(old_conn_state, 0);
437b15b8 733
6675bce2
JN
734 /*
735 * Although we don't support or enable CPU PWM with LPT/SPT based
736 * systems, it may have been enabled prior to loading the
737 * driver. Disable to avoid warnings on LCPLL disable.
738 *
739 * This needs rework if we need to add support for CPU PWM on PCH split
740 * platforms.
741 */
742 tmp = I915_READ(BLC_PWM_CPU_CTL2);
743 if (tmp & BLM_PWM_ENABLE) {
744 DRM_DEBUG_KMS("cpu backlight was enabled, disabling\n");
745 I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
746 }
747
437b15b8
JN
748 tmp = I915_READ(BLC_PWM_PCH_CTL1);
749 I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
750}
751
7d025e08 752static void pch_disable_backlight(const struct drm_connector_state *old_conn_state)
7bd688cd 753{
7d025e08 754 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
e6cb3727 755 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd
JN
756 u32 tmp;
757
7d025e08 758 intel_panel_actually_set_backlight(old_conn_state, 0);
3bd712e5 759
7bd688cd
JN
760 tmp = I915_READ(BLC_PWM_CPU_CTL2);
761 I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
762
763 tmp = I915_READ(BLC_PWM_PCH_CTL1);
764 I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
765}
766
7d025e08 767static void i9xx_disable_backlight(const struct drm_connector_state *old_conn_state)
3bd712e5 768{
7d025e08 769 intel_panel_actually_set_backlight(old_conn_state, 0);
3bd712e5
JN
770}
771
7d025e08 772static void i965_disable_backlight(const struct drm_connector_state *old_conn_state)
7bd688cd 773{
7d025e08 774 struct drm_i915_private *dev_priv = to_i915(old_conn_state->connector->dev);
7bd688cd
JN
775 u32 tmp;
776
7d025e08 777 intel_panel_actually_set_backlight(old_conn_state, 0);
3bd712e5 778
7bd688cd
JN
779 tmp = I915_READ(BLC_PWM_CTL2);
780 I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
781}
782
7d025e08 783static void vlv_disable_backlight(const struct drm_connector_state *old_conn_state)
7bd688cd 784{
7d025e08 785 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
e6cb3727 786 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7d025e08 787 enum pipe pipe = to_intel_crtc(old_conn_state->crtc)->pipe;
7bd688cd
JN
788 u32 tmp;
789
7d025e08 790 intel_panel_actually_set_backlight(old_conn_state, 0);
3bd712e5 791
7bd688cd
JN
792 tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
793 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
794}
795
7d025e08 796static void bxt_disable_backlight(const struct drm_connector_state *old_conn_state)
0fb890c0 797{
7d025e08 798 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
e6cb3727 799 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
022e4e52
SK
800 struct intel_panel *panel = &connector->panel;
801 u32 tmp, val;
0fb890c0 802
7d025e08 803 intel_panel_actually_set_backlight(old_conn_state, 0);
0fb890c0 804
022e4e52
SK
805 tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
806 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
807 tmp & ~BXT_BLC_PWM_ENABLE);
808
809 if (panel->backlight.controller == 1) {
810 val = I915_READ(UTIL_PIN_CTL);
811 val &= ~UTIL_PIN_ENABLE;
812 I915_WRITE(UTIL_PIN_CTL, val);
813 }
0fb890c0
VK
814}
815
7d025e08 816static void cnp_disable_backlight(const struct drm_connector_state *old_conn_state)
4c9f7086 817{
7d025e08 818 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
4c9f7086
RV
819 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
820 struct intel_panel *panel = &connector->panel;
821 u32 tmp;
822
7d025e08 823 intel_panel_actually_set_backlight(old_conn_state, 0);
4c9f7086
RV
824
825 tmp = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
826 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
827 tmp & ~BXT_BLC_PWM_ENABLE);
828}
829
7d025e08 830static void pwm_disable_backlight(const struct drm_connector_state *old_conn_state)
b029e66f 831{
7d025e08 832 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
b029e66f
SK
833 struct intel_panel *panel = &connector->panel;
834
835 /* Disable the backlight */
328f75bb 836 intel_panel_actually_set_backlight(old_conn_state, 0);
b029e66f
SK
837 usleep_range(2000, 3000);
838 pwm_disable(panel->backlight.pwm);
839}
840
b037d58f 841void intel_panel_disable_backlight(const struct drm_connector_state *old_conn_state)
f52c619a 842{
b037d58f 843 struct intel_connector *connector = to_intel_connector(old_conn_state->connector);
e6cb3727 844 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
58c68779 845 struct intel_panel *panel = &connector->panel;
8ba2d185 846
260d8f98 847 if (!panel->backlight.present)
752aa88a
JB
848 return;
849
3f577573 850 /*
5389e916 851 * Do not disable backlight on the vga_switcheroo path. When switching
3f577573
JN
852 * away from i915, the other client may depend on i915 to handle the
853 * backlight. This will leave the backlight on unnecessarily when
854 * another client is not activated.
855 */
91c8a326 856 if (dev_priv->drm.switch_power_state == DRM_SWITCH_POWER_CHANGING) {
3f577573
JN
857 DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
858 return;
859 }
860
07f11d49 861 mutex_lock(&dev_priv->backlight_lock);
47356eb6 862
ab656bb9
JN
863 if (panel->backlight.device)
864 panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
58c68779 865 panel->backlight.enabled = false;
7d025e08 866 panel->backlight.disable(old_conn_state);
24ded204 867
07f11d49 868 mutex_unlock(&dev_priv->backlight_lock);
7bd688cd 869}
24ded204 870
7d025e08
ML
871static void lpt_enable_backlight(const struct intel_crtc_state *crtc_state,
872 const struct drm_connector_state *conn_state)
96ab4c70 873{
7d025e08 874 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 875 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
96ab4c70 876 struct intel_panel *panel = &connector->panel;
e29aff05 877 u32 pch_ctl1, pch_ctl2, schicken;
96ab4c70
SV
878
879 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
880 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
881 DRM_DEBUG_KMS("pch backlight already enabled\n");
882 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
883 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
884 }
24ded204 885
e29aff05
SL
886 if (HAS_PCH_LPT(dev_priv)) {
887 schicken = I915_READ(SOUTH_CHICKEN2);
888 if (panel->backlight.alternate_pwm_increment)
889 schicken |= LPT_PWM_GRANULARITY;
890 else
891 schicken &= ~LPT_PWM_GRANULARITY;
892 I915_WRITE(SOUTH_CHICKEN2, schicken);
893 } else {
894 schicken = I915_READ(SOUTH_CHICKEN1);
895 if (panel->backlight.alternate_pwm_increment)
896 schicken |= SPT_PWM_GRANULARITY;
897 else
898 schicken &= ~SPT_PWM_GRANULARITY;
899 I915_WRITE(SOUTH_CHICKEN1, schicken);
900 }
901
96ab4c70
SV
902 pch_ctl2 = panel->backlight.max << 16;
903 I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
a4f32fc3 904
96ab4c70
SV
905 pch_ctl1 = 0;
906 if (panel->backlight.active_low_pwm)
907 pch_ctl1 |= BLM_PCH_POLARITY;
8ba2d185 908
e6b2627c
JN
909 /* After LPT, override is the default. */
910 if (HAS_PCH_LPT(dev_priv))
911 pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
96ab4c70
SV
912
913 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
914 POSTING_READ(BLC_PWM_PCH_CTL1);
915 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
916
917 /* This won't stick until the above enable. */
7d025e08 918 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
47356eb6
CW
919}
920
7d025e08
ML
921static void pch_enable_backlight(const struct intel_crtc_state *crtc_state,
922 const struct drm_connector_state *conn_state)
7bd688cd 923{
7d025e08 924 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 925 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
3bd712e5 926 struct intel_panel *panel = &connector->panel;
7d025e08 927 enum transcoder cpu_transcoder = crtc_state->cpu_transcoder;
b35684b8 928 u32 cpu_ctl2, pch_ctl1, pch_ctl2;
7bd688cd 929
b35684b8
JN
930 cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
931 if (cpu_ctl2 & BLM_PWM_ENABLE) {
813008cd 932 DRM_DEBUG_KMS("cpu backlight already enabled\n");
b35684b8
JN
933 cpu_ctl2 &= ~BLM_PWM_ENABLE;
934 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
935 }
7bd688cd 936
b35684b8
JN
937 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
938 if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
939 DRM_DEBUG_KMS("pch backlight already enabled\n");
940 pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
941 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
942 }
7bd688cd
JN
943
944 if (cpu_transcoder == TRANSCODER_EDP)
b35684b8 945 cpu_ctl2 = BLM_TRANSCODER_EDP;
7bd688cd 946 else
b35684b8
JN
947 cpu_ctl2 = BLM_PIPE(cpu_transcoder);
948 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
7bd688cd 949 POSTING_READ(BLC_PWM_CPU_CTL2);
b35684b8 950 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
3bd712e5 951
b35684b8 952 /* This won't stick until the above enable. */
7d025e08 953 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
b35684b8
JN
954
955 pch_ctl2 = panel->backlight.max << 16;
956 I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
957
b35684b8
JN
958 pch_ctl1 = 0;
959 if (panel->backlight.active_low_pwm)
960 pch_ctl1 |= BLM_PCH_POLARITY;
96ab4c70 961
b35684b8
JN
962 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
963 POSTING_READ(BLC_PWM_PCH_CTL1);
964 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
3bd712e5
JN
965}
966
7d025e08
ML
967static void i9xx_enable_backlight(const struct intel_crtc_state *crtc_state,
968 const struct drm_connector_state *conn_state)
3bd712e5 969{
7d025e08 970 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 971 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
3bd712e5 972 struct intel_panel *panel = &connector->panel;
b35684b8
JN
973 u32 ctl, freq;
974
975 ctl = I915_READ(BLC_PWM_CTL);
976 if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
813008cd 977 DRM_DEBUG_KMS("backlight already enabled\n");
b35684b8
JN
978 I915_WRITE(BLC_PWM_CTL, 0);
979 }
3bd712e5 980
b35684b8
JN
981 freq = panel->backlight.max;
982 if (panel->backlight.combination_mode)
983 freq /= 0xff;
984
985 ctl = freq << 17;
b6ab66aa 986 if (panel->backlight.combination_mode)
b35684b8 987 ctl |= BLM_LEGACY_MODE;
e6cb3727 988 if (IS_PINEVIEW(dev_priv) && panel->backlight.active_low_pwm)
b35684b8
JN
989 ctl |= BLM_POLARITY_PNV;
990
991 I915_WRITE(BLC_PWM_CTL, ctl);
992 POSTING_READ(BLC_PWM_CTL);
993
994 /* XXX: combine this into above write? */
7d025e08 995 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
2059ac3b
JN
996
997 /*
998 * Needed to enable backlight on some 855gm models. BLC_HIST_CTL is
999 * 855gm only, but checking for gen2 is safe, as 855gm is the only gen2
1000 * that has backlight.
1001 */
cf819eff 1002 if (IS_GEN(dev_priv, 2))
2059ac3b 1003 I915_WRITE(BLC_HIST_CTL, BLM_HISTOGRAM_ENABLE);
7bd688cd 1004}
8ba2d185 1005
7d025e08
ML
1006static void i965_enable_backlight(const struct intel_crtc_state *crtc_state,
1007 const struct drm_connector_state *conn_state)
7bd688cd 1008{
7d025e08 1009 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 1010 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
3bd712e5 1011 struct intel_panel *panel = &connector->panel;
7d025e08 1012 enum pipe pipe = to_intel_crtc(conn_state->crtc)->pipe;
b35684b8 1013 u32 ctl, ctl2, freq;
7bd688cd 1014
b35684b8
JN
1015 ctl2 = I915_READ(BLC_PWM_CTL2);
1016 if (ctl2 & BLM_PWM_ENABLE) {
813008cd 1017 DRM_DEBUG_KMS("backlight already enabled\n");
b35684b8
JN
1018 ctl2 &= ~BLM_PWM_ENABLE;
1019 I915_WRITE(BLC_PWM_CTL2, ctl2);
1020 }
7bd688cd 1021
b35684b8
JN
1022 freq = panel->backlight.max;
1023 if (panel->backlight.combination_mode)
1024 freq /= 0xff;
7bd688cd 1025
b35684b8
JN
1026 ctl = freq << 16;
1027 I915_WRITE(BLC_PWM_CTL, ctl);
3bd712e5 1028
b35684b8
JN
1029 ctl2 = BLM_PIPE(pipe);
1030 if (panel->backlight.combination_mode)
1031 ctl2 |= BLM_COMBINATION_MODE;
1032 if (panel->backlight.active_low_pwm)
1033 ctl2 |= BLM_POLARITY_I965;
1034 I915_WRITE(BLC_PWM_CTL2, ctl2);
1035 POSTING_READ(BLC_PWM_CTL2);
1036 I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
2e7eeeb5 1037
7d025e08 1038 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
7bd688cd
JN
1039}
1040
7d025e08
ML
1041static void vlv_enable_backlight(const struct intel_crtc_state *crtc_state,
1042 const struct drm_connector_state *conn_state)
7bd688cd 1043{
7d025e08 1044 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 1045 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
3bd712e5 1046 struct intel_panel *panel = &connector->panel;
7d025e08 1047 enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
b35684b8 1048 u32 ctl, ctl2;
7bd688cd 1049
b35684b8
JN
1050 ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
1051 if (ctl2 & BLM_PWM_ENABLE) {
813008cd 1052 DRM_DEBUG_KMS("backlight already enabled\n");
b35684b8
JN
1053 ctl2 &= ~BLM_PWM_ENABLE;
1054 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
1055 }
7bd688cd 1056
b35684b8
JN
1057 ctl = panel->backlight.max << 16;
1058 I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
7bd688cd 1059
b35684b8 1060 /* XXX: combine this into above write? */
7d025e08 1061 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
7bd688cd 1062
b35684b8
JN
1063 ctl2 = 0;
1064 if (panel->backlight.active_low_pwm)
1065 ctl2 |= BLM_POLARITY_I965;
1066 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
7bd688cd 1067 POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
b35684b8 1068 I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
47356eb6
CW
1069}
1070
7d025e08
ML
1071static void bxt_enable_backlight(const struct intel_crtc_state *crtc_state,
1072 const struct drm_connector_state *conn_state)
0fb890c0 1073{
7d025e08 1074 struct intel_connector *connector = to_intel_connector(conn_state->connector);
e6cb3727 1075 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
0fb890c0 1076 struct intel_panel *panel = &connector->panel;
7d025e08 1077 enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
022e4e52
SK
1078 u32 pwm_ctl, val;
1079
add03379 1080 /* Controller 1 uses the utility pin. */
022e4e52
SK
1081 if (panel->backlight.controller == 1) {
1082 val = I915_READ(UTIL_PIN_CTL);
1083 if (val & UTIL_PIN_ENABLE) {
1084 DRM_DEBUG_KMS("util pin already enabled\n");
1085 val &= ~UTIL_PIN_ENABLE;
1086 I915_WRITE(UTIL_PIN_CTL, val);
1087 }
0fb890c0 1088
022e4e52
SK
1089 val = 0;
1090 if (panel->backlight.util_pin_active_low)
1091 val |= UTIL_PIN_POLARITY;
1092 I915_WRITE(UTIL_PIN_CTL, val | UTIL_PIN_PIPE(pipe) |
1093 UTIL_PIN_MODE_PWM | UTIL_PIN_ENABLE);
1094 }
1095
1096 pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
0fb890c0
VK
1097 if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
1098 DRM_DEBUG_KMS("backlight already enabled\n");
1099 pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
022e4e52
SK
1100 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1101 pwm_ctl);
0fb890c0
VK
1102 }
1103
022e4e52
SK
1104 I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller),
1105 panel->backlight.max);
0fb890c0 1106
7d025e08 1107 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
0fb890c0
VK
1108
1109 pwm_ctl = 0;
1110 if (panel->backlight.active_low_pwm)
1111 pwm_ctl |= BXT_BLC_PWM_POLARITY;
1112
022e4e52
SK
1113 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl);
1114 POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1115 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1116 pwm_ctl | BXT_BLC_PWM_ENABLE);
0fb890c0
VK
1117}
1118
7d025e08
ML
1119static void cnp_enable_backlight(const struct intel_crtc_state *crtc_state,
1120 const struct drm_connector_state *conn_state)
4c9f7086 1121{
7d025e08 1122 struct intel_connector *connector = to_intel_connector(conn_state->connector);
4c9f7086
RV
1123 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1124 struct intel_panel *panel = &connector->panel;
1125 u32 pwm_ctl;
1126
1127 pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1128 if (pwm_ctl & BXT_BLC_PWM_ENABLE) {
1129 DRM_DEBUG_KMS("backlight already enabled\n");
1130 pwm_ctl &= ~BXT_BLC_PWM_ENABLE;
1131 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1132 pwm_ctl);
1133 }
1134
1135 I915_WRITE(BXT_BLC_PWM_FREQ(panel->backlight.controller),
1136 panel->backlight.max);
1137
7d025e08 1138 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
4c9f7086
RV
1139
1140 pwm_ctl = 0;
1141 if (panel->backlight.active_low_pwm)
1142 pwm_ctl |= BXT_BLC_PWM_POLARITY;
1143
1144 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller), pwm_ctl);
1145 POSTING_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1146 I915_WRITE(BXT_BLC_PWM_CTL(panel->backlight.controller),
1147 pwm_ctl | BXT_BLC_PWM_ENABLE);
1148}
1149
7d025e08
ML
1150static void pwm_enable_backlight(const struct intel_crtc_state *crtc_state,
1151 const struct drm_connector_state *conn_state)
b029e66f 1152{
7d025e08 1153 struct intel_connector *connector = to_intel_connector(conn_state->connector);
b029e66f
SK
1154 struct intel_panel *panel = &connector->panel;
1155
1156 pwm_enable(panel->backlight.pwm);
7d025e08 1157 intel_panel_actually_set_backlight(conn_state, panel->backlight.level);
b029e66f
SK
1158}
1159
63a23d24
ML
1160static void __intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
1161 const struct drm_connector_state *conn_state)
47356eb6 1162{
b037d58f 1163 struct intel_connector *connector = to_intel_connector(conn_state->connector);
58c68779 1164 struct intel_panel *panel = &connector->panel;
47356eb6 1165
f91c15e0
JN
1166 WARN_ON(panel->backlight.max == 0);
1167
13f3fbe8 1168 if (panel->backlight.level <= panel->backlight.min) {
f91c15e0 1169 panel->backlight.level = panel->backlight.max;
58c68779
JN
1170 if (panel->backlight.device)
1171 panel->backlight.device->props.brightness =
6dda730e
JN
1172 scale_hw_to_user(connector,
1173 panel->backlight.level,
1174 panel->backlight.device->props.max_brightness);
b6b3ba5b 1175 }
47356eb6 1176
7d025e08 1177 panel->backlight.enable(crtc_state, conn_state);
58c68779 1178 panel->backlight.enabled = true;
ab656bb9
JN
1179 if (panel->backlight.device)
1180 panel->backlight.device->props.power = FB_BLANK_UNBLANK;
63a23d24
ML
1181}
1182
1183void intel_panel_enable_backlight(const struct intel_crtc_state *crtc_state,
1184 const struct drm_connector_state *conn_state)
1185{
1186 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1187 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1188 struct intel_panel *panel = &connector->panel;
1189 enum pipe pipe = to_intel_crtc(crtc_state->base.crtc)->pipe;
1190
1191 if (!panel->backlight.present)
1192 return;
1193
1194 DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
1195
1196 mutex_lock(&dev_priv->backlight_lock);
1197
1198 __intel_panel_enable_backlight(crtc_state, conn_state);
8ba2d185 1199
07f11d49 1200 mutex_unlock(&dev_priv->backlight_lock);
47356eb6
CW
1201}
1202
912e8b12 1203#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
fd94d53e
AB
1204static u32 intel_panel_get_backlight(struct intel_connector *connector)
1205{
1206 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1207 struct intel_panel *panel = &connector->panel;
1208 u32 val = 0;
1209
1210 mutex_lock(&dev_priv->backlight_lock);
1211
1212 if (panel->backlight.enabled) {
1213 val = panel->backlight.get(connector);
1214 val = intel_panel_compute_brightness(connector, val);
1215 }
1216
1217 mutex_unlock(&dev_priv->backlight_lock);
1218
1219 DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
1220 return val;
1221}
1222
1223/* set backlight brightness to level in range [0..max], scaling wrt hw min */
1224static void intel_panel_set_backlight(const struct drm_connector_state *conn_state,
1225 u32 user_level, u32 user_max)
1226{
1227 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1228 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1229 struct intel_panel *panel = &connector->panel;
1230 u32 hw_level;
1231
1232 if (!panel->backlight.present)
1233 return;
1234
1235 mutex_lock(&dev_priv->backlight_lock);
1236
1237 WARN_ON(panel->backlight.max == 0);
1238
1239 hw_level = scale_user_to_hw(connector, user_level, user_max);
1240 panel->backlight.level = hw_level;
1241
1242 if (panel->backlight.enabled)
1243 intel_panel_actually_set_backlight(conn_state, hw_level);
1244
1245 mutex_unlock(&dev_priv->backlight_lock);
1246}
1247
db31af1d 1248static int intel_backlight_device_update_status(struct backlight_device *bd)
aaa6fd2a 1249{
752aa88a 1250 struct intel_connector *connector = bl_get_data(bd);
ab656bb9 1251 struct intel_panel *panel = &connector->panel;
752aa88a
JB
1252 struct drm_device *dev = connector->base.dev;
1253
51fd371b 1254 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
540b5d02
CW
1255 DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
1256 bd->props.brightness, bd->props.max_brightness);
7d025e08 1257 intel_panel_set_backlight(connector->base.state, bd->props.brightness,
d6540632 1258 bd->props.max_brightness);
ab656bb9
JN
1259
1260 /*
1261 * Allow flipping bl_power as a sub-state of enabled. Sadly the
1262 * backlight class device does not make it easy to to differentiate
1263 * between callbacks for brightness and bl_power, so our backlight_power
1264 * callback needs to take this into account.
1265 */
1266 if (panel->backlight.enabled) {
5507faeb 1267 if (panel->backlight.power) {
e6755fb7
JN
1268 bool enable = bd->props.power == FB_BLANK_UNBLANK &&
1269 bd->props.brightness != 0;
5507faeb 1270 panel->backlight.power(connector, enable);
ab656bb9
JN
1271 }
1272 } else {
1273 bd->props.power = FB_BLANK_POWERDOWN;
1274 }
1275
51fd371b 1276 drm_modeset_unlock(&dev->mode_config.connection_mutex);
aaa6fd2a
MG
1277 return 0;
1278}
1279
db31af1d 1280static int intel_backlight_device_get_brightness(struct backlight_device *bd)
aaa6fd2a 1281{
752aa88a
JB
1282 struct intel_connector *connector = bl_get_data(bd);
1283 struct drm_device *dev = connector->base.dev;
fac5e23e 1284 struct drm_i915_private *dev_priv = to_i915(dev);
2cb2cb5f 1285 intel_wakeref_t wakeref;
d4225a53 1286 int ret = 0;
752aa88a 1287
d4225a53
CW
1288 with_intel_runtime_pm(dev_priv, wakeref) {
1289 u32 hw_level;
6dda730e 1290
d4225a53 1291 drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
6dda730e 1292
d4225a53
CW
1293 hw_level = intel_panel_get_backlight(connector);
1294 ret = scale_hw_to_user(connector,
1295 hw_level, bd->props.max_brightness);
1296
1297 drm_modeset_unlock(&dev->mode_config.connection_mutex);
1298 }
752aa88a 1299
7bd688cd 1300 return ret;
aaa6fd2a
MG
1301}
1302
db31af1d
JN
1303static const struct backlight_ops intel_backlight_device_ops = {
1304 .update_status = intel_backlight_device_update_status,
1305 .get_brightness = intel_backlight_device_get_brightness,
aaa6fd2a
MG
1306};
1307
1ebaa0b9 1308int intel_backlight_device_register(struct intel_connector *connector)
aaa6fd2a 1309{
58c68779 1310 struct intel_panel *panel = &connector->panel;
aaa6fd2a 1311 struct backlight_properties props;
aaa6fd2a 1312
58c68779 1313 if (WARN_ON(panel->backlight.device))
dc652f90
JN
1314 return -ENODEV;
1315
0962c3c9
VS
1316 if (!panel->backlight.present)
1317 return 0;
1318
6dda730e 1319 WARN_ON(panel->backlight.max == 0);
7bd688cd 1320
af437cfd 1321 memset(&props, 0, sizeof(props));
aaa6fd2a 1322 props.type = BACKLIGHT_RAW;
6dda730e
JN
1323
1324 /*
1325 * Note: Everything should work even if the backlight device max
1326 * presented to the userspace is arbitrarily chosen.
1327 */
7bd688cd 1328 props.max_brightness = panel->backlight.max;
6dda730e
JN
1329 props.brightness = scale_hw_to_user(connector,
1330 panel->backlight.level,
1331 props.max_brightness);
58c68779 1332
ab656bb9
JN
1333 if (panel->backlight.enabled)
1334 props.power = FB_BLANK_UNBLANK;
1335 else
1336 props.power = FB_BLANK_POWERDOWN;
1337
58c68779
JN
1338 /*
1339 * Note: using the same name independent of the connector prevents
1340 * registration of multiple backlight devices in the driver.
1341 */
1342 panel->backlight.device =
aaa6fd2a 1343 backlight_device_register("intel_backlight",
db31af1d
JN
1344 connector->base.kdev,
1345 connector,
1346 &intel_backlight_device_ops, &props);
aaa6fd2a 1347
58c68779 1348 if (IS_ERR(panel->backlight.device)) {
aaa6fd2a 1349 DRM_ERROR("Failed to register backlight: %ld\n",
58c68779
JN
1350 PTR_ERR(panel->backlight.device));
1351 panel->backlight.device = NULL;
aaa6fd2a
MG
1352 return -ENODEV;
1353 }
0962c3c9
VS
1354
1355 DRM_DEBUG_KMS("Connector %s backlight sysfs interface registered\n",
1356 connector->base.name);
1357
aaa6fd2a
MG
1358 return 0;
1359}
1360
e63d87c0 1361void intel_backlight_device_unregister(struct intel_connector *connector)
aaa6fd2a 1362{
58c68779
JN
1363 struct intel_panel *panel = &connector->panel;
1364
1365 if (panel->backlight.device) {
1366 backlight_device_unregister(panel->backlight.device);
1367 panel->backlight.device = NULL;
dc652f90 1368 }
aaa6fd2a 1369}
db31af1d
JN
1370#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
1371
4c9f7086
RV
1372/*
1373 * CNP: PWM clock frequency is 19.2 MHz or 24 MHz.
1374 * PWM increment = 1
1375 */
1376static u32 cnp_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1377{
1378 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1379
1380 return DIV_ROUND_CLOSEST(KHz(dev_priv->rawclk_freq), pwm_freq_hz);
1381}
1382
2dd6982e
JN
1383/*
1384 * BXT: PWM clock frequency = 19.2 MHz.
1385 */
1386static u32 bxt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1387{
37f2248e 1388 return DIV_ROUND_CLOSEST(KHz(19200), pwm_freq_hz);
2dd6982e
JN
1389}
1390
f91c15e0 1391/*
aa17cdb4
JN
1392 * SPT: This value represents the period of the PWM stream in clock periods
1393 * multiplied by 16 (default increment) or 128 (alternate increment selected in
1394 * SCHICKEN_1 bit 0). PWM clock is 24 MHz.
1395 */
1396static u32 spt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1397{
32b421e7 1398 struct intel_panel *panel = &connector->panel;
e7dc33f3 1399 u32 mul;
aa17cdb4 1400
32b421e7 1401 if (panel->backlight.alternate_pwm_increment)
aa17cdb4
JN
1402 mul = 128;
1403 else
1404 mul = 16;
1405
37f2248e 1406 return DIV_ROUND_CLOSEST(MHz(24), pwm_freq_hz * mul);
aa17cdb4
JN
1407}
1408
1409/*
1410 * LPT: This value represents the period of the PWM stream in clock periods
1411 * multiplied by 128 (default increment) or 16 (alternate increment, selected in
1412 * LPT SOUTH_CHICKEN2 register bit 5).
1413 */
1414static u32 lpt_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1415{
e6cb3727 1416 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
32b421e7 1417 struct intel_panel *panel = &connector->panel;
aa17cdb4
JN
1418 u32 mul, clock;
1419
32b421e7 1420 if (panel->backlight.alternate_pwm_increment)
aa17cdb4
JN
1421 mul = 16;
1422 else
1423 mul = 128;
1424
56f5f700 1425 if (HAS_PCH_LPT_H(dev_priv))
aa17cdb4
JN
1426 clock = MHz(135); /* LPT:H */
1427 else
1428 clock = MHz(24); /* LPT:LP */
1429
37f2248e 1430 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
aa17cdb4
JN
1431}
1432
1433/*
1434 * ILK/SNB/IVB: This value represents the period of the PWM stream in PCH
1435 * display raw clocks multiplied by 128.
1436 */
1437static u32 pch_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1438{
e7dc33f3 1439 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
aa17cdb4 1440
37f2248e 1441 return DIV_ROUND_CLOSEST(KHz(dev_priv->rawclk_freq), pwm_freq_hz * 128);
aa17cdb4
JN
1442}
1443
1444/*
1445 * Gen2: This field determines the number of time base events (display core
1446 * clock frequency/32) in total for a complete cycle of modulated backlight
1447 * control.
f91c15e0 1448 *
aa17cdb4
JN
1449 * Gen3: A time base event equals the display core clock ([DevPNV] HRAW clock)
1450 * divided by 32.
1451 */
1452static u32 i9xx_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1453{
e7dc33f3 1454 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
aa17cdb4
JN
1455 int clock;
1456
e7dc33f3
VS
1457 if (IS_PINEVIEW(dev_priv))
1458 clock = KHz(dev_priv->rawclk_freq);
aa17cdb4 1459 else
49cd97a3 1460 clock = KHz(dev_priv->cdclk.hw.cdclk);
aa17cdb4 1461
37f2248e 1462 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 32);
aa17cdb4
JN
1463}
1464
1465/*
1466 * Gen4: This value represents the period of the PWM stream in display core
83d83392
VS
1467 * clocks ([DevCTG] HRAW clocks) multiplied by 128.
1468 *
aa17cdb4
JN
1469 */
1470static u32 i965_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1471{
3bed7f4d 1472 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
83d83392
VS
1473 int clock;
1474
1475 if (IS_G4X(dev_priv))
e7dc33f3 1476 clock = KHz(dev_priv->rawclk_freq);
83d83392 1477 else
49cd97a3 1478 clock = KHz(dev_priv->cdclk.hw.cdclk);
aa17cdb4 1479
37f2248e 1480 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * 128);
aa17cdb4
JN
1481}
1482
1483/*
1484 * VLV: This value represents the period of the PWM stream in display core
1485 * clocks ([DevCTG] 200MHz HRAW clocks) multiplied by 128 or 25MHz S0IX clocks
1486 * multiplied by 16. CHV uses a 19.2MHz S0IX clock.
1487 */
1488static u32 vlv_hz_to_pwm(struct intel_connector *connector, u32 pwm_freq_hz)
1489{
e7dc33f3
VS
1490 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1491 int mul, clock;
aa17cdb4
JN
1492
1493 if ((I915_READ(CBR1_VLV) & CBR_PWM_CLOCK_MUX_SELECT) == 0) {
e7dc33f3
VS
1494 if (IS_CHERRYVIEW(dev_priv))
1495 clock = KHz(19200);
aa17cdb4 1496 else
e7dc33f3
VS
1497 clock = MHz(25);
1498 mul = 16;
aa17cdb4 1499 } else {
e7dc33f3
VS
1500 clock = KHz(dev_priv->rawclk_freq);
1501 mul = 128;
aa17cdb4 1502 }
e7dc33f3 1503
37f2248e 1504 return DIV_ROUND_CLOSEST(clock, pwm_freq_hz * mul);
aa17cdb4
JN
1505}
1506
1507static u32 get_backlight_max_vbt(struct intel_connector *connector)
1508{
e6cb3727 1509 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
5507faeb 1510 struct intel_panel *panel = &connector->panel;
aa17cdb4
JN
1511 u16 pwm_freq_hz = dev_priv->vbt.backlight.pwm_freq_hz;
1512 u32 pwm;
1513
5075222b
JN
1514 if (!panel->backlight.hz_to_pwm) {
1515 DRM_DEBUG_KMS("backlight frequency conversion not supported\n");
aa17cdb4
JN
1516 return 0;
1517 }
1518
5075222b
JN
1519 if (pwm_freq_hz) {
1520 DRM_DEBUG_KMS("VBT defined backlight frequency %u Hz\n",
1521 pwm_freq_hz);
1522 } else {
1523 pwm_freq_hz = 200;
1524 DRM_DEBUG_KMS("default backlight frequency %u Hz\n",
1525 pwm_freq_hz);
aa17cdb4
JN
1526 }
1527
5507faeb 1528 pwm = panel->backlight.hz_to_pwm(connector, pwm_freq_hz);
aa17cdb4
JN
1529 if (!pwm) {
1530 DRM_DEBUG_KMS("backlight frequency conversion failed\n");
1531 return 0;
1532 }
1533
aa17cdb4
JN
1534 return pwm;
1535}
1536
1537/*
1538 * Note: The setup hooks can't assume pipe is set!
f91c15e0 1539 */
6dda730e
JN
1540static u32 get_backlight_min_vbt(struct intel_connector *connector)
1541{
e6cb3727 1542 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
6dda730e 1543 struct intel_panel *panel = &connector->panel;
e1c412e7 1544 int min;
6dda730e
JN
1545
1546 WARN_ON(panel->backlight.max == 0);
1547
e1c412e7
JN
1548 /*
1549 * XXX: If the vbt value is 255, it makes min equal to max, which leads
1550 * to problems. There are such machines out there. Either our
1551 * interpretation is wrong or the vbt has bogus data. Or both. Safeguard
1552 * against this by letting the minimum be at most (arbitrarily chosen)
1553 * 25% of the max.
1554 */
1555 min = clamp_t(int, dev_priv->vbt.backlight.min_brightness, 0, 64);
1556 if (min != dev_priv->vbt.backlight.min_brightness) {
1557 DRM_DEBUG_KMS("clamping VBT min backlight %d/255 to %d/255\n",
1558 dev_priv->vbt.backlight.min_brightness, min);
1559 }
1560
6dda730e 1561 /* vbt value is a coefficient in range [0..255] */
e1c412e7 1562 return scale(min, 0, 255, 0, panel->backlight.max);
6dda730e
JN
1563}
1564
437b15b8 1565static int lpt_setup_backlight(struct intel_connector *connector, enum pipe unused)
aaa6fd2a 1566{
e6cb3727 1567 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
96ab4c70 1568 struct intel_panel *panel = &connector->panel;
5b1ec9ac
ML
1569 u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
1570 bool alt, cpu_mode;
32b421e7
JN
1571
1572 if (HAS_PCH_LPT(dev_priv))
1573 alt = I915_READ(SOUTH_CHICKEN2) & LPT_PWM_GRANULARITY;
1574 else
1575 alt = I915_READ(SOUTH_CHICKEN1) & SPT_PWM_GRANULARITY;
1576 panel->backlight.alternate_pwm_increment = alt;
96ab4c70
SV
1577
1578 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1579 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1580
1581 pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1582 panel->backlight.max = pch_ctl2 >> 16;
aa17cdb4 1583
5b1ec9ac
ML
1584 cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
1585
aa17cdb4
JN
1586 if (!panel->backlight.max)
1587 panel->backlight.max = get_backlight_max_vbt(connector);
1588
96ab4c70
SV
1589 if (!panel->backlight.max)
1590 return -ENODEV;
1591
6dda730e
JN
1592 panel->backlight.min = get_backlight_min_vbt(connector);
1593
5b1ec9ac
ML
1594 panel->backlight.enabled = pch_ctl1 & BLM_PCH_PWM_ENABLE;
1595
1596 cpu_mode = panel->backlight.enabled && HAS_PCH_LPT(dev_priv) &&
1597 !(pch_ctl1 & BLM_PCH_OVERRIDE_ENABLE) &&
1598 (cpu_ctl2 & BLM_PWM_ENABLE);
1599 if (cpu_mode)
1600 val = pch_get_backlight(connector);
1601 else
1602 val = lpt_get_backlight(connector);
46e69f39
JN
1603 val = intel_panel_compute_brightness(connector, val);
1604 panel->backlight.level = clamp(val, panel->backlight.min,
1605 panel->backlight.max);
96ab4c70 1606
5b1ec9ac
ML
1607 if (cpu_mode) {
1608 DRM_DEBUG_KMS("CPU backlight register was enabled, switching to PCH override\n");
1609
1610 /* Write converted CPU PWM value to PCH override register */
1611 lpt_set_backlight(connector->base.state, panel->backlight.level);
1612 I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_OVERRIDE_ENABLE);
1613
1614 I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 & ~BLM_PWM_ENABLE);
1615 }
96ab4c70
SV
1616
1617 return 0;
1618}
1619
6517d273 1620static int pch_setup_backlight(struct intel_connector *connector, enum pipe unused)
7bd688cd 1621{
e6cb3727 1622 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd 1623 struct intel_panel *panel = &connector->panel;
636baebf 1624 u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
7bd688cd 1625
636baebf
JN
1626 pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
1627 panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
1628
1629 pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
1630 panel->backlight.max = pch_ctl2 >> 16;
aa17cdb4
JN
1631
1632 if (!panel->backlight.max)
1633 panel->backlight.max = get_backlight_max_vbt(connector);
1634
7bd688cd
JN
1635 if (!panel->backlight.max)
1636 return -ENODEV;
1637
6dda730e
JN
1638 panel->backlight.min = get_backlight_min_vbt(connector);
1639
7bd688cd 1640 val = pch_get_backlight(connector);
46e69f39
JN
1641 val = intel_panel_compute_brightness(connector, val);
1642 panel->backlight.level = clamp(val, panel->backlight.min,
1643 panel->backlight.max);
7bd688cd 1644
636baebf
JN
1645 cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
1646 panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
46e69f39 1647 (pch_ctl1 & BLM_PCH_PWM_ENABLE);
636baebf 1648
7bd688cd
JN
1649 return 0;
1650}
1651
6517d273 1652static int i9xx_setup_backlight(struct intel_connector *connector, enum pipe unused)
7bd688cd 1653{
e6cb3727 1654 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd 1655 struct intel_panel *panel = &connector->panel;
636baebf
JN
1656 u32 ctl, val;
1657
1658 ctl = I915_READ(BLC_PWM_CTL);
1659
cf819eff 1660 if (IS_GEN(dev_priv, 2) || IS_I915GM(dev_priv) || IS_I945GM(dev_priv))
636baebf
JN
1661 panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
1662
e6cb3727 1663 if (IS_PINEVIEW(dev_priv))
636baebf
JN
1664 panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
1665
1666 panel->backlight.max = ctl >> 17;
aa17cdb4
JN
1667
1668 if (!panel->backlight.max) {
1669 panel->backlight.max = get_backlight_max_vbt(connector);
1670 panel->backlight.max >>= 1;
1671 }
7bd688cd 1672
7bd688cd
JN
1673 if (!panel->backlight.max)
1674 return -ENODEV;
1675
aa17cdb4
JN
1676 if (panel->backlight.combination_mode)
1677 panel->backlight.max *= 0xff;
1678
6dda730e
JN
1679 panel->backlight.min = get_backlight_min_vbt(connector);
1680
7bd688cd 1681 val = i9xx_get_backlight(connector);
46e69f39
JN
1682 val = intel_panel_compute_brightness(connector, val);
1683 panel->backlight.level = clamp(val, panel->backlight.min,
1684 panel->backlight.max);
7bd688cd 1685
46e69f39 1686 panel->backlight.enabled = val != 0;
636baebf 1687
7bd688cd
JN
1688 return 0;
1689}
1690
6517d273 1691static int i965_setup_backlight(struct intel_connector *connector, enum pipe unused)
7bd688cd 1692{
e6cb3727 1693 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd 1694 struct intel_panel *panel = &connector->panel;
636baebf
JN
1695 u32 ctl, ctl2, val;
1696
1697 ctl2 = I915_READ(BLC_PWM_CTL2);
1698 panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1699 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1700
1701 ctl = I915_READ(BLC_PWM_CTL);
1702 panel->backlight.max = ctl >> 16;
aa17cdb4
JN
1703
1704 if (!panel->backlight.max)
1705 panel->backlight.max = get_backlight_max_vbt(connector);
7bd688cd 1706
7bd688cd
JN
1707 if (!panel->backlight.max)
1708 return -ENODEV;
1709
aa17cdb4
JN
1710 if (panel->backlight.combination_mode)
1711 panel->backlight.max *= 0xff;
1712
6dda730e
JN
1713 panel->backlight.min = get_backlight_min_vbt(connector);
1714
7bd688cd 1715 val = i9xx_get_backlight(connector);
46e69f39
JN
1716 val = intel_panel_compute_brightness(connector, val);
1717 panel->backlight.level = clamp(val, panel->backlight.min,
1718 panel->backlight.max);
7bd688cd 1719
46e69f39 1720 panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE;
636baebf 1721
7bd688cd
JN
1722 return 0;
1723}
1724
6517d273 1725static int vlv_setup_backlight(struct intel_connector *connector, enum pipe pipe)
7bd688cd 1726{
e6cb3727 1727 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd 1728 struct intel_panel *panel = &connector->panel;
636baebf 1729 u32 ctl, ctl2, val;
7bd688cd 1730
6517d273
VS
1731 if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
1732 return -ENODEV;
1733
1734 ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
636baebf
JN
1735 panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1736
6517d273 1737 ctl = I915_READ(VLV_BLC_PWM_CTL(pipe));
636baebf 1738 panel->backlight.max = ctl >> 16;
aa17cdb4
JN
1739
1740 if (!panel->backlight.max)
1741 panel->backlight.max = get_backlight_max_vbt(connector);
1742
7bd688cd
JN
1743 if (!panel->backlight.max)
1744 return -ENODEV;
1745
6dda730e
JN
1746 panel->backlight.min = get_backlight_min_vbt(connector);
1747
e6cb3727 1748 val = _vlv_get_backlight(dev_priv, pipe);
46e69f39
JN
1749 val = intel_panel_compute_brightness(connector, val);
1750 panel->backlight.level = clamp(val, panel->backlight.min,
1751 panel->backlight.max);
7bd688cd 1752
46e69f39 1753 panel->backlight.enabled = ctl2 & BLM_PWM_ENABLE;
636baebf 1754
7bd688cd
JN
1755 return 0;
1756}
1757
0fb890c0
VK
1758static int
1759bxt_setup_backlight(struct intel_connector *connector, enum pipe unused)
1760{
e6cb3727 1761 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
0fb890c0
VK
1762 struct intel_panel *panel = &connector->panel;
1763 u32 pwm_ctl, val;
1764
add03379 1765 panel->backlight.controller = dev_priv->vbt.backlight.controller;
0fb890c0 1766
022e4e52
SK
1767 pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1768
add03379 1769 /* Controller 1 uses the utility pin. */
022e4e52
SK
1770 if (panel->backlight.controller == 1) {
1771 val = I915_READ(UTIL_PIN_CTL);
1772 panel->backlight.util_pin_active_low =
1773 val & UTIL_PIN_POLARITY;
1774 }
1775
1776 panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
1777 panel->backlight.max =
1778 I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller));
aa17cdb4
JN
1779
1780 if (!panel->backlight.max)
1781 panel->backlight.max = get_backlight_max_vbt(connector);
1782
0fb890c0
VK
1783 if (!panel->backlight.max)
1784 return -ENODEV;
1785
c3881128
LS
1786 panel->backlight.min = get_backlight_min_vbt(connector);
1787
0fb890c0 1788 val = bxt_get_backlight(connector);
46e69f39
JN
1789 val = intel_panel_compute_brightness(connector, val);
1790 panel->backlight.level = clamp(val, panel->backlight.min,
1791 panel->backlight.max);
0fb890c0 1792
46e69f39 1793 panel->backlight.enabled = pwm_ctl & BXT_BLC_PWM_ENABLE;
0fb890c0
VK
1794
1795 return 0;
1796}
1797
4c9f7086
RV
1798static int
1799cnp_setup_backlight(struct intel_connector *connector, enum pipe unused)
1800{
1801 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1802 struct intel_panel *panel = &connector->panel;
1803 u32 pwm_ctl, val;
1804
1805 /*
ccf6e0d9
AS
1806 * CNP has the BXT implementation of backlight, but with only one
1807 * controller. TODO: ICP has multiple controllers but we only use
1808 * controller 0 for now.
4c9f7086
RV
1809 */
1810 panel->backlight.controller = 0;
1811
1812 pwm_ctl = I915_READ(BXT_BLC_PWM_CTL(panel->backlight.controller));
1813
1814 panel->backlight.active_low_pwm = pwm_ctl & BXT_BLC_PWM_POLARITY;
1815 panel->backlight.max =
1816 I915_READ(BXT_BLC_PWM_FREQ(panel->backlight.controller));
1817
1818 if (!panel->backlight.max)
1819 panel->backlight.max = get_backlight_max_vbt(connector);
1820
1821 if (!panel->backlight.max)
1822 return -ENODEV;
1823
f44e354f
LS
1824 panel->backlight.min = get_backlight_min_vbt(connector);
1825
4c9f7086
RV
1826 val = bxt_get_backlight(connector);
1827 val = intel_panel_compute_brightness(connector, val);
1828 panel->backlight.level = clamp(val, panel->backlight.min,
1829 panel->backlight.max);
1830
1831 panel->backlight.enabled = pwm_ctl & BXT_BLC_PWM_ENABLE;
1832
1833 return 0;
1834}
1835
b029e66f
SK
1836static int pwm_setup_backlight(struct intel_connector *connector,
1837 enum pipe pipe)
1838{
1839 struct drm_device *dev = connector->base.dev;
1840 struct intel_panel *panel = &connector->panel;
1841 int retval;
1842
1843 /* Get the PWM chip for backlight control */
1844 panel->backlight.pwm = pwm_get(dev->dev, "pwm_backlight");
1845 if (IS_ERR(panel->backlight.pwm)) {
1846 DRM_ERROR("Failed to own the pwm chip\n");
1847 panel->backlight.pwm = NULL;
1848 return -ENODEV;
1849 }
1850
2347aa7c
BB
1851 /*
1852 * FIXME: pwm_apply_args() should be removed when switching to
1853 * the atomic PWM API.
1854 */
1855 pwm_apply_args(panel->backlight.pwm);
1856
b029e66f
SK
1857 retval = pwm_config(panel->backlight.pwm, CRC_PMIC_PWM_PERIOD_NS,
1858 CRC_PMIC_PWM_PERIOD_NS);
1859 if (retval < 0) {
1860 DRM_ERROR("Failed to configure the pwm chip\n");
1861 pwm_put(panel->backlight.pwm);
1862 panel->backlight.pwm = NULL;
1863 return retval;
1864 }
1865
1866 panel->backlight.min = 0; /* 0% */
1867 panel->backlight.max = 100; /* 100% */
1868 panel->backlight.level = DIV_ROUND_UP(
1869 pwm_get_duty_cycle(panel->backlight.pwm) * 100,
1870 CRC_PMIC_PWM_PERIOD_NS);
1871 panel->backlight.enabled = panel->backlight.level != 0;
1872
1873 return 0;
1874}
1875
63a23d24
ML
1876void intel_panel_update_backlight(struct intel_encoder *encoder,
1877 const struct intel_crtc_state *crtc_state,
1878 const struct drm_connector_state *conn_state)
1879{
1880 struct intel_connector *connector = to_intel_connector(conn_state->connector);
1881 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
1882 struct intel_panel *panel = &connector->panel;
1883
1884 if (!panel->backlight.present)
1885 return;
1886
1887 mutex_lock(&dev_priv->backlight_lock);
1888 if (!panel->backlight.enabled)
1889 __intel_panel_enable_backlight(crtc_state, conn_state);
1890
1891 mutex_unlock(&dev_priv->backlight_lock);
1892}
1893
6517d273 1894int intel_panel_setup_backlight(struct drm_connector *connector, enum pipe pipe)
aaa6fd2a 1895{
e6cb3727 1896 struct drm_i915_private *dev_priv = to_i915(connector->dev);
db31af1d 1897 struct intel_connector *intel_connector = to_intel_connector(connector);
58c68779 1898 struct intel_panel *panel = &intel_connector->panel;
7bd688cd 1899 int ret;
db31af1d 1900
c675949e 1901 if (!dev_priv->vbt.backlight.present) {
9c72cc6f
SD
1902 if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
1903 DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
1904 } else {
1905 DRM_DEBUG_KMS("no backlight present per VBT\n");
1906 return 0;
1907 }
c675949e
JN
1908 }
1909
5507faeb
JN
1910 /* ensure intel_panel has been initialized first */
1911 if (WARN_ON(!panel->backlight.setup))
1912 return -ENODEV;
1913
7bd688cd 1914 /* set level and max in panel struct */
07f11d49 1915 mutex_lock(&dev_priv->backlight_lock);
5507faeb 1916 ret = panel->backlight.setup(intel_connector, pipe);
07f11d49 1917 mutex_unlock(&dev_priv->backlight_lock);
7bd688cd
JN
1918
1919 if (ret) {
1920 DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
c23cc417 1921 connector->name);
7bd688cd
JN
1922 return ret;
1923 }
db31af1d 1924
c91c9f32
JN
1925 panel->backlight.present = true;
1926
0962c3c9
VS
1927 DRM_DEBUG_KMS("Connector %s backlight initialized, %s, brightness %u/%u\n",
1928 connector->name,
08c4d7fc 1929 enableddisabled(panel->backlight.enabled),
0962c3c9 1930 panel->backlight.level, panel->backlight.max);
c445b3b1 1931
aaa6fd2a
MG
1932 return 0;
1933}
1934
19dfe572 1935static void intel_panel_destroy_backlight(struct intel_panel *panel)
aaa6fd2a 1936{
b029e66f
SK
1937 /* dispose of the pwm */
1938 if (panel->backlight.pwm)
1939 pwm_put(panel->backlight.pwm);
1940
c91c9f32 1941 panel->backlight.present = false;
aaa6fd2a 1942}
1d508706 1943
7bd688cd 1944/* Set up chip specific backlight functions */
5507faeb
JN
1945static void
1946intel_panel_init_backlight_funcs(struct intel_panel *panel)
7bd688cd 1947{
e6cb3727 1948 struct intel_connector *connector =
5507faeb 1949 container_of(panel, struct intel_connector, panel);
e6cb3727 1950 struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
7bd688cd 1951
e7156c83
YA
1952 if (connector->base.connector_type == DRM_MODE_CONNECTOR_eDP &&
1953 intel_dp_aux_init_backlight_funcs(connector) == 0)
1954 return;
1955
90198355
JN
1956 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI &&
1957 intel_dsi_dcs_init_backlight_funcs(connector) == 0)
1958 return;
1959
cc3f90f0 1960 if (IS_GEN9_LP(dev_priv)) {
5507faeb
JN
1961 panel->backlight.setup = bxt_setup_backlight;
1962 panel->backlight.enable = bxt_enable_backlight;
1963 panel->backlight.disable = bxt_disable_backlight;
1964 panel->backlight.set = bxt_set_backlight;
1965 panel->backlight.get = bxt_get_backlight;
2dd6982e 1966 panel->backlight.hz_to_pwm = bxt_hz_to_pwm;
c6c30b91 1967 } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_CNP) {
4c9f7086
RV
1968 panel->backlight.setup = cnp_setup_backlight;
1969 panel->backlight.enable = cnp_enable_backlight;
1970 panel->backlight.disable = cnp_disable_backlight;
1971 panel->backlight.set = bxt_set_backlight;
1972 panel->backlight.get = bxt_get_backlight;
1973 panel->backlight.hz_to_pwm = cnp_hz_to_pwm;
c6c30b91 1974 } else if (INTEL_PCH_TYPE(dev_priv) >= PCH_LPT) {
5507faeb
JN
1975 panel->backlight.setup = lpt_setup_backlight;
1976 panel->backlight.enable = lpt_enable_backlight;
1977 panel->backlight.disable = lpt_disable_backlight;
1978 panel->backlight.set = lpt_set_backlight;
1979 panel->backlight.get = lpt_get_backlight;
e6cb3727 1980 if (HAS_PCH_LPT(dev_priv))
5507faeb 1981 panel->backlight.hz_to_pwm = lpt_hz_to_pwm;
aa17cdb4 1982 else
5507faeb 1983 panel->backlight.hz_to_pwm = spt_hz_to_pwm;
e6cb3727 1984 } else if (HAS_PCH_SPLIT(dev_priv)) {
5507faeb
JN
1985 panel->backlight.setup = pch_setup_backlight;
1986 panel->backlight.enable = pch_enable_backlight;
1987 panel->backlight.disable = pch_disable_backlight;
1988 panel->backlight.set = pch_set_backlight;
1989 panel->backlight.get = pch_get_backlight;
1990 panel->backlight.hz_to_pwm = pch_hz_to_pwm;
e6cb3727 1991 } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
92c4565e 1992 if (connector->base.connector_type == DRM_MODE_CONNECTOR_DSI) {
5507faeb
JN
1993 panel->backlight.setup = pwm_setup_backlight;
1994 panel->backlight.enable = pwm_enable_backlight;
1995 panel->backlight.disable = pwm_disable_backlight;
1996 panel->backlight.set = pwm_set_backlight;
1997 panel->backlight.get = pwm_get_backlight;
b029e66f 1998 } else {
5507faeb
JN
1999 panel->backlight.setup = vlv_setup_backlight;
2000 panel->backlight.enable = vlv_enable_backlight;
2001 panel->backlight.disable = vlv_disable_backlight;
2002 panel->backlight.set = vlv_set_backlight;
2003 panel->backlight.get = vlv_get_backlight;
2004 panel->backlight.hz_to_pwm = vlv_hz_to_pwm;
b029e66f 2005 }
cf819eff 2006 } else if (IS_GEN(dev_priv, 4)) {
5507faeb
JN
2007 panel->backlight.setup = i965_setup_backlight;
2008 panel->backlight.enable = i965_enable_backlight;
2009 panel->backlight.disable = i965_disable_backlight;
2010 panel->backlight.set = i9xx_set_backlight;
2011 panel->backlight.get = i9xx_get_backlight;
2012 panel->backlight.hz_to_pwm = i965_hz_to_pwm;
7bd688cd 2013 } else {
5507faeb
JN
2014 panel->backlight.setup = i9xx_setup_backlight;
2015 panel->backlight.enable = i9xx_enable_backlight;
2016 panel->backlight.disable = i9xx_disable_backlight;
2017 panel->backlight.set = i9xx_set_backlight;
2018 panel->backlight.get = i9xx_get_backlight;
2019 panel->backlight.hz_to_pwm = i9xx_hz_to_pwm;
7bd688cd
JN
2020 }
2021}
2022
dd06f90e 2023int intel_panel_init(struct intel_panel *panel,
4b6ed685
VK
2024 struct drm_display_mode *fixed_mode,
2025 struct drm_display_mode *downclock_mode)
1d508706 2026{
5507faeb
JN
2027 intel_panel_init_backlight_funcs(panel);
2028
dd06f90e 2029 panel->fixed_mode = fixed_mode;
4b6ed685 2030 panel->downclock_mode = downclock_mode;
dd06f90e 2031
1d508706
JN
2032 return 0;
2033}
2034
2035void intel_panel_fini(struct intel_panel *panel)
2036{
dd06f90e
JN
2037 struct intel_connector *intel_connector =
2038 container_of(panel, struct intel_connector, panel);
2039
19dfe572
VS
2040 intel_panel_destroy_backlight(panel);
2041
dd06f90e
JN
2042 if (panel->fixed_mode)
2043 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
ec9ed197
VK
2044
2045 if (panel->downclock_mode)
2046 drm_mode_destroy(intel_connector->base.dev,
2047 panel->downclock_mode);
1d508706 2048}