intel_lvds.c 34.5 KB
Newer Older
J
Jesse Barnes 已提交
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
/*
 * Copyright © 2006-2007 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>
 */

30
#include <acpi/button.h>
31
#include <linux/dmi.h>
J
Jesse Barnes 已提交
32
#include <linux/i2c.h>
33
#include <linux/slab.h>
34
#include <linux/vga_switcheroo.h>
35
#include <drm/drmP.h>
36
#include <drm/drm_atomic_helper.h>
37 38
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
J
Jesse Barnes 已提交
39
#include "intel_drv.h"
40
#include <drm/i915_drm.h>
J
Jesse Barnes 已提交
41
#include "i915_drv.h"
42
#include <linux/acpi.h>
J
Jesse Barnes 已提交
43

44
/* Private structure for the integrated LVDS support */
45 46
struct intel_lvds_connector {
	struct intel_connector base;
47

48
	struct notifier_block lid_notifier;
49 50
};

51 52 53 54 55 56 57 58 59 60 61 62 63 64
struct intel_lvds_pps {
	/* 100us units */
	int t1_t2;
	int t3;
	int t4;
	int t5;
	int tx;

	int divider;

	int port;
	bool powerdown_on_reset;
};

65
struct intel_lvds_encoder {
C
Chris Wilson 已提交
66
	struct intel_encoder base;
67

68
	bool is_dual_link;
69
	i915_reg_t reg;
70
	u32 a3_power;
71

72 73 74
	struct intel_lvds_pps init_pps;
	u32 init_lvds_val;

75
	struct intel_lvds_connector *attached_connector;
76 77
};

78
static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
C
Chris Wilson 已提交
79
{
80
	return container_of(encoder, struct intel_lvds_encoder, base.base);
C
Chris Wilson 已提交
81 82
}

83
static struct intel_lvds_connector *to_lvds_connector(struct drm_connector *connector)
84
{
85
	return container_of(connector, struct intel_lvds_connector, base.base);
86 87
}

88 89 90 91
static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
				    enum pipe *pipe)
{
	struct drm_device *dev = encoder->base.dev;
92
	struct drm_i915_private *dev_priv = to_i915(dev);
D
Daniel Vetter 已提交
93
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
94
	enum intel_display_power_domain power_domain;
D
Daniel Vetter 已提交
95
	u32 tmp;
96
	bool ret;
97

98
	power_domain = intel_display_port_power_domain(encoder);
99
	if (!intel_display_power_get_if_enabled(dev_priv, power_domain))
100 101
		return false;

102 103
	ret = false;

D
Daniel Vetter 已提交
104
	tmp = I915_READ(lvds_encoder->reg);
105 106

	if (!(tmp & LVDS_PORT_EN))
107
		goto out;
108

109
	if (HAS_PCH_CPT(dev_priv))
110 111 112 113
		*pipe = PORT_TO_PIPE_CPT(tmp);
	else
		*pipe = PORT_TO_PIPE(tmp);

114 115 116 117 118 119
	ret = true;

out:
	intel_display_power_put(dev_priv, power_domain);

	return ret;
120 121
}

122
static void intel_lvds_get_config(struct intel_encoder *encoder,
123
				  struct intel_crtc_state *pipe_config)
124 125
{
	struct drm_device *dev = encoder->base.dev;
126
	struct drm_i915_private *dev_priv = to_i915(dev);
127 128
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
	u32 tmp, flags = 0;
129

130
	tmp = I915_READ(lvds_encoder->reg);
131 132 133 134 135 136 137 138 139
	if (tmp & LVDS_HSYNC_POLARITY)
		flags |= DRM_MODE_FLAG_NHSYNC;
	else
		flags |= DRM_MODE_FLAG_PHSYNC;
	if (tmp & LVDS_VSYNC_POLARITY)
		flags |= DRM_MODE_FLAG_NVSYNC;
	else
		flags |= DRM_MODE_FLAG_PVSYNC;

140
	pipe_config->base.adjusted_mode.flags |= flags;
141

142 143 144 145
	if (INTEL_INFO(dev)->gen < 5)
		pipe_config->gmch_pfit.lvds_border_bits =
			tmp & LVDS_BORDER_ENABLE;

146 147 148 149 150 151 152
	/* gen2/3 store dither state in pfit control, needs to match */
	if (INTEL_INFO(dev)->gen < 4) {
		tmp = I915_READ(PFIT_CONTROL);

		pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
	}

153
	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
154 155
}

156 157 158 159 160 161 162 163 164 165 166 167 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 226 227 228 229 230 231 232
static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
					struct intel_lvds_pps *pps)
{
	u32 val;

	pps->powerdown_on_reset = I915_READ(PP_CONTROL(0)) & PANEL_POWER_RESET;

	val = I915_READ(PP_ON_DELAYS(0));
	pps->port = (val & PANEL_PORT_SELECT_MASK) >>
		    PANEL_PORT_SELECT_SHIFT;
	pps->t1_t2 = (val & PANEL_POWER_UP_DELAY_MASK) >>
		     PANEL_POWER_UP_DELAY_SHIFT;
	pps->t5 = (val & PANEL_LIGHT_ON_DELAY_MASK) >>
		  PANEL_LIGHT_ON_DELAY_SHIFT;

	val = I915_READ(PP_OFF_DELAYS(0));
	pps->t3 = (val & PANEL_POWER_DOWN_DELAY_MASK) >>
		  PANEL_POWER_DOWN_DELAY_SHIFT;
	pps->tx = (val & PANEL_LIGHT_OFF_DELAY_MASK) >>
		  PANEL_LIGHT_OFF_DELAY_SHIFT;

	val = I915_READ(PP_DIVISOR(0));
	pps->divider = (val & PP_REFERENCE_DIVIDER_MASK) >>
		       PP_REFERENCE_DIVIDER_SHIFT;
	val = (val & PANEL_POWER_CYCLE_DELAY_MASK) >>
	      PANEL_POWER_CYCLE_DELAY_SHIFT;
	/*
	 * Remove the BSpec specified +1 (100ms) offset that accounts for a
	 * too short power-cycle delay due to the asynchronous programming of
	 * the register.
	 */
	if (val)
		val--;
	/* Convert from 100ms to 100us units */
	pps->t4 = val * 1000;

	if (INTEL_INFO(dev_priv)->gen <= 4 &&
	    pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
		DRM_DEBUG_KMS("Panel power timings uninitialized, "
			      "setting defaults\n");
		/* Set T2 to 40ms and T5 to 200ms in 100 usec units */
		pps->t1_t2 = 40 * 10;
		pps->t5 = 200 * 10;
		/* Set T3 to 35ms and Tx to 200ms in 100 usec units */
		pps->t3 = 35 * 10;
		pps->tx = 200 * 10;
	}

	DRM_DEBUG_DRIVER("LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
			 "divider %d port %d powerdown_on_reset %d\n",
			 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
			 pps->divider, pps->port, pps->powerdown_on_reset);
}

static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
				   struct intel_lvds_pps *pps)
{
	u32 val;

	val = I915_READ(PP_CONTROL(0));
	WARN_ON((val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
	if (pps->powerdown_on_reset)
		val |= PANEL_POWER_RESET;
	I915_WRITE(PP_CONTROL(0), val);

	I915_WRITE(PP_ON_DELAYS(0), (pps->port << PANEL_PORT_SELECT_SHIFT) |
				    (pps->t1_t2 << PANEL_POWER_UP_DELAY_SHIFT) |
				    (pps->t5 << PANEL_LIGHT_ON_DELAY_SHIFT));
	I915_WRITE(PP_OFF_DELAYS(0), (pps->t3 << PANEL_POWER_DOWN_DELAY_SHIFT) |
				     (pps->tx << PANEL_LIGHT_OFF_DELAY_SHIFT));

	val = pps->divider << PP_REFERENCE_DIVIDER_SHIFT;
	val |= (DIV_ROUND_UP(pps->t4, 1000) + 1) <<
	       PANEL_POWER_CYCLE_DELAY_SHIFT;
	I915_WRITE(PP_DIVISOR(0), val);
}

233 234 235
static void intel_pre_enable_lvds(struct intel_encoder *encoder,
				  struct intel_crtc_state *pipe_config,
				  struct drm_connector_state *conn_state)
236 237
{
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
238 239 240
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
	struct intel_crtc *crtc = to_intel_crtc(pipe_config->base.crtc);
	const struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
241
	int pipe = crtc->pipe;
242 243
	u32 temp;

244
	if (HAS_PCH_SPLIT(dev_priv)) {
245 246
		assert_fdi_rx_pll_disabled(dev_priv, pipe);
		assert_shared_dpll_disabled(dev_priv,
247
					    pipe_config->shared_dpll);
248 249 250 251
	} else {
		assert_pll_disabled(dev_priv, pipe);
	}

252 253 254
	intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);

	temp = lvds_encoder->init_lvds_val;
255
	temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
256

257
	if (HAS_PCH_CPT(dev_priv)) {
258 259
		temp &= ~PORT_TRANS_SEL_MASK;
		temp |= PORT_TRANS_SEL_CPT(pipe);
260
	} else {
261 262 263 264 265
		if (pipe == 1) {
			temp |= LVDS_PIPEB_SELECT;
		} else {
			temp &= ~LVDS_PIPEB_SELECT;
		}
266
	}
267

268
	/* set the corresponsding LVDS_BORDER bit */
269
	temp &= ~LVDS_BORDER_ENABLE;
270
	temp |= pipe_config->gmch_pfit.lvds_border_bits;
271 272 273 274 275 276 277 278 279 280
	/* Set the B0-B3 data pairs corresponding to whether we're going to
	 * set the DPLLs for dual-channel mode or not.
	 */
	if (lvds_encoder->is_dual_link)
		temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
	else
		temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);

	/* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
	 * appropriately here, but we need to look more thoroughly into how
281 282
	 * panels behave in the two modes. For now, let's just maintain the
	 * value we got from the BIOS.
283
	 */
284 285
	temp &= ~LVDS_A3_POWER_MASK;
	temp |= lvds_encoder->a3_power;
286 287 288 289

	/* Set the dithering flag on LVDS as needed, note that there is no
	 * special lvds dither control bit on pch-split platforms, dithering is
	 * only controlled through the PIPECONF reg. */
290
	if (IS_GEN4(dev_priv)) {
291 292
		/* Bspec wording suggests that LVDS port dithering only exists
		 * for 18bpp panels. */
293
		if (pipe_config->dither && pipe_config->pipe_bpp == 18)
294 295 296 297 298
			temp |= LVDS_ENABLE_DITHER;
		else
			temp &= ~LVDS_ENABLE_DITHER;
	}
	temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
299
	if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
300
		temp |= LVDS_HSYNC_POLARITY;
301
	if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
302 303 304 305 306
		temp |= LVDS_VSYNC_POLARITY;

	I915_WRITE(lvds_encoder->reg, temp);
}

J
Jesse Barnes 已提交
307 308 309
/**
 * Sets the power state for the panel.
 */
310 311 312
static void intel_enable_lvds(struct intel_encoder *encoder,
			      struct intel_crtc_state *pipe_config,
			      struct drm_connector_state *conn_state)
J
Jesse Barnes 已提交
313
{
314
	struct drm_device *dev = encoder->base.dev;
315
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
316 317
	struct intel_connector *intel_connector =
		&lvds_encoder->attached_connector->base;
318
	struct drm_i915_private *dev_priv = to_i915(dev);
J
Jesse Barnes 已提交
319

D
Daniel Vetter 已提交
320
	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
321

322
	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON);
D
Daniel Vetter 已提交
323
	POSTING_READ(lvds_encoder->reg);
324
	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 1000))
325
		DRM_ERROR("timed out waiting for panel to power on\n");
326

327
	intel_panel_enable_backlight(intel_connector);
328 329
}

330 331 332
static void intel_disable_lvds(struct intel_encoder *encoder,
			       struct intel_crtc_state *old_crtc_state,
			       struct drm_connector_state *old_conn_state)
333
{
334
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
335
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
336

337
	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~PANEL_POWER_ON);
338
	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
339
		DRM_ERROR("timed out waiting for panel to power off\n");
340

D
Daniel Vetter 已提交
341 342
	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
	POSTING_READ(lvds_encoder->reg);
J
Jesse Barnes 已提交
343 344
}

345 346 347 348
static void gmch_disable_lvds(struct intel_encoder *encoder,
			      struct intel_crtc_state *old_crtc_state,
			      struct drm_connector_state *old_conn_state)

349 350 351 352 353 354 355
{
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
	struct intel_connector *intel_connector =
		&lvds_encoder->attached_connector->base;

	intel_panel_disable_backlight(intel_connector);

356
	intel_disable_lvds(encoder, old_crtc_state, old_conn_state);
357 358
}

359 360 361
static void pch_disable_lvds(struct intel_encoder *encoder,
			     struct intel_crtc_state *old_crtc_state,
			     struct drm_connector_state *old_conn_state)
362 363 364 365 366 367 368 369
{
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
	struct intel_connector *intel_connector =
		&lvds_encoder->attached_connector->base;

	intel_panel_disable_backlight(intel_connector);
}

370 371 372
static void pch_post_disable_lvds(struct intel_encoder *encoder,
				  struct intel_crtc_state *old_crtc_state,
				  struct drm_connector_state *old_conn_state)
373
{
374
	intel_disable_lvds(encoder, old_crtc_state, old_conn_state);
375 376
}

377 378 379
static enum drm_mode_status
intel_lvds_mode_valid(struct drm_connector *connector,
		      struct drm_display_mode *mode)
J
Jesse Barnes 已提交
380
{
381 382
	struct intel_connector *intel_connector = to_intel_connector(connector);
	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
M
Mika Kahola 已提交
383
	int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
J
Jesse Barnes 已提交
384

385 386 387 388
	if (mode->hdisplay > fixed_mode->hdisplay)
		return MODE_PANEL;
	if (mode->vdisplay > fixed_mode->vdisplay)
		return MODE_PANEL;
M
Mika Kahola 已提交
389 390
	if (fixed_mode->clock > max_pixclk)
		return MODE_CLOCK_HIGH;
J
Jesse Barnes 已提交
391 392 393 394

	return MODE_OK;
}

395
static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
396 397
				      struct intel_crtc_state *pipe_config,
				      struct drm_connector_state *conn_state)
J
Jesse Barnes 已提交
398
{
399
	struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
400 401
	struct intel_lvds_encoder *lvds_encoder =
		to_lvds_encoder(&intel_encoder->base);
402 403
	struct intel_connector *intel_connector =
		&lvds_encoder->attached_connector->base;
404
	struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
405
	struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
406
	unsigned int lvds_bpp;
J
Jesse Barnes 已提交
407 408

	/* Should never happen!! */
409
	if (INTEL_GEN(dev_priv) < 4 && intel_crtc->pipe == 0) {
410
		DRM_ERROR("Can't support LVDS on pipe A\n");
J
Jesse Barnes 已提交
411 412 413
		return false;
	}

414
	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
415 416 417 418
		lvds_bpp = 8*3;
	else
		lvds_bpp = 6*3;

419
	if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
420 421 422 423
		DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
			      pipe_config->pipe_bpp, lvds_bpp);
		pipe_config->pipe_bpp = lvds_bpp;
	}
424

J
Jesse Barnes 已提交
425
	/*
426
	 * We have timings from the BIOS for the panel, put them in
J
Jesse Barnes 已提交
427 428 429 430
	 * to the adjusted mode.  The CRTC will be set up for this mode,
	 * with the panel scaling set up to source from the H/VDisplay
	 * of the original mode.
	 */
431
	intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
432
			       adjusted_mode);
433

434
	if (HAS_PCH_SPLIT(dev_priv)) {
435 436
		pipe_config->has_pch_encoder = true;

437 438
		intel_pch_panel_fitting(intel_crtc, pipe_config,
					intel_connector->panel.fitting_mode);
439 440 441
	} else {
		intel_gmch_panel_fitting(intel_crtc, pipe_config,
					 intel_connector->panel.fitting_mode);
J
Jesse Barnes 已提交
442

443
	}
444

J
Jesse Barnes 已提交
445 446 447 448 449 450 451 452 453 454 455 456
	/*
	 * XXX: It would be nice to support lower refresh rates on the
	 * panels to reduce power consumption, and perhaps match the
	 * user's requested refresh rate.
	 */

	return true;
}

/**
 * Detect the LVDS connection.
 *
457 458 459
 * Since LVDS doesn't have hotlug, we use the lid as a proxy.  Open means
 * connected and closed means disconnected.  We also send hotplug events as
 * needed, using lid status notification from the input layer.
J
Jesse Barnes 已提交
460
 */
461
static enum drm_connector_status
462
intel_lvds_detect(struct drm_connector *connector, bool force)
J
Jesse Barnes 已提交
463
{
464
	struct drm_device *dev = connector->dev;
465
	enum drm_connector_status status;
466

467
	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
468
		      connector->base.id, connector->name);
469

470 471 472
	status = intel_panel_detect(dev);
	if (status != connector_status_unknown)
		return status;
473

474
	return connector_status_connected;
J
Jesse Barnes 已提交
475 476 477 478 479 480 481
}

/**
 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
 */
static int intel_lvds_get_modes(struct drm_connector *connector)
{
482
	struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
J
Jesse Barnes 已提交
483
	struct drm_device *dev = connector->dev;
484
	struct drm_display_mode *mode;
J
Jesse Barnes 已提交
485

486
	/* use cached edid if we have one */
487
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
488
		return drm_add_edid_modes(connector, lvds_connector->base.edid);
J
Jesse Barnes 已提交
489

490
	mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
C
Chris Wilson 已提交
491
	if (mode == NULL)
492
		return 0;
J
Jesse Barnes 已提交
493

494 495
	drm_mode_probed_add(connector, mode);
	return 1;
J
Jesse Barnes 已提交
496 497
}

498 499
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
{
500
	DRM_INFO("Skipping forced modeset for %s\n", id->ident);
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
	return 1;
}

/* The GPU hangs up on these systems if modeset is performed on LID open */
static const struct dmi_system_id intel_no_modeset_on_lid[] = {
	{
		.callback = intel_no_modeset_on_lid_dmi_callback,
		.ident = "Toshiba Tecra A11",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
		},
	},

	{ }	/* terminating entry */
};

518
/*
519 520 521
 * Lid events. Note the use of 'modeset':
 *  - we set it to MODESET_ON_LID_OPEN on lid close,
 *    and set it to MODESET_DONE on open
522
 *  - we use it as a "only once" bit (ie we ignore
523 524 525 526
 *    duplicate events where it was already properly set)
 *  - the suspend/resume paths will set it to
 *    MODESET_SUSPENDED and ignore the lid open event,
 *    because they restore the mode ("lid open").
527
 */
528 529 530
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
			    void *unused)
{
531 532 533 534
	struct intel_lvds_connector *lvds_connector =
		container_of(nb, struct intel_lvds_connector, lid_notifier);
	struct drm_connector *connector = &lvds_connector->base.base;
	struct drm_device *dev = connector->dev;
535
	struct drm_i915_private *dev_priv = to_i915(dev);
536

537 538 539
	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
		return NOTIFY_OK;

540 541 542
	mutex_lock(&dev_priv->modeset_restore_lock);
	if (dev_priv->modeset_restore == MODESET_SUSPENDED)
		goto exit;
543 544 545 546
	/*
	 * check and update the status of LVDS connector after receiving
	 * the LID nofication event.
	 */
547
	connector->status = connector->funcs->detect(connector, false);
548

549 550
	/* Don't force modeset on machines where it causes a GPU lockup */
	if (dmi_check_system(intel_no_modeset_on_lid))
551
		goto exit;
552
	if (!acpi_lid_open()) {
553 554 555
		/* do modeset on next lid open event */
		dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
		goto exit;
556
	}
557

558 559
	if (dev_priv->modeset_restore == MODESET_DONE)
		goto exit;
560

561 562 563 564 565 566 567 568
	/*
	 * Some old platform's BIOS love to wreak havoc while the lid is closed.
	 * We try to detect this here and undo any damage. The split for PCH
	 * platforms is rather conservative and a bit arbitrary expect that on
	 * those platforms VGA disabling requires actual legacy VGA I/O access,
	 * and as part of the cleanup in the hw state restore we also redisable
	 * the vga plane.
	 */
569
	if (!HAS_PCH_SPLIT(dev_priv))
570
		intel_display_resume(dev);
571

572 573 574 575
	dev_priv->modeset_restore = MODESET_DONE;

exit:
	mutex_unlock(&dev_priv->modeset_restore_lock);
576 577 578
	return NOTIFY_OK;
}

J
Jesse Barnes 已提交
579 580 581 582 583 584 585 586 587
/**
 * intel_lvds_destroy - unregister and free LVDS structures
 * @connector: connector to free
 *
 * Unregister the DDC bus for this connector then free the driver private
 * structure.
 */
static void intel_lvds_destroy(struct drm_connector *connector)
{
588 589
	struct intel_lvds_connector *lvds_connector =
		to_lvds_connector(connector);
J
Jesse Barnes 已提交
590

591 592
	if (lvds_connector->lid_notifier.notifier_call)
		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
J
Jesse Barnes 已提交
593

594 595 596
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
		kfree(lvds_connector->base.edid);

597
	intel_panel_fini(&lvds_connector->base.panel);
598

J
Jesse Barnes 已提交
599 600 601 602
	drm_connector_cleanup(connector);
	kfree(connector);
}

603 604 605 606
static int intel_lvds_set_property(struct drm_connector *connector,
				   struct drm_property *property,
				   uint64_t value)
{
607
	struct intel_connector *intel_connector = to_intel_connector(connector);
608 609
	struct drm_device *dev = connector->dev;

610
	if (property == dev->mode_config.scaling_mode_property) {
611
		struct drm_crtc *crtc;
612

613 614
		if (value == DRM_MODE_SCALE_NONE) {
			DRM_DEBUG_KMS("no scaling not supported\n");
615
			return -EINVAL;
616
		}
617

618
		if (intel_connector->panel.fitting_mode == value) {
619 620 621
			/* the LVDS scaling property is not changed */
			return 0;
		}
622
		intel_connector->panel.fitting_mode = value;
623 624

		crtc = intel_attached_encoder(connector)->base.crtc;
625
		if (crtc && crtc->state->enable) {
626 627 628 629
			/*
			 * If the CRTC is enabled, the display will be changed
			 * according to the new panel fitting mode.
			 */
630
			intel_crtc_restore_mode(crtc);
631 632 633
		}
	}

634 635 636
	return 0;
}

J
Jesse Barnes 已提交
637 638 639 640 641 642
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
	.get_modes = intel_lvds_get_modes,
	.mode_valid = intel_lvds_mode_valid,
};

static const struct drm_connector_funcs intel_lvds_connector_funcs = {
643
	.dpms = drm_atomic_helper_connector_dpms,
J
Jesse Barnes 已提交
644 645
	.detect = intel_lvds_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
646
	.set_property = intel_lvds_set_property,
647
	.atomic_get_property = intel_connector_atomic_get_property,
648
	.late_register = intel_connector_register,
649
	.early_unregister = intel_connector_unregister,
J
Jesse Barnes 已提交
650
	.destroy = intel_lvds_destroy,
651
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
652
	.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
J
Jesse Barnes 已提交
653 654 655
};

static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
C
Chris Wilson 已提交
656
	.destroy = intel_encoder_destroy,
J
Jesse Barnes 已提交
657 658
};

659
static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
660
{
661
	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
662 663
	return 1;
}
J
Jesse Barnes 已提交
664

665
/* These systems claim to have LVDS, but really don't */
666
static const struct dmi_system_id intel_no_lvds[] = {
667 668 669 670
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Apple Mac Mini (Core series)",
		.matches = {
671
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
672 673 674 675 676 677 678
			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Apple Mac Mini (Core 2 series)",
		.matches = {
679
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698
			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "MSI IM-945GSE-A",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
			DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Dell Studio Hybrid",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
		},
	},
699 700
	{
		.callback = intel_no_lvds_dmi_callback,
701 702 703 704 705 706 707 708
		.ident = "Dell OptiPlex FX170",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
709 710 711 712 713 714
		.ident = "AOpen Mini PC",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
			DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
		},
	},
715 716 717 718 719 720 721 722
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "AOpen Mini PC MP915",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
			DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
		},
	},
723 724 725 726 727 728 729 730
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "AOpen i915GMm-HFS",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
		},
	},
731 732 733 734 735 736 737 738
	{
		.callback = intel_no_lvds_dmi_callback,
                .ident = "AOpen i45GMx-I",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
                },
        },
739 740 741 742 743 744 745
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Aopen i945GTt-VFA",
		.matches = {
			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
		},
	},
746 747 748 749 750 751 752 753
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Clientron U800",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
			DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
		},
	},
754
	{
755 756 757 758 759 760 761 762
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Clientron E830",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
                },
        },
        {
763 764 765 766 767 768 769
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Asus EeeBox PC EB1007",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
		},
	},
770 771 772 773 774 775 776 777
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Asus AT5NM10T-I",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
		},
	},
778 779
	{
		.callback = intel_no_lvds_dmi_callback,
780
		.ident = "Hewlett-Packard HP t5740",
781 782
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
783
			DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
784 785
		},
	},
786 787 788 789 790
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Hewlett-Packard t5745",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
791
			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
792 793 794 795 796 797 798
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Hewlett-Packard st5747",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
799
			DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
800 801
		},
	},
802 803 804 805 806 807 808 809
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "MSI Wind Box DC500",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
			DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
		},
	},
810 811 812 813 814 815 816 817
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Gigabyte GA-D525TUD",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
			DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
		},
	},
818 819 820 821 822 823 824 825
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Supermicro X7SPA-H",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
		},
	},
826 827 828 829 830 831 832 833
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Fujitsu Esprimo Q900",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
			DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
		},
	},
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D410PT",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D425KT",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
		},
	},
850 851 852 853 854 855 856 857
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D510MO",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),
		},
	},
858 859 860 861 862 863 864 865
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D525MW",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
		},
	},
866 867 868

	{ }	/* terminating entry */
};
J
Jesse Barnes 已提交
869

870 871 872 873 874 875 876 877 878
static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
{
	DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
	return 1;
}

static const struct dmi_system_id intel_dual_link_lvds[] = {
	{
		.callback = intel_dual_link_lvds_callback,
879 880 881 882 883 884 885 886 887
		.ident = "Apple MacBook Pro 15\" (2010)",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
		},
	},
	{
		.callback = intel_dual_link_lvds_callback,
		.ident = "Apple MacBook Pro 15\" (2011)",
888 889 890 891 892
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
		},
	},
893 894 895 896 897 898 899 900
	{
		.callback = intel_dual_link_lvds_callback,
		.ident = "Apple MacBook Pro 15\" (2012)",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
		},
	},
901 902 903
	{ }	/* terminating entry */
};

904
struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev)
905
{
906
	struct intel_encoder *intel_encoder;
907

908 909 910
	for_each_intel_encoder(dev, intel_encoder)
		if (intel_encoder->type == INTEL_OUTPUT_LVDS)
			return intel_encoder;
911

912 913 914 915 916 917
	return NULL;
}

bool intel_is_dual_link_lvds(struct drm_device *dev)
{
	struct intel_encoder *encoder = intel_get_lvds_encoder(dev);
918

919
	return encoder && to_lvds_encoder(&encoder->base)->is_dual_link;
920 921
}

D
Daniel Vetter 已提交
922
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
923
{
D
Daniel Vetter 已提交
924
	struct drm_device *dev = lvds_encoder->base.base.dev;
925
	unsigned int val;
926
	struct drm_i915_private *dev_priv = to_i915(dev);
927 928

	/* use the module option value if specified */
929 930
	if (i915.lvds_channel_mode > 0)
		return i915.lvds_channel_mode == 2;
931

932 933 934 935 936
	/* single channel LVDS is limited to 112 MHz */
	if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock
	    > 112999)
		return true;

937 938 939
	if (dmi_check_system(intel_dual_link_lvds))
		return true;

940 941 942 943 944
	/* BIOS should set the proper LVDS register value at boot, but
	 * in reality, it doesn't set the value when the lid is closed;
	 * we need to check "the value to be set" in VBT when LVDS
	 * register is uninitialized.
	 */
D
Daniel Vetter 已提交
945
	val = I915_READ(lvds_encoder->reg);
946
	if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
947
		val = dev_priv->vbt.bios_lvds_val;
948

949 950 951
	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
}

952
static bool intel_lvds_supported(struct drm_i915_private *dev_priv)
953 954 955
{
	/* With the introduction of the PCH we gained a dedicated
	 * LVDS presence pin, use it. */
956
	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
957 958 959 960
		return true;

	/* Otherwise LVDS was only attached to mobile products,
	 * except for the inglorious 830gm */
961 962
	if (INTEL_GEN(dev_priv) <= 4 &&
	    IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
963 964 965
		return true;

	return false;
966 967
}

J
Jesse Barnes 已提交
968 969 970 971 972 973 974
/**
 * intel_lvds_init - setup LVDS connectors on this device
 * @dev: drm device
 *
 * Create the connector, register the LVDS DDC bus, and try to figure out what
 * modes we can display on the LVDS panel (if present).
 */
975
void intel_lvds_init(struct drm_device *dev)
J
Jesse Barnes 已提交
976
{
977
	struct drm_i915_private *dev_priv = to_i915(dev);
978
	struct intel_lvds_encoder *lvds_encoder;
979
	struct intel_encoder *intel_encoder;
980
	struct intel_lvds_connector *lvds_connector;
981
	struct intel_connector *intel_connector;
J
Jesse Barnes 已提交
982 983 984
	struct drm_connector *connector;
	struct drm_encoder *encoder;
	struct drm_display_mode *scan; /* *modes, *bios_mode; */
985
	struct drm_display_mode *fixed_mode = NULL;
986
	struct drm_display_mode *downclock_mode = NULL;
987
	struct edid *edid;
988
	struct intel_crtc *crtc;
989
	i915_reg_t lvds_reg;
J
Jesse Barnes 已提交
990
	u32 lvds;
991 992
	int pipe;
	u8 pin;
J
Jesse Barnes 已提交
993

994
	if (!intel_lvds_supported(dev_priv))
995
		return;
996

997 998
	/* Skip init on machines we know falsely report LVDS */
	if (dmi_check_system(intel_no_lvds))
999
		return;
1000

1001
	if (HAS_PCH_SPLIT(dev_priv))
1002 1003 1004 1005 1006 1007
		lvds_reg = PCH_LVDS;
	else
		lvds_reg = LVDS;

	lvds = I915_READ(lvds_reg);

1008
	if (HAS_PCH_SPLIT(dev_priv)) {
1009
		if ((lvds & LVDS_DETECTED) == 0)
1010
			return;
1011
		if (dev_priv->vbt.edp.support) {
1012
			DRM_DEBUG_KMS("disable LVDS for eDP support\n");
1013
			return;
1014
		}
1015 1016
	}

1017
	pin = GMBUS_PIN_PANEL;
1018
	if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
1019
		if ((lvds & LVDS_PORT_EN) == 0) {
1020 1021 1022 1023 1024 1025
			DRM_DEBUG_KMS("LVDS is not present in VBT\n");
			return;
		}
		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
	}

1026
	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
1027
	if (!lvds_encoder)
1028
		return;
J
Jesse Barnes 已提交
1029

1030
	lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
1031
	if (!lvds_connector) {
1032
		kfree(lvds_encoder);
1033
		return;
1034 1035
	}

1036 1037 1038 1039 1040 1041
	if (intel_connector_init(&lvds_connector->base) < 0) {
		kfree(lvds_connector);
		kfree(lvds_encoder);
		return;
	}

1042 1043
	lvds_encoder->attached_connector = lvds_connector;

1044
	intel_encoder = &lvds_encoder->base;
1045
	encoder = &intel_encoder->base;
1046
	intel_connector = &lvds_connector->base;
C
Chris Wilson 已提交
1047
	connector = &intel_connector->base;
1048
	drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
J
Jesse Barnes 已提交
1049 1050
			   DRM_MODE_CONNECTOR_LVDS);

1051
	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
1052
			 DRM_MODE_ENCODER_LVDS, "LVDS");
J
Jesse Barnes 已提交
1053

1054
	intel_encoder->enable = intel_enable_lvds;
1055
	intel_encoder->pre_enable = intel_pre_enable_lvds;
1056
	intel_encoder->compute_config = intel_lvds_compute_config;
1057 1058 1059 1060 1061 1062
	if (HAS_PCH_SPLIT(dev_priv)) {
		intel_encoder->disable = pch_disable_lvds;
		intel_encoder->post_disable = pch_post_disable_lvds;
	} else {
		intel_encoder->disable = gmch_disable_lvds;
	}
1063
	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
1064
	intel_encoder->get_config = intel_lvds_get_config;
1065
	intel_connector->get_hw_state = intel_connector_get_hw_state;
1066

1067
	intel_connector_attach_encoder(intel_connector, intel_encoder);
J
Jesse Barnes 已提交
1068

1069 1070
	intel_encoder->type = INTEL_OUTPUT_LVDS;
	intel_encoder->port = PORT_NONE;
1071
	intel_encoder->cloneable = 0;
1072
	if (HAS_PCH_SPLIT(dev_priv))
J
Jesse Barnes 已提交
1073
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
1074
	else if (IS_GEN4(dev_priv))
1075
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
J
Jesse Barnes 已提交
1076 1077 1078
	else
		intel_encoder->crtc_mask = (1 << 1);

J
Jesse Barnes 已提交
1079 1080 1081 1082 1083
	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
	connector->interlace_allowed = false;
	connector->doublescan_allowed = false;

1084
	lvds_encoder->reg = lvds_reg;
D
Daniel Vetter 已提交
1085

1086 1087
	/* create the scaling mode property */
	drm_mode_create_scaling_mode_property(dev);
1088
	drm_object_attach_property(&connector->base,
1089
				      dev->mode_config.scaling_mode_property,
1090
				      DRM_MODE_SCALE_ASPECT);
1091
	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
1092 1093 1094 1095

	intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
	lvds_encoder->init_lvds_val = lvds;

J
Jesse Barnes 已提交
1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
	/*
	 * LVDS discovery:
	 * 1) check for EDID on DDC
	 * 2) check for VBT data
	 * 3) check to see if LVDS is already on
	 *    if none of the above, no panel
	 * 4) make sure lid is open
	 *    if closed, act like it's not there for now
	 */

	/*
	 * Attempt to get the fixed panel mode from DDC.  Assume that the
	 * preferred mode is the right one.
	 */
1110
	mutex_lock(&dev->mode_config.mutex);
1111 1112 1113 1114 1115 1116
	if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
		edid = drm_get_edid_switcheroo(connector,
				    intel_gmbus_get_adapter(dev_priv, pin));
	else
		edid = drm_get_edid(connector,
				    intel_gmbus_get_adapter(dev_priv, pin));
1117 1118
	if (edid) {
		if (drm_add_edid_modes(connector, edid)) {
1119
			drm_mode_connector_update_edid_property(connector,
1120
								edid);
1121
		} else {
1122 1123
			kfree(edid);
			edid = ERR_PTR(-EINVAL);
1124
		}
1125 1126
	} else {
		edid = ERR_PTR(-ENOENT);
1127
	}
1128 1129
	lvds_connector->base.edid = edid;

J
Jesse Barnes 已提交
1130 1131
	list_for_each_entry(scan, &connector->probed_modes, head) {
		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
1132 1133 1134
			DRM_DEBUG_KMS("using preferred mode from EDID: ");
			drm_mode_debug_printmodeline(scan);

1135
			fixed_mode = drm_mode_duplicate(dev, scan);
1136
			if (fixed_mode)
1137
				goto out;
J
Jesse Barnes 已提交
1138 1139 1140 1141
		}
	}

	/* Failed to get EDID, what about VBT? */
1142
	if (dev_priv->vbt.lfp_lvds_vbt_mode) {
1143
		DRM_DEBUG_KMS("using mode from VBT: ");
1144
		drm_mode_debug_printmodeline(dev_priv->vbt.lfp_lvds_vbt_mode);
1145

1146
		fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
1147 1148
		if (fixed_mode) {
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
1149 1150
			connector->display_info.width_mm = fixed_mode->width_mm;
			connector->display_info.height_mm = fixed_mode->height_mm;
1151 1152
			goto out;
		}
J
Jesse Barnes 已提交
1153 1154 1155 1156 1157 1158 1159
	}

	/*
	 * If we didn't get EDID, try checking if the panel is already turned
	 * on.  If so, assume that whatever is currently programmed is the
	 * correct mode.
	 */
1160

1161
	/* Ironlake: FIXME if still fail, not try pipe mode now */
1162
	if (HAS_PCH_SPLIT(dev_priv))
1163 1164
		goto failed;

J
Jesse Barnes 已提交
1165
	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
1166
	crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
J
Jesse Barnes 已提交
1167 1168

	if (crtc && (lvds & LVDS_PORT_EN)) {
1169
		fixed_mode = intel_crtc_mode_get(dev, &crtc->base);
1170
		if (fixed_mode) {
1171 1172
			DRM_DEBUG_KMS("using current (BIOS) mode: ");
			drm_mode_debug_printmodeline(fixed_mode);
1173
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
1174
			goto out;
J
Jesse Barnes 已提交
1175 1176 1177 1178
		}
	}

	/* If we still don't have a mode after all that, give up. */
1179
	if (!fixed_mode)
J
Jesse Barnes 已提交
1180 1181 1182
		goto failed;

out:
1183 1184
	mutex_unlock(&dev->mode_config.mutex);

1185
	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
1186
	intel_panel_setup_backlight(connector, INVALID_PIPE);
1187

D
Daniel Vetter 已提交
1188
	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
1189 1190 1191
	DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
		      lvds_encoder->is_dual_link ? "dual" : "single");

1192
	lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
1193

1194 1195
	lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
	if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
1196
		DRM_DEBUG_KMS("lid notifier registration failed\n");
1197
		lvds_connector->lid_notifier.notifier_call = NULL;
1198
	}
1199

1200
	return;
J
Jesse Barnes 已提交
1201 1202

failed:
1203 1204
	mutex_unlock(&dev->mode_config.mutex);

1205
	DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
J
Jesse Barnes 已提交
1206
	drm_connector_cleanup(connector);
1207
	drm_encoder_cleanup(encoder);
1208
	kfree(lvds_encoder);
1209
	kfree(lvds_connector);
1210
	return;
J
Jesse Barnes 已提交
1211
}