intel_panel.c 40.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * Copyright © 2006-2010 Intel Corporation
 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 *
 * Authors:
 *	Eric Anholt <eric@anholt.net>
 *      Dave Airlie <airlied@linux.ie>
 *      Jesse Barnes <jesse.barnes@intel.com>
 *      Chris Wilson <chris@chris-wilson.co.uk>
 */

31 32
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

33
#include <linux/moduleparam.h>
34 35 36
#include "intel_drv.h"

void
37
intel_fixed_panel_mode(const struct drm_display_mode *fixed_mode,
38 39
		       struct drm_display_mode *adjusted_mode)
{
40
	drm_mode_copy(adjusted_mode, fixed_mode);
41 42

	drm_mode_set_crtcinfo(adjusted_mode, 0);
43 44
}

J
Jani Nikula 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
/**
 * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
 * @dev: drm device
 * @fixed_mode : panel native mode
 * @connector: LVDS/eDP connector
 *
 * Return downclock_avail
 * Find the reduced downclock for LVDS/eDP in EDID.
 */
struct drm_display_mode *
intel_find_panel_downclock(struct drm_device *dev,
			struct drm_display_mode *fixed_mode,
			struct drm_connector *connector)
{
	struct drm_display_mode *scan, *tmp_mode;
	int temp_downclock;

	temp_downclock = fixed_mode->clock;
	tmp_mode = NULL;

	list_for_each_entry(scan, &connector->probed_modes, head) {
		/*
		 * If one mode has the same resolution with the fixed_panel
		 * mode while they have the different refresh rate, it means
		 * that the reduced downclock is found. In such
		 * case we can set the different FPx0/1 to dynamically select
		 * between low and high frequency.
		 */
		if (scan->hdisplay == fixed_mode->hdisplay &&
		    scan->hsync_start == fixed_mode->hsync_start &&
		    scan->hsync_end == fixed_mode->hsync_end &&
		    scan->htotal == fixed_mode->htotal &&
		    scan->vdisplay == fixed_mode->vdisplay &&
		    scan->vsync_start == fixed_mode->vsync_start &&
		    scan->vsync_end == fixed_mode->vsync_end &&
		    scan->vtotal == fixed_mode->vtotal) {
			if (scan->clock < temp_downclock) {
				/*
				 * The downclock is already found. But we
				 * expect to find the lower downclock.
				 */
				temp_downclock = scan->clock;
				tmp_mode = scan;
			}
		}
	}

	if (temp_downclock < fixed_mode->clock)
		return drm_mode_duplicate(dev, tmp_mode);
	else
		return NULL;
}

98 99
/* adjusted_mode has been preset to be the panel's fixed mode */
void
100 101 102
intel_pch_panel_fitting(struct intel_crtc *intel_crtc,
			struct intel_crtc_config *pipe_config,
			int fitting_mode)
103
{
104
	struct drm_display_mode *adjusted_mode;
105 106
	int x, y, width, height;

107 108
	adjusted_mode = &pipe_config->adjusted_mode;

109 110 111
	x = y = width = height = 0;

	/* Native modes don't need fitting */
112 113
	if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
	    adjusted_mode->vdisplay == pipe_config->pipe_src_h)
114 115 116 117
		goto done;

	switch (fitting_mode) {
	case DRM_MODE_SCALE_CENTER:
118 119
		width = pipe_config->pipe_src_w;
		height = pipe_config->pipe_src_h;
120 121 122 123 124 125 126
		x = (adjusted_mode->hdisplay - width + 1)/2;
		y = (adjusted_mode->vdisplay - height + 1)/2;
		break;

	case DRM_MODE_SCALE_ASPECT:
		/* Scale but preserve the aspect ratio */
		{
127 128 129 130
			u32 scaled_width = adjusted_mode->hdisplay
				* pipe_config->pipe_src_h;
			u32 scaled_height = pipe_config->pipe_src_w
				* adjusted_mode->vdisplay;
131
			if (scaled_width > scaled_height) { /* pillar */
132
				width = scaled_height / pipe_config->pipe_src_h;
133
				if (width & 1)
134
					width++;
135 136 137 138
				x = (adjusted_mode->hdisplay - width + 1) / 2;
				y = 0;
				height = adjusted_mode->vdisplay;
			} else if (scaled_width < scaled_height) { /* letter */
139
				height = scaled_width / pipe_config->pipe_src_w;
140 141
				if (height & 1)
				    height++;
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
				y = (adjusted_mode->vdisplay - height + 1) / 2;
				x = 0;
				width = adjusted_mode->hdisplay;
			} else {
				x = y = 0;
				width = adjusted_mode->hdisplay;
				height = adjusted_mode->vdisplay;
			}
		}
		break;

	case DRM_MODE_SCALE_FULLSCREEN:
		x = y = 0;
		width = adjusted_mode->hdisplay;
		height = adjusted_mode->vdisplay;
		break;
158 159 160 161

	default:
		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
		return;
162 163 164
	}

done:
165 166
	pipe_config->pch_pfit.pos = (x << 16) | y;
	pipe_config->pch_pfit.size = (width << 16) | height;
167
	pipe_config->pch_pfit.enabled = pipe_config->pch_pfit.size != 0;
168
}
169

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
static void
centre_horizontally(struct drm_display_mode *mode,
		    int width)
{
	u32 border, sync_pos, blank_width, sync_width;

	/* keep the hsync and hblank widths constant */
	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
	sync_pos = (blank_width - sync_width + 1) / 2;

	border = (mode->hdisplay - width + 1) / 2;
	border += border & 1; /* make the border even */

	mode->crtc_hdisplay = width;
	mode->crtc_hblank_start = width + border;
	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;

	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
}

static void
centre_vertically(struct drm_display_mode *mode,
		  int height)
{
	u32 border, sync_pos, blank_width, sync_width;

	/* keep the vsync and vblank widths constant */
	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
	sync_pos = (blank_width - sync_width + 1) / 2;

	border = (mode->vdisplay - height + 1) / 2;

	mode->crtc_vdisplay = height;
	mode->crtc_vblank_start = height + border;
	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;

	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
}

static inline u32 panel_fitter_scaling(u32 source, u32 target)
{
	/*
	 * Floating point operation is not supported. So the FACTOR
	 * is defined, which can avoid the floating point computation
	 * when calculating the panel ratio.
	 */
#define ACCURACY 12
#define FACTOR (1 << ACCURACY)
	u32 ratio = source * FACTOR / target;
	return (FACTOR * ratio + FACTOR/2) / FACTOR;
}

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
static void i965_scale_aspect(struct intel_crtc_config *pipe_config,
			      u32 *pfit_control)
{
	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
	u32 scaled_width = adjusted_mode->hdisplay *
		pipe_config->pipe_src_h;
	u32 scaled_height = pipe_config->pipe_src_w *
		adjusted_mode->vdisplay;

	/* 965+ is easy, it does everything in hw */
	if (scaled_width > scaled_height)
		*pfit_control |= PFIT_ENABLE |
			PFIT_SCALING_PILLAR;
	else if (scaled_width < scaled_height)
		*pfit_control |= PFIT_ENABLE |
			PFIT_SCALING_LETTER;
	else if (adjusted_mode->hdisplay != pipe_config->pipe_src_w)
		*pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
}

static void i9xx_scale_aspect(struct intel_crtc_config *pipe_config,
			      u32 *pfit_control, u32 *pfit_pgm_ratios,
			      u32 *border)
{
	struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
	u32 scaled_width = adjusted_mode->hdisplay *
		pipe_config->pipe_src_h;
	u32 scaled_height = pipe_config->pipe_src_w *
		adjusted_mode->vdisplay;
	u32 bits;

	/*
	 * For earlier chips we have to calculate the scaling
	 * ratio by hand and program it into the
	 * PFIT_PGM_RATIO register
	 */
	if (scaled_width > scaled_height) { /* pillar */
		centre_horizontally(adjusted_mode,
				    scaled_height /
				    pipe_config->pipe_src_h);

		*border = LVDS_BORDER_ENABLE;
		if (pipe_config->pipe_src_h != adjusted_mode->vdisplay) {
			bits = panel_fitter_scaling(pipe_config->pipe_src_h,
						    adjusted_mode->vdisplay);

			*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
					     bits << PFIT_VERT_SCALE_SHIFT);
			*pfit_control |= (PFIT_ENABLE |
					  VERT_INTERP_BILINEAR |
					  HORIZ_INTERP_BILINEAR);
		}
	} else if (scaled_width < scaled_height) { /* letter */
		centre_vertically(adjusted_mode,
				  scaled_width /
				  pipe_config->pipe_src_w);

		*border = LVDS_BORDER_ENABLE;
		if (pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
			bits = panel_fitter_scaling(pipe_config->pipe_src_w,
						    adjusted_mode->hdisplay);

			*pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
					     bits << PFIT_VERT_SCALE_SHIFT);
			*pfit_control |= (PFIT_ENABLE |
					  VERT_INTERP_BILINEAR |
					  HORIZ_INTERP_BILINEAR);
		}
	} else {
		/* Aspects match, Let hw scale both directions */
		*pfit_control |= (PFIT_ENABLE |
				  VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
				  VERT_INTERP_BILINEAR |
				  HORIZ_INTERP_BILINEAR);
	}
}

303 304 305 306 307 308
void intel_gmch_panel_fitting(struct intel_crtc *intel_crtc,
			      struct intel_crtc_config *pipe_config,
			      int fitting_mode)
{
	struct drm_device *dev = intel_crtc->base.dev;
	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
309
	struct drm_display_mode *adjusted_mode;
310 311 312 313

	adjusted_mode = &pipe_config->adjusted_mode;

	/* Native modes don't need fitting */
314 315
	if (adjusted_mode->hdisplay == pipe_config->pipe_src_w &&
	    adjusted_mode->vdisplay == pipe_config->pipe_src_h)
316 317 318 319 320 321 322 323
		goto out;

	switch (fitting_mode) {
	case DRM_MODE_SCALE_CENTER:
		/*
		 * For centered modes, we have to calculate border widths &
		 * heights and modify the values programmed into the CRTC.
		 */
324 325
		centre_horizontally(adjusted_mode, pipe_config->pipe_src_w);
		centre_vertically(adjusted_mode, pipe_config->pipe_src_h);
326 327 328 329
		border = LVDS_BORDER_ENABLE;
		break;
	case DRM_MODE_SCALE_ASPECT:
		/* Scale but preserve the aspect ratio */
330 331 332 333 334
		if (INTEL_INFO(dev)->gen >= 4)
			i965_scale_aspect(pipe_config, &pfit_control);
		else
			i9xx_scale_aspect(pipe_config, &pfit_control,
					  &pfit_pgm_ratios, &border);
335 336 337 338 339 340
		break;
	case DRM_MODE_SCALE_FULLSCREEN:
		/*
		 * Full scaling, even if it changes the aspect ratio.
		 * Fortunately this is all done for us in hw.
		 */
341 342
		if (pipe_config->pipe_src_h != adjusted_mode->vdisplay ||
		    pipe_config->pipe_src_w != adjusted_mode->hdisplay) {
343 344 345 346 347 348 349 350 351 352
			pfit_control |= PFIT_ENABLE;
			if (INTEL_INFO(dev)->gen >= 4)
				pfit_control |= PFIT_SCALING_AUTO;
			else
				pfit_control |= (VERT_AUTO_SCALE |
						 VERT_INTERP_BILINEAR |
						 HORIZ_AUTO_SCALE |
						 HORIZ_INTERP_BILINEAR);
		}
		break;
353 354 355
	default:
		WARN(1, "bad panel fit mode: %d\n", fitting_mode);
		return;
356 357 358 359 360 361 362 363 364 365 366 367 368 369
	}

	/* 965+ wants fuzzy fitting */
	/* FIXME: handle multiple panels by failing gracefully */
	if (INTEL_INFO(dev)->gen >= 4)
		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
				 PFIT_FILTER_FUZZY);

out:
	if ((pfit_control & PFIT_ENABLE) == 0) {
		pfit_control = 0;
		pfit_pgm_ratios = 0;
	}

370 371 372 373
	/* Make sure pre-965 set dither correctly for 18bpp panels. */
	if (INTEL_INFO(dev)->gen < 4 && pipe_config->pipe_bpp == 18)
		pfit_control |= PANEL_8TO6_DITHER_ENABLE;

374 375
	pipe_config->gmch_pfit.control = pfit_control;
	pipe_config->gmch_pfit.pgm_ratios = pfit_pgm_ratios;
376
	pipe_config->gmch_pfit.lvds_border_bits = border;
377 378
}

J
Jani Nikula 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
enum drm_connector_status
intel_panel_detect(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	/* Assume that the BIOS does not lie through the OpRegion... */
	if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) {
		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
			connector_status_connected :
			connector_status_disconnected;
	}

	switch (i915.panel_ignore_lid) {
	case -2:
		return connector_status_connected;
	case -1:
		return connector_status_disconnected;
	default:
		return connector_status_unknown;
	}
}

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
/**
 * scale - scale values from one range to another
 *
 * @source_val: value in range [@source_min..@source_max]
 *
 * Return @source_val in range [@source_min..@source_max] scaled to range
 * [@target_min..@target_max].
 */
static uint32_t scale(uint32_t source_val,
		      uint32_t source_min, uint32_t source_max,
		      uint32_t target_min, uint32_t target_max)
{
	uint64_t target_val;

	WARN_ON(source_min > source_max);
	WARN_ON(target_min > target_max);

	/* defensive */
	source_val = clamp(source_val, source_min, source_max);

	/* avoid overflows */
422 423
	target_val = DIV_ROUND_CLOSEST_ULL((uint64_t)(source_val - source_min) *
			(target_max - target_min), source_max - source_min);
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
	target_val += target_min;

	return target_val;
}

/* Scale user_level in range [0..user_max] to [hw_min..hw_max]. */
static inline u32 scale_user_to_hw(struct intel_connector *connector,
				   u32 user_level, u32 user_max)
{
	struct intel_panel *panel = &connector->panel;

	return scale(user_level, 0, user_max,
		     panel->backlight.min, panel->backlight.max);
}

/* Scale user_level in range [0..user_max] to [0..hw_max], clamping the result
 * to [hw_min..hw_max]. */
static inline u32 clamp_user_to_hw(struct intel_connector *connector,
				   u32 user_level, u32 user_max)
{
	struct intel_panel *panel = &connector->panel;
	u32 hw_level;

	hw_level = scale(user_level, 0, user_max, 0, panel->backlight.max);
	hw_level = clamp(hw_level, panel->backlight.min, panel->backlight.max);

	return hw_level;
}

/* Scale hw_level in range [hw_min..hw_max] to [0..user_max]. */
static inline u32 scale_hw_to_user(struct intel_connector *connector,
				   u32 hw_level, u32 user_max)
{
	struct intel_panel *panel = &connector->panel;

	return scale(hw_level, panel->backlight.min, panel->backlight.max,
		     0, user_max);
}

463 464
static u32 intel_panel_compute_brightness(struct intel_connector *connector,
					  u32 val)
465
{
466
	struct drm_device *dev = connector->base.dev;
467
	struct drm_i915_private *dev_priv = dev->dev_private;
468 469 470
	struct intel_panel *panel = &connector->panel;

	WARN_ON(panel->backlight.max == 0);
471

472
	if (i915.invert_brightness < 0)
473 474
		return val;

475
	if (i915.invert_brightness > 0 ||
476
	    dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) {
477
		return panel->backlight.max - val;
478
	}
479 480 481 482

	return val;
}

483
static u32 bdw_get_backlight(struct intel_connector *connector)
484
{
485
	struct drm_device *dev = connector->base.dev;
486
	struct drm_i915_private *dev_priv = dev->dev_private;
487

488 489
	return I915_READ(BLC_PWM_PCH_CTL2) & BACKLIGHT_DUTY_CYCLE_MASK;
}
490

491
static u32 pch_get_backlight(struct intel_connector *connector)
492
{
493
	struct drm_device *dev = connector->base.dev;
494
	struct drm_i915_private *dev_priv = dev->dev_private;
495

496 497
	return I915_READ(BLC_PWM_CPU_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
}
498

499 500 501 502
static u32 i9xx_get_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
503
	struct intel_panel *panel = &connector->panel;
504
	u32 val;
505

506 507 508
	val = I915_READ(BLC_PWM_CTL) & BACKLIGHT_DUTY_CYCLE_MASK;
	if (INTEL_INFO(dev)->gen < 4)
		val >>= 1;
509

510
	if (panel->backlight.combination_mode) {
511
		u8 lbpc;
512

513 514
		pci_read_config_byte(dev->pdev, PCI_LBPC, &lbpc);
		val *= lbpc;
515 516
	}

517 518 519 520 521 522 523
	return val;
}

static u32 _vlv_get_backlight(struct drm_device *dev, enum pipe pipe)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

524 525 526
	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
		return 0;

527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
	return I915_READ(VLV_BLC_PWM_CTL(pipe)) & BACKLIGHT_DUTY_CYCLE_MASK;
}

static u32 vlv_get_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	enum pipe pipe = intel_get_pipe_from_connector(connector);

	return _vlv_get_backlight(dev, pipe);
}

static u32 intel_panel_get_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32 val;

544
	mutex_lock(&dev_priv->backlight_lock);
545 546 547

	val = dev_priv->display.get_backlight(connector);
	val = intel_panel_compute_brightness(connector, val);
548

549
	mutex_unlock(&dev_priv->backlight_lock);
550

551 552 553 554
	DRM_DEBUG_DRIVER("get backlight PWM = %d\n", val);
	return val;
}

555
static void bdw_set_backlight(struct intel_connector *connector, u32 level)
556
{
557
	struct drm_device *dev = connector->base.dev;
558 559 560 561 562
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32 val = I915_READ(BLC_PWM_PCH_CTL2) & ~BACKLIGHT_DUTY_CYCLE_MASK;
	I915_WRITE(BLC_PWM_PCH_CTL2, val | level);
}

563
static void pch_set_backlight(struct intel_connector *connector, u32 level)
564
{
565
	struct drm_device *dev = connector->base.dev;
566
	struct drm_i915_private *dev_priv = dev->dev_private;
567 568 569 570
	u32 tmp;

	tmp = I915_READ(BLC_PWM_CPU_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
	I915_WRITE(BLC_PWM_CPU_CTL, tmp | level);
571 572
}

573
static void i9xx_set_backlight(struct intel_connector *connector, u32 level)
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
	u32 tmp, mask;
579

580 581
	WARN_ON(panel->backlight.max == 0);

582
	if (panel->backlight.combination_mode) {
583 584
		u8 lbpc;

585
		lbpc = level * 0xfe / panel->backlight.max + 1;
586 587 588 589
		level /= lbpc;
		pci_write_config_byte(dev->pdev, PCI_LBPC, lbpc);
	}

590 591 592
	if (IS_GEN4(dev)) {
		mask = BACKLIGHT_DUTY_CYCLE_MASK;
	} else {
593
		level <<= 1;
594 595
		mask = BACKLIGHT_DUTY_CYCLE_MASK_PNV;
	}
596

597
	tmp = I915_READ(BLC_PWM_CTL) & ~mask;
598 599 600 601 602 603 604 605 606 607
	I915_WRITE(BLC_PWM_CTL, tmp | level);
}

static void vlv_set_backlight(struct intel_connector *connector, u32 level)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	enum pipe pipe = intel_get_pipe_from_connector(connector);
	u32 tmp;

608 609 610
	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
		return;

611 612 613 614 615 616 617 618 619 620 621 622 623 624
	tmp = I915_READ(VLV_BLC_PWM_CTL(pipe)) & ~BACKLIGHT_DUTY_CYCLE_MASK;
	I915_WRITE(VLV_BLC_PWM_CTL(pipe), tmp | level);
}

static void
intel_panel_actually_set_backlight(struct intel_connector *connector, u32 level)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;

	DRM_DEBUG_DRIVER("set backlight PWM = %d\n", level);

	level = intel_panel_compute_brightness(connector, level);
	dev_priv->display.set_backlight(connector, level);
625
}
626

627 628 629
/* set backlight brightness to level in range [0..max], scaling wrt hw min */
static void intel_panel_set_backlight(struct intel_connector *connector,
				      u32 user_level, u32 user_max)
630
{
631
	struct drm_device *dev = connector->base.dev;
632
	struct drm_i915_private *dev_priv = dev->dev_private;
633
	struct intel_panel *panel = &connector->panel;
634
	enum pipe pipe = intel_get_pipe_from_connector(connector);
635
	u32 hw_level;
636

637
	if (!panel->backlight.present || pipe == INVALID_PIPE)
638 639
		return;

640
	mutex_lock(&dev_priv->backlight_lock);
641

642
	WARN_ON(panel->backlight.max == 0);
643

644 645 646 647 648 649
	hw_level = scale_user_to_hw(connector, user_level, user_max);
	panel->backlight.level = hw_level;

	if (panel->backlight.enabled)
		intel_panel_actually_set_backlight(connector, hw_level);

650
	mutex_unlock(&dev_priv->backlight_lock);
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667
}

/* set backlight brightness to level in range [0..max], assuming hw min is
 * respected.
 */
void intel_panel_set_backlight_acpi(struct intel_connector *connector,
				    u32 user_level, u32 user_max)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_panel *panel = &connector->panel;
	enum pipe pipe = intel_get_pipe_from_connector(connector);
	u32 hw_level;

	if (!panel->backlight.present || pipe == INVALID_PIPE)
		return;

668
	mutex_lock(&dev_priv->backlight_lock);
669 670 671 672 673

	WARN_ON(panel->backlight.max == 0);

	hw_level = clamp_user_to_hw(connector, user_level, user_max);
	panel->backlight.level = hw_level;
674

675
	if (panel->backlight.device)
676 677 678 679
		panel->backlight.device->props.brightness =
			scale_hw_to_user(connector,
					 panel->backlight.level,
					 panel->backlight.device->props.max_brightness);
680

681
	if (panel->backlight.enabled)
682
		intel_panel_actually_set_backlight(connector, hw_level);
683

684
	mutex_unlock(&dev_priv->backlight_lock);
685 686
}

687 688 689 690 691 692
static void pch_disable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32 tmp;

693 694
	intel_panel_actually_set_backlight(connector, 0);

695 696 697 698 699 700 701
	tmp = I915_READ(BLC_PWM_CPU_CTL2);
	I915_WRITE(BLC_PWM_CPU_CTL2, tmp & ~BLM_PWM_ENABLE);

	tmp = I915_READ(BLC_PWM_PCH_CTL1);
	I915_WRITE(BLC_PWM_PCH_CTL1, tmp & ~BLM_PCH_PWM_ENABLE);
}

702 703 704 705 706
static void i9xx_disable_backlight(struct intel_connector *connector)
{
	intel_panel_actually_set_backlight(connector, 0);
}

707 708 709 710 711 712
static void i965_disable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	u32 tmp;

713 714
	intel_panel_actually_set_backlight(connector, 0);

715 716 717 718 719 720 721 722 723 724 725
	tmp = I915_READ(BLC_PWM_CTL2);
	I915_WRITE(BLC_PWM_CTL2, tmp & ~BLM_PWM_ENABLE);
}

static void vlv_disable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	enum pipe pipe = intel_get_pipe_from_connector(connector);
	u32 tmp;

726 727 728
	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
		return;

729 730
	intel_panel_actually_set_backlight(connector, 0);

731 732 733 734
	tmp = I915_READ(VLV_BLC_PWM_CTL2(pipe));
	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), tmp & ~BLM_PWM_ENABLE);
}

735
void intel_panel_disable_backlight(struct intel_connector *connector)
736
{
737
	struct drm_device *dev = connector->base.dev;
738
	struct drm_i915_private *dev_priv = dev->dev_private;
739
	struct intel_panel *panel = &connector->panel;
740
	enum pipe pipe = intel_get_pipe_from_connector(connector);
741

742
	if (!panel->backlight.present || pipe == INVALID_PIPE)
743 744
		return;

745 746 747 748 749 750 751 752 753 754 755
	/*
	 * Do not disable backlight on the vgaswitcheroo path. When switching
	 * away from i915, the other client may depend on i915 to handle the
	 * backlight. This will leave the backlight on unnecessarily when
	 * another client is not activated.
	 */
	if (dev->switch_power_state == DRM_SWITCH_POWER_CHANGING) {
		DRM_DEBUG_DRIVER("Skipping backlight disable on vga switch\n");
		return;
	}

756
	mutex_lock(&dev_priv->backlight_lock);
757

758 759
	if (panel->backlight.device)
		panel->backlight.device->props.power = FB_BLANK_POWERDOWN;
760
	panel->backlight.enabled = false;
761
	dev_priv->display.disable_backlight(connector);
762

763
	mutex_unlock(&dev_priv->backlight_lock);
764
}
765

766 767 768 769 770 771 772 773 774 775 776 777 778
static void bdw_enable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_panel *panel = &connector->panel;
	u32 pch_ctl1, pch_ctl2;

	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
	if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
		DRM_DEBUG_KMS("pch backlight already enabled\n");
		pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
		I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
	}
779

780 781
	pch_ctl2 = panel->backlight.max << 16;
	I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);
782

783 784 785
	pch_ctl1 = 0;
	if (panel->backlight.active_low_pwm)
		pch_ctl1 |= BLM_PCH_POLARITY;
786

787 788 789
	/* After LPT, override is the default. */
	if (HAS_PCH_LPT(dev_priv))
		pch_ctl1 |= BLM_PCH_OVERRIDE_ENABLE;
790 791 792 793 794 795 796

	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
	POSTING_READ(BLC_PWM_PCH_CTL1);
	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);

	/* This won't stick until the above enable. */
	intel_panel_actually_set_backlight(connector, panel->backlight.level);
797 798
}

799 800 801 802
static void pch_enable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
803
	struct intel_panel *panel = &connector->panel;
804 805 806
	enum pipe pipe = intel_get_pipe_from_connector(connector);
	enum transcoder cpu_transcoder =
		intel_pipe_to_cpu_transcoder(dev_priv, pipe);
807
	u32 cpu_ctl2, pch_ctl1, pch_ctl2;
808

809 810
	cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
	if (cpu_ctl2 & BLM_PWM_ENABLE) {
811
		DRM_DEBUG_KMS("cpu backlight already enabled\n");
812 813 814
		cpu_ctl2 &= ~BLM_PWM_ENABLE;
		I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
	}
815

816 817 818 819 820 821
	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
	if (pch_ctl1 & BLM_PCH_PWM_ENABLE) {
		DRM_DEBUG_KMS("pch backlight already enabled\n");
		pch_ctl1 &= ~BLM_PCH_PWM_ENABLE;
		I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
	}
822 823

	if (cpu_transcoder == TRANSCODER_EDP)
824
		cpu_ctl2 = BLM_TRANSCODER_EDP;
825
	else
826 827
		cpu_ctl2 = BLM_PIPE(cpu_transcoder);
	I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2);
828
	POSTING_READ(BLC_PWM_CPU_CTL2);
829
	I915_WRITE(BLC_PWM_CPU_CTL2, cpu_ctl2 | BLM_PWM_ENABLE);
830

831
	/* This won't stick until the above enable. */
832
	intel_panel_actually_set_backlight(connector, panel->backlight.level);
833 834 835 836 837 838 839

	pch_ctl2 = panel->backlight.max << 16;
	I915_WRITE(BLC_PWM_PCH_CTL2, pch_ctl2);

	pch_ctl1 = 0;
	if (panel->backlight.active_low_pwm)
		pch_ctl1 |= BLM_PCH_POLARITY;
840

841 842 843
	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1);
	POSTING_READ(BLC_PWM_PCH_CTL1);
	I915_WRITE(BLC_PWM_PCH_CTL1, pch_ctl1 | BLM_PCH_PWM_ENABLE);
844 845 846 847
}

static void i9xx_enable_backlight(struct intel_connector *connector)
{
848 849
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
850
	struct intel_panel *panel = &connector->panel;
851 852 853 854
	u32 ctl, freq;

	ctl = I915_READ(BLC_PWM_CTL);
	if (ctl & BACKLIGHT_DUTY_CYCLE_MASK_PNV) {
855
		DRM_DEBUG_KMS("backlight already enabled\n");
856 857
		I915_WRITE(BLC_PWM_CTL, 0);
	}
858

859 860 861 862 863
	freq = panel->backlight.max;
	if (panel->backlight.combination_mode)
		freq /= 0xff;

	ctl = freq << 17;
864
	if (panel->backlight.combination_mode)
865 866 867 868 869 870 871 872
		ctl |= BLM_LEGACY_MODE;
	if (IS_PINEVIEW(dev) && panel->backlight.active_low_pwm)
		ctl |= BLM_POLARITY_PNV;

	I915_WRITE(BLC_PWM_CTL, ctl);
	POSTING_READ(BLC_PWM_CTL);

	/* XXX: combine this into above write? */
873
	intel_panel_actually_set_backlight(connector, panel->backlight.level);
874
}
875

876 877 878 879
static void i965_enable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
880
	struct intel_panel *panel = &connector->panel;
881
	enum pipe pipe = intel_get_pipe_from_connector(connector);
882
	u32 ctl, ctl2, freq;
883

884 885
	ctl2 = I915_READ(BLC_PWM_CTL2);
	if (ctl2 & BLM_PWM_ENABLE) {
886
		DRM_DEBUG_KMS("backlight already enabled\n");
887 888 889
		ctl2 &= ~BLM_PWM_ENABLE;
		I915_WRITE(BLC_PWM_CTL2, ctl2);
	}
890

891 892 893
	freq = panel->backlight.max;
	if (panel->backlight.combination_mode)
		freq /= 0xff;
894

895 896
	ctl = freq << 16;
	I915_WRITE(BLC_PWM_CTL, ctl);
897

898 899 900 901 902 903 904 905
	ctl2 = BLM_PIPE(pipe);
	if (panel->backlight.combination_mode)
		ctl2 |= BLM_COMBINATION_MODE;
	if (panel->backlight.active_low_pwm)
		ctl2 |= BLM_POLARITY_I965;
	I915_WRITE(BLC_PWM_CTL2, ctl2);
	POSTING_READ(BLC_PWM_CTL2);
	I915_WRITE(BLC_PWM_CTL2, ctl2 | BLM_PWM_ENABLE);
906 907

	intel_panel_actually_set_backlight(connector, panel->backlight.level);
908 909 910 911 912 913
}

static void vlv_enable_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
914
	struct intel_panel *panel = &connector->panel;
915
	enum pipe pipe = intel_get_pipe_from_connector(connector);
916
	u32 ctl, ctl2;
917

918 919 920
	if (WARN_ON(pipe != PIPE_A && pipe != PIPE_B))
		return;

921 922
	ctl2 = I915_READ(VLV_BLC_PWM_CTL2(pipe));
	if (ctl2 & BLM_PWM_ENABLE) {
923
		DRM_DEBUG_KMS("backlight already enabled\n");
924 925 926
		ctl2 &= ~BLM_PWM_ENABLE;
		I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
	}
927

928 929
	ctl = panel->backlight.max << 16;
	I915_WRITE(VLV_BLC_PWM_CTL(pipe), ctl);
930

931 932
	/* XXX: combine this into above write? */
	intel_panel_actually_set_backlight(connector, panel->backlight.level);
933

934 935 936 937
	ctl2 = 0;
	if (panel->backlight.active_low_pwm)
		ctl2 |= BLM_POLARITY_I965;
	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2);
938
	POSTING_READ(VLV_BLC_PWM_CTL2(pipe));
939
	I915_WRITE(VLV_BLC_PWM_CTL2(pipe), ctl2 | BLM_PWM_ENABLE);
940 941
}

942
void intel_panel_enable_backlight(struct intel_connector *connector)
943
{
944
	struct drm_device *dev = connector->base.dev;
945
	struct drm_i915_private *dev_priv = dev->dev_private;
946
	struct intel_panel *panel = &connector->panel;
947
	enum pipe pipe = intel_get_pipe_from_connector(connector);
948

949
	if (!panel->backlight.present || pipe == INVALID_PIPE)
950 951
		return;

952
	DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe));
953

954
	mutex_lock(&dev_priv->backlight_lock);
955

956 957
	WARN_ON(panel->backlight.max == 0);

958
	if (panel->backlight.level == 0) {
959
		panel->backlight.level = panel->backlight.max;
960 961
		if (panel->backlight.device)
			panel->backlight.device->props.brightness =
962 963 964
				scale_hw_to_user(connector,
						 panel->backlight.level,
						 panel->backlight.device->props.max_brightness);
965
	}
966

967
	dev_priv->display.enable_backlight(connector);
968
	panel->backlight.enabled = true;
969 970
	if (panel->backlight.device)
		panel->backlight.device->props.power = FB_BLANK_UNBLANK;
971

972
	mutex_unlock(&dev_priv->backlight_lock);
973 974
}

975
#if IS_ENABLED(CONFIG_BACKLIGHT_CLASS_DEVICE)
976
static int intel_backlight_device_update_status(struct backlight_device *bd)
977
{
978
	struct intel_connector *connector = bl_get_data(bd);
979
	struct intel_panel *panel = &connector->panel;
980 981
	struct drm_device *dev = connector->base.dev;

982
	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
983 984
	DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
		      bd->props.brightness, bd->props.max_brightness);
985
	intel_panel_set_backlight(connector, bd->props.brightness,
986
				  bd->props.max_brightness);
987 988 989 990 991 992 993 994 995

	/*
	 * Allow flipping bl_power as a sub-state of enabled. Sadly the
	 * backlight class device does not make it easy to to differentiate
	 * between callbacks for brightness and bl_power, so our backlight_power
	 * callback needs to take this into account.
	 */
	if (panel->backlight.enabled) {
		if (panel->backlight_power) {
996 997
			bool enable = bd->props.power == FB_BLANK_UNBLANK &&
				bd->props.brightness != 0;
998 999 1000 1001 1002 1003
			panel->backlight_power(connector, enable);
		}
	} else {
		bd->props.power = FB_BLANK_POWERDOWN;
	}

1004
	drm_modeset_unlock(&dev->mode_config.connection_mutex);
1005 1006 1007
	return 0;
}

1008
static int intel_backlight_device_get_brightness(struct backlight_device *bd)
1009
{
1010 1011
	struct intel_connector *connector = bl_get_data(bd);
	struct drm_device *dev = connector->base.dev;
1012
	struct drm_i915_private *dev_priv = dev->dev_private;
1013
	u32 hw_level;
1014
	int ret;
1015

1016
	intel_runtime_pm_get(dev_priv);
1017
	drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
1018 1019 1020 1021

	hw_level = intel_panel_get_backlight(connector);
	ret = scale_hw_to_user(connector, hw_level, bd->props.max_brightness);

1022
	drm_modeset_unlock(&dev->mode_config.connection_mutex);
1023
	intel_runtime_pm_put(dev_priv);
1024

1025
	return ret;
1026 1027
}

1028 1029 1030
static const struct backlight_ops intel_backlight_device_ops = {
	.update_status = intel_backlight_device_update_status,
	.get_brightness = intel_backlight_device_get_brightness,
1031 1032
};

1033
static int intel_backlight_device_register(struct intel_connector *connector)
1034
{
1035
	struct intel_panel *panel = &connector->panel;
1036 1037
	struct backlight_properties props;

1038
	if (WARN_ON(panel->backlight.device))
1039 1040
		return -ENODEV;

1041
	WARN_ON(panel->backlight.max == 0);
1042

1043
	memset(&props, 0, sizeof(props));
1044
	props.type = BACKLIGHT_RAW;
1045 1046 1047 1048 1049

	/*
	 * Note: Everything should work even if the backlight device max
	 * presented to the userspace is arbitrarily chosen.
	 */
1050
	props.max_brightness = panel->backlight.max;
1051 1052 1053
	props.brightness = scale_hw_to_user(connector,
					    panel->backlight.level,
					    props.max_brightness);
1054

1055 1056 1057 1058 1059
	if (panel->backlight.enabled)
		props.power = FB_BLANK_UNBLANK;
	else
		props.power = FB_BLANK_POWERDOWN;

1060 1061 1062 1063 1064
	/*
	 * Note: using the same name independent of the connector prevents
	 * registration of multiple backlight devices in the driver.
	 */
	panel->backlight.device =
1065
		backlight_device_register("intel_backlight",
1066 1067 1068
					  connector->base.kdev,
					  connector,
					  &intel_backlight_device_ops, &props);
1069

1070
	if (IS_ERR(panel->backlight.device)) {
1071
		DRM_ERROR("Failed to register backlight: %ld\n",
1072 1073
			  PTR_ERR(panel->backlight.device));
		panel->backlight.device = NULL;
1074 1075 1076 1077 1078
		return -ENODEV;
	}
	return 0;
}

1079
static void intel_backlight_device_unregister(struct intel_connector *connector)
1080
{
1081 1082 1083 1084 1085
	struct intel_panel *panel = &connector->panel;

	if (panel->backlight.device) {
		backlight_device_unregister(panel->backlight.device);
		panel->backlight.device = NULL;
1086
	}
1087
}
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
#else /* CONFIG_BACKLIGHT_CLASS_DEVICE */
static int intel_backlight_device_register(struct intel_connector *connector)
{
	return 0;
}
static void intel_backlight_device_unregister(struct intel_connector *connector)
{
}
#endif /* CONFIG_BACKLIGHT_CLASS_DEVICE */

1098 1099 1100 1101 1102 1103
/*
 * Note: The setup hooks can't assume pipe is set!
 *
 * XXX: Query mode clock or hardware clock and program PWM modulation frequency
 * appropriately when it's 0. Use VBT and/or sane defaults.
 */
1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
static u32 get_backlight_min_vbt(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_panel *panel = &connector->panel;

	WARN_ON(panel->backlight.max == 0);

	/* vbt value is a coefficient in range [0..255] */
	return scale(dev_priv->vbt.backlight.min_brightness, 0, 255,
		     0, panel->backlight.max);
}

1117
static int bdw_setup_backlight(struct intel_connector *connector)
1118
{
1119
	struct drm_device *dev = connector->base.dev;
1120
	struct drm_i915_private *dev_priv = dev->dev_private;
1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131
	struct intel_panel *panel = &connector->panel;
	u32 pch_ctl1, pch_ctl2, val;

	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
	panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;

	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
	panel->backlight.max = pch_ctl2 >> 16;
	if (!panel->backlight.max)
		return -ENODEV;

1132 1133
	panel->backlight.min = get_backlight_min_vbt(connector);

1134 1135 1136 1137 1138 1139 1140 1141 1142
	val = bdw_get_backlight(connector);
	panel->backlight.level = intel_panel_compute_brightness(connector, val);

	panel->backlight.enabled = (pch_ctl1 & BLM_PCH_PWM_ENABLE) &&
		panel->backlight.level != 0;

	return 0;
}

1143 1144
static int pch_setup_backlight(struct intel_connector *connector)
{
1145 1146
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
1147
	struct intel_panel *panel = &connector->panel;
1148
	u32 cpu_ctl2, pch_ctl1, pch_ctl2, val;
1149

1150 1151 1152 1153 1154
	pch_ctl1 = I915_READ(BLC_PWM_PCH_CTL1);
	panel->backlight.active_low_pwm = pch_ctl1 & BLM_PCH_POLARITY;

	pch_ctl2 = I915_READ(BLC_PWM_PCH_CTL2);
	panel->backlight.max = pch_ctl2 >> 16;
1155 1156 1157
	if (!panel->backlight.max)
		return -ENODEV;

1158 1159
	panel->backlight.min = get_backlight_min_vbt(connector);

1160 1161 1162
	val = pch_get_backlight(connector);
	panel->backlight.level = intel_panel_compute_brightness(connector, val);

1163 1164 1165 1166
	cpu_ctl2 = I915_READ(BLC_PWM_CPU_CTL2);
	panel->backlight.enabled = (cpu_ctl2 & BLM_PWM_ENABLE) &&
		(pch_ctl1 & BLM_PCH_PWM_ENABLE) && panel->backlight.level != 0;

1167 1168 1169 1170 1171
	return 0;
}

static int i9xx_setup_backlight(struct intel_connector *connector)
{
1172 1173
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
1174
	struct intel_panel *panel = &connector->panel;
1175 1176 1177 1178
	u32 ctl, val;

	ctl = I915_READ(BLC_PWM_CTL);

1179
	if (IS_GEN2(dev) || IS_I915GM(dev) || IS_I945GM(dev))
1180 1181 1182 1183 1184 1185 1186 1187
		panel->backlight.combination_mode = ctl & BLM_LEGACY_MODE;

	if (IS_PINEVIEW(dev))
		panel->backlight.active_low_pwm = ctl & BLM_POLARITY_PNV;

	panel->backlight.max = ctl >> 17;
	if (panel->backlight.combination_mode)
		panel->backlight.max *= 0xff;
1188 1189 1190 1191

	if (!panel->backlight.max)
		return -ENODEV;

1192 1193
	panel->backlight.min = get_backlight_min_vbt(connector);

1194 1195 1196
	val = i9xx_get_backlight(connector);
	panel->backlight.level = intel_panel_compute_brightness(connector, val);

1197 1198
	panel->backlight.enabled = panel->backlight.level != 0;

1199 1200 1201 1202 1203
	return 0;
}

static int i965_setup_backlight(struct intel_connector *connector)
{
1204 1205
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
1206
	struct intel_panel *panel = &connector->panel;
1207 1208 1209 1210 1211 1212 1213 1214 1215 1216
	u32 ctl, ctl2, val;

	ctl2 = I915_READ(BLC_PWM_CTL2);
	panel->backlight.combination_mode = ctl2 & BLM_COMBINATION_MODE;
	panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;

	ctl = I915_READ(BLC_PWM_CTL);
	panel->backlight.max = ctl >> 16;
	if (panel->backlight.combination_mode)
		panel->backlight.max *= 0xff;
1217 1218 1219 1220

	if (!panel->backlight.max)
		return -ENODEV;

1221 1222
	panel->backlight.min = get_backlight_min_vbt(connector);

1223 1224 1225
	val = i9xx_get_backlight(connector);
	panel->backlight.level = intel_panel_compute_brightness(connector, val);

1226 1227 1228
	panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
		panel->backlight.level != 0;

1229 1230 1231 1232 1233 1234 1235 1236 1237
	return 0;
}

static int vlv_setup_backlight(struct intel_connector *connector)
{
	struct drm_device *dev = connector->base.dev;
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_panel *panel = &connector->panel;
	enum pipe pipe;
1238
	u32 ctl, ctl2, val;
1239

1240
	for_each_pipe(dev_priv, pipe) {
1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
		u32 cur_val = I915_READ(VLV_BLC_PWM_CTL(pipe));

		/* Skip if the modulation freq is already set */
		if (cur_val & ~BACKLIGHT_DUTY_CYCLE_MASK)
			continue;

		cur_val &= BACKLIGHT_DUTY_CYCLE_MASK;
		I915_WRITE(VLV_BLC_PWM_CTL(pipe), (0xf42 << 16) |
			   cur_val);
	}

1252 1253 1254 1255 1256
	ctl2 = I915_READ(VLV_BLC_PWM_CTL2(PIPE_A));
	panel->backlight.active_low_pwm = ctl2 & BLM_POLARITY_I965;

	ctl = I915_READ(VLV_BLC_PWM_CTL(PIPE_A));
	panel->backlight.max = ctl >> 16;
1257 1258 1259
	if (!panel->backlight.max)
		return -ENODEV;

1260 1261
	panel->backlight.min = get_backlight_min_vbt(connector);

1262 1263 1264
	val = _vlv_get_backlight(dev, PIPE_A);
	panel->backlight.level = intel_panel_compute_brightness(connector, val);

1265 1266 1267
	panel->backlight.enabled = (ctl2 & BLM_PWM_ENABLE) &&
		panel->backlight.level != 0;

1268 1269 1270
	return 0;
}

1271
int intel_panel_setup_backlight(struct drm_connector *connector)
1272
{
1273
	struct drm_device *dev = connector->dev;
1274
	struct drm_i915_private *dev_priv = dev->dev_private;
1275
	struct intel_connector *intel_connector = to_intel_connector(connector);
1276
	struct intel_panel *panel = &intel_connector->panel;
1277
	int ret;
1278

1279
	if (!dev_priv->vbt.backlight.present) {
1280 1281 1282 1283 1284 1285
		if (dev_priv->quirks & QUIRK_BACKLIGHT_PRESENT) {
			DRM_DEBUG_KMS("no backlight present per VBT, but present per quirk\n");
		} else {
			DRM_DEBUG_KMS("no backlight present per VBT\n");
			return 0;
		}
1286 1287
	}

1288
	/* set level and max in panel struct */
1289
	mutex_lock(&dev_priv->backlight_lock);
1290
	ret = dev_priv->display.setup_backlight(intel_connector);
1291
	mutex_unlock(&dev_priv->backlight_lock);
1292 1293 1294

	if (ret) {
		DRM_DEBUG_KMS("failed to setup backlight for connector %s\n",
1295
			      connector->name);
1296 1297
		return ret;
	}
1298 1299 1300

	intel_backlight_device_register(intel_connector);

1301 1302
	panel->backlight.present = true;

1303 1304 1305 1306 1307 1308
	DRM_DEBUG_KMS("backlight initialized, %s, brightness %u/%u, "
		      "sysfs interface %sregistered\n",
		      panel->backlight.enabled ? "enabled" : "disabled",
		      panel->backlight.level, panel->backlight.max,
		      panel->backlight.device ? "" : "not ");

1309 1310 1311
	return 0;
}

1312
void intel_panel_destroy_backlight(struct drm_connector *connector)
1313
{
1314
	struct intel_connector *intel_connector = to_intel_connector(connector);
1315
	struct intel_panel *panel = &intel_connector->panel;
1316

1317
	panel->backlight.present = false;
1318
	intel_backlight_device_unregister(intel_connector);
1319
}
1320

1321 1322 1323 1324 1325
/* Set up chip specific backlight functions */
void intel_panel_init_backlight_funcs(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

1326
	if (IS_BROADWELL(dev) || (INTEL_INFO(dev)->gen >= 9)) {
1327 1328 1329 1330 1331 1332
		dev_priv->display.setup_backlight = bdw_setup_backlight;
		dev_priv->display.enable_backlight = bdw_enable_backlight;
		dev_priv->display.disable_backlight = pch_disable_backlight;
		dev_priv->display.set_backlight = bdw_set_backlight;
		dev_priv->display.get_backlight = bdw_get_backlight;
	} else if (HAS_PCH_SPLIT(dev)) {
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351
		dev_priv->display.setup_backlight = pch_setup_backlight;
		dev_priv->display.enable_backlight = pch_enable_backlight;
		dev_priv->display.disable_backlight = pch_disable_backlight;
		dev_priv->display.set_backlight = pch_set_backlight;
		dev_priv->display.get_backlight = pch_get_backlight;
	} else if (IS_VALLEYVIEW(dev)) {
		dev_priv->display.setup_backlight = vlv_setup_backlight;
		dev_priv->display.enable_backlight = vlv_enable_backlight;
		dev_priv->display.disable_backlight = vlv_disable_backlight;
		dev_priv->display.set_backlight = vlv_set_backlight;
		dev_priv->display.get_backlight = vlv_get_backlight;
	} else if (IS_GEN4(dev)) {
		dev_priv->display.setup_backlight = i965_setup_backlight;
		dev_priv->display.enable_backlight = i965_enable_backlight;
		dev_priv->display.disable_backlight = i965_disable_backlight;
		dev_priv->display.set_backlight = i9xx_set_backlight;
		dev_priv->display.get_backlight = i9xx_get_backlight;
	} else {
		dev_priv->display.setup_backlight = i9xx_setup_backlight;
1352 1353
		dev_priv->display.enable_backlight = i9xx_enable_backlight;
		dev_priv->display.disable_backlight = i9xx_disable_backlight;
1354 1355 1356 1357 1358
		dev_priv->display.set_backlight = i9xx_set_backlight;
		dev_priv->display.get_backlight = i9xx_get_backlight;
	}
}

1359
int intel_panel_init(struct intel_panel *panel,
1360 1361
		     struct drm_display_mode *fixed_mode,
		     struct drm_display_mode *downclock_mode)
1362
{
1363
	panel->fixed_mode = fixed_mode;
1364
	panel->downclock_mode = downclock_mode;
1365

1366 1367 1368 1369 1370
	return 0;
}

void intel_panel_fini(struct intel_panel *panel)
{
1371 1372 1373 1374 1375
	struct intel_connector *intel_connector =
		container_of(panel, struct intel_connector, panel);

	if (panel->fixed_mode)
		drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1376 1377 1378 1379

	if (panel->downclock_mode)
		drm_mode_destroy(intel_connector->base.dev,
				panel->downclock_mode);
1380
}