intel_lvds.c 33.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 92 93 94 95 96 97 98 99 100 101 102 103
bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
			     i915_reg_t lvds_reg, enum pipe *pipe)
{
	u32 val;

	val = I915_READ(lvds_reg);

	/* asserts want to know the pipe even if the port is disabled */
	if (HAS_PCH_CPT(dev_priv))
		*pipe = (val & LVDS_PIPE_SEL_MASK_CPT) >> LVDS_PIPE_SEL_SHIFT_CPT;
	else
		*pipe = (val & LVDS_PIPE_SEL_MASK) >> LVDS_PIPE_SEL_SHIFT;

	return val & LVDS_PORT_EN;
}

104 105 106
static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
				    enum pipe *pipe)
{
107
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
D
Daniel Vetter 已提交
108
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
109
	bool ret;
110

111 112
	if (!intel_display_power_get_if_enabled(dev_priv,
						encoder->power_domain))
113 114
		return false;

115
	ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
116

117
	intel_display_power_put(dev_priv, encoder->power_domain);
118 119

	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_i915_private *dev_priv = to_i915(encoder->base.dev);
126 127
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
	u32 tmp, flags = 0;
128

129 130
	pipe_config->output_types |= BIT(INTEL_OUTPUT_LVDS);

131
	tmp = I915_READ(lvds_encoder->reg);
132 133 134 135 136 137 138 139 140
	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;

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

143
	if (INTEL_GEN(dev_priv) < 5)
144 145 146
		pipe_config->gmch_pfit.lvds_border_bits =
			tmp & LVDS_BORDER_ENABLE;

147
	/* gen2/3 store dither state in pfit control, needs to match */
148
	if (INTEL_GEN(dev_priv) < 4) {
149 150 151 152 153
		tmp = I915_READ(PFIT_CONTROL);

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

154
	pipe_config->base.adjusted_mode.crtc_clock = pipe_config->port_clock;
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
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;

193
	if (INTEL_GEN(dev_priv) <= 4 &&
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 233
	    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);
}

234
static void intel_pre_enable_lvds(struct intel_encoder *encoder,
235 236
				  const struct intel_crtc_state *pipe_config,
				  const struct drm_connector_state *conn_state)
237 238
{
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
239 240 241
	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;
242
	int pipe = crtc->pipe;
243 244
	u32 temp;

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

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

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

258
	if (HAS_PCH_CPT(dev_priv)) {
259 260
		temp &= ~LVDS_PIPE_SEL_MASK_CPT;
		temp |= LVDS_PIPE_SEL_CPT(pipe);
261
	} else {
262 263
		temp &= ~LVDS_PIPE_SEL_MASK;
		temp |= LVDS_PIPE_SEL(pipe);
264
	}
265

266
	/* set the corresponsding LVDS_BORDER bit */
267
	temp &= ~LVDS_BORDER_ENABLE;
268
	temp |= pipe_config->gmch_pfit.lvds_border_bits;
C
Chris Wilson 已提交
269 270 271

	/*
	 * Set the B0-B3 data pairs corresponding to whether we're going to
272 273 274 275 276 277 278
	 * 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);

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

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

	I915_WRITE(lvds_encoder->reg, temp);
}

C
Chris Wilson 已提交
312
/*
J
Jesse Barnes 已提交
313 314
 * Sets the power state for the panel.
 */
315
static void intel_enable_lvds(struct intel_encoder *encoder,
316 317
			      const struct intel_crtc_state *pipe_config,
			      const struct drm_connector_state *conn_state)
J
Jesse Barnes 已提交
318
{
319
	struct drm_device *dev = encoder->base.dev;
320
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
321
	struct drm_i915_private *dev_priv = to_i915(dev);
J
Jesse Barnes 已提交
322

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

325
	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) | PANEL_POWER_ON);
D
Daniel Vetter 已提交
326
	POSTING_READ(lvds_encoder->reg);
327 328

	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, PP_ON, 5000))
329
		DRM_ERROR("timed out waiting for panel to power on\n");
330

331
	intel_panel_enable_backlight(pipe_config, conn_state);
332 333
}

334
static void intel_disable_lvds(struct intel_encoder *encoder,
335 336
			       const struct intel_crtc_state *old_crtc_state,
			       const struct drm_connector_state *old_conn_state)
337
{
338
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
339
	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
340

341
	I915_WRITE(PP_CONTROL(0), I915_READ(PP_CONTROL(0)) & ~PANEL_POWER_ON);
342
	if (intel_wait_for_register(dev_priv, PP_STATUS(0), PP_ON, 0, 1000))
343
		DRM_ERROR("timed out waiting for panel to power off\n");
344

D
Daniel Vetter 已提交
345 346
	I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
	POSTING_READ(lvds_encoder->reg);
J
Jesse Barnes 已提交
347 348
}

349
static void gmch_disable_lvds(struct intel_encoder *encoder,
350 351
			      const struct intel_crtc_state *old_crtc_state,
			      const struct drm_connector_state *old_conn_state)
352

353
{
354
	intel_panel_disable_backlight(old_conn_state);
355

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

359
static void pch_disable_lvds(struct intel_encoder *encoder,
360 361
			     const struct intel_crtc_state *old_crtc_state,
			     const struct drm_connector_state *old_conn_state)
362
{
363
	intel_panel_disable_backlight(old_conn_state);
364 365
}

366
static void pch_post_disable_lvds(struct intel_encoder *encoder,
367 368
				  const struct intel_crtc_state *old_crtc_state,
				  const struct drm_connector_state *old_conn_state)
369
{
370
	intel_disable_lvds(encoder, old_crtc_state, old_conn_state);
371 372
}

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

381 382 383 384
	if (mode->hdisplay > fixed_mode->hdisplay)
		return MODE_PANEL;
	if (mode->vdisplay > fixed_mode->vdisplay)
		return MODE_PANEL;
M
Mika Kahola 已提交
385 386
	if (fixed_mode->clock > max_pixclk)
		return MODE_CLOCK_HIGH;
J
Jesse Barnes 已提交
387 388 389 390

	return MODE_OK;
}

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

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

410
	if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
411 412 413 414
		lvds_bpp = 8*3;
	else
		lvds_bpp = 6*3;

415
	if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
416 417 418 419
		DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
			      pipe_config->pipe_bpp, lvds_bpp);
		pipe_config->pipe_bpp = lvds_bpp;
	}
420

J
Jesse Barnes 已提交
421
	/*
422
	 * We have timings from the BIOS for the panel, put them in
J
Jesse Barnes 已提交
423 424 425 426
	 * 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.
	 */
427
	intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
428
			       adjusted_mode);
429

430
	if (HAS_PCH_SPLIT(dev_priv)) {
431 432
		pipe_config->has_pch_encoder = true;

433
		intel_pch_panel_fitting(intel_crtc, pipe_config,
434
					conn_state->scaling_mode);
435 436
	} else {
		intel_gmch_panel_fitting(intel_crtc, pipe_config,
437
					 conn_state->scaling_mode);
J
Jesse Barnes 已提交
438

439
	}
440

J
Jesse Barnes 已提交
441 442 443 444 445 446 447 448 449
	/*
	 * 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;
}

C
Chris Wilson 已提交
450
/*
J
Jesse Barnes 已提交
451 452
 * Detect the LVDS connection.
 *
453 454 455
 * 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 已提交
456
 */
457
static enum drm_connector_status
458
intel_lvds_detect(struct drm_connector *connector, bool force)
J
Jesse Barnes 已提交
459
{
460
	struct drm_i915_private *dev_priv = to_i915(connector->dev);
461
	enum drm_connector_status status;
462

463
	DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
464
		      connector->base.id, connector->name);
465

466
	status = intel_panel_detect(dev_priv);
467 468
	if (status != connector_status_unknown)
		return status;
469

470
	return connector_status_connected;
J
Jesse Barnes 已提交
471 472
}

C
Chris Wilson 已提交
473
/*
J
Jesse Barnes 已提交
474 475 476 477
 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
 */
static int intel_lvds_get_modes(struct drm_connector *connector)
{
478
	struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
J
Jesse Barnes 已提交
479
	struct drm_device *dev = connector->dev;
480
	struct drm_display_mode *mode;
J
Jesse Barnes 已提交
481

482
	/* use cached edid if we have one */
483
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
484
		return drm_add_edid_modes(connector, lvds_connector->base.edid);
J
Jesse Barnes 已提交
485

486
	mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
C
Chris Wilson 已提交
487
	if (mode == NULL)
488
		return 0;
J
Jesse Barnes 已提交
489

490 491
	drm_mode_probed_add(connector, mode);
	return 1;
J
Jesse Barnes 已提交
492 493
}

494 495
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
{
496
	DRM_INFO("Skipping forced modeset for %s\n", id->ident);
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
	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 */
};

514
/*
515 516 517
 * 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
518
 *  - we use it as a "only once" bit (ie we ignore
519 520 521 522
 *    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").
523
 */
524 525 526
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
			    void *unused)
{
527 528 529 530
	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;
531
	struct drm_i915_private *dev_priv = to_i915(dev);
532

533 534 535
	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
		return NOTIFY_OK;

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

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

554 555
	if (dev_priv->modeset_restore == MODESET_DONE)
		goto exit;
556

557 558 559 560 561 562 563 564
	/*
	 * 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.
	 */
565
	if (!HAS_PCH_SPLIT(dev_priv))
566
		intel_display_resume(dev);
567

568 569 570 571
	dev_priv->modeset_restore = MODESET_DONE;

exit:
	mutex_unlock(&dev_priv->modeset_restore_lock);
572 573 574
	return NOTIFY_OK;
}

J
Jesse Barnes 已提交
575 576 577 578 579 580 581 582 583
/**
 * 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)
{
584 585
	struct intel_lvds_connector *lvds_connector =
		to_lvds_connector(connector);
J
Jesse Barnes 已提交
586

587 588
	if (lvds_connector->lid_notifier.notifier_call)
		acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
J
Jesse Barnes 已提交
589

590 591 592
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
		kfree(lvds_connector->base.edid);

593
	intel_panel_fini(&lvds_connector->base.panel);
594

J
Jesse Barnes 已提交
595 596 597 598 599 600 601
	drm_connector_cleanup(connector);
	kfree(connector);
}

static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
	.get_modes = intel_lvds_get_modes,
	.mode_valid = intel_lvds_mode_valid,
602
	.atomic_check = intel_digital_connector_atomic_check,
J
Jesse Barnes 已提交
603 604 605 606 607
};

static const struct drm_connector_funcs intel_lvds_connector_funcs = {
	.detect = intel_lvds_detect,
	.fill_modes = drm_helper_probe_single_connector_modes,
608 609
	.atomic_get_property = intel_digital_connector_atomic_get_property,
	.atomic_set_property = intel_digital_connector_atomic_set_property,
610
	.late_register = intel_connector_register,
611
	.early_unregister = intel_connector_unregister,
J
Jesse Barnes 已提交
612
	.destroy = intel_lvds_destroy,
613
	.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
614
	.atomic_duplicate_state = intel_digital_connector_duplicate_state,
J
Jesse Barnes 已提交
615 616 617
};

static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
C
Chris Wilson 已提交
618
	.destroy = intel_encoder_destroy,
J
Jesse Barnes 已提交
619 620
};

621
static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
622
{
623
	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
624 625
	return 1;
}
J
Jesse Barnes 已提交
626

627
/* These systems claim to have LVDS, but really don't */
628
static const struct dmi_system_id intel_no_lvds[] = {
629 630 631 632
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Apple Mac Mini (Core series)",
		.matches = {
633
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
634 635 636 637 638 639 640
			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Apple Mac Mini (Core 2 series)",
		.matches = {
641
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660
			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"),
		},
	},
661 662
	{
		.callback = intel_no_lvds_dmi_callback,
663 664 665 666 667 668 669 670
		.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,
671 672 673 674 675 676
		.ident = "AOpen Mini PC",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
			DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
		},
	},
677 678 679 680 681 682 683 684
	{
		.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"),
		},
	},
685 686 687 688 689 690 691 692
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "AOpen i915GMm-HFS",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
		},
	},
693 694 695 696 697 698 699 700
	{
		.callback = intel_no_lvds_dmi_callback,
                .ident = "AOpen i45GMx-I",
                .matches = {
                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
                },
        },
701 702 703 704 705 706 707
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Aopen i945GTt-VFA",
		.matches = {
			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
		},
	},
708 709 710 711 712 713 714 715
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Clientron U800",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
			DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
		},
	},
716
	{
717 718 719 720 721 722 723 724
                .callback = intel_no_lvds_dmi_callback,
                .ident = "Clientron E830",
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
                },
        },
        {
725 726 727 728 729 730 731
		.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"),
		},
	},
732 733 734 735 736 737 738 739
	{
		.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"),
		},
	},
740 741
	{
		.callback = intel_no_lvds_dmi_callback,
742
		.ident = "Hewlett-Packard HP t5740",
743 744
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
745
			DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
746 747
		},
	},
748 749 750 751 752
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Hewlett-Packard t5745",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
753
			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
754 755 756 757 758 759 760
		},
	},
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Hewlett-Packard st5747",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
761
			DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
762 763
		},
	},
764 765 766 767 768 769 770 771
	{
		.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"),
		},
	},
772 773 774 775 776 777 778 779
	{
		.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"),
		},
	},
780 781 782 783 784 785 786 787
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Supermicro X7SPA-H",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
		},
	},
788 789 790 791 792 793 794 795
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Fujitsu Esprimo Q900",
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
			DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
		},
	},
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
	{
		.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"),
		},
	},
812 813 814 815 816 817 818 819
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D510MO",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),
		},
	},
820 821 822 823 824 825 826 827
	{
		.callback = intel_no_lvds_dmi_callback,
		.ident = "Intel D525MW",
		.matches = {
			DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
			DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
		},
	},
828 829 830

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

832 833 834 835 836 837 838 839 840
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,
841 842 843 844 845 846 847 848 849
		.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)",
850 851 852 853 854
		.matches = {
			DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
			DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
		},
	},
855 856 857 858 859 860 861 862
	{
		.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"),
		},
	},
863 864 865
	{ }	/* terminating entry */
};

866
struct intel_encoder *intel_get_lvds_encoder(struct drm_device *dev)
867
{
868
	struct intel_encoder *intel_encoder;
869

870 871 872
	for_each_intel_encoder(dev, intel_encoder)
		if (intel_encoder->type == INTEL_OUTPUT_LVDS)
			return intel_encoder;
873

874 875 876 877 878 879
	return NULL;
}

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

881
	return encoder && to_lvds_encoder(&encoder->base)->is_dual_link;
882 883
}

D
Daniel Vetter 已提交
884
static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
885
{
D
Daniel Vetter 已提交
886
	struct drm_device *dev = lvds_encoder->base.base.dev;
887
	unsigned int val;
888
	struct drm_i915_private *dev_priv = to_i915(dev);
889 890

	/* use the module option value if specified */
891 892
	if (i915_modparams.lvds_channel_mode > 0)
		return i915_modparams.lvds_channel_mode == 2;
893

894 895 896 897 898
	/* single channel LVDS is limited to 112 MHz */
	if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock
	    > 112999)
		return true;

899 900 901
	if (dmi_check_system(intel_dual_link_lvds))
		return true;

C
Chris Wilson 已提交
902 903
	/*
	 * BIOS should set the proper LVDS register value at boot, but
904 905 906 907
	 * 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 已提交
908
	val = I915_READ(lvds_encoder->reg);
909 910 911 912 913
	if (HAS_PCH_CPT(dev_priv))
		val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK_CPT);
	else
		val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK);
	if (val == 0)
914
		val = dev_priv->vbt.bios_lvds_val;
915

916 917 918
	return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
}

919
static bool intel_lvds_supported(struct drm_i915_private *dev_priv)
920
{
C
Chris Wilson 已提交
921 922 923 924
	/*
	 * With the introduction of the PCH we gained a dedicated
	 * LVDS presence pin, use it.
	 */
925
	if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv))
926 927
		return true;

C
Chris Wilson 已提交
928 929 930 931
	/*
	 * Otherwise LVDS was only attached to mobile products,
	 * except for the inglorious 830gm
	 */
932 933
	if (INTEL_GEN(dev_priv) <= 4 &&
	    IS_MOBILE(dev_priv) && !IS_I830(dev_priv))
934 935 936
		return true;

	return false;
937 938
}

J
Jesse Barnes 已提交
939 940
/**
 * intel_lvds_init - setup LVDS connectors on this device
C
Chris Wilson 已提交
941
 * @dev_priv: i915 device
J
Jesse Barnes 已提交
942 943 944 945
 *
 * Create the connector, register the LVDS DDC bus, and try to figure out what
 * modes we can display on the LVDS panel (if present).
 */
946
void intel_lvds_init(struct drm_i915_private *dev_priv)
J
Jesse Barnes 已提交
947
{
948
	struct drm_device *dev = &dev_priv->drm;
949
	struct intel_lvds_encoder *lvds_encoder;
950
	struct intel_encoder *intel_encoder;
951
	struct intel_lvds_connector *lvds_connector;
952
	struct intel_connector *intel_connector;
J
Jesse Barnes 已提交
953 954 955
	struct drm_connector *connector;
	struct drm_encoder *encoder;
	struct drm_display_mode *scan; /* *modes, *bios_mode; */
956
	struct drm_display_mode *fixed_mode = NULL;
957
	struct drm_display_mode *downclock_mode = NULL;
958
	struct edid *edid;
959
	i915_reg_t lvds_reg;
J
Jesse Barnes 已提交
960
	u32 lvds;
961
	u8 pin;
962
	u32 allowed_scalers;
J
Jesse Barnes 已提交
963

964
	if (!intel_lvds_supported(dev_priv))
965
		return;
966

967 968
	/* Skip init on machines we know falsely report LVDS */
	if (dmi_check_system(intel_no_lvds))
969
		return;
970

971
	if (HAS_PCH_SPLIT(dev_priv))
972 973 974 975 976 977
		lvds_reg = PCH_LVDS;
	else
		lvds_reg = LVDS;

	lvds = I915_READ(lvds_reg);

978
	if (HAS_PCH_SPLIT(dev_priv)) {
979
		if ((lvds & LVDS_DETECTED) == 0)
980
			return;
981
		if (dev_priv->vbt.edp.support) {
982
			DRM_DEBUG_KMS("disable LVDS for eDP support\n");
983
			return;
984
		}
985 986
	}

987
	pin = GMBUS_PIN_PANEL;
988
	if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
989
		if ((lvds & LVDS_PORT_EN) == 0) {
990 991 992 993 994 995
			DRM_DEBUG_KMS("LVDS is not present in VBT\n");
			return;
		}
		DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
	}

996
	lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
997
	if (!lvds_encoder)
998
		return;
J
Jesse Barnes 已提交
999

1000
	lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
1001
	if (!lvds_connector) {
1002
		kfree(lvds_encoder);
1003
		return;
1004 1005
	}

1006 1007 1008 1009 1010 1011
	if (intel_connector_init(&lvds_connector->base) < 0) {
		kfree(lvds_connector);
		kfree(lvds_encoder);
		return;
	}

1012 1013
	lvds_encoder->attached_connector = lvds_connector;

1014
	intel_encoder = &lvds_encoder->base;
1015
	encoder = &intel_encoder->base;
1016
	intel_connector = &lvds_connector->base;
C
Chris Wilson 已提交
1017
	connector = &intel_connector->base;
1018
	drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
J
Jesse Barnes 已提交
1019 1020
			   DRM_MODE_CONNECTOR_LVDS);

1021
	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
1022
			 DRM_MODE_ENCODER_LVDS, "LVDS");
J
Jesse Barnes 已提交
1023

1024
	intel_encoder->enable = intel_enable_lvds;
1025
	intel_encoder->pre_enable = intel_pre_enable_lvds;
1026
	intel_encoder->compute_config = intel_lvds_compute_config;
1027 1028 1029 1030 1031 1032
	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;
	}
1033
	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
1034
	intel_encoder->get_config = intel_lvds_get_config;
1035
	intel_connector->get_hw_state = intel_connector_get_hw_state;
1036

1037
	intel_connector_attach_encoder(intel_connector, intel_encoder);
J
Jesse Barnes 已提交
1038

1039
	intel_encoder->type = INTEL_OUTPUT_LVDS;
1040
	intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
1041
	intel_encoder->port = PORT_NONE;
1042
	intel_encoder->cloneable = 0;
1043
	if (HAS_PCH_SPLIT(dev_priv))
J
Jesse Barnes 已提交
1044
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
1045
	else if (IS_GEN4(dev_priv))
1046
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
J
Jesse Barnes 已提交
1047 1048 1049
	else
		intel_encoder->crtc_mask = (1 << 1);

J
Jesse Barnes 已提交
1050 1051 1052 1053 1054
	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
	connector->interlace_allowed = false;
	connector->doublescan_allowed = false;

1055
	lvds_encoder->reg = lvds_reg;
D
Daniel Vetter 已提交
1056

1057
	/* create the scaling mode property */
1058 1059 1060 1061
	allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT);
	allowed_scalers |= BIT(DRM_MODE_SCALE_FULLSCREEN);
	allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);
	drm_connector_attach_scaling_mode_property(connector, allowed_scalers);
1062
	connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT;
1063 1064 1065 1066

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

J
Jesse Barnes 已提交
1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080
	/*
	 * 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.
	 */
1081
	mutex_lock(&dev->mode_config.mutex);
1082 1083 1084 1085 1086 1087
	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));
1088 1089
	if (edid) {
		if (drm_add_edid_modes(connector, edid)) {
1090
			drm_mode_connector_update_edid_property(connector,
1091
								edid);
1092
		} else {
1093 1094
			kfree(edid);
			edid = ERR_PTR(-EINVAL);
1095
		}
1096 1097
	} else {
		edid = ERR_PTR(-ENOENT);
1098
	}
1099 1100
	lvds_connector->base.edid = edid;

J
Jesse Barnes 已提交
1101 1102
	list_for_each_entry(scan, &connector->probed_modes, head) {
		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
1103 1104 1105
			DRM_DEBUG_KMS("using preferred mode from EDID: ");
			drm_mode_debug_printmodeline(scan);

1106
			fixed_mode = drm_mode_duplicate(dev, scan);
1107
			if (fixed_mode)
1108
				goto out;
J
Jesse Barnes 已提交
1109 1110 1111 1112
		}
	}

	/* Failed to get EDID, what about VBT? */
1113
	if (dev_priv->vbt.lfp_lvds_vbt_mode) {
1114
		DRM_DEBUG_KMS("using mode from VBT: ");
1115
		drm_mode_debug_printmodeline(dev_priv->vbt.lfp_lvds_vbt_mode);
1116

1117
		fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
1118 1119
		if (fixed_mode) {
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
1120 1121
			connector->display_info.width_mm = fixed_mode->width_mm;
			connector->display_info.height_mm = fixed_mode->height_mm;
1122 1123
			goto out;
		}
J
Jesse Barnes 已提交
1124 1125 1126 1127 1128 1129 1130
	}

	/*
	 * 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.
	 */
1131 1132 1133 1134 1135
	fixed_mode = intel_encoder_current_mode(intel_encoder);
	if (fixed_mode) {
		DRM_DEBUG_KMS("using current (BIOS) mode: ");
		drm_mode_debug_printmodeline(fixed_mode);
		fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
J
Jesse Barnes 已提交
1136 1137 1138
	}

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

out:
1143 1144
	mutex_unlock(&dev->mode_config.mutex);

1145 1146
	intel_panel_init(&intel_connector->panel, fixed_mode, NULL,
			 downclock_mode);
1147
	intel_panel_setup_backlight(connector, INVALID_PIPE);
1148

D
Daniel Vetter 已提交
1149
	lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
1150 1151 1152
	DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
		      lvds_encoder->is_dual_link ? "dual" : "single");

1153
	lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
1154

1155 1156
	lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
	if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
1157
		DRM_DEBUG_KMS("lid notifier registration failed\n");
1158
		lvds_connector->lid_notifier.notifier_call = NULL;
1159
	}
1160

1161
	return;
J
Jesse Barnes 已提交
1162 1163

failed:
1164 1165
	mutex_unlock(&dev->mode_config.mutex);

1166
	DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
J
Jesse Barnes 已提交
1167
	drm_connector_cleanup(connector);
1168
	drm_encoder_cleanup(encoder);
1169
	kfree(lvds_encoder);
1170
	kfree(lvds_connector);
1171
	return;
J
Jesse Barnes 已提交
1172
}