Subversion Repositories Kolibri OS

Rev

Rev 3031 | Rev 3480 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2330 Serge 1
/*
2
 * Copyright © 2006-2007 Intel Corporation
3
 * Copyright (c) 2006 Dave Airlie 
4
 *
5
 * Permission is hereby granted, free of charge, to any person obtaining a
6
 * copy of this software and associated documentation files (the "Software"),
7
 * to deal in the Software without restriction, including without limitation
8
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9
 * and/or sell copies of the Software, and to permit persons to whom the
10
 * Software is furnished to do so, subject to the following conditions:
11
 *
12
 * The above copyright notice and this permission notice (including the next
13
 * paragraph) shall be included in all copies or substantial portions of the
14
 * Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22
 * DEALINGS IN THE SOFTWARE.
23
 *
24
 * Authors:
25
 *	Eric Anholt 
26
 *      Dave Airlie 
27
 *      Jesse Barnes 
28
 */
29
 
30
//#include 
31
//#include 
32
#include 
33
#include 
3031 serge 34
#include 
35
#include 
36
#include 
2330 Serge 37
#include "intel_drv.h"
3031 serge 38
#include 
2330 Serge 39
#include "i915_drv.h"
40
//#include 
41
 
42
/* Private structure for the integrated LVDS support */
3243 Serge 43
struct intel_lvds_connector {
44
	struct intel_connector base;
45
 
46
//	struct notifier_block lid_notifier;
47
};
48
 
49
struct intel_lvds_encoder {
2330 Serge 50
	struct intel_encoder base;
51
 
52
	u32 pfit_control;
53
	u32 pfit_pgm_ratios;
54
	bool pfit_dirty;
55
 
3243 Serge 56
	struct intel_lvds_connector *attached_connector;
2330 Serge 57
};
58
 
3243 Serge 59
static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
2330 Serge 60
{
3243 Serge 61
	return container_of(encoder, struct intel_lvds_encoder, base.base);
2330 Serge 62
}
63
 
3243 Serge 64
static struct intel_lvds_connector *to_lvds_connector(struct drm_connector *connector)
2330 Serge 65
{
3243 Serge 66
	return container_of(connector, struct intel_lvds_connector, base.base);
2330 Serge 67
}
68
 
3031 serge 69
static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
70
				    enum pipe *pipe)
71
{
72
	struct drm_device *dev = encoder->base.dev;
73
	struct drm_i915_private *dev_priv = dev->dev_private;
74
	u32 lvds_reg, tmp;
75
 
76
	if (HAS_PCH_SPLIT(dev)) {
77
		lvds_reg = PCH_LVDS;
78
	} else {
79
		lvds_reg = LVDS;
80
	}
81
 
82
	tmp = I915_READ(lvds_reg);
83
 
84
	if (!(tmp & LVDS_PORT_EN))
85
		return false;
86
 
87
	if (HAS_PCH_CPT(dev))
88
		*pipe = PORT_TO_PIPE_CPT(tmp);
89
	else
90
		*pipe = PORT_TO_PIPE(tmp);
91
 
92
	return true;
93
}
94
 
2330 Serge 95
/**
96
 * Sets the power state for the panel.
97
 */
3031 serge 98
static void intel_enable_lvds(struct intel_encoder *encoder)
2330 Serge 99
{
3031 serge 100
	struct drm_device *dev = encoder->base.dev;
3243 Serge 101
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
3031 serge 102
	struct intel_crtc *intel_crtc = to_intel_crtc(encoder->base.crtc);
2330 Serge 103
	struct drm_i915_private *dev_priv = dev->dev_private;
104
	u32 ctl_reg, lvds_reg, stat_reg;
105
 
106
	if (HAS_PCH_SPLIT(dev)) {
107
		ctl_reg = PCH_PP_CONTROL;
108
		lvds_reg = PCH_LVDS;
109
		stat_reg = PCH_PP_STATUS;
110
	} else {
111
		ctl_reg = PP_CONTROL;
112
		lvds_reg = LVDS;
113
		stat_reg = PP_STATUS;
114
	}
115
 
116
	I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN);
117
 
3243 Serge 118
	if (lvds_encoder->pfit_dirty) {
2330 Serge 119
		/*
120
		 * Enable automatic panel scaling so that non-native modes
121
		 * fill the screen.  The panel fitter should only be
122
		 * adjusted whilst the pipe is disabled, according to
123
		 * register description and PRM.
124
		 */
125
		DRM_DEBUG_KMS("applying panel-fitter: %x, %x\n",
3243 Serge 126
			      lvds_encoder->pfit_control,
127
			      lvds_encoder->pfit_pgm_ratios);
2330 Serge 128
 
3243 Serge 129
		I915_WRITE(PFIT_PGM_RATIOS, lvds_encoder->pfit_pgm_ratios);
130
		I915_WRITE(PFIT_CONTROL, lvds_encoder->pfit_control);
131
		lvds_encoder->pfit_dirty = false;
2330 Serge 132
	}
133
 
134
	I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
135
	POSTING_READ(lvds_reg);
136
	if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
137
		DRM_ERROR("timed out waiting for panel to power on\n");
138
 
3031 serge 139
	intel_panel_enable_backlight(dev, intel_crtc->pipe);
2330 Serge 140
}
141
 
3031 serge 142
static void intel_disable_lvds(struct intel_encoder *encoder)
2330 Serge 143
{
3031 serge 144
	struct drm_device *dev = encoder->base.dev;
3243 Serge 145
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
2330 Serge 146
	struct drm_i915_private *dev_priv = dev->dev_private;
147
	u32 ctl_reg, lvds_reg, stat_reg;
148
 
149
	if (HAS_PCH_SPLIT(dev)) {
150
		ctl_reg = PCH_PP_CONTROL;
151
		lvds_reg = PCH_LVDS;
152
		stat_reg = PCH_PP_STATUS;
153
	} else {
154
		ctl_reg = PP_CONTROL;
155
		lvds_reg = LVDS;
156
		stat_reg = PP_STATUS;
157
	}
158
 
159
	intel_panel_disable_backlight(dev);
160
 
161
	I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
162
	if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
163
		DRM_ERROR("timed out waiting for panel to power off\n");
164
 
3243 Serge 165
	if (lvds_encoder->pfit_control) {
2330 Serge 166
		I915_WRITE(PFIT_CONTROL, 0);
3243 Serge 167
		lvds_encoder->pfit_dirty = true;
2330 Serge 168
	}
169
 
170
	I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN);
171
	POSTING_READ(lvds_reg);
172
}
173
 
174
static int intel_lvds_mode_valid(struct drm_connector *connector,
175
				 struct drm_display_mode *mode)
176
{
3243 Serge 177
	struct intel_connector *intel_connector = to_intel_connector(connector);
178
	struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
2330 Serge 179
 
180
	if (mode->hdisplay > fixed_mode->hdisplay)
181
		return MODE_PANEL;
182
	if (mode->vdisplay > fixed_mode->vdisplay)
183
		return MODE_PANEL;
184
 
185
	return MODE_OK;
186
}
187
 
188
static void
189
centre_horizontally(struct drm_display_mode *mode,
190
		    int width)
191
{
192
	u32 border, sync_pos, blank_width, sync_width;
193
 
194
	/* keep the hsync and hblank widths constant */
195
	sync_width = mode->crtc_hsync_end - mode->crtc_hsync_start;
196
	blank_width = mode->crtc_hblank_end - mode->crtc_hblank_start;
197
	sync_pos = (blank_width - sync_width + 1) / 2;
198
 
199
	border = (mode->hdisplay - width + 1) / 2;
200
	border += border & 1; /* make the border even */
201
 
202
	mode->crtc_hdisplay = width;
203
	mode->crtc_hblank_start = width + border;
204
	mode->crtc_hblank_end = mode->crtc_hblank_start + blank_width;
205
 
206
	mode->crtc_hsync_start = mode->crtc_hblank_start + sync_pos;
207
	mode->crtc_hsync_end = mode->crtc_hsync_start + sync_width;
3031 serge 208
 
209
	mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
2330 Serge 210
}
211
 
212
static void
213
centre_vertically(struct drm_display_mode *mode,
214
		  int height)
215
{
216
	u32 border, sync_pos, blank_width, sync_width;
217
 
218
	/* keep the vsync and vblank widths constant */
219
	sync_width = mode->crtc_vsync_end - mode->crtc_vsync_start;
220
	blank_width = mode->crtc_vblank_end - mode->crtc_vblank_start;
221
	sync_pos = (blank_width - sync_width + 1) / 2;
222
 
223
	border = (mode->vdisplay - height + 1) / 2;
224
 
225
	mode->crtc_vdisplay = height;
226
	mode->crtc_vblank_start = height + border;
227
	mode->crtc_vblank_end = mode->crtc_vblank_start + blank_width;
228
 
229
	mode->crtc_vsync_start = mode->crtc_vblank_start + sync_pos;
230
	mode->crtc_vsync_end = mode->crtc_vsync_start + sync_width;
3031 serge 231
 
232
	mode->private_flags |= INTEL_MODE_CRTC_TIMINGS_SET;
2330 Serge 233
}
234
 
235
static inline u32 panel_fitter_scaling(u32 source, u32 target)
236
{
237
	/*
238
	 * Floating point operation is not supported. So the FACTOR
239
	 * is defined, which can avoid the floating point computation
240
	 * when calculating the panel ratio.
241
	 */
242
#define ACCURACY 12
243
#define FACTOR (1 << ACCURACY)
244
	u32 ratio = source * FACTOR / target;
245
	return (FACTOR * ratio + FACTOR/2) / FACTOR;
246
}
247
 
248
static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
3031 serge 249
				  const struct drm_display_mode *mode,
2330 Serge 250
				  struct drm_display_mode *adjusted_mode)
251
{
252
	struct drm_device *dev = encoder->dev;
253
	struct drm_i915_private *dev_priv = dev->dev_private;
3243 Serge 254
	struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);
255
	struct intel_connector *intel_connector =
256
		&lvds_encoder->attached_connector->base;
257
	struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
2330 Serge 258
	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
259
	int pipe;
260
 
261
	/* Should never happen!! */
262
	if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
263
		DRM_ERROR("Can't support LVDS on pipe A\n");
264
		return false;
265
	}
266
 
3243 Serge 267
	if (intel_encoder_check_is_cloned(&lvds_encoder->base))
2330 Serge 268
			return false;
269
 
270
	/*
271
	 * We have timings from the BIOS for the panel, put them in
272
	 * to the adjusted mode.  The CRTC will be set up for this mode,
273
	 * with the panel scaling set up to source from the H/VDisplay
274
	 * of the original mode.
275
	 */
3243 Serge 276
	intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
277
			       adjusted_mode);
2330 Serge 278
 
279
	if (HAS_PCH_SPLIT(dev)) {
3243 Serge 280
		intel_pch_panel_fitting(dev,
281
					intel_connector->panel.fitting_mode,
2330 Serge 282
					mode, adjusted_mode);
283
		return true;
284
	}
285
 
286
	/* Native modes don't need fitting */
287
	if (adjusted_mode->hdisplay == mode->hdisplay &&
288
	    adjusted_mode->vdisplay == mode->vdisplay)
289
		goto out;
290
 
291
	/* 965+ wants fuzzy fitting */
292
	if (INTEL_INFO(dev)->gen >= 4)
293
		pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) |
294
				 PFIT_FILTER_FUZZY);
295
 
296
	/*
297
	 * Enable automatic panel scaling for non-native modes so that they fill
298
	 * the screen.  Should be enabled before the pipe is enabled, according
299
	 * to register description and PRM.
300
	 * Change the value here to see the borders for debugging
301
	 */
302
	for_each_pipe(pipe)
303
		I915_WRITE(BCLRPAT(pipe), 0);
304
 
3031 serge 305
	drm_mode_set_crtcinfo(adjusted_mode, 0);
306
 
3243 Serge 307
	switch (intel_connector->panel.fitting_mode) {
2330 Serge 308
	case DRM_MODE_SCALE_CENTER:
309
		/*
310
		 * For centered modes, we have to calculate border widths &
311
		 * heights and modify the values programmed into the CRTC.
312
		 */
313
		centre_horizontally(adjusted_mode, mode->hdisplay);
314
		centre_vertically(adjusted_mode, mode->vdisplay);
315
		border = LVDS_BORDER_ENABLE;
316
		break;
317
 
318
	case DRM_MODE_SCALE_ASPECT:
319
		/* Scale but preserve the aspect ratio */
320
		if (INTEL_INFO(dev)->gen >= 4) {
321
			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
322
			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
323
 
324
			/* 965+ is easy, it does everything in hw */
325
			if (scaled_width > scaled_height)
326
				pfit_control |= PFIT_ENABLE | PFIT_SCALING_PILLAR;
327
			else if (scaled_width < scaled_height)
328
				pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER;
329
			else if (adjusted_mode->hdisplay != mode->hdisplay)
330
				pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO;
331
		} else {
332
			u32 scaled_width = adjusted_mode->hdisplay * mode->vdisplay;
333
			u32 scaled_height = mode->hdisplay * adjusted_mode->vdisplay;
334
			/*
335
			 * For earlier chips we have to calculate the scaling
336
			 * ratio by hand and program it into the
337
			 * PFIT_PGM_RATIO register
338
			 */
339
			if (scaled_width > scaled_height) { /* pillar */
340
				centre_horizontally(adjusted_mode, scaled_height / mode->vdisplay);
341
 
342
				border = LVDS_BORDER_ENABLE;
343
				if (mode->vdisplay != adjusted_mode->vdisplay) {
344
					u32 bits = panel_fitter_scaling(mode->vdisplay, adjusted_mode->vdisplay);
345
					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
346
							    bits << PFIT_VERT_SCALE_SHIFT);
347
					pfit_control |= (PFIT_ENABLE |
348
							 VERT_INTERP_BILINEAR |
349
							 HORIZ_INTERP_BILINEAR);
350
				}
351
			} else if (scaled_width < scaled_height) { /* letter */
352
				centre_vertically(adjusted_mode, scaled_width / mode->hdisplay);
353
 
354
				border = LVDS_BORDER_ENABLE;
355
				if (mode->hdisplay != adjusted_mode->hdisplay) {
356
					u32 bits = panel_fitter_scaling(mode->hdisplay, adjusted_mode->hdisplay);
357
					pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT |
358
							    bits << PFIT_VERT_SCALE_SHIFT);
359
					pfit_control |= (PFIT_ENABLE |
360
							 VERT_INTERP_BILINEAR |
361
							 HORIZ_INTERP_BILINEAR);
362
				}
363
			} else
364
				/* Aspects match, Let hw scale both directions */
365
				pfit_control |= (PFIT_ENABLE |
366
						 VERT_AUTO_SCALE | HORIZ_AUTO_SCALE |
367
						 VERT_INTERP_BILINEAR |
368
						 HORIZ_INTERP_BILINEAR);
369
		}
370
		break;
371
 
372
	case DRM_MODE_SCALE_FULLSCREEN:
373
		/*
374
		 * Full scaling, even if it changes the aspect ratio.
375
		 * Fortunately this is all done for us in hw.
376
		 */
377
		if (mode->vdisplay != adjusted_mode->vdisplay ||
378
		    mode->hdisplay != adjusted_mode->hdisplay) {
379
			pfit_control |= PFIT_ENABLE;
380
			if (INTEL_INFO(dev)->gen >= 4)
381
				pfit_control |= PFIT_SCALING_AUTO;
382
			else
383
				pfit_control |= (VERT_AUTO_SCALE |
384
						 VERT_INTERP_BILINEAR |
385
						 HORIZ_AUTO_SCALE |
386
						 HORIZ_INTERP_BILINEAR);
387
		}
388
		break;
389
 
390
	default:
391
		break;
392
	}
393
 
394
out:
395
	/* If not enabling scaling, be consistent and always use 0. */
396
	if ((pfit_control & PFIT_ENABLE) == 0) {
397
		pfit_control = 0;
398
		pfit_pgm_ratios = 0;
399
	}
400
 
401
	/* Make sure pre-965 set dither correctly */
402
	if (INTEL_INFO(dev)->gen < 4 && dev_priv->lvds_dither)
403
		pfit_control |= PANEL_8TO6_DITHER_ENABLE;
404
 
3243 Serge 405
	if (pfit_control != lvds_encoder->pfit_control ||
406
	    pfit_pgm_ratios != lvds_encoder->pfit_pgm_ratios) {
407
		lvds_encoder->pfit_control = pfit_control;
408
		lvds_encoder->pfit_pgm_ratios = pfit_pgm_ratios;
409
		lvds_encoder->pfit_dirty = true;
2330 Serge 410
	}
411
	dev_priv->lvds_border_bits = border;
412
 
413
	/*
414
	 * XXX: It would be nice to support lower refresh rates on the
415
	 * panels to reduce power consumption, and perhaps match the
416
	 * user's requested refresh rate.
417
	 */
418
 
419
	return true;
420
}
421
 
422
static void intel_lvds_mode_set(struct drm_encoder *encoder,
423
				struct drm_display_mode *mode,
424
				struct drm_display_mode *adjusted_mode)
425
{
426
	/*
427
	 * The LVDS pin pair will already have been turned on in the
428
	 * intel_crtc_mode_set since it has a large impact on the DPLL
429
	 * settings.
430
	 */
431
}
432
 
433
/**
434
 * Detect the LVDS connection.
435
 *
436
 * Since LVDS doesn't have hotlug, we use the lid as a proxy.  Open means
437
 * connected and closed means disconnected.  We also send hotplug events as
438
 * needed, using lid status notification from the input layer.
439
 */
440
static enum drm_connector_status
441
intel_lvds_detect(struct drm_connector *connector, bool force)
442
{
443
	struct drm_device *dev = connector->dev;
444
	enum drm_connector_status status;
445
 
446
	status = intel_panel_detect(dev);
447
	if (status != connector_status_unknown)
448
		return status;
449
 
450
	return connector_status_connected;
451
}
452
 
453
/**
454
 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
455
 */
456
static int intel_lvds_get_modes(struct drm_connector *connector)
457
{
3243 Serge 458
	struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
2330 Serge 459
	struct drm_device *dev = connector->dev;
460
	struct drm_display_mode *mode;
461
 
3243 Serge 462
	/* use cached edid if we have one */
463
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
464
		return drm_add_edid_modes(connector, lvds_connector->base.edid);
2330 Serge 465
 
3243 Serge 466
	mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
2330 Serge 467
	if (mode == NULL)
468
		return 0;
469
 
470
	drm_mode_probed_add(connector, mode);
471
	return 1;
472
}
473
 
474
static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
475
{
3031 serge 476
	DRM_INFO("Skipping forced modeset for %s\n", id->ident);
2330 Serge 477
	return 1;
478
}
479
 
480
/* The GPU hangs up on these systems if modeset is performed on LID open */
481
static const struct dmi_system_id intel_no_modeset_on_lid[] = {
482
	{
483
		.callback = intel_no_modeset_on_lid_dmi_callback,
484
		.ident = "Toshiba Tecra A11",
485
		.matches = {
486
			DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
487
			DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
488
		},
489
	},
490
 
491
	{ }	/* terminating entry */
492
};
493
 
494
#if 0
495
/*
496
 * Lid events. Note the use of 'modeset_on_lid':
497
 *  - we set it on lid close, and reset it on open
498
 *  - we use it as a "only once" bit (ie we ignore
499
 *    duplicate events where it was already properly
500
 *    set/reset)
501
 *  - the suspend/resume paths will also set it to
502
 *    zero, since they restore the mode ("lid open").
503
 */
504
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
505
			    void *unused)
506
{
3243 Serge 507
	struct intel_lvds_connector *lvds_connector =
508
		container_of(nb, struct intel_lvds_connector, lid_notifier);
509
	struct drm_connector *connector = &lvds_connector->base.base;
510
	struct drm_device *dev = connector->dev;
511
	struct drm_i915_private *dev_priv = dev->dev_private;
2330 Serge 512
 
513
	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
514
		return NOTIFY_OK;
515
 
516
	/*
517
	 * check and update the status of LVDS connector after receiving
518
	 * the LID nofication event.
519
	 */
3243 Serge 520
	connector->status = connector->funcs->detect(connector, false);
2330 Serge 521
 
522
	/* Don't force modeset on machines where it causes a GPU lockup */
523
	if (dmi_check_system(intel_no_modeset_on_lid))
524
		return NOTIFY_OK;
525
	if (!acpi_lid_open()) {
526
		dev_priv->modeset_on_lid = 1;
527
		return NOTIFY_OK;
528
	}
529
 
530
	if (!dev_priv->modeset_on_lid)
531
		return NOTIFY_OK;
532
 
533
	dev_priv->modeset_on_lid = 0;
534
 
535
	mutex_lock(&dev->mode_config.mutex);
3243 Serge 536
	intel_modeset_setup_hw_state(dev, true);
2330 Serge 537
	mutex_unlock(&dev->mode_config.mutex);
538
 
539
	return NOTIFY_OK;
540
}
541
#endif
542
 
543
/**
544
 * intel_lvds_destroy - unregister and free LVDS structures
545
 * @connector: connector to free
546
 *
547
 * Unregister the DDC bus for this connector then free the driver private
548
 * structure.
549
 */
550
static void intel_lvds_destroy(struct drm_connector *connector)
551
{
3243 Serge 552
	struct intel_lvds_connector *lvds_connector =
553
		to_lvds_connector(connector);
2330 Serge 554
 
555
 
3243 Serge 556
	if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
557
		kfree(lvds_connector->base.edid);
558
 
559
	intel_panel_destroy_backlight(connector->dev);
560
	intel_panel_fini(&lvds_connector->base.panel);
561
 
2330 Serge 562
	drm_sysfs_connector_remove(connector);
563
	drm_connector_cleanup(connector);
564
	kfree(connector);
565
}
566
 
567
static int intel_lvds_set_property(struct drm_connector *connector,
568
				   struct drm_property *property,
569
				   uint64_t value)
570
{
3243 Serge 571
	struct intel_connector *intel_connector = to_intel_connector(connector);
2330 Serge 572
	struct drm_device *dev = connector->dev;
573
 
574
	if (property == dev->mode_config.scaling_mode_property) {
3243 Serge 575
		struct drm_crtc *crtc;
2330 Serge 576
 
577
		if (value == DRM_MODE_SCALE_NONE) {
578
			DRM_DEBUG_KMS("no scaling not supported\n");
579
			return -EINVAL;
580
		}
581
 
3243 Serge 582
		if (intel_connector->panel.fitting_mode == value) {
2330 Serge 583
			/* the LVDS scaling property is not changed */
584
			return 0;
585
		}
3243 Serge 586
		intel_connector->panel.fitting_mode = value;
587
 
588
		crtc = intel_attached_encoder(connector)->base.crtc;
2330 Serge 589
		if (crtc && crtc->enabled) {
590
			/*
591
			 * If the CRTC is enabled, the display will be changed
592
			 * according to the new panel fitting mode.
593
			 */
3031 serge 594
			intel_set_mode(crtc, &crtc->mode,
2330 Serge 595
				crtc->x, crtc->y, crtc->fb);
596
		}
597
	}
598
 
599
	return 0;
600
}
601
 
602
static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = {
603
	.mode_fixup = intel_lvds_mode_fixup,
604
	.mode_set = intel_lvds_mode_set,
3031 serge 605
	.disable = intel_encoder_noop,
2330 Serge 606
};
607
 
608
static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
609
	.get_modes = intel_lvds_get_modes,
610
	.mode_valid = intel_lvds_mode_valid,
611
	.best_encoder = intel_best_encoder,
612
};
613
 
614
static const struct drm_connector_funcs intel_lvds_connector_funcs = {
3031 serge 615
	.dpms = intel_connector_dpms,
2330 Serge 616
	.detect = intel_lvds_detect,
617
	.fill_modes = drm_helper_probe_single_connector_modes,
618
	.set_property = intel_lvds_set_property,
619
	.destroy = intel_lvds_destroy,
620
};
621
 
622
static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
623
	.destroy = intel_encoder_destroy,
624
};
625
 
2351 Serge 626
static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
2330 Serge 627
{
3031 serge 628
	DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
2330 Serge 629
	return 1;
630
}
631
 
632
/* These systems claim to have LVDS, but really don't */
633
static const struct dmi_system_id intel_no_lvds[] = {
634
	{
635
		.callback = intel_no_lvds_dmi_callback,
636
		.ident = "Apple Mac Mini (Core series)",
637
		.matches = {
638
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
639
			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
640
		},
641
	},
642
	{
643
		.callback = intel_no_lvds_dmi_callback,
644
		.ident = "Apple Mac Mini (Core 2 series)",
645
		.matches = {
646
			DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
647
			DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
648
		},
649
	},
650
	{
651
		.callback = intel_no_lvds_dmi_callback,
652
		.ident = "MSI IM-945GSE-A",
653
		.matches = {
654
			DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
655
			DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
656
		},
657
	},
658
	{
659
		.callback = intel_no_lvds_dmi_callback,
660
		.ident = "Dell Studio Hybrid",
661
		.matches = {
662
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
663
			DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
664
		},
665
	},
666
	{
667
		.callback = intel_no_lvds_dmi_callback,
668
		.ident = "Dell OptiPlex FX170",
669
		.matches = {
670
			DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
671
			DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
672
		},
673
	},
674
	{
675
		.callback = intel_no_lvds_dmi_callback,
676
		.ident = "AOpen Mini PC",
677
		.matches = {
678
			DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
679
			DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
680
		},
681
	},
682
	{
683
		.callback = intel_no_lvds_dmi_callback,
684
		.ident = "AOpen Mini PC MP915",
685
		.matches = {
686
			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
687
			DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
688
		},
689
	},
690
	{
691
		.callback = intel_no_lvds_dmi_callback,
692
		.ident = "AOpen i915GMm-HFS",
693
		.matches = {
694
			DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
695
			DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
696
		},
697
	},
698
	{
699
		.callback = intel_no_lvds_dmi_callback,
2351 Serge 700
                .ident = "AOpen i45GMx-I",
701
                .matches = {
702
                        DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
703
                        DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
704
                },
705
        },
706
	{
707
		.callback = intel_no_lvds_dmi_callback,
2330 Serge 708
		.ident = "Aopen i945GTt-VFA",
709
		.matches = {
710
			DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
711
		},
712
	},
713
	{
714
		.callback = intel_no_lvds_dmi_callback,
715
		.ident = "Clientron U800",
716
		.matches = {
717
			DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
718
			DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
719
		},
720
	},
721
	{
722
		.callback = intel_no_lvds_dmi_callback,
2342 Serge 723
                .ident = "Clientron E830",
724
                .matches = {
725
                        DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
726
                        DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
727
                },
728
        },
729
        {
730
		.callback = intel_no_lvds_dmi_callback,
2330 Serge 731
		.ident = "Asus EeeBox PC EB1007",
732
		.matches = {
733
			DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
734
			DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
735
		},
736
	},
2342 Serge 737
	{
738
		.callback = intel_no_lvds_dmi_callback,
739
		.ident = "Asus AT5NM10T-I",
740
		.matches = {
741
			DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
742
			DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
743
		},
744
	},
3031 serge 745
	{
746
		.callback = intel_no_lvds_dmi_callback,
747
		.ident = "Hewlett-Packard HP t5740e Thin Client",
748
		.matches = {
749
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
750
			DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"),
751
		},
752
	},
753
	{
754
		.callback = intel_no_lvds_dmi_callback,
755
		.ident = "Hewlett-Packard t5745",
756
		.matches = {
757
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
758
			DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
759
		},
760
	},
761
	{
762
		.callback = intel_no_lvds_dmi_callback,
763
		.ident = "Hewlett-Packard st5747",
764
		.matches = {
765
			DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
766
			DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
767
		},
768
	},
769
	{
770
		.callback = intel_no_lvds_dmi_callback,
771
		.ident = "MSI Wind Box DC500",
772
		.matches = {
773
			DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
774
			DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
775
		},
776
	},
777
	{
778
		.callback = intel_no_lvds_dmi_callback,
779
		.ident = "Gigabyte GA-D525TUD",
780
		.matches = {
781
			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
782
			DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
783
		},
784
	},
785
	{
786
		.callback = intel_no_lvds_dmi_callback,
787
		.ident = "Supermicro X7SPA-H",
788
		.matches = {
789
			DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
790
			DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
791
		},
792
	},
2330 Serge 793
 
794
	{ }	/* terminating entry */
795
};
796
 
797
/**
798
 * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
799
 * @dev: drm device
800
 * @connector: LVDS connector
801
 *
802
 * Find the reduced downclock for LVDS in EDID.
803
 */
804
static void intel_find_lvds_downclock(struct drm_device *dev,
805
				      struct drm_display_mode *fixed_mode,
806
				      struct drm_connector *connector)
807
{
808
	struct drm_i915_private *dev_priv = dev->dev_private;
809
	struct drm_display_mode *scan;
810
	int temp_downclock;
811
 
812
	temp_downclock = fixed_mode->clock;
813
	list_for_each_entry(scan, &connector->probed_modes, head) {
814
		/*
815
		 * If one mode has the same resolution with the fixed_panel
816
		 * mode while they have the different refresh rate, it means
817
		 * that the reduced downclock is found for the LVDS. In such
818
		 * case we can set the different FPx0/1 to dynamically select
819
		 * between low and high frequency.
820
		 */
821
		if (scan->hdisplay == fixed_mode->hdisplay &&
822
		    scan->hsync_start == fixed_mode->hsync_start &&
823
		    scan->hsync_end == fixed_mode->hsync_end &&
824
		    scan->htotal == fixed_mode->htotal &&
825
		    scan->vdisplay == fixed_mode->vdisplay &&
826
		    scan->vsync_start == fixed_mode->vsync_start &&
827
		    scan->vsync_end == fixed_mode->vsync_end &&
828
		    scan->vtotal == fixed_mode->vtotal) {
829
			if (scan->clock < temp_downclock) {
830
				/*
831
				 * The downclock is already found. But we
832
				 * expect to find the lower downclock.
833
				 */
834
				temp_downclock = scan->clock;
835
			}
836
		}
837
	}
838
	if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
839
		/* We found the downclock for LVDS. */
840
		dev_priv->lvds_downclock_avail = 1;
841
		dev_priv->lvds_downclock = temp_downclock;
842
		DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
843
			      "Normal clock %dKhz, downclock %dKhz\n",
844
			      fixed_mode->clock, temp_downclock);
845
	}
846
}
847
 
848
/*
849
 * Enumerate the child dev array parsed from VBT to check whether
850
 * the LVDS is present.
851
 * If it is present, return 1.
852
 * If it is not present, return false.
853
 * If no child dev is parsed from VBT, it assumes that the LVDS is present.
854
 */
855
static bool lvds_is_present_in_vbt(struct drm_device *dev,
856
				   u8 *i2c_pin)
857
{
858
	struct drm_i915_private *dev_priv = dev->dev_private;
859
	int i;
860
 
861
	if (!dev_priv->child_dev_num)
862
		return true;
863
 
864
	for (i = 0; i < dev_priv->child_dev_num; i++) {
865
		struct child_device_config *child = dev_priv->child_dev + i;
866
 
867
		/* If the device type is not LFP, continue.
868
		 * We have to check both the new identifiers as well as the
869
		 * old for compatibility with some BIOSes.
870
		 */
871
		if (child->device_type != DEVICE_TYPE_INT_LFP &&
872
		    child->device_type != DEVICE_TYPE_LFP)
873
			continue;
874
 
3031 serge 875
		if (intel_gmbus_is_port_valid(child->i2c_pin))
2330 Serge 876
		    *i2c_pin = child->i2c_pin;
877
 
878
		/* However, we cannot trust the BIOS writers to populate
879
		 * the VBT correctly.  Since LVDS requires additional
880
		 * information from AIM blocks, a non-zero addin offset is
881
		 * a good indicator that the LVDS is actually present.
882
		 */
883
		if (child->addin_offset)
884
			return true;
885
 
886
		/* But even then some BIOS writers perform some black magic
887
		 * and instantiate the device without reference to any
888
		 * additional data.  Trust that if the VBT was written into
889
		 * the OpRegion then they have validated the LVDS's existence.
890
		 */
891
		if (dev_priv->opregion.vbt)
892
			return true;
893
	}
894
 
895
	return false;
896
}
897
 
3031 serge 898
static bool intel_lvds_supported(struct drm_device *dev)
899
{
900
	/* With the introduction of the PCH we gained a dedicated
901
	 * LVDS presence pin, use it. */
902
	if (HAS_PCH_SPLIT(dev))
903
		return true;
904
 
905
	/* Otherwise LVDS was only attached to mobile products,
906
	 * except for the inglorious 830gm */
907
	return IS_MOBILE(dev) && !IS_I830(dev);
908
}
909
 
2330 Serge 910
/**
911
 * intel_lvds_init - setup LVDS connectors on this device
912
 * @dev: drm device
913
 *
914
 * Create the connector, register the LVDS DDC bus, and try to figure out what
915
 * modes we can display on the LVDS panel (if present).
916
 */
917
bool intel_lvds_init(struct drm_device *dev)
918
{
919
	struct drm_i915_private *dev_priv = dev->dev_private;
3243 Serge 920
	struct intel_lvds_encoder *lvds_encoder;
2330 Serge 921
	struct intel_encoder *intel_encoder;
3243 Serge 922
	struct intel_lvds_connector *lvds_connector;
2330 Serge 923
	struct intel_connector *intel_connector;
924
	struct drm_connector *connector;
925
	struct drm_encoder *encoder;
926
	struct drm_display_mode *scan; /* *modes, *bios_mode; */
3243 Serge 927
	struct drm_display_mode *fixed_mode = NULL;
928
	struct edid *edid;
2330 Serge 929
	struct drm_crtc *crtc;
930
	u32 lvds;
931
	int pipe;
932
	u8 pin;
933
 
3031 serge 934
	if (!intel_lvds_supported(dev))
935
		return false;
936
 
2330 Serge 937
	/* Skip init on machines we know falsely report LVDS */
938
//   if (dmi_check_system(intel_no_lvds))
939
//       return false;
940
 
941
	pin = GMBUS_PORT_PANEL;
942
	if (!lvds_is_present_in_vbt(dev, &pin)) {
943
		DRM_DEBUG_KMS("LVDS is not present in VBT\n");
944
		return false;
945
	}
946
 
947
	if (HAS_PCH_SPLIT(dev)) {
948
		if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
949
			return false;
950
		if (dev_priv->edp.support) {
951
			DRM_DEBUG_KMS("disable LVDS for eDP support\n");
952
			return false;
953
		}
954
	}
955
 
3243 Serge 956
	lvds_encoder = kzalloc(sizeof(struct intel_lvds_encoder), GFP_KERNEL);
957
	if (!lvds_encoder)
2330 Serge 958
		return false;
959
 
3243 Serge 960
	lvds_connector = kzalloc(sizeof(struct intel_lvds_connector), GFP_KERNEL);
961
	if (!lvds_connector) {
962
		kfree(lvds_encoder);
2330 Serge 963
		return false;
964
	}
965
 
3243 Serge 966
	lvds_encoder->attached_connector = lvds_connector;
967
 
2330 Serge 968
	if (!HAS_PCH_SPLIT(dev)) {
3243 Serge 969
		lvds_encoder->pfit_control = I915_READ(PFIT_CONTROL);
2330 Serge 970
	}
971
 
3243 Serge 972
	intel_encoder = &lvds_encoder->base;
2330 Serge 973
	encoder = &intel_encoder->base;
3243 Serge 974
	intel_connector = &lvds_connector->base;
2330 Serge 975
	connector = &intel_connector->base;
976
	drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
977
			   DRM_MODE_CONNECTOR_LVDS);
978
 
979
	drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
980
			 DRM_MODE_ENCODER_LVDS);
981
 
3031 serge 982
	intel_encoder->enable = intel_enable_lvds;
983
	intel_encoder->disable = intel_disable_lvds;
984
	intel_encoder->get_hw_state = intel_lvds_get_hw_state;
985
	intel_connector->get_hw_state = intel_connector_get_hw_state;
986
 
2330 Serge 987
	intel_connector_attach_encoder(intel_connector, intel_encoder);
988
	intel_encoder->type = INTEL_OUTPUT_LVDS;
989
 
3031 serge 990
	intel_encoder->cloneable = false;
2342 Serge 991
	if (HAS_PCH_SPLIT(dev))
992
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
3031 serge 993
	else if (IS_GEN4(dev))
994
		intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
2342 Serge 995
	else
2330 Serge 996
	intel_encoder->crtc_mask = (1 << 1);
2342 Serge 997
 
2330 Serge 998
	drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs);
999
	drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
1000
	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
1001
	connector->interlace_allowed = false;
1002
	connector->doublescan_allowed = false;
1003
 
1004
	/* create the scaling mode property */
1005
	drm_mode_create_scaling_mode_property(dev);
3243 Serge 1006
	drm_object_attach_property(&connector->base,
2330 Serge 1007
				      dev->mode_config.scaling_mode_property,
1008
				      DRM_MODE_SCALE_ASPECT);
3243 Serge 1009
	intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
2330 Serge 1010
	/*
1011
	 * LVDS discovery:
1012
	 * 1) check for EDID on DDC
1013
	 * 2) check for VBT data
1014
	 * 3) check to see if LVDS is already on
1015
	 *    if none of the above, no panel
1016
	 * 4) make sure lid is open
1017
	 *    if closed, act like it's not there for now
1018
	 */
1019
 
1020
	/*
1021
	 * Attempt to get the fixed panel mode from DDC.  Assume that the
1022
	 * preferred mode is the right one.
1023
	 */
3243 Serge 1024
	edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
1025
	if (edid) {
1026
		if (drm_add_edid_modes(connector, edid)) {
2330 Serge 1027
			drm_mode_connector_update_edid_property(connector,
3243 Serge 1028
								edid);
2330 Serge 1029
		} else {
3243 Serge 1030
			kfree(edid);
1031
			edid = ERR_PTR(-EINVAL);
2330 Serge 1032
		}
3243 Serge 1033
	} else {
1034
		edid = ERR_PTR(-ENOENT);
2330 Serge 1035
	}
3243 Serge 1036
	lvds_connector->base.edid = edid;
1037
 
1038
	if (IS_ERR_OR_NULL(edid)) {
2330 Serge 1039
		/* Didn't get an EDID, so
1040
		 * Set wide sync ranges so we get all modes
1041
		 * handed to valid_mode for checking
1042
		 */
1043
		connector->display_info.min_vfreq = 0;
1044
		connector->display_info.max_vfreq = 200;
1045
		connector->display_info.min_hfreq = 0;
1046
		connector->display_info.max_hfreq = 200;
1047
	}
1048
 
1049
	list_for_each_entry(scan, &connector->probed_modes, head) {
1050
		if (scan->type & DRM_MODE_TYPE_PREFERRED) {
3243 Serge 1051
			DRM_DEBUG_KMS("using preferred mode from EDID: ");
1052
			drm_mode_debug_printmodeline(scan);
1053
 
1054
			fixed_mode = drm_mode_duplicate(dev, scan);
1055
			if (fixed_mode) {
1056
				intel_find_lvds_downclock(dev, fixed_mode,
2330 Serge 1057
						  connector);
1058
			goto out;
1059
		}
1060
	}
3243 Serge 1061
	}
2330 Serge 1062
 
1063
	/* Failed to get EDID, what about VBT? */
1064
	if (dev_priv->lfp_lvds_vbt_mode) {
3243 Serge 1065
		DRM_DEBUG_KMS("using mode from VBT: ");
1066
		drm_mode_debug_printmodeline(dev_priv->lfp_lvds_vbt_mode);
1067
 
1068
		fixed_mode = drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
1069
		if (fixed_mode) {
1070
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
2330 Serge 1071
			goto out;
1072
		}
1073
	}
1074
 
1075
	/*
1076
	 * If we didn't get EDID, try checking if the panel is already turned
1077
	 * on.  If so, assume that whatever is currently programmed is the
1078
	 * correct mode.
1079
	 */
1080
 
1081
	/* Ironlake: FIXME if still fail, not try pipe mode now */
1082
	if (HAS_PCH_SPLIT(dev))
1083
		goto failed;
1084
 
1085
	lvds = I915_READ(LVDS);
1086
	pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
1087
	crtc = intel_get_crtc_for_pipe(dev, pipe);
1088
 
1089
	if (crtc && (lvds & LVDS_PORT_EN)) {
3243 Serge 1090
		fixed_mode = intel_crtc_mode_get(dev, crtc);
1091
		if (fixed_mode) {
1092
			DRM_DEBUG_KMS("using current (BIOS) mode: ");
1093
			drm_mode_debug_printmodeline(fixed_mode);
1094
			fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
2330 Serge 1095
			goto out;
1096
		}
1097
	}
1098
 
1099
	/* If we still don't have a mode after all that, give up. */
3243 Serge 1100
	if (!fixed_mode)
2330 Serge 1101
		goto failed;
1102
 
1103
out:
1104
		/*
1105
		 * Unlock registers and just
1106
		 * leave them unlocked
1107
		 */
3031 serge 1108
	if (HAS_PCH_SPLIT(dev)) {
2330 Serge 1109
		I915_WRITE(PCH_PP_CONTROL,
1110
			   I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
1111
	} else {
1112
		I915_WRITE(PP_CONTROL,
1113
			   I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
1114
	}
1115
//   dev_priv->lid_notifier.notifier_call = intel_lid_notify;
1116
//   if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
1117
//       DRM_DEBUG_KMS("lid notifier registration failed\n");
1118
 //      dev_priv->lid_notifier.notifier_call = NULL;
1119
//   }
1120
	drm_sysfs_connector_add(connector);
1121
 
3243 Serge 1122
	intel_panel_init(&intel_connector->panel, fixed_mode);
1123
	intel_panel_setup_backlight(connector);
2330 Serge 1124
 
1125
	return true;
1126
 
1127
failed:
1128
	DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
1129
	drm_connector_cleanup(connector);
1130
	drm_encoder_cleanup(encoder);
3243 Serge 1131
	if (fixed_mode)
1132
		drm_mode_destroy(dev, fixed_mode);
1133
	kfree(lvds_encoder);
1134
	kfree(lvds_connector);
2330 Serge 1135
	return false;
1136
}