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