blob: cba04ddc8b01dddb5101ce8a18cdfcb2dcc3c429 [file] [log] [blame]
Jesse Barnes79e53942008-11-07 14:24:08 -08001/*
2 * Copyright © 2006-2007 Intel Corporation
3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Eric Anholt <eric@anholt.net>
26 * Dave Airlie <airlied@linux.ie>
27 * Jesse Barnes <jesse.barnes@intel.com>
28 */
29
Jesse Barnesc1c7af62009-09-10 15:28:03 -070030#include <acpi/button.h>
Paul Collins565dcd42009-02-04 23:05:41 +130031#include <linux/dmi.h>
Jesse Barnes79e53942008-11-07 14:24:08 -080032#include <linux/i2c.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090033#include <linux/slab.h>
David Howells760285e2012-10-02 18:01:07 +010034#include <drm/drmP.h>
35#include <drm/drm_crtc.h>
36#include <drm/drm_edid.h>
Jesse Barnes79e53942008-11-07 14:24:08 -080037#include "intel_drv.h"
David Howells760285e2012-10-02 18:01:07 +010038#include <drm/i915_drm.h>
Jesse Barnes79e53942008-11-07 14:24:08 -080039#include "i915_drv.h"
Zhao Yakuie99da352009-06-26 09:46:18 +080040#include <linux/acpi.h>
Jesse Barnes79e53942008-11-07 14:24:08 -080041
Zhao Yakui3fbe18d2009-06-22 15:31:25 +080042/* Private structure for the integrated LVDS support */
Jani Nikulac7362c42012-10-19 14:51:44 +030043struct intel_lvds_connector {
44 struct intel_connector base;
Jani Nikuladb1740a2012-10-19 14:51:45 +030045
46 struct notifier_block lid_notifier;
Jani Nikulac7362c42012-10-19 14:51:44 +030047};
48
Jani Nikula29b99b42012-10-19 14:51:43 +030049struct intel_lvds_encoder {
Chris Wilsonea5b2132010-08-04 13:50:23 +010050 struct intel_encoder base;
Chris Wilson788319d2010-09-12 17:34:41 +010051
Daniel Vetter13c7d872012-11-26 17:22:10 +010052 bool is_dual_link;
Daniel Vetter7dec0602012-09-11 14:12:25 +020053 u32 reg;
Chris Wilson788319d2010-09-12 17:34:41 +010054
Jani Nikula62165e02012-10-19 14:51:47 +030055 struct intel_lvds_connector *attached_connector;
Zhao Yakui3fbe18d2009-06-22 15:31:25 +080056};
57
Jani Nikula29b99b42012-10-19 14:51:43 +030058static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
Chris Wilsonea5b2132010-08-04 13:50:23 +010059{
Jani Nikula29b99b42012-10-19 14:51:43 +030060 return container_of(encoder, struct intel_lvds_encoder, base.base);
Chris Wilsonea5b2132010-08-04 13:50:23 +010061}
62
Jani Nikulac7362c42012-10-19 14:51:44 +030063static struct intel_lvds_connector *to_lvds_connector(struct drm_connector *connector)
Chris Wilson788319d2010-09-12 17:34:41 +010064{
Jani Nikulac7362c42012-10-19 14:51:44 +030065 return container_of(connector, struct intel_lvds_connector, base.base);
Chris Wilson788319d2010-09-12 17:34:41 +010066}
67
Daniel Vetterb1dc3322012-07-02 21:09:00 +020068static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
69 enum pipe *pipe)
70{
71 struct drm_device *dev = encoder->base.dev;
72 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter7dec0602012-09-11 14:12:25 +020073 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
Paulo Zanoni34a6c702014-07-04 13:38:35 -030074 enum intel_display_power_domain power_domain;
Daniel Vetter7dec0602012-09-11 14:12:25 +020075 u32 tmp;
Daniel Vetterb1dc3322012-07-02 21:09:00 +020076
Paulo Zanoni34a6c702014-07-04 13:38:35 -030077 power_domain = intel_display_port_power_domain(encoder);
78 if (!intel_display_power_enabled(dev_priv, power_domain))
79 return false;
80
Daniel Vetter7dec0602012-09-11 14:12:25 +020081 tmp = I915_READ(lvds_encoder->reg);
Daniel Vetterb1dc3322012-07-02 21:09:00 +020082
83 if (!(tmp & LVDS_PORT_EN))
84 return false;
85
86 if (HAS_PCH_CPT(dev))
87 *pipe = PORT_TO_PIPE_CPT(tmp);
88 else
89 *pipe = PORT_TO_PIPE(tmp);
90
91 return true;
92}
93
Jesse Barnes045ac3b2013-05-14 17:08:26 -070094static void intel_lvds_get_config(struct intel_encoder *encoder,
95 struct intel_crtc_config *pipe_config)
96{
97 struct drm_device *dev = encoder->base.dev;
98 struct drm_i915_private *dev_priv = dev->dev_private;
99 u32 lvds_reg, tmp, flags = 0;
Ville Syrjälä18442d02013-09-13 16:00:08 +0300100 int dotclock;
Jesse Barnes045ac3b2013-05-14 17:08:26 -0700101
102 if (HAS_PCH_SPLIT(dev))
103 lvds_reg = PCH_LVDS;
104 else
105 lvds_reg = LVDS;
106
107 tmp = I915_READ(lvds_reg);
108 if (tmp & LVDS_HSYNC_POLARITY)
109 flags |= DRM_MODE_FLAG_NHSYNC;
110 else
111 flags |= DRM_MODE_FLAG_PHSYNC;
112 if (tmp & LVDS_VSYNC_POLARITY)
113 flags |= DRM_MODE_FLAG_NVSYNC;
114 else
115 flags |= DRM_MODE_FLAG_PVSYNC;
116
117 pipe_config->adjusted_mode.flags |= flags;
Daniel Vetter06922822013-07-11 13:35:40 +0200118
Ville Syrjälä18442d02013-09-13 16:00:08 +0300119 dotclock = pipe_config->port_clock;
120
121 if (HAS_PCH_SPLIT(dev_priv->dev))
122 ironlake_check_encoder_dotclock(pipe_config, dotclock);
123
Damien Lespiau241bfc32013-09-25 16:45:37 +0100124 pipe_config->adjusted_mode.crtc_clock = dotclock;
Jesse Barnes045ac3b2013-05-14 17:08:26 -0700125}
126
Daniel Vetterf6736a12013-06-05 13:34:30 +0200127static void intel_pre_enable_lvds(struct intel_encoder *encoder)
Daniel Vetterfc683092012-11-26 17:22:12 +0100128{
129 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
130 struct drm_device *dev = encoder->base.dev;
131 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter55607e82013-06-16 21:42:39 +0200132 struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
Ville Syrjälä4c6df4b2013-09-02 21:13:39 +0300133 const struct drm_display_mode *adjusted_mode =
134 &crtc->config.adjusted_mode;
Daniel Vetter55607e82013-06-16 21:42:39 +0200135 int pipe = crtc->pipe;
Daniel Vetterfc683092012-11-26 17:22:12 +0100136 u32 temp;
137
Daniel Vetter55607e82013-06-16 21:42:39 +0200138 if (HAS_PCH_SPLIT(dev)) {
139 assert_fdi_rx_pll_disabled(dev_priv, pipe);
140 assert_shared_dpll_disabled(dev_priv,
141 intel_crtc_to_shared_dpll(crtc));
142 } else {
143 assert_pll_disabled(dev_priv, pipe);
144 }
145
Daniel Vetterfc683092012-11-26 17:22:12 +0100146 temp = I915_READ(lvds_encoder->reg);
147 temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
Daniel Vetter62810e52012-11-26 17:22:13 +0100148
149 if (HAS_PCH_CPT(dev)) {
150 temp &= ~PORT_TRANS_SEL_MASK;
151 temp |= PORT_TRANS_SEL_CPT(pipe);
Daniel Vetterfc683092012-11-26 17:22:12 +0100152 } else {
Daniel Vetter62810e52012-11-26 17:22:13 +0100153 if (pipe == 1) {
154 temp |= LVDS_PIPEB_SELECT;
155 } else {
156 temp &= ~LVDS_PIPEB_SELECT;
157 }
Daniel Vetterfc683092012-11-26 17:22:12 +0100158 }
Daniel Vetter62810e52012-11-26 17:22:13 +0100159
Daniel Vetterfc683092012-11-26 17:22:12 +0100160 /* set the corresponsding LVDS_BORDER bit */
Daniel Vetter2fa2fe92013-05-07 23:34:16 +0200161 temp &= ~LVDS_BORDER_ENABLE;
Daniel Vetter55607e82013-06-16 21:42:39 +0200162 temp |= crtc->config.gmch_pfit.lvds_border_bits;
Daniel Vetterfc683092012-11-26 17:22:12 +0100163 /* Set the B0-B3 data pairs corresponding to whether we're going to
164 * set the DPLLs for dual-channel mode or not.
165 */
166 if (lvds_encoder->is_dual_link)
167 temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
168 else
169 temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
170
171 /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
172 * appropriately here, but we need to look more thoroughly into how
173 * panels behave in the two modes.
174 */
Daniel Vetter62810e52012-11-26 17:22:13 +0100175
176 /* Set the dithering flag on LVDS as needed, note that there is no
177 * special lvds dither control bit on pch-split platforms, dithering is
178 * only controlled through the PIPECONF reg. */
179 if (INTEL_INFO(dev)->gen == 4) {
Daniel Vetterd8b32242013-04-25 17:54:44 +0200180 /* Bspec wording suggests that LVDS port dithering only exists
181 * for 18bpp panels. */
Daniel Vetter55607e82013-06-16 21:42:39 +0200182 if (crtc->config.dither && crtc->config.pipe_bpp == 18)
Daniel Vetterfc683092012-11-26 17:22:12 +0100183 temp |= LVDS_ENABLE_DITHER;
184 else
185 temp &= ~LVDS_ENABLE_DITHER;
186 }
187 temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
Ville Syrjälä4c6df4b2013-09-02 21:13:39 +0300188 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
Daniel Vetterfc683092012-11-26 17:22:12 +0100189 temp |= LVDS_HSYNC_POLARITY;
Ville Syrjälä4c6df4b2013-09-02 21:13:39 +0300190 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
Daniel Vetterfc683092012-11-26 17:22:12 +0100191 temp |= LVDS_VSYNC_POLARITY;
192
193 I915_WRITE(lvds_encoder->reg, temp);
194}
195
Jesse Barnes79e53942008-11-07 14:24:08 -0800196/**
Jesse Barnes79e53942008-11-07 14:24:08 -0800197 * Sets the power state for the panel.
198 */
Daniel Vetterc22834e2012-06-30 15:31:28 +0200199static void intel_enable_lvds(struct intel_encoder *encoder)
Jesse Barnes79e53942008-11-07 14:24:08 -0800200{
Daniel Vetterc22834e2012-06-30 15:31:28 +0200201 struct drm_device *dev = encoder->base.dev;
Jani Nikula29b99b42012-10-19 14:51:43 +0300202 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
Jesse Barnes752aa882013-10-31 18:55:49 +0200203 struct intel_connector *intel_connector =
204 &lvds_encoder->attached_connector->base;
Jesse Barnes79e53942008-11-07 14:24:08 -0800205 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter7dec0602012-09-11 14:12:25 +0200206 u32 ctl_reg, stat_reg;
Zhenyu Wang541998a2009-06-05 15:38:44 +0800207
Eric Anholtc619eed2010-01-28 16:45:52 -0800208 if (HAS_PCH_SPLIT(dev)) {
Zhenyu Wang541998a2009-06-05 15:38:44 +0800209 ctl_reg = PCH_PP_CONTROL;
Keith Packardde842ef2011-08-06 10:30:45 -0700210 stat_reg = PCH_PP_STATUS;
Zhenyu Wang541998a2009-06-05 15:38:44 +0800211 } else {
212 ctl_reg = PP_CONTROL;
Keith Packardde842ef2011-08-06 10:30:45 -0700213 stat_reg = PP_STATUS;
Zhenyu Wang541998a2009-06-05 15:38:44 +0800214 }
Jesse Barnes79e53942008-11-07 14:24:08 -0800215
Daniel Vetter7dec0602012-09-11 14:12:25 +0200216 I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
Chris Wilsone9e331a2010-09-13 01:16:10 +0100217
Chris Wilson2a1292f2010-12-05 19:21:18 +0000218 I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
Daniel Vetter7dec0602012-09-11 14:12:25 +0200219 POSTING_READ(lvds_encoder->reg);
Keith Packardde842ef2011-08-06 10:30:45 -0700220 if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
221 DRM_ERROR("timed out waiting for panel to power on\n");
Chris Wilson2a1292f2010-12-05 19:21:18 +0000222
Jesse Barnes752aa882013-10-31 18:55:49 +0200223 intel_panel_enable_backlight(intel_connector);
Chris Wilson2a1292f2010-12-05 19:21:18 +0000224}
225
Daniel Vetterc22834e2012-06-30 15:31:28 +0200226static void intel_disable_lvds(struct intel_encoder *encoder)
Chris Wilson2a1292f2010-12-05 19:21:18 +0000227{
Daniel Vetterc22834e2012-06-30 15:31:28 +0200228 struct drm_device *dev = encoder->base.dev;
Jani Nikula29b99b42012-10-19 14:51:43 +0300229 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
Jesse Barnes752aa882013-10-31 18:55:49 +0200230 struct intel_connector *intel_connector =
231 &lvds_encoder->attached_connector->base;
Chris Wilson2a1292f2010-12-05 19:21:18 +0000232 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter7dec0602012-09-11 14:12:25 +0200233 u32 ctl_reg, stat_reg;
Chris Wilson2a1292f2010-12-05 19:21:18 +0000234
235 if (HAS_PCH_SPLIT(dev)) {
236 ctl_reg = PCH_PP_CONTROL;
Keith Packardde842ef2011-08-06 10:30:45 -0700237 stat_reg = PCH_PP_STATUS;
Chris Wilson2a1292f2010-12-05 19:21:18 +0000238 } else {
239 ctl_reg = PP_CONTROL;
Keith Packardde842ef2011-08-06 10:30:45 -0700240 stat_reg = PP_STATUS;
Chris Wilson2a1292f2010-12-05 19:21:18 +0000241 }
242
Jesse Barnes752aa882013-10-31 18:55:49 +0200243 intel_panel_disable_backlight(intel_connector);
Chris Wilson2a1292f2010-12-05 19:21:18 +0000244
245 I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
Keith Packardde842ef2011-08-06 10:30:45 -0700246 if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
247 DRM_ERROR("timed out waiting for panel to power off\n");
Chris Wilson2a1292f2010-12-05 19:21:18 +0000248
Daniel Vetter7dec0602012-09-11 14:12:25 +0200249 I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
250 POSTING_READ(lvds_encoder->reg);
Jesse Barnes79e53942008-11-07 14:24:08 -0800251}
252
Damien Lespiauc19de8e2013-11-28 15:29:18 +0000253static enum drm_mode_status
254intel_lvds_mode_valid(struct drm_connector *connector,
255 struct drm_display_mode *mode)
Jesse Barnes79e53942008-11-07 14:24:08 -0800256{
Jani Nikuladd06f902012-10-19 14:51:50 +0300257 struct intel_connector *intel_connector = to_intel_connector(connector);
258 struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
Jesse Barnes79e53942008-11-07 14:24:08 -0800259
Chris Wilson788319d2010-09-12 17:34:41 +0100260 if (mode->hdisplay > fixed_mode->hdisplay)
261 return MODE_PANEL;
262 if (mode->vdisplay > fixed_mode->vdisplay)
263 return MODE_PANEL;
Jesse Barnes79e53942008-11-07 14:24:08 -0800264
265 return MODE_OK;
266}
267
Daniel Vetter7ae89232013-03-27 00:44:52 +0100268static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
269 struct intel_crtc_config *pipe_config)
Jesse Barnes79e53942008-11-07 14:24:08 -0800270{
Daniel Vetter7ae89232013-03-27 00:44:52 +0100271 struct drm_device *dev = intel_encoder->base.dev;
Jesse Barnes79e53942008-11-07 14:24:08 -0800272 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter7ae89232013-03-27 00:44:52 +0100273 struct intel_lvds_encoder *lvds_encoder =
274 to_lvds_encoder(&intel_encoder->base);
Jani Nikula4d891522012-10-26 12:03:59 +0300275 struct intel_connector *intel_connector =
276 &lvds_encoder->attached_connector->base;
Daniel Vetter7ae89232013-03-27 00:44:52 +0100277 struct drm_display_mode *adjusted_mode = &pipe_config->adjusted_mode;
Jani Nikula29b99b42012-10-19 14:51:43 +0300278 struct intel_crtc *intel_crtc = lvds_encoder->base.new_crtc;
Daniel Vetter4e53c2e2013-03-27 00:44:58 +0100279 unsigned int lvds_bpp;
Jesse Barnes79e53942008-11-07 14:24:08 -0800280
281 /* Should never happen!! */
Chris Wilsona6c45cf2010-09-17 00:32:17 +0100282 if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
Keith Packard1ae8c0a2009-06-28 15:42:17 -0700283 DRM_ERROR("Can't support LVDS on pipe A\n");
Jesse Barnes79e53942008-11-07 14:24:08 -0800284 return false;
285 }
286
Daniel Vetter4e53c2e2013-03-27 00:44:58 +0100287 if ((I915_READ(lvds_encoder->reg) & LVDS_A3_POWER_MASK) ==
288 LVDS_A3_POWER_UP)
289 lvds_bpp = 8*3;
290 else
291 lvds_bpp = 6*3;
292
Daniel Vettere29c22c2013-02-21 00:00:16 +0100293 if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
Daniel Vetter4e53c2e2013-03-27 00:44:58 +0100294 DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
295 pipe_config->pipe_bpp, lvds_bpp);
296 pipe_config->pipe_bpp = lvds_bpp;
297 }
Daniel Vetterd8b32242013-04-25 17:54:44 +0200298
Jesse Barnes79e53942008-11-07 14:24:08 -0800299 /*
Chris Wilson71677042010-07-17 13:38:43 +0100300 * We have timings from the BIOS for the panel, put them in
Jesse Barnes79e53942008-11-07 14:24:08 -0800301 * to the adjusted mode. The CRTC will be set up for this mode,
302 * with the panel scaling set up to source from the H/VDisplay
303 * of the original mode.
304 */
Jani Nikula4d891522012-10-26 12:03:59 +0300305 intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
Jani Nikuladd06f902012-10-19 14:51:50 +0300306 adjusted_mode);
Chris Wilson1d8e1c72010-08-07 11:01:28 +0100307
308 if (HAS_PCH_SPLIT(dev)) {
Daniel Vetter5bfe2ac2013-03-27 00:44:55 +0100309 pipe_config->has_pch_encoder = true;
310
Jesse Barnesb074cec2013-04-25 12:55:02 -0700311 intel_pch_panel_fitting(intel_crtc, pipe_config,
312 intel_connector->panel.fitting_mode);
Jesse Barnes2dd24552013-04-25 12:55:01 -0700313 } else {
314 intel_gmch_panel_fitting(intel_crtc, pipe_config,
315 intel_connector->panel.fitting_mode);
Jesse Barnes79e53942008-11-07 14:24:08 -0800316
Daniel Vetter21d8a472013-07-12 08:07:30 +0200317 }
Daniel Vetterf9bef082012-04-15 19:53:19 +0200318
Zhao Yakuia3e17eb2009-10-10 10:42:37 +0800319 /*
Jesse Barnes79e53942008-11-07 14:24:08 -0800320 * XXX: It would be nice to support lower refresh rates on the
321 * panels to reduce power consumption, and perhaps match the
322 * user's requested refresh rate.
323 */
324
325 return true;
326}
327
Jesse Barnes79e53942008-11-07 14:24:08 -0800328/**
329 * Detect the LVDS connection.
330 *
Jesse Barnesb42d4c52009-09-10 15:28:04 -0700331 * Since LVDS doesn't have hotlug, we use the lid as a proxy. Open means
332 * connected and closed means disconnected. We also send hotplug events as
333 * needed, using lid status notification from the input layer.
Jesse Barnes79e53942008-11-07 14:24:08 -0800334 */
Chris Wilson7b334fc2010-09-09 23:51:02 +0100335static enum drm_connector_status
Chris Wilson930a9e22010-09-14 11:07:23 +0100336intel_lvds_detect(struct drm_connector *connector, bool force)
Jesse Barnes79e53942008-11-07 14:24:08 -0800337{
Jesse Barnes7b9c5ab2010-02-12 09:30:00 -0800338 struct drm_device *dev = connector->dev;
Chris Wilson6ee3b5a2011-03-24 13:26:43 +0000339 enum drm_connector_status status;
Jesse Barnesb42d4c52009-09-10 15:28:04 -0700340
Chris Wilson164c8592013-07-20 20:27:08 +0100341 DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
Jani Nikulac23cc412014-06-03 14:56:17 +0300342 connector->base.id, connector->name);
Chris Wilson164c8592013-07-20 20:27:08 +0100343
Chris Wilsonfe16d942011-02-12 10:29:38 +0000344 status = intel_panel_detect(dev);
345 if (status != connector_status_unknown)
346 return status;
Chris Wilson01fe9db2011-01-16 19:37:30 +0000347
Chris Wilson6ee3b5a2011-03-24 13:26:43 +0000348 return connector_status_connected;
Jesse Barnes79e53942008-11-07 14:24:08 -0800349}
350
351/**
352 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
353 */
354static int intel_lvds_get_modes(struct drm_connector *connector)
355{
Jani Nikula62165e02012-10-19 14:51:47 +0300356 struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
Jesse Barnes79e53942008-11-07 14:24:08 -0800357 struct drm_device *dev = connector->dev;
Chris Wilson788319d2010-09-12 17:34:41 +0100358 struct drm_display_mode *mode;
Jesse Barnes79e53942008-11-07 14:24:08 -0800359
Jani Nikula9cd300e2012-10-19 14:51:52 +0300360 /* use cached edid if we have one */
Chris Wilson2aa4f092012-11-21 16:14:04 +0000361 if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
Jani Nikula9cd300e2012-10-19 14:51:52 +0300362 return drm_add_edid_modes(connector, lvds_connector->base.edid);
Jesse Barnes79e53942008-11-07 14:24:08 -0800363
Jani Nikuladd06f902012-10-19 14:51:50 +0300364 mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
Chris Wilson311bd682011-01-13 19:06:50 +0000365 if (mode == NULL)
Chris Wilson788319d2010-09-12 17:34:41 +0100366 return 0;
Jesse Barnes79e53942008-11-07 14:24:08 -0800367
Chris Wilson788319d2010-09-12 17:34:41 +0100368 drm_mode_probed_add(connector, mode);
369 return 1;
Jesse Barnes79e53942008-11-07 14:24:08 -0800370}
371
Thomas Bächler0544edf2010-07-02 10:44:23 +0200372static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
373{
Daniel Vetterbc0daf42012-04-01 13:16:49 +0200374 DRM_INFO("Skipping forced modeset for %s\n", id->ident);
Thomas Bächler0544edf2010-07-02 10:44:23 +0200375 return 1;
376}
377
378/* The GPU hangs up on these systems if modeset is performed on LID open */
379static const struct dmi_system_id intel_no_modeset_on_lid[] = {
380 {
381 .callback = intel_no_modeset_on_lid_dmi_callback,
382 .ident = "Toshiba Tecra A11",
383 .matches = {
384 DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
385 DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
386 },
387 },
388
389 { } /* terminating entry */
390};
391
Linus Torvaldsc9354c82009-11-02 09:29:55 -0800392/*
Zhang Ruib8efb172013-02-05 15:41:53 +0800393 * Lid events. Note the use of 'modeset':
394 * - we set it to MODESET_ON_LID_OPEN on lid close,
395 * and set it to MODESET_DONE on open
Linus Torvaldsc9354c82009-11-02 09:29:55 -0800396 * - we use it as a "only once" bit (ie we ignore
Zhang Ruib8efb172013-02-05 15:41:53 +0800397 * duplicate events where it was already properly set)
398 * - the suspend/resume paths will set it to
399 * MODESET_SUSPENDED and ignore the lid open event,
400 * because they restore the mode ("lid open").
Linus Torvaldsc9354c82009-11-02 09:29:55 -0800401 */
Jesse Barnesc1c7af62009-09-10 15:28:03 -0700402static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
403 void *unused)
404{
Jani Nikuladb1740a2012-10-19 14:51:45 +0300405 struct intel_lvds_connector *lvds_connector =
406 container_of(nb, struct intel_lvds_connector, lid_notifier);
407 struct drm_connector *connector = &lvds_connector->base.base;
408 struct drm_device *dev = connector->dev;
409 struct drm_i915_private *dev_priv = dev->dev_private;
Jesse Barnesc1c7af62009-09-10 15:28:03 -0700410
Alex Williamson2fb4e612011-04-21 16:08:14 -0600411 if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
412 return NOTIFY_OK;
413
Zhang Ruib8efb172013-02-05 15:41:53 +0800414 mutex_lock(&dev_priv->modeset_restore_lock);
415 if (dev_priv->modeset_restore == MODESET_SUSPENDED)
416 goto exit;
Zhao Yakuia2565372009-12-11 09:26:11 +0800417 /*
418 * check and update the status of LVDS connector after receiving
419 * the LID nofication event.
420 */
Jani Nikuladb1740a2012-10-19 14:51:45 +0300421 connector->status = connector->funcs->detect(connector, false);
Chris Wilson7b334fc2010-09-09 23:51:02 +0100422
Thomas Bächler0544edf2010-07-02 10:44:23 +0200423 /* Don't force modeset on machines where it causes a GPU lockup */
424 if (dmi_check_system(intel_no_modeset_on_lid))
Zhang Ruib8efb172013-02-05 15:41:53 +0800425 goto exit;
Linus Torvaldsc9354c82009-11-02 09:29:55 -0800426 if (!acpi_lid_open()) {
Zhang Ruib8efb172013-02-05 15:41:53 +0800427 /* do modeset on next lid open event */
428 dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
429 goto exit;
Jesse Barnes06891e22009-09-14 10:58:48 -0700430 }
Jesse Barnesc1c7af62009-09-10 15:28:03 -0700431
Zhang Ruib8efb172013-02-05 15:41:53 +0800432 if (dev_priv->modeset_restore == MODESET_DONE)
433 goto exit;
Linus Torvaldsc9354c82009-11-02 09:29:55 -0800434
Daniel Vetter5be19d92013-10-09 10:47:12 +0200435 /*
436 * Some old platform's BIOS love to wreak havoc while the lid is closed.
437 * We try to detect this here and undo any damage. The split for PCH
438 * platforms is rather conservative and a bit arbitrary expect that on
439 * those platforms VGA disabling requires actual legacy VGA I/O access,
440 * and as part of the cleanup in the hw state restore we also redisable
441 * the vga plane.
442 */
443 if (!HAS_PCH_SPLIT(dev)) {
444 drm_modeset_lock_all(dev);
445 intel_modeset_setup_hw_state(dev, true);
446 drm_modeset_unlock_all(dev);
447 }
Jesse Barnes06324192009-09-10 15:28:05 -0700448
Zhang Ruib8efb172013-02-05 15:41:53 +0800449 dev_priv->modeset_restore = MODESET_DONE;
450
451exit:
452 mutex_unlock(&dev_priv->modeset_restore_lock);
Jesse Barnesc1c7af62009-09-10 15:28:03 -0700453 return NOTIFY_OK;
454}
455
Jesse Barnes79e53942008-11-07 14:24:08 -0800456/**
457 * intel_lvds_destroy - unregister and free LVDS structures
458 * @connector: connector to free
459 *
460 * Unregister the DDC bus for this connector then free the driver private
461 * structure.
462 */
463static void intel_lvds_destroy(struct drm_connector *connector)
464{
Jani Nikuladb1740a2012-10-19 14:51:45 +0300465 struct intel_lvds_connector *lvds_connector =
466 to_lvds_connector(connector);
Jesse Barnes79e53942008-11-07 14:24:08 -0800467
Jani Nikuladb1740a2012-10-19 14:51:45 +0300468 if (lvds_connector->lid_notifier.notifier_call)
469 acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
Matthew Garrettaaa6fd22011-08-12 12:11:33 +0200470
Jani Nikula9cd300e2012-10-19 14:51:52 +0300471 if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
472 kfree(lvds_connector->base.edid);
473
Jani Nikula1d508702012-10-19 14:51:49 +0300474 intel_panel_fini(&lvds_connector->base.panel);
Jani Nikuladb1740a2012-10-19 14:51:45 +0300475
Jesse Barnes79e53942008-11-07 14:24:08 -0800476 drm_connector_cleanup(connector);
477 kfree(connector);
478}
479
Jesse Barnes335041e2009-01-22 22:22:06 +1000480static int intel_lvds_set_property(struct drm_connector *connector,
481 struct drm_property *property,
482 uint64_t value)
483{
Jani Nikula4d891522012-10-26 12:03:59 +0300484 struct intel_connector *intel_connector = to_intel_connector(connector);
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800485 struct drm_device *dev = connector->dev;
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800486
Chris Wilson788319d2010-09-12 17:34:41 +0100487 if (property == dev->mode_config.scaling_mode_property) {
Jani Nikula62165e02012-10-19 14:51:47 +0300488 struct drm_crtc *crtc;
Zhenyu Wangbb8a3562010-03-29 16:40:50 +0800489
Jesse Barnes53bd8382009-07-01 10:04:40 -0700490 if (value == DRM_MODE_SCALE_NONE) {
491 DRM_DEBUG_KMS("no scaling not supported\n");
Chris Wilson788319d2010-09-12 17:34:41 +0100492 return -EINVAL;
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800493 }
Chris Wilson788319d2010-09-12 17:34:41 +0100494
Jani Nikula4d891522012-10-26 12:03:59 +0300495 if (intel_connector->panel.fitting_mode == value) {
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800496 /* the LVDS scaling property is not changed */
497 return 0;
498 }
Jani Nikula4d891522012-10-26 12:03:59 +0300499 intel_connector->panel.fitting_mode = value;
Jani Nikula62165e02012-10-19 14:51:47 +0300500
501 crtc = intel_attached_encoder(connector)->base.crtc;
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800502 if (crtc && crtc->enabled) {
503 /*
504 * If the CRTC is enabled, the display will be changed
505 * according to the new panel fitting mode.
506 */
Chris Wilsonc0c36b942012-12-19 16:08:43 +0000507 intel_crtc_restore_mode(crtc);
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800508 }
509 }
510
Jesse Barnes335041e2009-01-22 22:22:06 +1000511 return 0;
512}
513
Jesse Barnes79e53942008-11-07 14:24:08 -0800514static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
515 .get_modes = intel_lvds_get_modes,
516 .mode_valid = intel_lvds_mode_valid,
Chris Wilsondf0e9242010-09-09 16:20:55 +0100517 .best_encoder = intel_best_encoder,
Jesse Barnes79e53942008-11-07 14:24:08 -0800518};
519
520static const struct drm_connector_funcs intel_lvds_connector_funcs = {
Daniel Vetterc22834e2012-06-30 15:31:28 +0200521 .dpms = intel_connector_dpms,
Jesse Barnes79e53942008-11-07 14:24:08 -0800522 .detect = intel_lvds_detect,
523 .fill_modes = drm_helper_probe_single_connector_modes,
Jesse Barnes335041e2009-01-22 22:22:06 +1000524 .set_property = intel_lvds_set_property,
Jesse Barnes79e53942008-11-07 14:24:08 -0800525 .destroy = intel_lvds_destroy,
526};
527
Jesse Barnes79e53942008-11-07 14:24:08 -0800528static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
Chris Wilsonea5b2132010-08-04 13:50:23 +0100529 .destroy = intel_encoder_destroy,
Jesse Barnes79e53942008-11-07 14:24:08 -0800530};
531
Jarod Wilson425d2442009-05-05 10:00:25 -0400532static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
533{
Daniel Vetterbc0daf42012-04-01 13:16:49 +0200534 DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
Jarod Wilson425d2442009-05-05 10:00:25 -0400535 return 1;
536}
Jesse Barnes79e53942008-11-07 14:24:08 -0800537
Jarod Wilson425d2442009-05-05 10:00:25 -0400538/* These systems claim to have LVDS, but really don't */
Jaswinder Singh Rajput93c05f22009-06-04 09:41:19 +1000539static const struct dmi_system_id intel_no_lvds[] = {
Jarod Wilson425d2442009-05-05 10:00:25 -0400540 {
541 .callback = intel_no_lvds_dmi_callback,
542 .ident = "Apple Mac Mini (Core series)",
543 .matches = {
Keith Packard98acd462009-06-14 12:31:58 -0700544 DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
Jarod Wilson425d2442009-05-05 10:00:25 -0400545 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
546 },
547 },
548 {
549 .callback = intel_no_lvds_dmi_callback,
550 .ident = "Apple Mac Mini (Core 2 series)",
551 .matches = {
Keith Packard98acd462009-06-14 12:31:58 -0700552 DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
Jarod Wilson425d2442009-05-05 10:00:25 -0400553 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
554 },
555 },
556 {
557 .callback = intel_no_lvds_dmi_callback,
558 .ident = "MSI IM-945GSE-A",
559 .matches = {
560 DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
561 DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
562 },
563 },
564 {
565 .callback = intel_no_lvds_dmi_callback,
566 .ident = "Dell Studio Hybrid",
567 .matches = {
568 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
569 DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
570 },
571 },
Jarod Wilson70aa96c2009-05-27 17:20:39 -0400572 {
573 .callback = intel_no_lvds_dmi_callback,
Pieterjan Camerlynckb0662542011-07-26 16:23:54 +0200574 .ident = "Dell OptiPlex FX170",
575 .matches = {
576 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
577 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
578 },
579 },
580 {
581 .callback = intel_no_lvds_dmi_callback,
Jarod Wilson70aa96c2009-05-27 17:20:39 -0400582 .ident = "AOpen Mini PC",
583 .matches = {
584 DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
585 DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
586 },
587 },
Michael Cousinfa0864b2009-06-05 21:16:22 +0200588 {
589 .callback = intel_no_lvds_dmi_callback,
Tormod Voldened8c7542009-07-13 22:26:48 +0200590 .ident = "AOpen Mini PC MP915",
591 .matches = {
592 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
593 DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
594 },
595 },
596 {
597 .callback = intel_no_lvds_dmi_callback,
Knut Petersen22ab70d2011-01-14 15:38:10 +0000598 .ident = "AOpen i915GMm-HFS",
599 .matches = {
600 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
601 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
602 },
603 },
604 {
605 .callback = intel_no_lvds_dmi_callback,
Daniel Vettere57b6882012-02-08 16:42:52 +0100606 .ident = "AOpen i45GMx-I",
607 .matches = {
608 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
609 DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
610 },
611 },
612 {
613 .callback = intel_no_lvds_dmi_callback,
Michael Cousinfa0864b2009-06-05 21:16:22 +0200614 .ident = "Aopen i945GTt-VFA",
615 .matches = {
616 DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
617 },
618 },
Stefan Bader9875557ee82010-03-29 17:53:12 +0200619 {
620 .callback = intel_no_lvds_dmi_callback,
621 .ident = "Clientron U800",
622 .matches = {
623 DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
624 DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
625 },
626 },
Hans de Goede6a574b52011-06-04 15:39:21 +0200627 {
Joel Sass44306ab2012-01-10 13:03:55 -0500628 .callback = intel_no_lvds_dmi_callback,
629 .ident = "Clientron E830",
630 .matches = {
631 DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
632 DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
633 },
634 },
635 {
Hans de Goede6a574b52011-06-04 15:39:21 +0200636 .callback = intel_no_lvds_dmi_callback,
637 .ident = "Asus EeeBox PC EB1007",
638 .matches = {
639 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
640 DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
641 },
642 },
Adam Jackson0999bbe2011-11-28 12:22:56 -0500643 {
644 .callback = intel_no_lvds_dmi_callback,
645 .ident = "Asus AT5NM10T-I",
646 .matches = {
647 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
648 DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
649 },
650 },
Marc Gariepyf5b8a7e2012-02-09 09:35:21 -0500651 {
652 .callback = intel_no_lvds_dmi_callback,
Ben Mesman45a211d2013-04-16 20:00:28 +0200653 .ident = "Hewlett-Packard HP t5740",
Jan-Benedict Glaw33471112012-05-22 15:21:53 +0200654 .matches = {
655 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
Ben Mesman45a211d2013-04-16 20:00:28 +0200656 DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
Jan-Benedict Glaw33471112012-05-22 15:21:53 +0200657 },
658 },
659 {
660 .callback = intel_no_lvds_dmi_callback,
Marc Gariepyf5b8a7e2012-02-09 09:35:21 -0500661 .ident = "Hewlett-Packard t5745",
662 .matches = {
663 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
Marc Gariepy62004972012-05-01 13:37:57 -0400664 DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
Marc Gariepyf5b8a7e2012-02-09 09:35:21 -0500665 },
666 },
667 {
668 .callback = intel_no_lvds_dmi_callback,
669 .ident = "Hewlett-Packard st5747",
670 .matches = {
671 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
Marc Gariepy62004972012-05-01 13:37:57 -0400672 DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
Marc Gariepyf5b8a7e2012-02-09 09:35:21 -0500673 },
674 },
Anisse Astier97effad2012-03-07 18:36:35 +0100675 {
676 .callback = intel_no_lvds_dmi_callback,
677 .ident = "MSI Wind Box DC500",
678 .matches = {
679 DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
680 DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
681 },
682 },
Sjoerd Simons9756fe32012-06-22 09:43:07 +0200683 {
684 .callback = intel_no_lvds_dmi_callback,
Calvin Waltona51d4ed2012-08-24 07:56:31 -0400685 .ident = "Gigabyte GA-D525TUD",
686 .matches = {
687 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
688 DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
689 },
690 },
Chris Wilsonc31407a2012-10-18 21:07:01 +0100691 {
692 .callback = intel_no_lvds_dmi_callback,
693 .ident = "Supermicro X7SPA-H",
694 .matches = {
695 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
696 DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
697 },
698 },
Christian Lamparter9e9dd0e2013-04-03 14:34:11 +0200699 {
700 .callback = intel_no_lvds_dmi_callback,
701 .ident = "Fujitsu Esprimo Q900",
702 .matches = {
703 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
704 DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
705 },
706 },
Chris Wilsone5614f02013-07-03 15:05:03 -0700707 {
708 .callback = intel_no_lvds_dmi_callback,
Rob Pearce645378d2013-10-27 16:13:42 +0000709 .ident = "Intel D410PT",
710 .matches = {
711 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
712 DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
713 },
714 },
715 {
716 .callback = intel_no_lvds_dmi_callback,
717 .ident = "Intel D425KT",
718 .matches = {
719 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
720 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
721 },
722 },
723 {
724 .callback = intel_no_lvds_dmi_callback,
Chris Wilsone5614f02013-07-03 15:05:03 -0700725 .ident = "Intel D510MO",
726 .matches = {
727 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
728 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),
729 },
730 },
Jani Nikuladcf6d292013-07-03 15:05:05 -0700731 {
732 .callback = intel_no_lvds_dmi_callback,
733 .ident = "Intel D525MW",
734 .matches = {
735 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
736 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
737 },
738 },
Jarod Wilson425d2442009-05-05 10:00:25 -0400739
740 { } /* terminating entry */
741};
Jesse Barnes79e53942008-11-07 14:24:08 -0800742
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800743/*
744 * Enumerate the child dev array parsed from VBT to check whether
745 * the LVDS is present.
746 * If it is present, return 1.
747 * If it is not present, return false.
748 * If no child dev is parsed from VBT, it assumes that the LVDS is present.
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800749 */
Chris Wilson270eea02010-09-24 01:15:02 +0100750static bool lvds_is_present_in_vbt(struct drm_device *dev,
751 u8 *i2c_pin)
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800752{
753 struct drm_i915_private *dev_priv = dev->dev_private;
Chris Wilson425904d2010-08-22 18:21:42 +0100754 int i;
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800755
Rodrigo Vivi41aa3442013-05-09 20:03:18 -0300756 if (!dev_priv->vbt.child_dev_num)
Chris Wilson425904d2010-08-22 18:21:42 +0100757 return true;
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800758
Rodrigo Vivi41aa3442013-05-09 20:03:18 -0300759 for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
Paulo Zanoni768f69c2013-09-11 18:02:47 -0300760 union child_device_config *uchild = dev_priv->vbt.child_dev + i;
761 struct old_child_dev_config *child = &uchild->old;
Chris Wilson425904d2010-08-22 18:21:42 +0100762
763 /* If the device type is not LFP, continue.
764 * We have to check both the new identifiers as well as the
765 * old for compatibility with some BIOSes.
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800766 */
Chris Wilson425904d2010-08-22 18:21:42 +0100767 if (child->device_type != DEVICE_TYPE_INT_LFP &&
768 child->device_type != DEVICE_TYPE_LFP)
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800769 continue;
770
Daniel Kurtz3bd7d902012-03-28 02:36:14 +0800771 if (intel_gmbus_is_port_valid(child->i2c_pin))
772 *i2c_pin = child->i2c_pin;
Chris Wilson270eea02010-09-24 01:15:02 +0100773
Chris Wilson425904d2010-08-22 18:21:42 +0100774 /* However, we cannot trust the BIOS writers to populate
775 * the VBT correctly. Since LVDS requires additional
776 * information from AIM blocks, a non-zero addin offset is
777 * a good indicator that the LVDS is actually present.
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800778 */
Chris Wilson425904d2010-08-22 18:21:42 +0100779 if (child->addin_offset)
780 return true;
781
782 /* But even then some BIOS writers perform some black magic
783 * and instantiate the device without reference to any
784 * additional data. Trust that if the VBT was written into
785 * the OpRegion then they have validated the LVDS's existence.
786 */
787 if (dev_priv->opregion.vbt)
788 return true;
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800789 }
Chris Wilson425904d2010-08-22 18:21:42 +0100790
791 return false;
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800792}
793
Daniel Vetter1974cad2012-11-26 17:22:09 +0100794static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
795{
796 DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
797 return 1;
798}
799
800static const struct dmi_system_id intel_dual_link_lvds[] = {
801 {
802 .callback = intel_dual_link_lvds_callback,
803 .ident = "Apple MacBook Pro (Core i5/i7 Series)",
804 .matches = {
805 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
806 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
807 },
808 },
809 { } /* terminating entry */
810};
811
812bool intel_is_dual_link_lvds(struct drm_device *dev)
813{
Daniel Vetter13c7d872012-11-26 17:22:10 +0100814 struct intel_encoder *encoder;
815 struct intel_lvds_encoder *lvds_encoder;
816
817 list_for_each_entry(encoder, &dev->mode_config.encoder_list,
818 base.head) {
819 if (encoder->type == INTEL_OUTPUT_LVDS) {
820 lvds_encoder = to_lvds_encoder(&encoder->base);
821
822 return lvds_encoder->is_dual_link;
823 }
824 }
825
826 return false;
827}
828
Daniel Vetter7dec0602012-09-11 14:12:25 +0200829static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
Daniel Vetter13c7d872012-11-26 17:22:10 +0100830{
Daniel Vetter7dec0602012-09-11 14:12:25 +0200831 struct drm_device *dev = lvds_encoder->base.base.dev;
Daniel Vetter1974cad2012-11-26 17:22:09 +0100832 unsigned int val;
833 struct drm_i915_private *dev_priv = dev->dev_private;
Daniel Vetter1974cad2012-11-26 17:22:09 +0100834
835 /* use the module option value if specified */
Jani Nikulad330a952014-01-21 11:24:25 +0200836 if (i915.lvds_channel_mode > 0)
837 return i915.lvds_channel_mode == 2;
Daniel Vetter1974cad2012-11-26 17:22:09 +0100838
839 if (dmi_check_system(intel_dual_link_lvds))
840 return true;
841
Daniel Vetter13c7d872012-11-26 17:22:10 +0100842 /* BIOS should set the proper LVDS register value at boot, but
843 * in reality, it doesn't set the value when the lid is closed;
844 * we need to check "the value to be set" in VBT when LVDS
845 * register is uninitialized.
846 */
Daniel Vetter7dec0602012-09-11 14:12:25 +0200847 val = I915_READ(lvds_encoder->reg);
Daniel Vetter13c7d872012-11-26 17:22:10 +0100848 if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
Rodrigo Vivi41aa3442013-05-09 20:03:18 -0300849 val = dev_priv->vbt.bios_lvds_val;
Daniel Vetter13c7d872012-11-26 17:22:10 +0100850
Daniel Vetter1974cad2012-11-26 17:22:09 +0100851 return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
852}
853
Chris Wilsonf3cfcba2012-02-09 09:35:53 +0000854static bool intel_lvds_supported(struct drm_device *dev)
855{
856 /* With the introduction of the PCH we gained a dedicated
857 * LVDS presence pin, use it. */
Paulo Zanoni311e3592013-03-06 20:03:19 -0300858 if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
Chris Wilsonf3cfcba2012-02-09 09:35:53 +0000859 return true;
860
861 /* Otherwise LVDS was only attached to mobile products,
862 * except for the inglorious 830gm */
Paulo Zanoni311e3592013-03-06 20:03:19 -0300863 if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
864 return true;
865
866 return false;
Chris Wilsonf3cfcba2012-02-09 09:35:53 +0000867}
868
Zhao Yakui18f9ed12009-11-20 03:24:16 +0000869/**
Jesse Barnes79e53942008-11-07 14:24:08 -0800870 * intel_lvds_init - setup LVDS connectors on this device
871 * @dev: drm device
872 *
873 * Create the connector, register the LVDS DDC bus, and try to figure out what
874 * modes we can display on the LVDS panel (if present).
875 */
Daniel Vetterc9093352013-06-06 22:22:47 +0200876void intel_lvds_init(struct drm_device *dev)
Jesse Barnes79e53942008-11-07 14:24:08 -0800877{
878 struct drm_i915_private *dev_priv = dev->dev_private;
Jani Nikula29b99b42012-10-19 14:51:43 +0300879 struct intel_lvds_encoder *lvds_encoder;
Eric Anholt21d40d32010-03-25 11:11:14 -0700880 struct intel_encoder *intel_encoder;
Jani Nikulac7362c42012-10-19 14:51:44 +0300881 struct intel_lvds_connector *lvds_connector;
Zhenyu Wangbb8a3562010-03-29 16:40:50 +0800882 struct intel_connector *intel_connector;
Jesse Barnes79e53942008-11-07 14:24:08 -0800883 struct drm_connector *connector;
884 struct drm_encoder *encoder;
885 struct drm_display_mode *scan; /* *modes, *bios_mode; */
Jani Nikuladd06f902012-10-19 14:51:50 +0300886 struct drm_display_mode *fixed_mode = NULL;
Vandana Kannan4b6ed682014-02-11 14:26:36 +0530887 struct drm_display_mode *downclock_mode = NULL;
Jani Nikula9cd300e2012-10-19 14:51:52 +0300888 struct edid *edid;
Jesse Barnes79e53942008-11-07 14:24:08 -0800889 struct drm_crtc *crtc;
890 u32 lvds;
Chris Wilson270eea02010-09-24 01:15:02 +0100891 int pipe;
892 u8 pin;
Jesse Barnes79e53942008-11-07 14:24:08 -0800893
Chris Wilsonf3cfcba2012-02-09 09:35:53 +0000894 if (!intel_lvds_supported(dev))
Daniel Vetterc9093352013-06-06 22:22:47 +0200895 return;
Chris Wilsonf3cfcba2012-02-09 09:35:53 +0000896
Jarod Wilson425d2442009-05-05 10:00:25 -0400897 /* Skip init on machines we know falsely report LVDS */
898 if (dmi_check_system(intel_no_lvds))
Daniel Vetterc9093352013-06-06 22:22:47 +0200899 return;
Paul Collins565dcd42009-02-04 23:05:41 +1300900
Chris Wilson270eea02010-09-24 01:15:02 +0100901 pin = GMBUS_PORT_PANEL;
902 if (!lvds_is_present_in_vbt(dev, &pin)) {
Matthew Garrett11ba1592009-12-15 13:55:24 -0500903 DRM_DEBUG_KMS("LVDS is not present in VBT\n");
Daniel Vetterc9093352013-06-06 22:22:47 +0200904 return;
Zhao Yakui7cf4f692009-11-24 09:48:47 +0800905 }
Zhao Yakuie99da352009-06-26 09:46:18 +0800906
Eric Anholtc619eed2010-01-28 16:45:52 -0800907 if (HAS_PCH_SPLIT(dev)) {
Zhenyu Wang541998a2009-06-05 15:38:44 +0800908 if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
Daniel Vetterc9093352013-06-06 22:22:47 +0200909 return;
Rodrigo Vivi41aa3442013-05-09 20:03:18 -0300910 if (dev_priv->vbt.edp_support) {
Zhao Yakui28c97732009-10-09 11:39:41 +0800911 DRM_DEBUG_KMS("disable LVDS for eDP support\n");
Daniel Vetterc9093352013-06-06 22:22:47 +0200912 return;
Zhenyu Wang32f9d652009-07-24 01:00:32 +0800913 }
Zhenyu Wang541998a2009-06-05 15:38:44 +0800914 }
915
Daniel Vetterb14c5672013-09-19 12:18:32 +0200916 lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
Jani Nikula29b99b42012-10-19 14:51:43 +0300917 if (!lvds_encoder)
Daniel Vetterc9093352013-06-06 22:22:47 +0200918 return;
Jesse Barnes79e53942008-11-07 14:24:08 -0800919
Daniel Vetterb14c5672013-09-19 12:18:32 +0200920 lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
Jani Nikulac7362c42012-10-19 14:51:44 +0300921 if (!lvds_connector) {
Jani Nikula29b99b42012-10-19 14:51:43 +0300922 kfree(lvds_encoder);
Daniel Vetterc9093352013-06-06 22:22:47 +0200923 return;
Jesse Barnes79e53942008-11-07 14:24:08 -0800924 }
925
Jani Nikula62165e02012-10-19 14:51:47 +0300926 lvds_encoder->attached_connector = lvds_connector;
Zhenyu Wangbb8a3562010-03-29 16:40:50 +0800927
Jani Nikula29b99b42012-10-19 14:51:43 +0300928 intel_encoder = &lvds_encoder->base;
Chris Wilson4ef69c72010-09-09 15:14:28 +0100929 encoder = &intel_encoder->base;
Jani Nikulac7362c42012-10-19 14:51:44 +0300930 intel_connector = &lvds_connector->base;
Chris Wilsonea5b2132010-08-04 13:50:23 +0100931 connector = &intel_connector->base;
Zhenyu Wangbb8a3562010-03-29 16:40:50 +0800932 drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
Jesse Barnes79e53942008-11-07 14:24:08 -0800933 DRM_MODE_CONNECTOR_LVDS);
934
Chris Wilson4ef69c72010-09-09 15:14:28 +0100935 drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
Jesse Barnes79e53942008-11-07 14:24:08 -0800936 DRM_MODE_ENCODER_LVDS);
937
Daniel Vetterc22834e2012-06-30 15:31:28 +0200938 intel_encoder->enable = intel_enable_lvds;
Daniel Vetterf6736a12013-06-05 13:34:30 +0200939 intel_encoder->pre_enable = intel_pre_enable_lvds;
Daniel Vetter7ae89232013-03-27 00:44:52 +0100940 intel_encoder->compute_config = intel_lvds_compute_config;
Daniel Vetterc22834e2012-06-30 15:31:28 +0200941 intel_encoder->disable = intel_disable_lvds;
Daniel Vetterb1dc3322012-07-02 21:09:00 +0200942 intel_encoder->get_hw_state = intel_lvds_get_hw_state;
Jesse Barnes045ac3b2013-05-14 17:08:26 -0700943 intel_encoder->get_config = intel_lvds_get_config;
Daniel Vetterb1dc3322012-07-02 21:09:00 +0200944 intel_connector->get_hw_state = intel_connector_get_hw_state;
Imre Deak4932e2c2014-02-11 17:12:48 +0200945 intel_connector->unregister = intel_connector_unregister;
Daniel Vetterc22834e2012-06-30 15:31:28 +0200946
Chris Wilsondf0e9242010-09-09 16:20:55 +0100947 intel_connector_attach_encoder(intel_connector, intel_encoder);
Eric Anholt21d40d32010-03-25 11:11:14 -0700948 intel_encoder->type = INTEL_OUTPUT_LVDS;
Jesse Barnes79e53942008-11-07 14:24:08 -0800949
Ville Syrjäläbc079e82014-03-03 16:15:28 +0200950 intel_encoder->cloneable = 0;
Jesse Barnes27f82272011-09-02 12:54:37 -0700951 if (HAS_PCH_SPLIT(dev))
952 intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
Daniel Vetter0b9f43a2012-06-05 10:07:11 +0200953 else if (IS_GEN4(dev))
954 intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
Jesse Barnes27f82272011-09-02 12:54:37 -0700955 else
956 intel_encoder->crtc_mask = (1 << 1);
957
Jesse Barnes79e53942008-11-07 14:24:08 -0800958 drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
959 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
960 connector->interlace_allowed = false;
961 connector->doublescan_allowed = false;
962
Daniel Vetter7dec0602012-09-11 14:12:25 +0200963 if (HAS_PCH_SPLIT(dev)) {
964 lvds_encoder->reg = PCH_LVDS;
965 } else {
966 lvds_encoder->reg = LVDS;
967 }
968
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800969 /* create the scaling mode property */
970 drm_mode_create_scaling_mode_property(dev);
Rob Clark662595d2012-10-11 20:36:04 -0500971 drm_object_attach_property(&connector->base,
Zhao Yakui3fbe18d2009-06-22 15:31:25 +0800972 dev->mode_config.scaling_mode_property,
Jesse Barnesdd1ea372010-06-24 11:05:10 -0700973 DRM_MODE_SCALE_ASPECT);
Jani Nikula4d891522012-10-26 12:03:59 +0300974 intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
Jesse Barnes79e53942008-11-07 14:24:08 -0800975 /*
976 * LVDS discovery:
977 * 1) check for EDID on DDC
978 * 2) check for VBT data
979 * 3) check to see if LVDS is already on
980 * if none of the above, no panel
981 * 4) make sure lid is open
982 * if closed, act like it's not there for now
983 */
984
Jesse Barnes79e53942008-11-07 14:24:08 -0800985 /*
986 * Attempt to get the fixed panel mode from DDC. Assume that the
987 * preferred mode is the right one.
988 */
Daniel Vetter4da98542014-03-21 23:22:35 +0100989 mutex_lock(&dev->mode_config.mutex);
Jani Nikula9cd300e2012-10-19 14:51:52 +0300990 edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
991 if (edid) {
992 if (drm_add_edid_modes(connector, edid)) {
Chris Wilson3f8ff0e2010-11-08 23:20:52 +0000993 drm_mode_connector_update_edid_property(connector,
Jani Nikula9cd300e2012-10-19 14:51:52 +0300994 edid);
Chris Wilson3f8ff0e2010-11-08 23:20:52 +0000995 } else {
Jani Nikula9cd300e2012-10-19 14:51:52 +0300996 kfree(edid);
997 edid = ERR_PTR(-EINVAL);
Chris Wilson3f8ff0e2010-11-08 23:20:52 +0000998 }
Jani Nikula9cd300e2012-10-19 14:51:52 +0300999 } else {
1000 edid = ERR_PTR(-ENOENT);
Chris Wilson3f8ff0e2010-11-08 23:20:52 +00001001 }
Jani Nikula9cd300e2012-10-19 14:51:52 +03001002 lvds_connector->base.edid = edid;
1003
1004 if (IS_ERR_OR_NULL(edid)) {
Chris Wilson788319d2010-09-12 17:34:41 +01001005 /* Didn't get an EDID, so
1006 * Set wide sync ranges so we get all modes
1007 * handed to valid_mode for checking
1008 */
1009 connector->display_info.min_vfreq = 0;
1010 connector->display_info.max_vfreq = 200;
1011 connector->display_info.min_hfreq = 0;
1012 connector->display_info.max_hfreq = 200;
1013 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001014
1015 list_for_each_entry(scan, &connector->probed_modes, head) {
Jesse Barnes79e53942008-11-07 14:24:08 -08001016 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001017 DRM_DEBUG_KMS("using preferred mode from EDID: ");
1018 drm_mode_debug_printmodeline(scan);
1019
Jani Nikuladd06f902012-10-19 14:51:50 +03001020 fixed_mode = drm_mode_duplicate(dev, scan);
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001021 if (fixed_mode) {
Vandana Kannan4b6ed682014-02-11 14:26:36 +05301022 downclock_mode =
Vandana Kannanec9ed192013-12-10 13:37:36 +05301023 intel_find_panel_downclock(dev,
1024 fixed_mode, connector);
Vandana Kannan4b6ed682014-02-11 14:26:36 +05301025 if (downclock_mode != NULL &&
1026 i915.lvds_downclock) {
Vandana Kannanec9ed192013-12-10 13:37:36 +05301027 /* We found the downclock for LVDS. */
1028 dev_priv->lvds_downclock_avail = true;
1029 dev_priv->lvds_downclock =
Vandana Kannanec9ed192013-12-10 13:37:36 +05301030 downclock_mode->clock;
1031 DRM_DEBUG_KMS("LVDS downclock is found"
1032 " in EDID. Normal clock %dKhz, "
1033 "downclock %dKhz\n",
1034 fixed_mode->clock,
1035 dev_priv->lvds_downclock);
1036 }
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001037 goto out;
1038 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001039 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001040 }
1041
1042 /* Failed to get EDID, what about VBT? */
Rodrigo Vivi41aa3442013-05-09 20:03:18 -03001043 if (dev_priv->vbt.lfp_lvds_vbt_mode) {
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001044 DRM_DEBUG_KMS("using mode from VBT: ");
Rodrigo Vivi41aa3442013-05-09 20:03:18 -03001045 drm_mode_debug_printmodeline(dev_priv->vbt.lfp_lvds_vbt_mode);
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001046
Rodrigo Vivi41aa3442013-05-09 20:03:18 -03001047 fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
Jani Nikuladd06f902012-10-19 14:51:50 +03001048 if (fixed_mode) {
1049 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
Jesse Barnese285f3cd2009-01-14 10:53:36 -08001050 goto out;
1051 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001052 }
1053
1054 /*
1055 * If we didn't get EDID, try checking if the panel is already turned
1056 * on. If so, assume that whatever is currently programmed is the
1057 * correct mode.
1058 */
Zhenyu Wang541998a2009-06-05 15:38:44 +08001059
Adam Jacksonf2b115e2009-12-03 17:14:42 -05001060 /* Ironlake: FIXME if still fail, not try pipe mode now */
Eric Anholtc619eed2010-01-28 16:45:52 -08001061 if (HAS_PCH_SPLIT(dev))
Zhenyu Wang541998a2009-06-05 15:38:44 +08001062 goto failed;
1063
Jesse Barnes79e53942008-11-07 14:24:08 -08001064 lvds = I915_READ(LVDS);
1065 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
Chris Wilsonf875c152010-09-09 15:44:14 +01001066 crtc = intel_get_crtc_for_pipe(dev, pipe);
Jesse Barnes79e53942008-11-07 14:24:08 -08001067
1068 if (crtc && (lvds & LVDS_PORT_EN)) {
Jani Nikuladd06f902012-10-19 14:51:50 +03001069 fixed_mode = intel_crtc_mode_get(dev, crtc);
1070 if (fixed_mode) {
Chris Wilson6a9d51b2012-11-21 16:14:03 +00001071 DRM_DEBUG_KMS("using current (BIOS) mode: ");
1072 drm_mode_debug_printmodeline(fixed_mode);
Jani Nikuladd06f902012-10-19 14:51:50 +03001073 fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
Paul Collins565dcd42009-02-04 23:05:41 +13001074 goto out;
Jesse Barnes79e53942008-11-07 14:24:08 -08001075 }
1076 }
1077
1078 /* If we still don't have a mode after all that, give up. */
Jani Nikuladd06f902012-10-19 14:51:50 +03001079 if (!fixed_mode)
Jesse Barnes79e53942008-11-07 14:24:08 -08001080 goto failed;
1081
Jesse Barnes79e53942008-11-07 14:24:08 -08001082out:
Daniel Vetter4da98542014-03-21 23:22:35 +01001083 mutex_unlock(&dev->mode_config.mutex);
1084
Daniel Vetter7dec0602012-09-11 14:12:25 +02001085 lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
Daniel Vetter13c7d872012-11-26 17:22:10 +01001086 DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
1087 lvds_encoder->is_dual_link ? "dual" : "single");
1088
Daniel Vetter24ded202012-06-05 12:14:54 +02001089 /*
1090 * Unlock registers and just
1091 * leave them unlocked
1092 */
Eric Anholtc619eed2010-01-28 16:45:52 -08001093 if (HAS_PCH_SPLIT(dev)) {
Keith Packarded10fca2011-08-06 10:33:12 -07001094 I915_WRITE(PCH_PP_CONTROL,
1095 I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
1096 } else {
Keith Packarded10fca2011-08-06 10:33:12 -07001097 I915_WRITE(PP_CONTROL,
1098 I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
Zhenyu Wang541998a2009-06-05 15:38:44 +08001099 }
Jani Nikuladb1740a2012-10-19 14:51:45 +03001100 lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
1101 if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
Zhao Yakui28c97732009-10-09 11:39:41 +08001102 DRM_DEBUG_KMS("lid notifier registration failed\n");
Jani Nikuladb1740a2012-10-19 14:51:45 +03001103 lvds_connector->lid_notifier.notifier_call = NULL;
Jesse Barnesc1c7af62009-09-10 15:28:03 -07001104 }
Jesse Barnes79e53942008-11-07 14:24:08 -08001105 drm_sysfs_connector_add(connector);
Matthew Garrettaaa6fd22011-08-12 12:11:33 +02001106
Vandana Kannan4b6ed682014-02-11 14:26:36 +05301107 intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
Jani Nikula0657b6b2012-10-19 14:51:46 +03001108 intel_panel_setup_backlight(connector);
Matthew Garrettaaa6fd22011-08-12 12:11:33 +02001109
Daniel Vetterc9093352013-06-06 22:22:47 +02001110 return;
Jesse Barnes79e53942008-11-07 14:24:08 -08001111
1112failed:
Daniel Vetter4da98542014-03-21 23:22:35 +01001113 mutex_unlock(&dev->mode_config.mutex);
1114
Zhao Yakui8a4c47f2009-07-20 13:48:04 +08001115 DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
Jesse Barnes79e53942008-11-07 14:24:08 -08001116 drm_connector_cleanup(connector);
Shaohua Li1991bdf2009-11-17 17:19:23 +08001117 drm_encoder_cleanup(encoder);
Jani Nikula29b99b42012-10-19 14:51:43 +03001118 kfree(lvds_encoder);
Jani Nikulac7362c42012-10-19 14:51:44 +03001119 kfree(lvds_connector);
Daniel Vetterc9093352013-06-06 22:22:47 +02001120 return;
Jesse Barnes79e53942008-11-07 14:24:08 -08001121}