xref: /dragonfly/sys/dev/drm/i915/intel_panel.c (revision 267c04fd)
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 
31 #include <linux/moduleparam.h>
32 #include "intel_drv.h"
33 
34 #define PCI_LBPC 0xf4 /* legacy/combination backlight modes */
35 
36 void
37 intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
38 		       struct drm_display_mode *adjusted_mode)
39 {
40 	drm_mode_copy(adjusted_mode, fixed_mode);
41 
42 	drm_mode_set_crtcinfo(adjusted_mode, 0);
43 }
44 
45 /* adjusted_mode has been preset to be the panel's fixed mode */
46 void
47 intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
48 			struct intel_crtc_config *pipe_config,
49 			int fitting_mode)
50 {
51 	struct drm_display_mode *adjusted_mode;
52 	int x, y, width, height;
53 
54 	adjusted_mode = &pipe_config->adjusted_mode;
55 
56 	x = y = width = height = 0;
57 
58 	/* Native modes don't need fitting */
59 	if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
60 	    adjusted_mode->vdisplay == pipe_config->pipe_src_h)
61 		goto done;
62 
63 	switch (fitting_mode) {
64 	case DRM_MODE_SCALE_CENTER:
65 		width = pipe_config->pipe_src_w;
66 		height = pipe_config->pipe_src_h;
67 		x = (adjusted_mode->hdisplay - width + 1)/2;
68 		y = (adjusted_mode->vdisplay - height + 1)/2;
69 		break;
70 
71 	case DRM_MODE_SCALE_ASPECT:
72 		/* Scale but preserve the aspect ratio */
73 		{
74 			u32 scaled_width = adjusted_mode->hdisplay
75 				* pipe_config->pipe_src_h;
76 			u32 scaled_height = pipe_config->pipe_src_w
77 				* adjusted_mode->vdisplay;
78 			if (scaled_width > scaled_height) { /* pillar */
79 				width = scaled_height / pipe_config->pipe_src_h;
80 				if (width & 1)
81 					width++;
82 				x = (adjusted_mode->hdisplay - width + 1) / 2;
83 				y = 0;
84 				height = adjusted_mode->vdisplay;
85 			} else if (scaled_width < scaled_height) { /* letter */
86 				height = scaled_width / pipe_config->pipe_src_w;
87 				if (height & 1)
88 				    height++;
89 				y = (adjusted_mode->vdisplay - height + 1) / 2;
90 				x = 0;
91 				width = adjusted_mode->hdisplay;
92 			} else {
93 				x = y = 0;
94 				width = adjusted_mode->hdisplay;
95 				height = adjusted_mode->vdisplay;
96 			}
97 		}
98 		break;
99 
100 	case DRM_MODE_SCALE_FULLSCREEN:
101 		x = y = 0;
102 		width = adjusted_mode->hdisplay;
103 		height = adjusted_mode->vdisplay;
104 		break;
105 
106 	default:
107 		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
108 		return;
109 	}
110 
111 done:
112 	pipe_config->pch_pfit.pos = (x << 16) | y;
113 	pipe_config->pch_pfit.size = (width << 16) | height;
114 	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
115 }
116 
117 static void
118 centre_horizontally(struct drm_display_mode *mode,
119 		    int width)
120 {
121 	u32 border, sync_pos, blank_width, sync_width;
122 
123 	/* keep the hsync and hblank widths constant */
124 	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
125 	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
126 	sync_pos = (blank_width - sync_width + 1) / 2;
127 
128 	border = (mode->hdisplay - width + 1) / 2;
129 	border += border & 1; /* make the border even */
130 
131 	mode->crtc_hdisplay = width;
132 	mode->crtc_hblank_start = width + border;
133 	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
134 
135 	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
136 	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
137 }
138 
139 static void
140 centre_vertically(struct drm_display_mode *mode,
141 		  int height)
142 {
143 	u32 border, sync_pos, blank_width, sync_width;
144 
145 	/* keep the vsync and vblank widths constant */
146 	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
147 	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
148 	sync_pos = (blank_width - sync_width + 1) / 2;
149 
150 	border = (mode->vdisplay - height + 1) / 2;
151 
152 	mode->crtc_vdisplay = height;
153 	mode->crtc_vblank_start = height + border;
154 	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
155 
156 	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
157 	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
158 }
159 
160 static inline u32 panel_fitter_scaling(u32 source, u32 target)
161 {
162 	/*
163 	 * Floating point operation is not supported. So the FACTOR
164 	 * is defined, which can avoid the floating point computation
165 	 * when calculating the panel ratio.
166 	 */
167 #define ACCURACY 12
168 #define FACTOR (1 << ACCURACY)
169 	u32 ratio = source * FACTOR / target;
170 	return (FACTOR * ratio + FACTOR/2) / FACTOR;
171 }
172 
173 static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
174 			      u32 *pfit_control)
175 {
176 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
177 	u32 scaled_width = adjusted_mode->hdisplay *
178 		pipe_config->pipe_src_h;
179 	u32 scaled_height = pipe_config->pipe_src_w *
180 		adjusted_mode->vdisplay;
181 
182 	/* 965+ is easy, it does everything in hw */
183 	if (scaled_width > scaled_height)
184 		*pfit_control |= PFIT_ENABLE |
185 			PFIT_SCALING_PILLAR;
186 	else if (scaled_width < scaled_height)
187 		*pfit_control |= PFIT_ENABLE |
188 			PFIT_SCALING_LETTER;
189 	else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
190 		*pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
191 }
192 
193 static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
194 			      u32 *pfit_control, u32 *pfit_pgm_ratios,
195 			      u32 *border)
196 {
197 	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
198 	u32 scaled_width = adjusted_mode->hdisplay *
199 		pipe_config->pipe_src_h;
200 	u32 scaled_height = pipe_config->pipe_src_w *
201 		adjusted_mode->vdisplay;
202 	u32 bits;
203 
204 	/*
205 	 * For earlier chips we have to calculate the scaling
206 	 * ratio by hand and program it into the
207 	 * PFIT_PGM_RATIO register
208 	 */
209 	if (scaled_width > scaled_height) { /* pillar */
210 		centre_horizontally(adjusted_mode,
211 				    scaled_height /
212 				    pipe_config->pipe_src_h);
213 
214 		*border = LVDS_BORDER_ENABLE;
215 		if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
216 			bits = panel_fitter_scaling(pipe_config->pipe_src_h,
217 						    adjusted_mode->vdisplay);
218 
219 			*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
220 					     bits << PFIT_VERT_SCALE_SHIFT);
221 			*pfit_control |= (PFIT_ENABLE |
222 					  VERT_INTERP_BILINEAR |
223 					  HORIZ_INTERP_BILINEAR);
224 		}
225 	} else if (scaled_width < scaled_height) { /* letter */
226 		centre_vertically(adjusted_mode,
227 				  scaled_width /
228 				  pipe_config->pipe_src_w);
229 
230 		*border = LVDS_BORDER_ENABLE;
231 		if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
232 			bits = panel_fitter_scaling(pipe_config->pipe_src_w,
233 						    adjusted_mode->hdisplay);
234 
235 			*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
236 					     bits << PFIT_VERT_SCALE_SHIFT);
237 			*pfit_control |= (PFIT_ENABLE |
238 					  VERT_INTERP_BILINEAR |
239 					  HORIZ_INTERP_BILINEAR);
240 		}
241 	} else {
242 		/* Aspects match, Let hw scale both directions */
243 		*pfit_control |= (PFIT_ENABLE |
244 				  VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
245 				  VERT_INTERP_BILINEAR |
246 				  HORIZ_INTERP_BILINEAR);
247 	}
248 }
249 
250 void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
251 			      struct intel_crtc_config *pipe_config,
252 			      int fitting_mode)
253 {
254 	struct drm_device *dev = intel_crtc->base.dev;
255 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
256 	struct drm_display_mode *adjusted_mode;
257 
258 	adjusted_mode = &pipe_config->adjusted_mode;
259 
260 	/* Native modes don't need fitting */
261 	if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
262 	    adjusted_mode->vdisplay == pipe_config->pipe_src_h)
263 		goto out;
264 
265 	switch (fitting_mode) {
266 	case DRM_MODE_SCALE_CENTER:
267 		/*
268 		 * For centered modes, we have to calculate border widths &
269 		 * heights and modify the values programmed into the CRTC.
270 		 */
271 		centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
272 		centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
273 		border = LVDS_BORDER_ENABLE;
274 		break;
275 	case DRM_MODE_SCALE_ASPECT:
276 		/* Scale but preserve the aspect ratio */
277 		if (INTEL_INFO(dev)->gen >= 4)
278 			i965_scale_aspect(pipe_config, &pfit_control);
279 		else
280 			i9xx_scale_aspect(pipe_config, &pfit_control,
281 					  &pfit_pgm_ratios, &border);
282 		break;
283 	case DRM_MODE_SCALE_FULLSCREEN:
284 		/*
285 		 * Full scaling, even if it changes the aspect ratio.
286 		 * Fortunately this is all done for us in hw.
287 		 */
288 		if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
289 		    pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
290 			pfit_control |= PFIT_ENABLE;
291 			if (INTEL_INFO(dev)->gen >= 4)
292 				pfit_control |= PFIT_SCALING_AUTO;
293 			else
294 				pfit_control |= (VERT_AUTO_SCALE |
295 						 VERT_INTERP_BILINEAR |
296 						 HORIZ_AUTO_SCALE |
297 						 HORIZ_INTERP_BILINEAR);
298 		}
299 		break;
300 	default:
301 		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
302 		return;
303 	}
304 
305 	/* 965+ wants fuzzy fitting */
306 	/* FIXME: handle multiple panels by failing gracefully */
307 	if (INTEL_INFO(dev)->gen >= 4)
308 		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
309 				 PFIT_FILTER_FUZZY);
310 
311 out:
312 	if ((pfit_control & PFIT_ENABLE) == 0) {
313 		pfit_control = 0;
314 		pfit_pgm_ratios = 0;
315 	}
316 
317 	/* Make sure pre-965 set dither correctly for 18bpp panels. */
318 	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
319 		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
320 
321 	pipe_config->gmch_pfit.control = pfit_control;
322 	pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
323 	pipe_config->gmch_pfit.lvds_border_bits = border;
324 }
325 
326 static int i915_panel_invert_brightness;
327 TUNABLE_INT("drm.i915.panel_invert_brightness", &i915_panel_invert_brightness);
328 MODULE_PARM_DESC(invert_brightness, "Invert backlight brightness "
329 	"(-1 force normal, 0 machine defaults, 1 force inversion), please "
330 	"report PCI device ID, subsystem vendor and subsystem device ID "
331 	"to dri-devel@lists.freedesktop.org, if your machine needs it. "
332 	"It will then be included in an upcoming module version.");
333 module_param_named(invert_brightness, i915_panel_invert_brightness, int, 0600);
334 static u32 intel_panel_compute_brightness(struct intel_connector *connector,
335 					  u32 val)
336 {
337 	struct drm_device *dev = connector->base.dev;
338 	struct drm_i915_private *dev_priv = dev->dev_private;
339 	struct intel_panel *panel = &connector->panel;
340 
341 	WARN_ON(panel->backlight.max == 0);
342 
343 	if (i915_panel_invert_brightness < 0)
344 		return val;
345 
346 	if (i915_panel_invert_brightness > 0 ||
347 	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
348 		return panel->backlight.max - val;
349 	}
350 
351 	return val;
352 }
353 
354 static u32 bdw_get_backlight(struct intel_connector *connector)
355 {
356 	struct drm_device *dev = connector->base.dev;
357 	struct drm_i915_private *dev_priv = dev->dev_private;
358 
359 	return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
360 }
361 
362 static u32 pch_get_backlight(struct intel_connector *connector)
363 {
364 	struct drm_device *dev = connector->base.dev;
365 	struct drm_i915_private *dev_priv = dev->dev_private;
366 
367 	return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
368 }
369 
370 static u32 i9xx_get_backlight(struct intel_connector *connector)
371 {
372 	struct drm_device *dev = connector->base.dev;
373 	struct drm_i915_private *dev_priv = dev->dev_private;
374 	struct intel_panel *panel = &connector->panel;
375 	u32 val;
376 
377 	val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
378 	if (INTEL_INFO(dev)->gen < 4)
379 		val >>= 1;
380 
381 	if (panel->backlight.combination_mode) {
382 		u8 lbpc;
383 
384 		pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
385 		val *= lbpc;
386 	}
387 
388 	return val;
389 }
390 
391 static u32 _vlv_get_backlight(struct drm_device *dev, enum i915_pipe pipe)
392 {
393 	struct drm_i915_private *dev_priv = dev->dev_private;
394 
395 	return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
396 }
397 
398 static u32 vlv_get_backlight(struct intel_connector *connector)
399 {
400 	struct drm_device *dev = connector->base.dev;
401 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
402 
403 	return _vlv_get_backlight(dev, pipe);
404 }
405 
406 #if 0
407 static u32 intel_panel_get_backlight(struct intel_connector *connector)
408 {
409 	struct drm_device *dev = connector->base.dev;
410 	struct drm_i915_private *dev_priv = dev->dev_private;
411 	u32 val;
412 
413 	spin_lock(&dev_priv->backlight_lock);
414 
415 	val = dev_priv->display.get_backlight(connector);
416 	val = intel_panel_compute_brightness(connector, val);
417 
418 	spin_unlock(&dev_priv->backlight_lock);
419 
420 	DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
421 	return val;
422 }
423 #endif
424 
425 static void bdw_set_backlight(struct intel_connector *connector, u32 level)
426 {
427 	struct drm_device *dev = connector->base.dev;
428 	struct drm_i915_private *dev_priv = dev->dev_private;
429 	u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
430 	I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
431 }
432 
433 static void pch_set_backlight(struct intel_connector *connector, u32 level)
434 {
435 	struct drm_device *dev = connector->base.dev;
436 	struct drm_i915_private *dev_priv = dev->dev_private;
437 	u32 tmp;
438 
439 	tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
440 	I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
441 }
442 
443 static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
444 {
445 	struct drm_device *dev = connector->base.dev;
446 	struct drm_i915_private *dev_priv = dev->dev_private;
447 	struct intel_panel *panel = &connector->panel;
448 	u32 tmp, mask;
449 
450 	WARN_ON(panel->backlight.max == 0);
451 
452 	if (panel->backlight.combination_mode) {
453 		u8 lbpc;
454 
455 		lbpc = level * 0xfe / panel->backlight.max + 1;
456 		level /= lbpc;
457 		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
458 	}
459 
460 	if (IS_GEN4(dev)) {
461 		mask = BACKLIGHT_DUTY_CYCLE_MASK;
462 	} else {
463 		level <<= 1;
464 		mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
465 	}
466 
467 	tmp = I915_READ(BLC_PWM_CTL) & ~mask;
468 	I915_WRITE(BLC_PWM_CTL, tmp | level);
469 }
470 
471 static void vlv_set_backlight(struct intel_connector *connector, u32 level)
472 {
473 	struct drm_device *dev = connector->base.dev;
474 	struct drm_i915_private *dev_priv = dev->dev_private;
475 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
476 	u32 tmp;
477 
478 	tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
479 	I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
480 }
481 
482 static void
483 intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
484 {
485 	struct drm_device *dev = connector->base.dev;
486 	struct drm_i915_private *dev_priv = dev->dev_private;
487 
488 	DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);
489 
490 	level = intel_panel_compute_brightness(connector, level);
491 	dev_priv->display.set_backlight(connector, level);
492 }
493 
494 /* set backlight brightness to level in range [0..max] */
495 void intel_panel_set_backlight(struct intel_connector *connector, u32 level,
496 			       u32 max)
497 {
498 	struct drm_device *dev = connector->base.dev;
499 	struct drm_i915_private *dev_priv = dev->dev_private;
500 	struct intel_panel *panel = &connector->panel;
501 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
502 	u32 freq;
503 
504 	if (!panel->backlight.present || pipe == INVALID_PIPE)
505 		return;
506 
507 	spin_lock(&dev_priv->backlight_lock);
508 
509 	WARN_ON(panel->backlight.max == 0);
510 
511 	/* scale to hardware max, but be careful to not overflow */
512 	freq = panel->backlight.max;
513 	if (freq < max)
514 		level = level * freq / max;
515 	else
516 		level = freq / max * level;
517 
518 	panel->backlight.level = level;
519 	if (panel->backlight.device)
520 		panel->backlight.device->props.brightness = level;
521 
522 	if (panel->backlight.enabled)
523 		intel_panel_actually_set_backlight(connector, level);
524 
525 	spin_unlock(&dev_priv->backlight_lock);
526 }
527 
528 static void pch_disable_backlight(struct intel_connector *connector)
529 {
530 	struct drm_device *dev = connector->base.dev;
531 	struct drm_i915_private *dev_priv = dev->dev_private;
532 	u32 tmp;
533 
534 	intel_panel_actually_set_backlight(connector, 0);
535 
536 	tmp = I915_READ(BLC_PWM_CPU_CTL2);
537 	I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);
538 
539 	tmp = I915_READ(BLC_PWM_PCH_CTL1);
540 	I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
541 }
542 
543 static void i9xx_disable_backlight(struct intel_connector *connector)
544 {
545 	intel_panel_actually_set_backlight(connector, 0);
546 }
547 
548 static void i965_disable_backlight(struct intel_connector *connector)
549 {
550 	struct drm_device *dev = connector->base.dev;
551 	struct drm_i915_private *dev_priv = dev->dev_private;
552 	u32 tmp;
553 
554 	intel_panel_actually_set_backlight(connector, 0);
555 
556 	tmp = I915_READ(BLC_PWM_CTL2);
557 	I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
558 }
559 
560 static void vlv_disable_backlight(struct intel_connector *connector)
561 {
562 	struct drm_device *dev = connector->base.dev;
563 	struct drm_i915_private *dev_priv = dev->dev_private;
564 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
565 	u32 tmp;
566 
567 	intel_panel_actually_set_backlight(connector, 0);
568 
569 	tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
570 	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
571 }
572 
573 void intel_panel_disable_backlight(struct intel_connector *connector)
574 {
575 	struct drm_device *dev = connector->base.dev;
576 	struct drm_i915_private *dev_priv = dev->dev_private;
577 	struct intel_panel *panel = &connector->panel;
578 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
579 
580 	if (!panel->backlight.present || pipe == INVALID_PIPE)
581 		return;
582 
583 	/*
584 	 * Do not disable backlight on the vgaswitcheroo path. When switching
585 	 * away from i915, the other client may depend on i915 to handle the
586 	 * backlight. This will leave the backlight on unnecessarily when
587 	 * another client is not activated.
588 	 */
589 	if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
590 		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
591 		return;
592 	}
593 
594 	spin_lock(&dev_priv->backlight_lock);
595 
596 	panel->backlight.enabled = false;
597 	dev_priv->display.disable_backlight(connector);
598 
599 	spin_unlock(&dev_priv->backlight_lock);
600 }
601 
602 static void bdw_enable_backlight(struct intel_connector *connector)
603 {
604 	struct drm_device *dev = connector->base.dev;
605 	struct drm_i915_private *dev_priv = dev->dev_private;
606 	struct intel_panel *panel = &connector->panel;
607 	u32 pch_ctl1, pch_ctl2;
608 
609 	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
610 	if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
611 		DRM_DEBUG_KMS("pch backlight already enabled\n");
612 		pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
613 		I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
614 	}
615 
616 	pch_ctl2 = panel->backlight.max << 16;
617 	I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
618 
619 	pch_ctl1 = 0;
620 	if (panel->backlight.active_low_pwm)
621 		pch_ctl1 |= BLM_PCH_POLARITY;
622 
623 	/* BDW always uses the pch pwm controls. */
624 	pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
625 
626 	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
627 	POSTING_READ(BLC_PWM_PCH_CTL1);
628 	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
629 
630 	/* This won't stick until the above enable. */
631 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
632  }
633 
634 static void pch_enable_backlight(struct intel_connector *connector)
635 {
636 	struct drm_device *dev = connector->base.dev;
637 	struct drm_i915_private *dev_priv = dev->dev_private;
638 	struct intel_panel *panel = &connector->panel;
639 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
640 	enum transcoder cpu_transcoder =
641 		intel_pipe_to_cpu_transcoder(dev_priv, pipe);
642 	u32 cpu_ctl2, pch_ctl1, pch_ctl2;
643 
644 	cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
645 	if (cpu_ctl2 & BLM_PWM_ENABLE) {
646 		WARN(1, "cpu backlight already enabled\n");
647 		cpu_ctl2 &= ~BLM_PWM_ENABLE;
648 		I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
649 	}
650 
651 	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
652 	if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
653 		DRM_DEBUG_KMS("pch backlight already enabled\n");
654 		pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
655 		I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
656 	}
657 
658 	if (cpu_transcoder == TRANSCODER_EDP)
659 		cpu_ctl2 = BLM_TRANSCODER_EDP;
660 	else
661 		cpu_ctl2 = BLM_PIPE(cpu_transcoder);
662 	I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
663 	POSTING_READ(BLC_PWM_CPU_CTL2);
664 	I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
665 
666 	/* This won't stick until the above enable. */
667 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
668 
669 	pch_ctl2 = panel->backlight.max << 16;
670 	I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
671 
672 	pch_ctl1 = 0;
673 	if (panel->backlight.active_low_pwm)
674 		pch_ctl1 |= BLM_PCH_POLARITY;
675 	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
676 	POSTING_READ(BLC_PWM_PCH_CTL1);
677 	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
678 }
679 
680 static void i9xx_enable_backlight(struct intel_connector *connector)
681 {
682 	struct drm_device *dev = connector->base.dev;
683 	struct drm_i915_private *dev_priv = dev->dev_private;
684 	struct intel_panel *panel = &connector->panel;
685 	u32 ctl, freq;
686 
687 	ctl = I915_READ(BLC_PWM_CTL);
688 	if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
689 		WARN(1, "backlight already enabled\n");
690 		I915_WRITE(BLC_PWM_CTL, 0);
691 	}
692 
693 	freq = panel->backlight.max;
694 	if (panel->backlight.combination_mode)
695 		freq /= 0xff;
696 
697 	ctl = freq << 17;
698 	if (panel->backlight.combination_mode)
699 		ctl |= BLM_LEGACY_MODE;
700 	if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
701 		ctl |= BLM_POLARITY_PNV;
702 
703 	I915_WRITE(BLC_PWM_CTL, ctl);
704 	POSTING_READ(BLC_PWM_CTL);
705 
706 	/* XXX: combine this into above write? */
707 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
708 }
709 
710 static void i965_enable_backlight(struct intel_connector *connector)
711 {
712 	struct drm_device *dev = connector->base.dev;
713 	struct drm_i915_private *dev_priv = dev->dev_private;
714 	struct intel_panel *panel = &connector->panel;
715 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
716 	u32 ctl, ctl2, freq;
717 
718 	ctl2 = I915_READ(BLC_PWM_CTL2);
719 	if (ctl2 & BLM_PWM_ENABLE) {
720 		WARN(1, "backlight already enabled\n");
721 		ctl2 &= ~BLM_PWM_ENABLE;
722 		I915_WRITE(BLC_PWM_CTL2, ctl2);
723 	}
724 
725 	freq = panel->backlight.max;
726 	if (panel->backlight.combination_mode)
727 		freq /= 0xff;
728 
729 	ctl = freq << 16;
730 	I915_WRITE(BLC_PWM_CTL, ctl);
731 
732 	/* XXX: combine this into above write? */
733 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
734 
735 	ctl2 = BLM_PIPE(pipe);
736 	if (panel->backlight.combination_mode)
737 		ctl2 |= BLM_COMBINATION_MODE;
738 	if (panel->backlight.active_low_pwm)
739 		ctl2 |= BLM_POLARITY_I965;
740 	I915_WRITE(BLC_PWM_CTL2, ctl2);
741 	POSTING_READ(BLC_PWM_CTL2);
742 	I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
743 }
744 
745 static void vlv_enable_backlight(struct intel_connector *connector)
746 {
747 	struct drm_device *dev = connector->base.dev;
748 	struct drm_i915_private *dev_priv = dev->dev_private;
749 	struct intel_panel *panel = &connector->panel;
750 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
751 	u32 ctl, ctl2;
752 
753 	ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
754 	if (ctl2 & BLM_PWM_ENABLE) {
755 		WARN(1, "backlight already enabled\n");
756 		ctl2 &= ~BLM_PWM_ENABLE;
757 		I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
758 	}
759 
760 	ctl = panel->backlight.max << 16;
761 	I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
762 
763 	/* XXX: combine this into above write? */
764 	intel_panel_actually_set_backlight(connector, panel->backlight.level);
765 
766 	ctl2 = 0;
767 	if (panel->backlight.active_low_pwm)
768 		ctl2 |= BLM_POLARITY_I965;
769 	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
770 	POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
771 	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
772 }
773 
774 void intel_panel_enable_backlight(struct intel_connector *connector)
775 {
776 	struct drm_device *dev = connector->base.dev;
777 	struct drm_i915_private *dev_priv = dev->dev_private;
778 	struct intel_panel *panel = &connector->panel;
779 	enum i915_pipe pipe = intel_get_pipe_from_connector(connector);
780 
781 	if (!panel->backlight.present || pipe == INVALID_PIPE)
782 		return;
783 
784 	DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
785 
786 	spin_lock(&dev_priv->backlight_lock);
787 
788 	WARN_ON(panel->backlight.max == 0);
789 
790 	if (panel->backlight.level == 0) {
791 		panel->backlight.level = panel->backlight.max;
792 		if (panel->backlight.device)
793 			panel->backlight.device->props.brightness =
794 				panel->backlight.level;
795 	}
796 
797 	dev_priv->display.enable_backlight(connector);
798 	panel->backlight.enabled = true;
799 
800 	spin_unlock(&dev_priv->backlight_lock);
801 }
802 
803 enum drm_connector_status
804 intel_panel_detect(struct drm_device *dev)
805 {
806 	struct drm_i915_private *dev_priv = dev->dev_private;
807 
808 	/* Assume that the BIOS does not lie through the OpRegion... */
809 	if (!i915_panel_ignore_lid && dev_priv->opregion.lid_state) {
810 		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
811 			connector_status_connected :
812 			connector_status_disconnected;
813 	}
814 
815 	switch (i915_panel_ignore_lid) {
816 	case -2:
817 		return connector_status_connected;
818 	case -1:
819 		return connector_status_disconnected;
820 	default:
821 		return connector_status_unknown;
822 	}
823 }
824 
825 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
826 static int intel_backlight_device_update_status(struct backlight_device *bd)
827 {
828 	struct intel_connector *connector = bl_get_data(bd);
829 	struct drm_device *dev = connector->base.dev;
830 
831 	mutex_lock(&dev->mode_config.mutex);
832 	DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
833 		      bd->props.brightness, bd->props.max_brightness);
834 	intel_panel_set_backlight(connector, bd->props.brightness,
835 				  bd->props.max_brightness);
836 	mutex_unlock(&dev->mode_config.mutex);
837 	return 0;
838 }
839 
840 static int intel_backlight_device_get_brightness(struct backlight_device *bd)
841 {
842 	struct intel_connector *connector = bl_get_data(bd);
843 	struct drm_device *dev = connector->base.dev;
844 	struct drm_i915_private *dev_priv = dev->dev_private;
845 	int ret;
846 
847 	intel_runtime_pm_get(dev_priv);
848 	mutex_lock(&dev->mode_config.mutex);
849 	ret = intel_panel_get_backlight(connector);
850 	mutex_unlock(&dev->mode_config.mutex);
851 	intel_runtime_pm_put(dev_priv);
852 
853 	return ret;
854 }
855 
856 static const struct backlight_ops intel_backlight_device_ops = {
857 	.update_status = intel_backlight_device_update_status,
858 	.get_brightness = intel_backlight_device_get_brightness,
859 };
860 
861 static int intel_backlight_device_register(struct intel_connector *connector)
862 {
863 	struct intel_panel *panel = &connector->panel;
864 	struct backlight_properties props;
865 
866 	if (WARN_ON(panel->backlight.device))
867 		return -ENODEV;
868 
869 	BUG_ON(panel->backlight.max == 0);
870 
871 	memset(&props, 0, sizeof(props));
872 	props.type = BACKLIGHT_RAW;
873 	props.brightness = panel->backlight.level;
874 	props.max_brightness = panel->backlight.max;
875 
876 	/*
877 	 * Note: using the same name independent of the connector prevents
878 	 * registration of multiple backlight devices in the driver.
879 	 */
880 	panel->backlight.device =
881 		backlight_device_register("intel_backlight",
882 					  connector->base.kdev,
883 					  connector,
884 					  &intel_backlight_device_ops, &props);
885 
886 	if (IS_ERR(panel->backlight.device)) {
887 		DRM_ERROR("Failed to register backlight: %ld\n",
888 			  PTR_ERR(panel->backlight.device));
889 		panel->backlight.device = NULL;
890 		return -ENODEV;
891 	}
892 	return 0;
893 }
894 
895 static void intel_backlight_device_unregister(struct intel_connector *connector)
896 {
897 	struct intel_panel *panel = &connector->panel;
898 
899 	if (panel->backlight.device) {
900 		backlight_device_unregister(panel->backlight.device);
901 		panel->backlight.device = NULL;
902 	}
903 }
904 #else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
905 static int intel_backlight_device_register(struct intel_connector *connector)
906 {
907 	return 0;
908 }
909 static void intel_backlight_device_unregister(struct intel_connector *connector)
910 {
911 }
912 #endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */
913 
914 /*
915  * Note: The setup hooks can't assume pipe is set!
916  *
917  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
918  * appropriately when it's 0. Use VBT and/or sane defaults.
919  */
920 static int bdw_setup_backlight(struct intel_connector *connector)
921 {
922 	struct drm_device *dev = connector->base.dev;
923 	struct drm_i915_private *dev_priv = dev->dev_private;
924 	struct intel_panel *panel = &connector->panel;
925 	u32 pch_ctl1, pch_ctl2, val;
926 
927 	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
928 	panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
929 
930 	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
931 	panel->backlight.max = pch_ctl2 >> 16;
932 	if (!panel->backlight.max)
933 		return -ENODEV;
934 
935 	val = bdw_get_backlight(connector);
936 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
937 
938 	panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
939 		panel->backlight.level != 0;
940 
941 	return 0;
942 }
943 
944 /*
945  * Note: The setup hooks can't assume pipe is set!
946  *
947  * XXX: Query mode clock or hardware clock and program PWM modulation frequency
948  * appropriately when it's 0. Use VBT and/or sane defaults.
949  */
950 static int pch_setup_backlight(struct intel_connector *connector)
951 {
952 	struct drm_device *dev = connector->base.dev;
953 	struct drm_i915_private *dev_priv = dev->dev_private;
954 	struct intel_panel *panel = &connector->panel;
955 	u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
956 
957 	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
958 	panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;
959 
960 	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
961 	panel->backlight.max = pch_ctl2 >> 16;
962 	if (!panel->backlight.max)
963 		return -ENODEV;
964 
965 	val = pch_get_backlight(connector);
966 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
967 
968 	cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
969 	panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
970 		(pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;
971 
972 	return 0;
973 }
974 
975 static int i9xx_setup_backlight(struct intel_connector *connector)
976 {
977 	struct drm_device *dev = connector->base.dev;
978 	struct drm_i915_private *dev_priv = dev->dev_private;
979 	struct intel_panel *panel = &connector->panel;
980 	u32 ctl, val;
981 
982 	ctl = I915_READ(BLC_PWM_CTL);
983 
984 	if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
985 		panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;
986 
987 	if (IS_PINEVIEW(dev))
988 		panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;
989 
990 	panel->backlight.max = ctl >> 17;
991 	if (panel->backlight.combination_mode)
992 		panel->backlight.max *= 0xff;
993 
994 	if (!panel->backlight.max)
995 		return -ENODEV;
996 
997 	val = i9xx_get_backlight(connector);
998 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
999 
1000 	panel->backlight.enabled = panel->backlight.level != 0;
1001 
1002 	return 0;
1003 }
1004 
1005 static int i965_setup_backlight(struct intel_connector *connector)
1006 {
1007 	struct drm_device *dev = connector->base.dev;
1008 	struct drm_i915_private *dev_priv = dev->dev_private;
1009 	struct intel_panel *panel = &connector->panel;
1010 	u32 ctl, ctl2, val;
1011 
1012 	ctl2 = I915_READ(BLC_PWM_CTL2);
1013 	panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
1014 	panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1015 
1016 	ctl = I915_READ(BLC_PWM_CTL);
1017 	panel->backlight.max = ctl >> 16;
1018 	if (panel->backlight.combination_mode)
1019 		panel->backlight.max *= 0xff;
1020 
1021 	if (!panel->backlight.max)
1022 		return -ENODEV;
1023 
1024 	val = i9xx_get_backlight(connector);
1025 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
1026 
1027 	panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1028 		panel->backlight.level != 0;
1029 
1030 	return 0;
1031 }
1032 
1033 static int vlv_setup_backlight(struct intel_connector *connector)
1034 {
1035 	struct drm_device *dev = connector->base.dev;
1036 	struct drm_i915_private *dev_priv = dev->dev_private;
1037 	struct intel_panel *panel = &connector->panel;
1038 	enum i915_pipe pipe;
1039 	u32 ctl, ctl2, val;
1040 
1041 	for_each_pipe(pipe) {
1042 		u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));
1043 
1044 		/* Skip if the modulation freq is already set */
1045 		if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
1046 			continue;
1047 
1048 		cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
1049 		I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
1050 			   cur_val);
1051 	}
1052 
1053 	ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
1054 	panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;
1055 
1056 	ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
1057 	panel->backlight.max = ctl >> 16;
1058 	if (!panel->backlight.max)
1059 		return -ENODEV;
1060 
1061 	val = _vlv_get_backlight(dev, PIPE_A);
1062 	panel->backlight.level = intel_panel_compute_brightness(connector, val);
1063 
1064 	panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
1065 		panel->backlight.level != 0;
1066 
1067 	return 0;
1068 }
1069 
1070 /*
1071  * Read max backlight level
1072  */
1073 static int
1074 sysctl_backlight_max(SYSCTL_HANDLER_ARGS)
1075 {
1076 	int err, val;
1077 	struct intel_connector *connector = arg1;
1078 	struct drm_device *dev = connector->base.dev;
1079 	struct drm_i915_private *dev_priv = dev->dev_private;
1080 	struct intel_panel *panel = &connector->panel;
1081 
1082 	spin_lock(&dev_priv->backlight_lock);
1083 	val = panel->backlight.max;
1084 	spin_unlock(&dev_priv->backlight_lock);
1085 
1086 	err = sysctl_handle_int(oidp, &val, 0, req);
1087 	return(err);
1088 }
1089 
1090 /*
1091  * Read/write backlight level
1092  */
1093 static int
1094 sysctl_backlight_handler(SYSCTL_HANDLER_ARGS)
1095 {
1096 	struct intel_connector *connector = arg1;
1097 	struct drm_device *dev = connector->base.dev;
1098 	struct drm_i915_private *dev_priv = dev->dev_private;
1099 	struct intel_panel *panel = &connector->panel;
1100 	int err, val;
1101 	u32 max_brightness;
1102 
1103 	val = panel->backlight.level;
1104 
1105 	spin_lock(&dev_priv->backlight_lock);
1106 	max_brightness = panel->backlight.max;
1107 	spin_unlock(&dev_priv->backlight_lock);
1108 
1109 	err = sysctl_handle_int(oidp, &val, 0, req);
1110 	if (err != 0 || req->newptr == NULL) {
1111 		return(err);
1112 	}
1113 
1114 	if (val != panel->backlight.level && val >=0 &&
1115 			val <= max_brightness) {
1116 		intel_panel_set_backlight(arg1, val, max_brightness);
1117 	}
1118 
1119 	return(err);
1120 }
1121 
1122 int intel_panel_setup_backlight(struct drm_connector *connector)
1123 {
1124 	struct drm_device *dev = connector->dev;
1125 	struct drm_i915_private *dev_priv = dev->dev_private;
1126 	struct intel_connector *intel_connector = to_intel_connector(connector);
1127 	struct intel_panel *panel = &intel_connector->panel;
1128 	int ret;
1129 
1130 	/* set level and max in panel struct */
1131 	spin_lock(&dev_priv->backlight_lock);
1132 	ret = dev_priv->display.setup_backlight(intel_connector);
1133 	spin_unlock(&dev_priv->backlight_lock);
1134 
1135 	if (ret) {
1136 		DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1137 			      drm_get_connector_name(connector));
1138 		return ret;
1139 	}
1140 
1141 	intel_backlight_device_register(intel_connector);
1142 
1143 	panel->backlight.present = true;
1144 
1145 	SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1146 			OID_AUTO, "backlight_max",
1147 			CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_ANYBODY,
1148 			connector, sizeof(int),
1149 			sysctl_backlight_max,
1150 			"I", "Max backlight level");
1151 	SYSCTL_ADD_PROC(&connector->dev->sysctl->ctx, &sysctl__hw_children,
1152 			OID_AUTO, "backlight_level",
1153 			CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_ANYBODY,
1154 			connector, sizeof(int),
1155 			sysctl_backlight_handler,
1156 			"I", "Backlight level");
1157 
1158 	return 0;
1159 }
1160 
1161 void intel_panel_destroy_backlight(struct drm_connector *connector)
1162 {
1163 	struct intel_connector *intel_connector = to_intel_connector(connector);
1164 	struct intel_panel *panel = &intel_connector->panel;
1165 
1166 	panel->backlight.present = false;
1167 	intel_backlight_device_unregister(intel_connector);
1168 }
1169 
1170 /**
1171  * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
1172  * @dev: drm device
1173  * @fixed_mode : panel native mode
1174  * @connector: LVDS/eDP connector
1175  *
1176  * Return downclock_avail
1177  * Find the reduced downclock for LVDS/eDP in EDID.
1178  */
1179 struct drm_display_mode *
1180 intel_find_panel_downclock(struct drm_device *dev,
1181 			struct drm_display_mode *fixed_mode,
1182 			struct drm_connector *connector)
1183 {
1184 	struct drm_display_mode *scan, *tmp_mode;
1185 	int temp_downclock;
1186 
1187 	temp_downclock = fixed_mode->clock;
1188 	tmp_mode = NULL;
1189 
1190 	list_for_each_entry(scan, &connector->probed_modes, head) {
1191 		/*
1192 		 * If one mode has the same resolution with the fixed_panel
1193 		 * mode while they have the different refresh rate, it means
1194 		 * that the reduced downclock is found. In such
1195 		 * case we can set the different FPx0/1 to dynamically select
1196 		 * between low and high frequency.
1197 		 */
1198 		if (scan->hdisplay == fixed_mode->hdisplay &&
1199 		    scan->hsync_start == fixed_mode->hsync_start &&
1200 		    scan->hsync_end == fixed_mode->hsync_end &&
1201 		    scan->htotal == fixed_mode->htotal &&
1202 		    scan->vdisplay == fixed_mode->vdisplay &&
1203 		    scan->vsync_start == fixed_mode->vsync_start &&
1204 		    scan->vsync_end == fixed_mode->vsync_end &&
1205 		    scan->vtotal == fixed_mode->vtotal) {
1206 			if (scan->clock < temp_downclock) {
1207 				/*
1208 				 * The downclock is already found. But we
1209 				 * expect to find the lower downclock.
1210 				 */
1211 				temp_downclock = scan->clock;
1212 				tmp_mode = scan;
1213 			}
1214 		}
1215 	}
1216 
1217 	if (temp_downclock < fixed_mode->clock)
1218 		return drm_mode_duplicate(dev, tmp_mode);
1219 	else
1220 		return NULL;
1221 }
1222 
1223 /* Set up chip specific backlight functions */
1224 void intel_panel_init_backlight_funcs(struct drm_device *dev)
1225 {
1226 	struct drm_i915_private *dev_priv = dev->dev_private;
1227 
1228 	if (IS_BROADWELL(dev)) {
1229 		dev_priv->display.setup_backlight = bdw_setup_backlight;
1230 		dev_priv->display.enable_backlight = bdw_enable_backlight;
1231 		dev_priv->display.disable_backlight = pch_disable_backlight;
1232 		dev_priv->display.set_backlight = bdw_set_backlight;
1233 		dev_priv->display.get_backlight = bdw_get_backlight;
1234 	} else if (HAS_PCH_SPLIT(dev)) {
1235 		dev_priv->display.setup_backlight = pch_setup_backlight;
1236 		dev_priv->display.enable_backlight = pch_enable_backlight;
1237 		dev_priv->display.disable_backlight = pch_disable_backlight;
1238 		dev_priv->display.set_backlight = pch_set_backlight;
1239 		dev_priv->display.get_backlight = pch_get_backlight;
1240 	} else if (IS_VALLEYVIEW(dev)) {
1241 		dev_priv->display.setup_backlight = vlv_setup_backlight;
1242 		dev_priv->display.enable_backlight = vlv_enable_backlight;
1243 		dev_priv->display.disable_backlight = vlv_disable_backlight;
1244 		dev_priv->display.set_backlight = vlv_set_backlight;
1245 		dev_priv->display.get_backlight = vlv_get_backlight;
1246 	} else if (IS_GEN4(dev)) {
1247 		dev_priv->display.setup_backlight = i965_setup_backlight;
1248 		dev_priv->display.enable_backlight = i965_enable_backlight;
1249 		dev_priv->display.disable_backlight = i965_disable_backlight;
1250 		dev_priv->display.set_backlight = i9xx_set_backlight;
1251 		dev_priv->display.get_backlight = i9xx_get_backlight;
1252 	} else {
1253 		dev_priv->display.setup_backlight = i9xx_setup_backlight;
1254 		dev_priv->display.enable_backlight = i9xx_enable_backlight;
1255 		dev_priv->display.disable_backlight = i9xx_disable_backlight;
1256 		dev_priv->display.set_backlight = i9xx_set_backlight;
1257 		dev_priv->display.get_backlight = i9xx_get_backlight;
1258 	}
1259 }
1260 
1261 int intel_panel_init(struct intel_panel *panel,
1262 		     struct drm_display_mode *fixed_mode)
1263 {
1264 	panel->fixed_mode = fixed_mode;
1265 
1266 	return 0;
1267 }
1268 
1269 void intel_panel_fini(struct intel_panel *panel)
1270 {
1271 	struct intel_connector *intel_connector =
1272 		container_of(panel, struct intel_connector, panel);
1273 
1274 	if (panel->fixed_mode)
1275 		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1276 
1277 	if (panel->downclock_mode)
1278 		drm_mode_destroy(intel_connector->base.dev,
1279 				panel->downclock_mode);
1280 }
1281