LCOV - code coverage report
Current view: top level - dev/pci/drm/i915 - intel_lvds.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 375 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 23 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       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             : 
      30             : #ifdef __linux__
      31             : #include <linux/dmi.h>
      32             : #include <linux/i2c.h>
      33             : #include <linux/slab.h>
      34             : #endif
      35             : #include <dev/pci/drm/drmP.h>
      36             : #include <dev/pci/drm/drm_atomic_helper.h>
      37             : #include <dev/pci/drm/drm_crtc.h>
      38             : #include <dev/pci/drm/drm_edid.h>
      39             : #include "intel_drv.h"
      40             : #include <dev/pci/drm/i915_drm.h>
      41             : #include "i915_drv.h"
      42             : #ifdef __linux__
      43             : #include <linux/acpi.h>
      44             : #endif
      45             : 
      46             : /* Private structure for the integrated LVDS support */
      47             : struct intel_lvds_connector {
      48             :         struct intel_connector base;
      49             : 
      50             :         struct notifier_block lid_notifier;
      51             : };
      52             : 
      53             : struct intel_lvds_encoder {
      54             :         struct intel_encoder base;
      55             : 
      56             :         bool is_dual_link;
      57             :         u32 reg;
      58             :         u32 a3_power;
      59             : 
      60             :         struct intel_lvds_connector *attached_connector;
      61             : };
      62             : 
      63           0 : static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
      64             : {
      65           0 :         return container_of(encoder, struct intel_lvds_encoder, base.base);
      66             : }
      67             : 
      68           0 : static struct intel_lvds_connector *to_lvds_connector(struct drm_connector *connector)
      69             : {
      70           0 :         return container_of(connector, struct intel_lvds_connector, base.base);
      71             : }
      72             : 
      73           0 : static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
      74             :                                     enum pipe *pipe)
      75             : {
      76           0 :         struct drm_device *dev = encoder->base.dev;
      77           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
      78           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
      79             :         enum intel_display_power_domain power_domain;
      80             :         u32 tmp;
      81             : 
      82           0 :         power_domain = intel_display_port_power_domain(encoder);
      83           0 :         if (!intel_display_power_is_enabled(dev_priv, power_domain))
      84           0 :                 return false;
      85             : 
      86           0 :         tmp = I915_READ(lvds_encoder->reg);
      87             : 
      88           0 :         if (!(tmp & LVDS_PORT_EN))
      89           0 :                 return false;
      90             : 
      91           0 :         if (HAS_PCH_CPT(dev))
      92           0 :                 *pipe = PORT_TO_PIPE_CPT(tmp);
      93             :         else
      94           0 :                 *pipe = PORT_TO_PIPE(tmp);
      95             : 
      96           0 :         return true;
      97           0 : }
      98             : 
      99           0 : static void intel_lvds_get_config(struct intel_encoder *encoder,
     100             :                                   struct intel_crtc_state *pipe_config)
     101             : {
     102           0 :         struct drm_device *dev = encoder->base.dev;
     103           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     104           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     105             :         u32 tmp, flags = 0;
     106             :         int dotclock;
     107             : 
     108           0 :         tmp = I915_READ(lvds_encoder->reg);
     109           0 :         if (tmp & LVDS_HSYNC_POLARITY)
     110           0 :                 flags |= DRM_MODE_FLAG_NHSYNC;
     111             :         else
     112             :                 flags |= DRM_MODE_FLAG_PHSYNC;
     113           0 :         if (tmp & LVDS_VSYNC_POLARITY)
     114           0 :                 flags |= DRM_MODE_FLAG_NVSYNC;
     115             :         else
     116           0 :                 flags |= DRM_MODE_FLAG_PVSYNC;
     117             : 
     118           0 :         pipe_config->base.adjusted_mode.flags |= flags;
     119             : 
     120             :         /* gen2/3 store dither state in pfit control, needs to match */
     121           0 :         if (INTEL_INFO(dev)->gen < 4) {
     122           0 :                 tmp = I915_READ(PFIT_CONTROL);
     123             : 
     124           0 :                 pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
     125           0 :         }
     126             : 
     127           0 :         dotclock = pipe_config->port_clock;
     128             : 
     129           0 :         if (HAS_PCH_SPLIT(dev_priv->dev))
     130           0 :                 ironlake_check_encoder_dotclock(pipe_config, dotclock);
     131             : 
     132           0 :         pipe_config->base.adjusted_mode.crtc_clock = dotclock;
     133           0 : }
     134             : 
     135           0 : static void intel_pre_enable_lvds(struct intel_encoder *encoder)
     136             : {
     137           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     138           0 :         struct drm_device *dev = encoder->base.dev;
     139           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     140           0 :         struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
     141           0 :         const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
     142           0 :         int pipe = crtc->pipe;
     143             :         u32 temp;
     144             : 
     145           0 :         if (HAS_PCH_SPLIT(dev)) {
     146           0 :                 assert_fdi_rx_pll_disabled(dev_priv, pipe);
     147           0 :                 assert_shared_dpll_disabled(dev_priv,
     148             :                                             intel_crtc_to_shared_dpll(crtc));
     149           0 :         } else {
     150           0 :                 assert_pll_disabled(dev_priv, pipe);
     151             :         }
     152             : 
     153           0 :         temp = I915_READ(lvds_encoder->reg);
     154           0 :         temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
     155             : 
     156           0 :         if (HAS_PCH_CPT(dev)) {
     157           0 :                 temp &= ~PORT_TRANS_SEL_MASK;
     158           0 :                 temp |= PORT_TRANS_SEL_CPT(pipe);
     159           0 :         } else {
     160           0 :                 if (pipe == 1) {
     161           0 :                         temp |= LVDS_PIPEB_SELECT;
     162           0 :                 } else {
     163           0 :                         temp &= ~LVDS_PIPEB_SELECT;
     164             :                 }
     165             :         }
     166             : 
     167             :         /* set the corresponsding LVDS_BORDER bit */
     168           0 :         temp &= ~LVDS_BORDER_ENABLE;
     169           0 :         temp |= crtc->config->gmch_pfit.lvds_border_bits;
     170             :         /* Set the B0-B3 data pairs corresponding to whether we're going to
     171             :          * set the DPLLs for dual-channel mode or not.
     172             :          */
     173           0 :         if (lvds_encoder->is_dual_link)
     174           0 :                 temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
     175             :         else
     176           0 :                 temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
     177             : 
     178             :         /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
     179             :          * appropriately here, but we need to look more thoroughly into how
     180             :          * panels behave in the two modes. For now, let's just maintain the
     181             :          * value we got from the BIOS.
     182             :          */
     183           0 :          temp &= ~LVDS_A3_POWER_MASK;
     184           0 :          temp |= lvds_encoder->a3_power;
     185             : 
     186             :         /* Set the dithering flag on LVDS as needed, note that there is no
     187             :          * special lvds dither control bit on pch-split platforms, dithering is
     188             :          * only controlled through the PIPECONF reg. */
     189           0 :         if (INTEL_INFO(dev)->gen == 4) {
     190             :                 /* Bspec wording suggests that LVDS port dithering only exists
     191             :                  * for 18bpp panels. */
     192           0 :                 if (crtc->config->dither && crtc->config->pipe_bpp == 18)
     193           0 :                         temp |= LVDS_ENABLE_DITHER;
     194             :                 else
     195           0 :                         temp &= ~LVDS_ENABLE_DITHER;
     196             :         }
     197           0 :         temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
     198           0 :         if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
     199           0 :                 temp |= LVDS_HSYNC_POLARITY;
     200           0 :         if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
     201           0 :                 temp |= LVDS_VSYNC_POLARITY;
     202             : 
     203           0 :         I915_WRITE(lvds_encoder->reg, temp);
     204           0 : }
     205             : 
     206             : /**
     207             :  * Sets the power state for the panel.
     208             :  */
     209           0 : static void intel_enable_lvds(struct intel_encoder *encoder)
     210             : {
     211           0 :         struct drm_device *dev = encoder->base.dev;
     212           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     213             :         struct intel_connector *intel_connector =
     214           0 :                 &lvds_encoder->attached_connector->base;
     215           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     216             :         u32 ctl_reg, stat_reg;
     217             : 
     218           0 :         if (HAS_PCH_SPLIT(dev)) {
     219             :                 ctl_reg = PCH_PP_CONTROL;
     220             :                 stat_reg = PCH_PP_STATUS;
     221           0 :         } else {
     222             :                 ctl_reg = PP_CONTROL;
     223             :                 stat_reg = PP_STATUS;
     224             :         }
     225             : 
     226           0 :         I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) | LVDS_PORT_EN);
     227             : 
     228           0 :         I915_WRITE(ctl_reg, I915_READ(ctl_reg) | POWER_TARGET_ON);
     229           0 :         POSTING_READ(lvds_encoder->reg);
     230           0 :         if (wait_for((I915_READ(stat_reg) & PP_ON) != 0, 1000))
     231           0 :                 DRM_ERROR("timed out waiting for panel to power on\n");
     232             : 
     233           0 :         intel_panel_enable_backlight(intel_connector);
     234           0 : }
     235             : 
     236           0 : static void intel_disable_lvds(struct intel_encoder *encoder)
     237             : {
     238           0 :         struct drm_device *dev = encoder->base.dev;
     239           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     240           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     241             :         u32 ctl_reg, stat_reg;
     242             : 
     243           0 :         if (HAS_PCH_SPLIT(dev)) {
     244             :                 ctl_reg = PCH_PP_CONTROL;
     245             :                 stat_reg = PCH_PP_STATUS;
     246           0 :         } else {
     247             :                 ctl_reg = PP_CONTROL;
     248             :                 stat_reg = PP_STATUS;
     249             :         }
     250             : 
     251           0 :         I915_WRITE(ctl_reg, I915_READ(ctl_reg) & ~POWER_TARGET_ON);
     252           0 :         if (wait_for((I915_READ(stat_reg) & PP_ON) == 0, 1000))
     253           0 :                 DRM_ERROR("timed out waiting for panel to power off\n");
     254             : 
     255           0 :         I915_WRITE(lvds_encoder->reg, I915_READ(lvds_encoder->reg) & ~LVDS_PORT_EN);
     256           0 :         POSTING_READ(lvds_encoder->reg);
     257           0 : }
     258             : 
     259           0 : static void gmch_disable_lvds(struct intel_encoder *encoder)
     260             : {
     261           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     262             :         struct intel_connector *intel_connector =
     263           0 :                 &lvds_encoder->attached_connector->base;
     264             : 
     265           0 :         intel_panel_disable_backlight(intel_connector);
     266             : 
     267           0 :         intel_disable_lvds(encoder);
     268           0 : }
     269             : 
     270           0 : static void pch_disable_lvds(struct intel_encoder *encoder)
     271             : {
     272           0 :         struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
     273             :         struct intel_connector *intel_connector =
     274           0 :                 &lvds_encoder->attached_connector->base;
     275             : 
     276           0 :         intel_panel_disable_backlight(intel_connector);
     277           0 : }
     278             : 
     279           0 : static void pch_post_disable_lvds(struct intel_encoder *encoder)
     280             : {
     281           0 :         intel_disable_lvds(encoder);
     282           0 : }
     283             : 
     284             : static enum drm_mode_status
     285           0 : intel_lvds_mode_valid(struct drm_connector *connector,
     286             :                       struct drm_display_mode *mode)
     287             : {
     288           0 :         struct intel_connector *intel_connector = to_intel_connector(connector);
     289           0 :         struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode;
     290           0 :         int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
     291             : 
     292           0 :         if (mode->hdisplay > fixed_mode->hdisplay)
     293           0 :                 return MODE_PANEL;
     294           0 :         if (mode->vdisplay > fixed_mode->vdisplay)
     295           0 :                 return MODE_PANEL;
     296           0 :         if (fixed_mode->clock > max_pixclk)
     297           0 :                 return MODE_CLOCK_HIGH;
     298             : 
     299           0 :         return MODE_OK;
     300           0 : }
     301             : 
     302           0 : static bool intel_lvds_compute_config(struct intel_encoder *intel_encoder,
     303             :                                       struct intel_crtc_state *pipe_config)
     304             : {
     305           0 :         struct drm_device *dev = intel_encoder->base.dev;
     306             :         struct intel_lvds_encoder *lvds_encoder =
     307           0 :                 to_lvds_encoder(&intel_encoder->base);
     308             :         struct intel_connector *intel_connector =
     309           0 :                 &lvds_encoder->attached_connector->base;
     310           0 :         struct drm_display_mode *adjusted_mode = &pipe_config->base.adjusted_mode;
     311           0 :         struct intel_crtc *intel_crtc = to_intel_crtc(pipe_config->base.crtc);
     312             :         unsigned int lvds_bpp;
     313             : 
     314             :         /* Should never happen!! */
     315           0 :         if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
     316           0 :                 DRM_ERROR("Can't support LVDS on pipe A\n");
     317           0 :                 return false;
     318             :         }
     319             : 
     320           0 :         if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
     321           0 :                 lvds_bpp = 8*3;
     322             :         else
     323             :                 lvds_bpp = 6*3;
     324             : 
     325           0 :         if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
     326             :                 DRM_DEBUG_KMS("forcing display bpp (was %d) to LVDS (%d)\n",
     327             :                               pipe_config->pipe_bpp, lvds_bpp);
     328           0 :                 pipe_config->pipe_bpp = lvds_bpp;
     329           0 :         }
     330             : 
     331             :         /*
     332             :          * We have timings from the BIOS for the panel, put them in
     333             :          * to the adjusted mode.  The CRTC will be set up for this mode,
     334             :          * with the panel scaling set up to source from the H/VDisplay
     335             :          * of the original mode.
     336             :          */
     337           0 :         intel_fixed_panel_mode(intel_connector->panel.fixed_mode,
     338             :                                adjusted_mode);
     339             : 
     340           0 :         if (HAS_PCH_SPLIT(dev)) {
     341           0 :                 pipe_config->has_pch_encoder = true;
     342             : 
     343           0 :                 intel_pch_panel_fitting(intel_crtc, pipe_config,
     344           0 :                                         intel_connector->panel.fitting_mode);
     345           0 :         } else {
     346           0 :                 intel_gmch_panel_fitting(intel_crtc, pipe_config,
     347           0 :                                          intel_connector->panel.fitting_mode);
     348             : 
     349             :         }
     350             : 
     351             :         /*
     352             :          * XXX: It would be nice to support lower refresh rates on the
     353             :          * panels to reduce power consumption, and perhaps match the
     354             :          * user's requested refresh rate.
     355             :          */
     356             : 
     357           0 :         return true;
     358           0 : }
     359             : 
     360             : /**
     361             :  * Detect the LVDS connection.
     362             :  *
     363             :  * Since LVDS doesn't have hotlug, we use the lid as a proxy.  Open means
     364             :  * connected and closed means disconnected.  We also send hotplug events as
     365             :  * needed, using lid status notification from the input layer.
     366             :  */
     367             : static enum drm_connector_status
     368           0 : intel_lvds_detect(struct drm_connector *connector, bool force)
     369             : {
     370           0 :         struct drm_device *dev = connector->dev;
     371             :         enum drm_connector_status status;
     372             : 
     373             :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
     374             :                       connector->base.id, connector->name);
     375             : 
     376           0 :         status = intel_panel_detect(dev);
     377           0 :         if (status != connector_status_unknown)
     378           0 :                 return status;
     379             : 
     380           0 :         return connector_status_connected;
     381           0 : }
     382             : 
     383             : /**
     384             :  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
     385             :  */
     386           0 : static int intel_lvds_get_modes(struct drm_connector *connector)
     387             : {
     388           0 :         struct intel_lvds_connector *lvds_connector = to_lvds_connector(connector);
     389           0 :         struct drm_device *dev = connector->dev;
     390             :         struct drm_display_mode *mode;
     391             : 
     392             :         /* use cached edid if we have one */
     393           0 :         if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
     394           0 :                 return drm_add_edid_modes(connector, lvds_connector->base.edid);
     395             : 
     396           0 :         mode = drm_mode_duplicate(dev, lvds_connector->base.panel.fixed_mode);
     397           0 :         if (mode == NULL)
     398           0 :                 return 0;
     399             : 
     400           0 :         drm_mode_probed_add(connector, mode);
     401           0 :         return 1;
     402           0 : }
     403             : 
     404             : #ifdef notyet
     405             : static int intel_no_modeset_on_lid_dmi_callback(const struct dmi_system_id *id)
     406             : {
     407             :         DRM_INFO("Skipping forced modeset for %s\n", id->ident);
     408             :         return 1;
     409             : }
     410             : 
     411             : /* The GPU hangs up on these systems if modeset is performed on LID open */
     412             : static const struct dmi_system_id intel_no_modeset_on_lid[] = {
     413             :         {
     414             :                 .callback = intel_no_modeset_on_lid_dmi_callback,
     415             :                 .ident = "Toshiba Tecra A11",
     416             :                 .matches = {
     417             :                         DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
     418             :                         DMI_MATCH(DMI_PRODUCT_NAME, "TECRA A11"),
     419             :                 },
     420             :         },
     421             : 
     422             :         { }     /* terminating entry */
     423             : };
     424             : 
     425             : /*
     426             :  * Lid events. Note the use of 'modeset':
     427             :  *  - we set it to MODESET_ON_LID_OPEN on lid close,
     428             :  *    and set it to MODESET_DONE on open
     429             :  *  - we use it as a "only once" bit (ie we ignore
     430             :  *    duplicate events where it was already properly set)
     431             :  *  - the suspend/resume paths will set it to
     432             :  *    MODESET_SUSPENDED and ignore the lid open event,
     433             :  *    because they restore the mode ("lid open").
     434             :  */
     435             : static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
     436             :                             void *unused)
     437             : {
     438             :         struct intel_lvds_connector *lvds_connector =
     439             :                 container_of(nb, struct intel_lvds_connector, lid_notifier);
     440             :         struct drm_connector *connector = &lvds_connector->base.base;
     441             :         struct drm_device *dev = connector->dev;
     442             :         struct drm_i915_private *dev_priv = dev->dev_private;
     443             : 
     444             :         if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
     445             :                 return NOTIFY_OK;
     446             : 
     447             :         mutex_lock(&dev_priv->modeset_restore_lock);
     448             :         if (dev_priv->modeset_restore == MODESET_SUSPENDED)
     449             :                 goto exit;
     450             :         /*
     451             :          * check and update the status of LVDS connector after receiving
     452             :          * the LID nofication event.
     453             :          */
     454             :         connector->status = connector->funcs->detect(connector, false);
     455             : 
     456             :         /* Don't force modeset on machines where it causes a GPU lockup */
     457             :         if (dmi_check_system(intel_no_modeset_on_lid))
     458             :                 goto exit;
     459             :         if (!acpi_lid_open()) {
     460             :                 /* do modeset on next lid open event */
     461             :                 dev_priv->modeset_restore = MODESET_ON_LID_OPEN;
     462             :                 goto exit;
     463             :         }
     464             : 
     465             :         if (dev_priv->modeset_restore == MODESET_DONE)
     466             :                 goto exit;
     467             : 
     468             :         /*
     469             :          * Some old platform's BIOS love to wreak havoc while the lid is closed.
     470             :          * We try to detect this here and undo any damage. The split for PCH
     471             :          * platforms is rather conservative and a bit arbitrary expect that on
     472             :          * those platforms VGA disabling requires actual legacy VGA I/O access,
     473             :          * and as part of the cleanup in the hw state restore we also redisable
     474             :          * the vga plane.
     475             :          */
     476             :         if (!HAS_PCH_SPLIT(dev)) {
     477             :                 drm_modeset_lock_all(dev);
     478             :                 intel_display_resume(dev);
     479             :                 drm_modeset_unlock_all(dev);
     480             :         }
     481             : 
     482             :         dev_priv->modeset_restore = MODESET_DONE;
     483             : 
     484             : exit:
     485             :         mutex_unlock(&dev_priv->modeset_restore_lock);
     486             :         return NOTIFY_OK;
     487             : }
     488             : #endif
     489             : 
     490             : /**
     491             :  * intel_lvds_destroy - unregister and free LVDS structures
     492             :  * @connector: connector to free
     493             :  *
     494             :  * Unregister the DDC bus for this connector then free the driver private
     495             :  * structure.
     496             :  */
     497           0 : static void intel_lvds_destroy(struct drm_connector *connector)
     498             : {
     499             :         struct intel_lvds_connector *lvds_connector =
     500           0 :                 to_lvds_connector(connector);
     501             : 
     502             : #ifdef notyet
     503             :         if (lvds_connector->lid_notifier.notifier_call)
     504             :                 acpi_lid_notifier_unregister(&lvds_connector->lid_notifier);
     505             : #endif
     506             : 
     507           0 :         if (!IS_ERR_OR_NULL(lvds_connector->base.edid))
     508           0 :                 kfree(lvds_connector->base.edid);
     509             : 
     510           0 :         intel_panel_fini(&lvds_connector->base.panel);
     511             : 
     512           0 :         drm_connector_cleanup(connector);
     513           0 :         kfree(connector);
     514           0 : }
     515             : 
     516           0 : static int intel_lvds_set_property(struct drm_connector *connector,
     517             :                                    struct drm_property *property,
     518             :                                    uint64_t value)
     519             : {
     520           0 :         struct intel_connector *intel_connector = to_intel_connector(connector);
     521           0 :         struct drm_device *dev = connector->dev;
     522             : 
     523           0 :         if (property == dev->mode_config.scaling_mode_property) {
     524             :                 struct drm_crtc *crtc;
     525             : 
     526           0 :                 if (value == DRM_MODE_SCALE_NONE) {
     527             :                         DRM_DEBUG_KMS("no scaling not supported\n");
     528           0 :                         return -EINVAL;
     529             :                 }
     530             : 
     531           0 :                 if (intel_connector->panel.fitting_mode == value) {
     532             :                         /* the LVDS scaling property is not changed */
     533           0 :                         return 0;
     534             :                 }
     535           0 :                 intel_connector->panel.fitting_mode = value;
     536             : 
     537           0 :                 crtc = intel_attached_encoder(connector)->base.crtc;
     538           0 :                 if (crtc && crtc->state->enable) {
     539             :                         /*
     540             :                          * If the CRTC is enabled, the display will be changed
     541             :                          * according to the new panel fitting mode.
     542             :                          */
     543           0 :                         intel_crtc_restore_mode(crtc);
     544           0 :                 }
     545           0 :         }
     546             : 
     547           0 :         return 0;
     548           0 : }
     549             : 
     550             : static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
     551             :         .get_modes = intel_lvds_get_modes,
     552             :         .mode_valid = intel_lvds_mode_valid,
     553             :         .best_encoder = intel_best_encoder,
     554             : };
     555             : 
     556             : static const struct drm_connector_funcs intel_lvds_connector_funcs = {
     557             :         .dpms = drm_atomic_helper_connector_dpms,
     558             :         .detect = intel_lvds_detect,
     559             :         .fill_modes = drm_helper_probe_single_connector_modes,
     560             :         .set_property = intel_lvds_set_property,
     561             :         .atomic_get_property = intel_connector_atomic_get_property,
     562             :         .destroy = intel_lvds_destroy,
     563             :         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
     564             :         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
     565             : };
     566             : 
     567             : static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
     568             :         .destroy = intel_encoder_destroy,
     569             : };
     570             : 
     571           0 : static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
     572             : {
     573             :         DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
     574           0 :         return 1;
     575             : }
     576             : 
     577             : /* These systems claim to have LVDS, but really don't */
     578             : static const struct dmi_system_id intel_no_lvds[] = {
     579             :         {
     580             :                 .callback = intel_no_lvds_dmi_callback,
     581             :                 .ident = "Apple Mac Mini (Core series)",
     582             :                 .matches = {
     583             :                         DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
     584             :                         DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
     585             :                 },
     586             :         },
     587             :         {
     588             :                 .callback = intel_no_lvds_dmi_callback,
     589             :                 .ident = "Apple Mac Mini (Core 2 series)",
     590             :                 .matches = {
     591             :                         DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
     592             :                         DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
     593             :                 },
     594             :         },
     595             :         {
     596             :                 .callback = intel_no_lvds_dmi_callback,
     597             :                 .ident = "MSI IM-945GSE-A",
     598             :                 .matches = {
     599             :                         DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
     600             :                         DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
     601             :                 },
     602             :         },
     603             :         {
     604             :                 .callback = intel_no_lvds_dmi_callback,
     605             :                 .ident = "Dell Studio Hybrid",
     606             :                 .matches = {
     607             :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     608             :                         DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
     609             :                 },
     610             :         },
     611             :         {
     612             :                 .callback = intel_no_lvds_dmi_callback,
     613             :                 .ident = "Dell OptiPlex FX170",
     614             :                 .matches = {
     615             :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     616             :                         DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
     617             :                 },
     618             :         },
     619             :         {
     620             :                 .callback = intel_no_lvds_dmi_callback,
     621             :                 .ident = "AOpen Mini PC",
     622             :                 .matches = {
     623             :                         DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
     624             :                         DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
     625             :                 },
     626             :         },
     627             :         {
     628             :                 .callback = intel_no_lvds_dmi_callback,
     629             :                 .ident = "AOpen Mini PC MP915",
     630             :                 .matches = {
     631             :                         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
     632             :                         DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
     633             :                 },
     634             :         },
     635             :         {
     636             :                 .callback = intel_no_lvds_dmi_callback,
     637             :                 .ident = "AOpen i915GMm-HFS",
     638             :                 .matches = {
     639             :                         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
     640             :                         DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
     641             :                 },
     642             :         },
     643             :         {
     644             :                 .callback = intel_no_lvds_dmi_callback,
     645             :                 .ident = "AOpen i45GMx-I",
     646             :                 .matches = {
     647             :                         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
     648             :                         DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
     649             :                 },
     650             :         },
     651             :         {
     652             :                 .callback = intel_no_lvds_dmi_callback,
     653             :                 .ident = "Aopen i945GTt-VFA",
     654             :                 .matches = {
     655             :                         DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
     656             :                 },
     657             :         },
     658             :         {
     659             :                 .callback = intel_no_lvds_dmi_callback,
     660             :                 .ident = "Clientron U800",
     661             :                 .matches = {
     662             :                         DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
     663             :                         DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
     664             :                 },
     665             :         },
     666             :         {
     667             :                 .callback = intel_no_lvds_dmi_callback,
     668             :                 .ident = "Clientron E830",
     669             :                 .matches = {
     670             :                         DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
     671             :                         DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
     672             :                 },
     673             :         },
     674             :         {
     675             :                 .callback = intel_no_lvds_dmi_callback,
     676             :                 .ident = "Asus EeeBox PC EB1007",
     677             :                 .matches = {
     678             :                         DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
     679             :                         DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
     680             :                 },
     681             :         },
     682             :         {
     683             :                 .callback = intel_no_lvds_dmi_callback,
     684             :                 .ident = "Asus AT5NM10T-I",
     685             :                 .matches = {
     686             :                         DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
     687             :                         DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
     688             :                 },
     689             :         },
     690             :         {
     691             :                 .callback = intel_no_lvds_dmi_callback,
     692             :                 .ident = "Hewlett-Packard HP t5740",
     693             :                 .matches = {
     694             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
     695             :                         DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
     696             :                 },
     697             :         },
     698             :         {
     699             :                 .callback = intel_no_lvds_dmi_callback,
     700             :                 .ident = "Hewlett-Packard t5745",
     701             :                 .matches = {
     702             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
     703             :                         DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
     704             :                 },
     705             :         },
     706             :         {
     707             :                 .callback = intel_no_lvds_dmi_callback,
     708             :                 .ident = "Hewlett-Packard st5747",
     709             :                 .matches = {
     710             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
     711             :                         DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
     712             :                 },
     713             :         },
     714             :         {
     715             :                 .callback = intel_no_lvds_dmi_callback,
     716             :                 .ident = "MSI Wind Box DC500",
     717             :                 .matches = {
     718             :                         DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
     719             :                         DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
     720             :                 },
     721             :         },
     722             :         {
     723             :                 .callback = intel_no_lvds_dmi_callback,
     724             :                 .ident = "Gigabyte GA-D525TUD",
     725             :                 .matches = {
     726             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
     727             :                         DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
     728             :                 },
     729             :         },
     730             :         {
     731             :                 .callback = intel_no_lvds_dmi_callback,
     732             :                 .ident = "Supermicro X7SPA-H",
     733             :                 .matches = {
     734             :                         DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
     735             :                         DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
     736             :                 },
     737             :         },
     738             :         {
     739             :                 .callback = intel_no_lvds_dmi_callback,
     740             :                 .ident = "Fujitsu Esprimo Q900",
     741             :                 .matches = {
     742             :                         DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
     743             :                         DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
     744             :                 },
     745             :         },
     746             :         {
     747             :                 .callback = intel_no_lvds_dmi_callback,
     748             :                 .ident = "Intel D410PT",
     749             :                 .matches = {
     750             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
     751             :                         DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
     752             :                 },
     753             :         },
     754             :         {
     755             :                 .callback = intel_no_lvds_dmi_callback,
     756             :                 .ident = "Intel D425KT",
     757             :                 .matches = {
     758             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
     759             :                         DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
     760             :                 },
     761             :         },
     762             :         {
     763             :                 .callback = intel_no_lvds_dmi_callback,
     764             :                 .ident = "Intel D510MO",
     765             :                 .matches = {
     766             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
     767             :                         DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),
     768             :                 },
     769             :         },
     770             :         {
     771             :                 .callback = intel_no_lvds_dmi_callback,
     772             :                 .ident = "Intel D525MW",
     773             :                 .matches = {
     774             :                         DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
     775             :                         DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
     776             :                 },
     777             :         },
     778             :         {
     779             :                 .callback = intel_no_lvds_dmi_callback,
     780             :                 .ident = "Radiant P845",
     781             :                 .matches = {
     782             :                         DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),
     783             :                         DMI_MATCH(DMI_PRODUCT_NAME, "P845"),
     784             :                 },
     785             :         },
     786             : 
     787             :         { }     /* terminating entry */
     788             : };
     789             : 
     790             : /*
     791             :  * Enumerate the child dev array parsed from VBT to check whether
     792             :  * the LVDS is present.
     793             :  * If it is present, return 1.
     794             :  * If it is not present, return false.
     795             :  * If no child dev is parsed from VBT, it assumes that the LVDS is present.
     796             :  */
     797           0 : static bool lvds_is_present_in_vbt(struct drm_device *dev,
     798             :                                    u8 *i2c_pin)
     799             : {
     800           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     801             :         int i;
     802             : 
     803           0 :         if (!dev_priv->vbt.child_dev_num)
     804           0 :                 return true;
     805             : 
     806           0 :         for (i = 0; i < dev_priv->vbt.child_dev_num; i++) {
     807           0 :                 union child_device_config *uchild = dev_priv->vbt.child_dev + i;
     808           0 :                 struct old_child_dev_config *child = &uchild->old;
     809             : 
     810             :                 /* If the device type is not LFP, continue.
     811             :                  * We have to check both the new identifiers as well as the
     812             :                  * old for compatibility with some BIOSes.
     813             :                  */
     814           0 :                 if (child->device_type != DEVICE_TYPE_INT_LFP &&
     815           0 :                     child->device_type != DEVICE_TYPE_LFP)
     816           0 :                         continue;
     817             : 
     818           0 :                 if (intel_gmbus_is_valid_pin(dev_priv, child->i2c_pin))
     819           0 :                         *i2c_pin = child->i2c_pin;
     820             : 
     821             :                 /* However, we cannot trust the BIOS writers to populate
     822             :                  * the VBT correctly.  Since LVDS requires additional
     823             :                  * information from AIM blocks, a non-zero addin offset is
     824             :                  * a good indicator that the LVDS is actually present.
     825             :                  */
     826           0 :                 if (child->addin_offset)
     827           0 :                         return true;
     828             : 
     829             :                 /* But even then some BIOS writers perform some black magic
     830             :                  * and instantiate the device without reference to any
     831             :                  * additional data.  Trust that if the VBT was written into
     832             :                  * the OpRegion then they have validated the LVDS's existence.
     833             :                  */
     834           0 :                 if (dev_priv->opregion.vbt)
     835           0 :                         return true;
     836           0 :         }
     837             : 
     838           0 :         return false;
     839           0 : }
     840             : 
     841           0 : static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
     842             : {
     843             :         DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
     844           0 :         return 1;
     845             : }
     846             : 
     847             : static const struct dmi_system_id intel_dual_link_lvds[] = {
     848             :         {
     849             :                 .callback = intel_dual_link_lvds_callback,
     850             :                 .ident = "Apple MacBook Pro 15\" (2010)",
     851             :                 .matches = {
     852             :                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
     853             :                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
     854             :                 },
     855             :         },
     856             :         {
     857             :                 .callback = intel_dual_link_lvds_callback,
     858             :                 .ident = "Apple MacBook Pro 15\" (2011)",
     859             :                 .matches = {
     860             :                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
     861             :                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
     862             :                 },
     863             :         },
     864             :         {
     865             :                 .callback = intel_dual_link_lvds_callback,
     866             :                 .ident = "Apple MacBook Pro 15\" (2012)",
     867             :                 .matches = {
     868             :                         DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
     869             :                         DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
     870             :                 },
     871             :         },
     872             :         { }     /* terminating entry */
     873             : };
     874             : 
     875           0 : bool intel_is_dual_link_lvds(struct drm_device *dev)
     876             : {
     877             :         struct intel_encoder *encoder;
     878             :         struct intel_lvds_encoder *lvds_encoder;
     879             : 
     880           0 :         for_each_intel_encoder(dev, encoder) {
     881           0 :                 if (encoder->type == INTEL_OUTPUT_LVDS) {
     882           0 :                         lvds_encoder = to_lvds_encoder(&encoder->base);
     883             : 
     884           0 :                         return lvds_encoder->is_dual_link;
     885             :                 }
     886             :         }
     887             : 
     888           0 :         return false;
     889           0 : }
     890             : 
     891           0 : static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
     892             : {
     893           0 :         struct drm_device *dev = lvds_encoder->base.base.dev;
     894             :         unsigned int val;
     895           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     896             : 
     897             :         /* use the module option value if specified */
     898           0 :         if (i915.lvds_channel_mode > 0)
     899           0 :                 return i915.lvds_channel_mode == 2;
     900             : 
     901             :         /* single channel LVDS is limited to 112 MHz */
     902           0 :         if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock
     903           0 :             > 112999)
     904           0 :                 return true;
     905             : 
     906           0 :         if (dmi_check_system(intel_dual_link_lvds))
     907           0 :                 return true;
     908             : 
     909             :         /* BIOS should set the proper LVDS register value at boot, but
     910             :          * in reality, it doesn't set the value when the lid is closed;
     911             :          * we need to check "the value to be set" in VBT when LVDS
     912             :          * register is uninitialized.
     913             :          */
     914           0 :         val = I915_READ(lvds_encoder->reg);
     915           0 :         if (!(val & ~(LVDS_PIPE_MASK | LVDS_DETECTED)))
     916           0 :                 val = dev_priv->vbt.bios_lvds_val;
     917             : 
     918           0 :         return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
     919           0 : }
     920             : 
     921           0 : static bool intel_lvds_supported(struct drm_device *dev)
     922             : {
     923             :         /* With the introduction of the PCH we gained a dedicated
     924             :          * LVDS presence pin, use it. */
     925           0 :         if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev))
     926           0 :                 return true;
     927             : 
     928             :         /* Otherwise LVDS was only attached to mobile products,
     929             :          * except for the inglorious 830gm */
     930           0 :         if (INTEL_INFO(dev)->gen <= 4 && IS_MOBILE(dev) && !IS_I830(dev))
     931           0 :                 return true;
     932             : 
     933           0 :         return false;
     934           0 : }
     935             : 
     936             : /**
     937             :  * intel_lvds_init - setup LVDS connectors on this device
     938             :  * @dev: drm device
     939             :  *
     940             :  * Create the connector, register the LVDS DDC bus, and try to figure out what
     941             :  * modes we can display on the LVDS panel (if present).
     942             :  */
     943           0 : void intel_lvds_init(struct drm_device *dev)
     944             : {
     945           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     946             :         struct intel_lvds_encoder *lvds_encoder;
     947             :         struct intel_encoder *intel_encoder;
     948             :         struct intel_lvds_connector *lvds_connector;
     949             :         struct intel_connector *intel_connector;
     950             :         struct drm_connector *connector;
     951             :         struct drm_encoder *encoder;
     952             :         struct drm_display_mode *scan; /* *modes, *bios_mode; */
     953             :         struct drm_display_mode *fixed_mode = NULL;
     954             :         struct drm_display_mode *downclock_mode = NULL;
     955             :         struct edid *edid;
     956             :         struct drm_crtc *crtc;
     957             :         u32 lvds_reg;
     958             :         u32 lvds;
     959             :         int pipe;
     960           0 :         u8 pin;
     961             : 
     962             :         /*
     963             :          * Unlock registers and just leave them unlocked. Do this before
     964             :          * checking quirk lists to avoid bogus WARNINGs.
     965             :          */
     966           0 :         if (HAS_PCH_SPLIT(dev)) {
     967           0 :                 I915_WRITE(PCH_PP_CONTROL,
     968             :                            I915_READ(PCH_PP_CONTROL) | PANEL_UNLOCK_REGS);
     969           0 :         } else if (INTEL_INFO(dev_priv)->gen < 5) {
     970           0 :                 I915_WRITE(PP_CONTROL,
     971             :                            I915_READ(PP_CONTROL) | PANEL_UNLOCK_REGS);
     972           0 :         }
     973           0 :         if (!intel_lvds_supported(dev))
     974           0 :                 return;
     975             : 
     976             :         /* Skip init on machines we know falsely report LVDS */
     977           0 :         if (dmi_check_system(intel_no_lvds))
     978           0 :                 return;
     979             : 
     980           0 :         if (HAS_PCH_SPLIT(dev))
     981           0 :                 lvds_reg = PCH_LVDS;
     982             :         else
     983             :                 lvds_reg = LVDS;
     984             : 
     985           0 :         lvds = I915_READ(lvds_reg);
     986             : 
     987           0 :         if (HAS_PCH_SPLIT(dev)) {
     988           0 :                 if ((lvds & LVDS_DETECTED) == 0)
     989           0 :                         return;
     990           0 :                 if (dev_priv->vbt.edp_support) {
     991             :                         DRM_DEBUG_KMS("disable LVDS for eDP support\n");
     992           0 :                         return;
     993             :                 }
     994             :         }
     995             : 
     996           0 :         pin = GMBUS_PIN_PANEL;
     997           0 :         if (!lvds_is_present_in_vbt(dev, &pin)) {
     998           0 :                 if ((lvds & LVDS_PORT_EN) == 0) {
     999             :                         DRM_DEBUG_KMS("LVDS is not present in VBT\n");
    1000           0 :                         return;
    1001             :                 }
    1002             :                 DRM_DEBUG_KMS("LVDS is not present in VBT, but enabled anyway\n");
    1003             :         }
    1004             : 
    1005             :          /* Set the Panel Power On/Off timings if uninitialized. */
    1006           0 :         if (INTEL_INFO(dev_priv)->gen < 5 &&
    1007           0 :             I915_READ(PP_ON_DELAYS) == 0 && I915_READ(PP_OFF_DELAYS) == 0) {
    1008             :                 /* Set T2 to 40ms and T5 to 200ms */
    1009           0 :                 I915_WRITE(PP_ON_DELAYS, 0x019007d0);
    1010             : 
    1011             :                 /* Set T3 to 35ms and Tx to 200ms */
    1012           0 :                 I915_WRITE(PP_OFF_DELAYS, 0x015e07d0);
    1013             : 
    1014             :                 DRM_DEBUG_KMS("Panel power timings uninitialized, setting defaults\n");
    1015           0 :         }
    1016             : 
    1017           0 :         lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
    1018           0 :         if (!lvds_encoder)
    1019           0 :                 return;
    1020             : 
    1021           0 :         lvds_connector = kzalloc(sizeof(*lvds_connector), GFP_KERNEL);
    1022           0 :         if (!lvds_connector) {
    1023           0 :                 kfree(lvds_encoder);
    1024           0 :                 return;
    1025             :         }
    1026             : 
    1027           0 :         if (intel_connector_init(&lvds_connector->base) < 0) {
    1028           0 :                 kfree(lvds_connector);
    1029           0 :                 kfree(lvds_encoder);
    1030           0 :                 return;
    1031             :         }
    1032             : 
    1033           0 :         lvds_encoder->attached_connector = lvds_connector;
    1034             : 
    1035           0 :         intel_encoder = &lvds_encoder->base;
    1036           0 :         encoder = &intel_encoder->base;
    1037             :         intel_connector = &lvds_connector->base;
    1038           0 :         connector = &intel_connector->base;
    1039           0 :         drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
    1040             :                            DRM_MODE_CONNECTOR_LVDS);
    1041             : 
    1042           0 :         drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
    1043             :                          DRM_MODE_ENCODER_LVDS);
    1044             : 
    1045           0 :         intel_encoder->enable = intel_enable_lvds;
    1046           0 :         intel_encoder->pre_enable = intel_pre_enable_lvds;
    1047           0 :         intel_encoder->compute_config = intel_lvds_compute_config;
    1048           0 :         if (HAS_PCH_SPLIT(dev_priv)) {
    1049           0 :                 intel_encoder->disable = pch_disable_lvds;
    1050           0 :                 intel_encoder->post_disable = pch_post_disable_lvds;
    1051           0 :         } else {
    1052           0 :                 intel_encoder->disable = gmch_disable_lvds;
    1053             :         }
    1054           0 :         intel_encoder->get_hw_state = intel_lvds_get_hw_state;
    1055           0 :         intel_encoder->get_config = intel_lvds_get_config;
    1056           0 :         intel_connector->get_hw_state = intel_connector_get_hw_state;
    1057           0 :         intel_connector->unregister = intel_connector_unregister;
    1058             : 
    1059           0 :         intel_connector_attach_encoder(intel_connector, intel_encoder);
    1060           0 :         intel_encoder->type = INTEL_OUTPUT_LVDS;
    1061             : 
    1062           0 :         intel_encoder->cloneable = 0;
    1063           0 :         if (HAS_PCH_SPLIT(dev))
    1064           0 :                 intel_encoder->crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
    1065           0 :         else if (IS_GEN4(dev))
    1066           0 :                 intel_encoder->crtc_mask = (1 << 0) | (1 << 1);
    1067             :         else
    1068           0 :                 intel_encoder->crtc_mask = (1 << 1);
    1069             : 
    1070           0 :         drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
    1071           0 :         connector->display_info.subpixel_order = SubPixelHorizontalRGB;
    1072           0 :         connector->interlace_allowed = false;
    1073           0 :         connector->doublescan_allowed = false;
    1074             : 
    1075           0 :         lvds_encoder->reg = lvds_reg;
    1076             : 
    1077             :         /* create the scaling mode property */
    1078           0 :         drm_mode_create_scaling_mode_property(dev);
    1079           0 :         drm_object_attach_property(&connector->base,
    1080           0 :                                       dev->mode_config.scaling_mode_property,
    1081             :                                       DRM_MODE_SCALE_ASPECT);
    1082           0 :         intel_connector->panel.fitting_mode = DRM_MODE_SCALE_ASPECT;
    1083             :         /*
    1084             :          * LVDS discovery:
    1085             :          * 1) check for EDID on DDC
    1086             :          * 2) check for VBT data
    1087             :          * 3) check to see if LVDS is already on
    1088             :          *    if none of the above, no panel
    1089             :          * 4) make sure lid is open
    1090             :          *    if closed, act like it's not there for now
    1091             :          */
    1092             : 
    1093             :         /*
    1094             :          * Attempt to get the fixed panel mode from DDC.  Assume that the
    1095             :          * preferred mode is the right one.
    1096             :          */
    1097           0 :         mutex_lock(&dev->mode_config.mutex);
    1098           0 :         edid = drm_get_edid(connector, intel_gmbus_get_adapter(dev_priv, pin));
    1099           0 :         if (edid) {
    1100           0 :                 if (drm_add_edid_modes(connector, edid)) {
    1101           0 :                         drm_mode_connector_update_edid_property(connector,
    1102             :                                                                 edid);
    1103           0 :                 } else {
    1104           0 :                         kfree(edid);
    1105           0 :                         edid = ERR_PTR(-EINVAL);
    1106             :                 }
    1107             :         } else {
    1108           0 :                 edid = ERR_PTR(-ENOENT);
    1109             :         }
    1110           0 :         lvds_connector->base.edid = edid;
    1111             : 
    1112           0 :         if (IS_ERR_OR_NULL(edid)) {
    1113             :                 /* Didn't get an EDID, so
    1114             :                  * Set wide sync ranges so we get all modes
    1115             :                  * handed to valid_mode for checking
    1116             :                  */
    1117           0 :                 connector->display_info.min_vfreq = 0;
    1118           0 :                 connector->display_info.max_vfreq = 200;
    1119           0 :                 connector->display_info.min_hfreq = 0;
    1120           0 :                 connector->display_info.max_hfreq = 200;
    1121           0 :         }
    1122             : 
    1123           0 :         list_for_each_entry(scan, &connector->probed_modes, head) {
    1124           0 :                 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
    1125             :                         DRM_DEBUG_KMS("using preferred mode from EDID: ");
    1126           0 :                         drm_mode_debug_printmodeline(scan);
    1127             : 
    1128           0 :                         fixed_mode = drm_mode_duplicate(dev, scan);
    1129           0 :                         if (fixed_mode)
    1130             :                                 goto out;
    1131             :                 }
    1132             :         }
    1133             : 
    1134             :         /* Failed to get EDID, what about VBT? */
    1135           0 :         if (dev_priv->vbt.lfp_lvds_vbt_mode) {
    1136             :                 DRM_DEBUG_KMS("using mode from VBT: ");
    1137           0 :                 drm_mode_debug_printmodeline(dev_priv->vbt.lfp_lvds_vbt_mode);
    1138             : 
    1139           0 :                 fixed_mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode);
    1140           0 :                 if (fixed_mode) {
    1141           0 :                         fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
    1142           0 :                         goto out;
    1143             :                 }
    1144             :         }
    1145             : 
    1146             :         /*
    1147             :          * If we didn't get EDID, try checking if the panel is already turned
    1148             :          * on.  If so, assume that whatever is currently programmed is the
    1149             :          * correct mode.
    1150             :          */
    1151             : 
    1152             :         /* Ironlake: FIXME if still fail, not try pipe mode now */
    1153           0 :         if (HAS_PCH_SPLIT(dev))
    1154             :                 goto failed;
    1155             : 
    1156           0 :         pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
    1157           0 :         crtc = intel_get_crtc_for_pipe(dev, pipe);
    1158             : 
    1159           0 :         if (crtc && (lvds & LVDS_PORT_EN)) {
    1160           0 :                 fixed_mode = intel_crtc_mode_get(dev, crtc);
    1161           0 :                 if (fixed_mode) {
    1162             :                         DRM_DEBUG_KMS("using current (BIOS) mode: ");
    1163           0 :                         drm_mode_debug_printmodeline(fixed_mode);
    1164           0 :                         fixed_mode->type |= DRM_MODE_TYPE_PREFERRED;
    1165           0 :                         goto out;
    1166             :                 }
    1167             :         }
    1168             : 
    1169             :         /* If we still don't have a mode after all that, give up. */
    1170           0 :         if (!fixed_mode)
    1171             :                 goto failed;
    1172             : 
    1173             : out:
    1174           0 :         mutex_unlock(&dev->mode_config.mutex);
    1175             : 
    1176           0 :         intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
    1177             : 
    1178           0 :         lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
    1179             :         DRM_DEBUG_KMS("detected %s-link lvds configuration\n",
    1180             :                       lvds_encoder->is_dual_link ? "dual" : "single");
    1181             : 
    1182           0 :         lvds_encoder->a3_power = I915_READ(lvds_encoder->reg) &
    1183             :                                  LVDS_A3_POWER_MASK;
    1184             : 
    1185             : #ifdef notyet
    1186             :         lvds_connector->lid_notifier.notifier_call = intel_lid_notify;
    1187             :         if (acpi_lid_notifier_register(&lvds_connector->lid_notifier)) {
    1188             :                 DRM_DEBUG_KMS("lid notifier registration failed\n");
    1189             :                 lvds_connector->lid_notifier.notifier_call = NULL;
    1190             :         }
    1191             : #endif
    1192           0 :         drm_connector_register(connector);
    1193             : 
    1194           0 :         intel_panel_setup_backlight(connector, INVALID_PIPE);
    1195             : 
    1196           0 :         return;
    1197             : 
    1198             : failed:
    1199           0 :         mutex_unlock(&dev->mode_config.mutex);
    1200             : 
    1201             :         DRM_DEBUG_KMS("No LVDS modes found, disabling.\n");
    1202           0 :         drm_connector_cleanup(connector);
    1203           0 :         drm_encoder_cleanup(encoder);
    1204           0 :         kfree(lvds_encoder);
    1205           0 :         kfree(lvds_connector);
    1206           0 :         return;
    1207           0 : }

Generated by: LCOV version 1.13