11b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/*
21b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * Copyright © 2006-2009 Intel Corporation
31b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *
41b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * This program is free software; you can redistribute it and/or modify it
51b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * under the terms and conditions of the GNU General Public License,
61b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * version 2, as published by the Free Software Foundation.
71b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *
81b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * This program is distributed in the hope it will be useful, but WITHOUT
91b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
101b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
111b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * more details.
121b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *
131b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * You should have received a copy of the GNU General Public License along with
141b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * this program; if not, write to the Free Software Foundation, Inc.,
151b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
161b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *
171b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * Authors:
181b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *	Eric Anholt <eric@anholt.net>
191b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *	Dave Airlie <airlied@linux.ie>
201b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *	Jesse Barnes <jesse.barnes@intel.com>
211b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox */
221b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
231b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include <linux/i2c.h>
241b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include <drm/drmP.h>
251b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include <asm/mrst.h>
261b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
271b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include "intel_bios.h"
281b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include "psb_drv.h"
291b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include "psb_intel_drv.h"
301b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include "psb_intel_reg.h"
311b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include "power.h"
321b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#include <linux/pm_runtime.h>
331b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
341b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/* The max/min PWM frequency in BPCR[31:17] - */
351b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/* The smallest number is 1 (not 0) that can fit in the
361b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * 15-bit field of the and then*/
371b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/* shifts to the left by one bit to get the actual 16-bit
381b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * value that the 15-bits correspond to.*/
391b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#define MRST_BLC_MAX_PWM_REG_FREQ	    0xFFFF
401b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#define BRIGHTNESS_MAX_LEVEL 100
411b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
421b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/**
431b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * Sets the power state for the panel.
441b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox */
451b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic void oaktrail_lvds_set_power(struct drm_device *dev,
469bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson				struct psb_intel_encoder *psb_intel_encoder,
479bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson				bool on)
481b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
491b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	u32 pp_status;
501b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
511b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
521b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (!gma_power_begin(dev, true))
531b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		return;
541b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
551b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (on) {
561b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
571b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  POWER_TARGET_ON);
581b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		do {
591b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			pp_status = REG_READ(PP_STATUS);
601b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		} while ((pp_status & (PP_ON | PP_READY)) == PP_READY);
611b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		dev_priv->is_lvds_on = true;
621b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		if (dev_priv->ops->lvds_bl_power)
631b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			dev_priv->ops->lvds_bl_power(dev, true);
641b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	} else {
651b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		if (dev_priv->ops->lvds_bl_power)
661b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			dev_priv->ops->lvds_bl_power(dev, false);
671b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
681b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  ~POWER_TARGET_ON);
691b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		do {
701b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			pp_status = REG_READ(PP_STATUS);
711b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		} while (pp_status & PP_ON);
721b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		dev_priv->is_lvds_on = false;
731b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		pm_request_idle(&dev->pdev->dev);
741b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	}
751b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	gma_power_end(dev);
761b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
771b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
781b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic void oaktrail_lvds_dpms(struct drm_encoder *encoder, int mode)
791b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
801b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_device *dev = encoder->dev;
819bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_encoder *psb_intel_encoder =
829bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson						to_psb_intel_encoder(encoder);
831b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
841b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (mode == DRM_MODE_DPMS_ON)
859bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		oaktrail_lvds_set_power(dev, psb_intel_encoder, true);
861b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	else
879bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		oaktrail_lvds_set_power(dev, psb_intel_encoder, false);
881b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
891b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* XXX: We never power down the LVDS pairs. */
901b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
911b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
921b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic void oaktrail_lvds_mode_set(struct drm_encoder *encoder,
931b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			       struct drm_display_mode *mode,
941b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			       struct drm_display_mode *adjusted_mode)
951b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
961b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_device *dev = encoder->dev;
971b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
989bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
999bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct drm_mode_config *mode_config = &dev->mode_config;
1009bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct drm_connector *connector = NULL;
1019bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct drm_crtc *crtc = encoder->crtc;
1021b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	u32 lvds_port;
1031b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	uint64_t v = DRM_MODE_SCALE_FULLSCREEN;
1041b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1051b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (!gma_power_begin(dev, true))
1061b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		return;
1071b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1081b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/*
1091b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * The LVDS pin pair will already have been turned on in the
1101b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * psb_intel_crtc_mode_set since it has a large impact on the DPLL
1111b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * settings.
1121b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 */
1131b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	lvds_port = (REG_READ(LVDS) &
1141b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		    (~LVDS_PIPEB_SELECT)) |
1151b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		    LVDS_PORT_EN |
1161b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		    LVDS_BORDER_EN;
1171b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1181b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* If the firmware says dither on Moorestown, or the BIOS does
1191b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	   on Oaktrail then enable dithering */
1201b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (mode_dev->panel_wants_dither || dev_priv->lvds_dither)
1211b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE;
1221b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1231b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	REG_WRITE(LVDS, lvds_port);
1241b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1259bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	/* Find the connector we're trying to set up */
1269bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	list_for_each_entry(connector, &mode_config->connector_list, head) {
1279bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		if (!connector->encoder || connector->encoder->crtc != crtc)
1289bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson			continue;
1299bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	}
1309bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson
1319bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	if (!connector) {
1329bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		DRM_ERROR("Couldn't find connector when setting mode");
1339bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		return;
1349bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	}
1359bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson
1361b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_connector_property_get_value(
1379bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		connector,
1381b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		dev->mode_config.scaling_mode_property,
1391b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		&v);
1401b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1411b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (v == DRM_MODE_SCALE_NO_SCALE)
1421b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		REG_WRITE(PFIT_CONTROL, 0);
1431b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	else if (v == DRM_MODE_SCALE_ASPECT) {
1441b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) ||
1451b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		    (mode->hdisplay != adjusted_mode->crtc_hdisplay)) {
1461b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) ==
1471b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			    (mode->hdisplay * adjusted_mode->crtc_vdisplay))
1481b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
1491b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			else if ((adjusted_mode->crtc_hdisplay *
1501b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				mode->vdisplay) > (mode->hdisplay *
1511b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				adjusted_mode->crtc_vdisplay))
1521b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
1531b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					  PFIT_SCALING_MODE_PILLARBOX);
1541b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			else
1551b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				REG_WRITE(PFIT_CONTROL, PFIT_ENABLE |
1561b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					  PFIT_SCALING_MODE_LETTERBOX);
1571b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		} else
1581b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
1591b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	} else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/
1601b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		REG_WRITE(PFIT_CONTROL, PFIT_ENABLE);
1611b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1621b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	gma_power_end(dev);
1631b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
1641b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1651b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic void oaktrail_lvds_prepare(struct drm_encoder *encoder)
1661b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
1671b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_device *dev = encoder->dev;
1689bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct drm_psb_private *dev_priv = dev->dev_private;
1699bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_encoder *psb_intel_encoder =
1709bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson						to_psb_intel_encoder(encoder);
1719bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
1721b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1731b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (!gma_power_begin(dev, true))
1741b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		return;
1751b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1761b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
1771b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
1781b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					  BACKLIGHT_DUTY_CYCLE_MASK);
1799bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	oaktrail_lvds_set_power(dev, psb_intel_encoder, false);
1801b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	gma_power_end(dev);
1811b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
1821b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1831b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic u32 oaktrail_lvds_get_max_backlight(struct drm_device *dev)
1841b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
1851b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
1861b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	u32 ret;
1871b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1881b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (gma_power_begin(dev, false)) {
1891b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		ret = ((REG_READ(BLC_PWM_CTL) &
1901b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  BACKLIGHT_MODULATION_FREQ_MASK) >>
1911b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
1921b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1931b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		gma_power_end(dev);
1941b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	} else
195648a8e342c5a754bdc62f003d3af90507c1abfdeAlan Cox		ret = ((dev_priv->regs.saveBLC_PWM_CTL &
1961b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  BACKLIGHT_MODULATION_FREQ_MASK) >>
1971b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			  BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
1981b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
1991b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	return ret;
2001b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
2011b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2021b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic void oaktrail_lvds_commit(struct drm_encoder *encoder)
2031b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
2041b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_device *dev = encoder->dev;
2059bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct drm_psb_private *dev_priv = dev->dev_private;
2069bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_encoder *psb_intel_encoder =
2079bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson						to_psb_intel_encoder(encoder);
2089bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
2091b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2101b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (mode_dev->backlight_duty_cycle == 0)
2111b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode_dev->backlight_duty_cycle =
2121b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					oaktrail_lvds_get_max_backlight(dev);
2139bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	oaktrail_lvds_set_power(dev, psb_intel_encoder, true);
2141b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
2151b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2161b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic const struct drm_encoder_helper_funcs oaktrail_lvds_helper_funcs = {
2171b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	.dpms = oaktrail_lvds_dpms,
2181b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	.mode_fixup = psb_intel_lvds_mode_fixup,
2191b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	.prepare = oaktrail_lvds_prepare,
2201b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	.mode_set = oaktrail_lvds_mode_set,
2211b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	.commit = oaktrail_lvds_commit,
2221b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox};
2231b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2241b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxstatic struct drm_display_mode lvds_configuration_modes[] = {
2251b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for TPO LTPS LPJ040K001A */
2261b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 33264, 800, 836,
2271b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   846, 1056, 0, 480, 489, 491, 525, 0, 0) },
2281b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for LVDS 800x480 */
2291b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("800x480",  DRM_MODE_TYPE_DRIVER, 30994, 800, 801,
2301b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   802, 1024, 0, 480, 481, 482, 525, 0, 0) },
2311b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
2321b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072,
2331b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   1104, 1184, 0, 600, 603, 604, 608, 0, 0) },
2341b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */
2351b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104,
2361b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   1136, 1184, 0, 600, 603, 604, 608, 0, 0) },
2371b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */
2381b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124,
2391b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   1204, 1312, 0, 600, 607, 610, 621, 0, 0) },
2401b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for LVDS 1024x768 */
2411b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048,
2421b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   1184, 1344, 0, 768, 771, 777, 806, 0, 0) },
2431b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* hard coded fixed mode for LVDS 1366x768 */
2441b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	{ DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430,
2451b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		   1558, 1664, 0, 768, 769, 770, 776, 0, 0) },
2461b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox};
2471b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2481b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/* Returns the panel fixed mode from configuration. */
2491b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2501b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Coxstatic void oaktrail_lvds_get_configuration_mode(struct drm_device *dev,
2511b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox					struct psb_intel_mode_device *mode_dev)
2521b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
2531b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_display_mode *mode = NULL;
2541b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
2551b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
2561b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2571b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	mode_dev->panel_fixed_mode = NULL;
2581b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox
2591b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	/* Use the firmware provided data on Moorestown */
2601b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/
2611b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode = kzalloc(sizeof(*mode), GFP_KERNEL);
2621b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		if (!mode)
2631b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox			return;
2641b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2651b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
2661b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
2671b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->hsync_start = mode->hdisplay + \
2681b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				((ti->hsync_offset_hi << 8) | \
2691b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				ti->hsync_offset_lo);
2701b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->hsync_end = mode->hsync_start + \
2711b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				((ti->hsync_pulse_width_hi << 8) | \
2721b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				ti->hsync_pulse_width_lo);
2731b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
2741b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox							ti->hblank_lo);
2751b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->vsync_start = \
2761b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			mode->vdisplay + ((ti->vsync_offset_hi << 4) | \
2771b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox						ti->vsync_offset_lo);
2781b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->vsync_end = \
2791b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \
2801b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox						ti->vsync_pulse_width_lo);
2811b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->vtotal = mode->vdisplay + \
2821b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				((ti->vblank_hi << 8) | ti->vblank_lo);
2831b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode->clock = ti->pixel_clock * 10;
2841b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#if 0
2851b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay);
2861b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay);
2871b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "HSS is %d\n", mode->hsync_start);
2881b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "HSE is %d\n", mode->hsync_end);
2891b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "htotal is %d\n", mode->htotal);
2901b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "VSS is %d\n", mode->vsync_start);
2911b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "VSE is %d\n", mode->vsync_end);
2921b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "vtotal is %d\n", mode->vtotal);
2931b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		printk(KERN_INFO "clock is %d\n", mode->clock);
2941b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox#endif
2951b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox		mode_dev->panel_fixed_mode = mode;
2961b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	}
2971b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
2981b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	/* Use the BIOS VBT mode if available */
2991b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	if (mode_dev->panel_fixed_mode == NULL && mode_dev->vbt_mode)
3001b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox		mode_dev->panel_fixed_mode = drm_mode_duplicate(dev,
3011b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox						mode_dev->vbt_mode);
3021b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox
3031b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	/* Then try the LVDS VBT mode */
3041b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	if (mode_dev->panel_fixed_mode == NULL)
3051b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox		if (dev_priv->lfp_lvds_vbt_mode)
3061b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox			mode_dev->panel_fixed_mode =
3071b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox				drm_mode_duplicate(dev,
3081b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox					dev_priv->lfp_lvds_vbt_mode);
3091b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	/* Then guess */
3101b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	if (mode_dev->panel_fixed_mode == NULL)
3111b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox		mode_dev->panel_fixed_mode
3121b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox			= drm_mode_duplicate(dev, &lvds_configuration_modes[2]);
3131b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox
3141b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	drm_mode_set_name(mode_dev->panel_fixed_mode);
3151b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	drm_mode_set_crtcinfo(mode_dev->panel_fixed_mode, 0);
3161b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
3171b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3181b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/**
3191b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * oaktrail_lvds_init - setup LVDS connectors on this device
3201b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * @dev: drm device
3211b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox *
3221b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * Create the connector, register the LVDS DDC bus, and try to figure out what
3231b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox * modes we can display on the LVDS panel (if present).
3241b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox */
3251b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxvoid oaktrail_lvds_init(struct drm_device *dev,
3261b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		    struct psb_intel_mode_device *mode_dev)
3271b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox{
3289bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_encoder *psb_intel_encoder;
3299bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	struct psb_intel_connector *psb_intel_connector;
3301b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_connector *connector;
3311b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_encoder *encoder;
3325d3852dcabacc918f8c1428171513b6d618221fdAlan Cox	struct drm_psb_private *dev_priv = dev->dev_private;
3331b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct edid *edid;
3341b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct i2c_adapter *i2c_adap;
3351b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	struct drm_display_mode *scan;	/* *modes, *bios_mode; */
3361b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3379bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	psb_intel_encoder = kzalloc(sizeof(struct psb_intel_encoder), GFP_KERNEL);
3389bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	if (!psb_intel_encoder)
3391b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		return;
3401b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3415d3852dcabacc918f8c1428171513b6d618221fdAlan Cox	psb_intel_connector = kzalloc(sizeof(struct psb_intel_connector), GFP_KERNEL);
3429bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	if (!psb_intel_connector)
3439bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		goto failed_connector;
3449bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson
3459bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	connector = &psb_intel_connector->base;
3469bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	encoder = &psb_intel_encoder->base;
3471b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	dev_priv->is_lvds_on = true;
3489bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	drm_connector_init(dev, connector,
3491b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			   &psb_intel_lvds_connector_funcs,
3501b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			   DRM_MODE_CONNECTOR_LVDS);
3511b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3529bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	drm_encoder_init(dev, encoder, &psb_intel_lvds_enc_funcs,
3531b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			 DRM_MODE_ENCODER_LVDS);
3541b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3559bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	psb_intel_connector_attach_encoder(psb_intel_connector,
3569bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson					   psb_intel_encoder);
3579bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	psb_intel_encoder->type = INTEL_OUTPUT_LVDS;
3581b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3591b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_encoder_helper_add(encoder, &oaktrail_lvds_helper_funcs);
3601b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_connector_helper_add(connector,
3611b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				 &psb_intel_lvds_connector_helper_funcs);
3621b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	connector->display_info.subpixel_order = SubPixelHorizontalRGB;
3631b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	connector->interlace_allowed = false;
3641b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	connector->doublescan_allowed = false;
3651b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3661b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_connector_attach_property(connector,
3671b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					dev->mode_config.scaling_mode_property,
3681b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					DRM_MODE_SCALE_FULLSCREEN);
3691b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_connector_attach_property(connector,
3701b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					dev_priv->backlight_property,
3711b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox					BRIGHTNESS_MAX_LEVEL);
3721b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3731b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	mode_dev->panel_wants_dither = false;
3741b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (dev_priv->vbt_data.size != 0x00)
3751b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode_dev->panel_wants_dither = (dev_priv->gct_data.
3761b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE);
377e2e022ec51a7e85ce4352a53fde1cd11d58e151aAlan Cox        if (dev_priv->lvds_dither)
378e2e022ec51a7e85ce4352a53fde1cd11d58e151aAlan Cox                mode_dev->panel_wants_dither = 1;
3791b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3801b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/*
3811b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * LVDS discovery:
3821b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * 1) check for EDID on DDC
3831b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * 2) check for VBT data
3841b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * 3) check to see if LVDS is already on
3851b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 *    if none of the above, no panel
3861b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * 4) make sure lid is open
3871b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 *    if closed, act like it's not there for now
3881b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 */
3891b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
3901b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus);
3911b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (i2c_adap == NULL)
3921b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		dev_err(dev->dev, "No ddc adapter available!\n");
3931b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/*
3941b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * Attempt to get the fixed panel mode from DDC.  Assume that the
3951b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * preferred mode is the right one.
3961b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 */
3971b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (i2c_adap) {
3981b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		edid = drm_get_edid(connector, i2c_adap);
3991b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		if (edid) {
4001b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			drm_mode_connector_update_edid_property(connector,
4011b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox									edid);
402cc2e991c1564c952fd21f850db8d4a8f43847c09Kirill A. Shutemov			drm_add_edid_modes(connector, edid);
4031b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			kfree(edid);
4041b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		}
4051b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4061b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		list_for_each_entry(scan, &connector->probed_modes, head) {
4071b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			if (scan->type & DRM_MODE_TYPE_PREFERRED) {
4081b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				mode_dev->panel_fixed_mode =
4091b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				    drm_mode_duplicate(dev, scan);
4101b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox				goto out;	/* FIXME: check for quirks */
4111b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox			}
4121b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		}
4131b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	}
4141b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/*
4151b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * If we didn't get EDID, try geting panel timing
4161b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 * from configuration data
4171b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	 */
4181b22edfd6efd02b6cb9cfe3389ed54731abb3a45Alan Cox	oaktrail_lvds_get_configuration_mode(dev, mode_dev);
4191b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4201b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (mode_dev->panel_fixed_mode) {
4211b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
4221b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		goto out;	/* FIXME: check for quirks */
4231b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	}
4241b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4251b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	/* If we still don't have a mode after all that, give up. */
4261b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	if (!mode_dev->panel_fixed_mode) {
4271b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
4281b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox		goto failed_find;
4291b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	}
4301b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4311b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxout:
4321b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_sysfs_connector_add(connector);
4331b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	return;
4341b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4351b082ccf5901108d3acd860a73d8c0442556c0bbAlan Coxfailed_find:
4361b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	dev_dbg(dev->dev, "No LVDS modes found, disabling.\n");
4379bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	if (psb_intel_encoder->ddc_bus)
4389bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson		psb_intel_i2c_destroy(psb_intel_encoder->ddc_bus);
4391b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4401b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox/* failed_ddc: */
4411b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
4421b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_encoder_cleanup(encoder);
4431b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox	drm_connector_cleanup(connector);
4449bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	kfree(psb_intel_connector);
4459bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobssonfailed_connector:
4469bd81acdb648509dbbc32d4da0477c9fae0d6a73Patrik Jakobsson	kfree(psb_intel_encoder);
4471b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox}
4481b082ccf5901108d3acd860a73d8c0442556c0bbAlan Cox
449