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

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2006-2007 Intel Corporation
       3             :  *
       4             :  * Permission is hereby granted, free of charge, to any person obtaining a
       5             :  * copy of this software and associated documentation files (the "Software"),
       6             :  * to deal in the Software without restriction, including without limitation
       7             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
       8             :  * and/or sell copies of the Software, and to permit persons to whom the
       9             :  * Software is furnished to do so, subject to the following conditions:
      10             :  *
      11             :  * The above copyright notice and this permission notice (including the next
      12             :  * paragraph) shall be included in all copies or substantial portions of the
      13             :  * Software.
      14             :  *
      15             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      16             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      17             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      18             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      19             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      20             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      21             :  * DEALINGS IN THE SOFTWARE.
      22             :  *
      23             :  * Authors:
      24             :  *      Eric Anholt <eric@anholt.net>
      25             :  */
      26             : 
      27             : #ifdef __linux__
      28             : #include <linux/dmi.h>
      29             : #include <linux/i2c.h>
      30             : #include <linux/slab.h>
      31             : #endif
      32             : #include <dev/pci/drm/drmP.h>
      33             : #include <dev/pci/drm/drm_atomic_helper.h>
      34             : #include <dev/pci/drm/drm_crtc.h>
      35             : #include <dev/pci/drm/drm_crtc_helper.h>
      36             : #include <dev/pci/drm/drm_edid.h>
      37             : #include "intel_drv.h"
      38             : #include <dev/pci/drm/i915_drm.h>
      39             : #include "i915_drv.h"
      40             : 
      41             : /* Here's the desired hotplug mode */
      42             : #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 |                \
      43             :                            ADPA_CRT_HOTPLUG_WARMUP_10MS |               \
      44             :                            ADPA_CRT_HOTPLUG_SAMPLE_4S |                 \
      45             :                            ADPA_CRT_HOTPLUG_VOLTAGE_50 |                \
      46             :                            ADPA_CRT_HOTPLUG_VOLREF_325MV |              \
      47             :                            ADPA_CRT_HOTPLUG_ENABLE)
      48             : 
      49             : struct intel_crt {
      50             :         struct intel_encoder base;
      51             :         /* DPMS state is stored in the connector, which we need in the
      52             :          * encoder's enable/disable callbacks */
      53             :         struct intel_connector *connector;
      54             :         bool force_hotplug_required;
      55             :         u32 adpa_reg;
      56             : };
      57             : 
      58           0 : static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
      59             : {
      60           0 :         return container_of(encoder, struct intel_crt, base);
      61             : }
      62             : 
      63           0 : static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
      64             : {
      65           0 :         return intel_encoder_to_crt(intel_attached_encoder(connector));
      66             : }
      67             : 
      68           0 : static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
      69             :                                    enum pipe *pipe)
      70             : {
      71           0 :         struct drm_device *dev = encoder->base.dev;
      72           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
      73           0 :         struct intel_crt *crt = intel_encoder_to_crt(encoder);
      74             :         enum intel_display_power_domain power_domain;
      75             :         u32 tmp;
      76             : 
      77           0 :         power_domain = intel_display_port_power_domain(encoder);
      78           0 :         if (!intel_display_power_is_enabled(dev_priv, power_domain))
      79           0 :                 return false;
      80             : 
      81           0 :         tmp = I915_READ(crt->adpa_reg);
      82             : 
      83           0 :         if (!(tmp & ADPA_DAC_ENABLE))
      84           0 :                 return false;
      85             : 
      86           0 :         if (HAS_PCH_CPT(dev))
      87           0 :                 *pipe = PORT_TO_PIPE_CPT(tmp);
      88             :         else
      89           0 :                 *pipe = PORT_TO_PIPE(tmp);
      90             : 
      91           0 :         return true;
      92           0 : }
      93             : 
      94           0 : static unsigned int intel_crt_get_flags(struct intel_encoder *encoder)
      95             : {
      96           0 :         struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
      97           0 :         struct intel_crt *crt = intel_encoder_to_crt(encoder);
      98             :         u32 tmp, flags = 0;
      99             : 
     100           0 :         tmp = I915_READ(crt->adpa_reg);
     101             : 
     102           0 :         if (tmp & ADPA_HSYNC_ACTIVE_HIGH)
     103           0 :                 flags |= DRM_MODE_FLAG_PHSYNC;
     104             :         else
     105             :                 flags |= DRM_MODE_FLAG_NHSYNC;
     106             : 
     107           0 :         if (tmp & ADPA_VSYNC_ACTIVE_HIGH)
     108           0 :                 flags |= DRM_MODE_FLAG_PVSYNC;
     109             :         else
     110           0 :                 flags |= DRM_MODE_FLAG_NVSYNC;
     111             : 
     112           0 :         return flags;
     113             : }
     114             : 
     115           0 : static void intel_crt_get_config(struct intel_encoder *encoder,
     116             :                                  struct intel_crtc_state *pipe_config)
     117             : {
     118           0 :         struct drm_device *dev = encoder->base.dev;
     119             :         int dotclock;
     120             : 
     121           0 :         pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
     122             : 
     123           0 :         dotclock = pipe_config->port_clock;
     124             : 
     125           0 :         if (HAS_PCH_SPLIT(dev))
     126           0 :                 ironlake_check_encoder_dotclock(pipe_config, dotclock);
     127             : 
     128           0 :         pipe_config->base.adjusted_mode.crtc_clock = dotclock;
     129           0 : }
     130             : 
     131           0 : static void hsw_crt_get_config(struct intel_encoder *encoder,
     132             :                                struct intel_crtc_state *pipe_config)
     133             : {
     134           0 :         intel_ddi_get_config(encoder, pipe_config);
     135             : 
     136           0 :         pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC |
     137             :                                               DRM_MODE_FLAG_NHSYNC |
     138             :                                               DRM_MODE_FLAG_PVSYNC |
     139             :                                               DRM_MODE_FLAG_NVSYNC);
     140           0 :         pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder);
     141           0 : }
     142             : 
     143             : /* Note: The caller is required to filter out dpms modes not supported by the
     144             :  * platform. */
     145           0 : static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
     146             : {
     147           0 :         struct drm_device *dev = encoder->base.dev;
     148           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     149           0 :         struct intel_crt *crt = intel_encoder_to_crt(encoder);
     150           0 :         struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
     151           0 :         const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
     152             :         u32 adpa;
     153             : 
     154           0 :         if (INTEL_INFO(dev)->gen >= 5)
     155           0 :                 adpa = ADPA_HOTPLUG_BITS;
     156             :         else
     157             :                 adpa = 0;
     158             : 
     159           0 :         if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
     160           0 :                 adpa |= ADPA_HSYNC_ACTIVE_HIGH;
     161           0 :         if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
     162           0 :                 adpa |= ADPA_VSYNC_ACTIVE_HIGH;
     163             : 
     164             :         /* For CPT allow 3 pipe config, for others just use A or B */
     165           0 :         if (HAS_PCH_LPT(dev))
     166             :                 ; /* Those bits don't exist here */
     167           0 :         else if (HAS_PCH_CPT(dev))
     168           0 :                 adpa |= PORT_TRANS_SEL_CPT(crtc->pipe);
     169           0 :         else if (crtc->pipe == 0)
     170           0 :                 adpa |= ADPA_PIPE_A_SELECT;
     171             :         else
     172           0 :                 adpa |= ADPA_PIPE_B_SELECT;
     173             : 
     174           0 :         if (!HAS_PCH_SPLIT(dev))
     175           0 :                 I915_WRITE(BCLRPAT(crtc->pipe), 0);
     176             : 
     177           0 :         switch (mode) {
     178             :         case DRM_MODE_DPMS_ON:
     179           0 :                 adpa |= ADPA_DAC_ENABLE;
     180           0 :                 break;
     181             :         case DRM_MODE_DPMS_STANDBY:
     182           0 :                 adpa |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
     183           0 :                 break;
     184             :         case DRM_MODE_DPMS_SUSPEND:
     185           0 :                 adpa |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
     186           0 :                 break;
     187             :         case DRM_MODE_DPMS_OFF:
     188           0 :                 adpa |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
     189           0 :                 break;
     190             :         }
     191             : 
     192           0 :         I915_WRITE(crt->adpa_reg, adpa);
     193           0 : }
     194             : 
     195           0 : static void intel_disable_crt(struct intel_encoder *encoder)
     196             : {
     197           0 :         intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
     198           0 : }
     199             : 
     200           0 : static void pch_disable_crt(struct intel_encoder *encoder)
     201             : {
     202           0 : }
     203             : 
     204           0 : static void pch_post_disable_crt(struct intel_encoder *encoder)
     205             : {
     206           0 :         intel_disable_crt(encoder);
     207           0 : }
     208             : 
     209           0 : static void intel_enable_crt(struct intel_encoder *encoder)
     210             : {
     211           0 :         struct intel_crt *crt = intel_encoder_to_crt(encoder);
     212             : 
     213           0 :         intel_crt_set_dpms(encoder, crt->connector->base.dpms);
     214           0 : }
     215             : 
     216             : static enum drm_mode_status
     217           0 : intel_crt_mode_valid(struct drm_connector *connector,
     218             :                      struct drm_display_mode *mode)
     219             : {
     220           0 :         struct drm_device *dev = connector->dev;
     221             : 
     222             :         int max_clock = 0;
     223           0 :         if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
     224           0 :                 return MODE_NO_DBLESCAN;
     225             : 
     226           0 :         if (mode->clock < 25000)
     227           0 :                 return MODE_CLOCK_LOW;
     228             : 
     229           0 :         if (IS_GEN2(dev))
     230           0 :                 max_clock = 350000;
     231             :         else
     232             :                 max_clock = 400000;
     233           0 :         if (mode->clock > max_clock)
     234           0 :                 return MODE_CLOCK_HIGH;
     235             : 
     236             :         /* The FDI receiver on LPT only supports 8bpc and only has 2 lanes. */
     237           0 :         if (HAS_PCH_LPT(dev) &&
     238           0 :             (ironlake_get_lanes_required(mode->clock, 270000, 24) > 2))
     239           0 :                 return MODE_CLOCK_HIGH;
     240             : 
     241           0 :         return MODE_OK;
     242           0 : }
     243             : 
     244           0 : static bool intel_crt_compute_config(struct intel_encoder *encoder,
     245             :                                      struct intel_crtc_state *pipe_config)
     246             : {
     247           0 :         struct drm_device *dev = encoder->base.dev;
     248             : 
     249           0 :         if (HAS_PCH_SPLIT(dev))
     250           0 :                 pipe_config->has_pch_encoder = true;
     251             : 
     252             :         /* LPT FDI RX only supports 8bpc. */
     253           0 :         if (HAS_PCH_LPT(dev)) {
     254           0 :                 if (pipe_config->bw_constrained && pipe_config->pipe_bpp < 24) {
     255             :                         DRM_DEBUG_KMS("LPT only supports 24bpp\n");
     256           0 :                         return false;
     257             :                 }
     258             : 
     259           0 :                 pipe_config->pipe_bpp = 24;
     260           0 :         }
     261             : 
     262             :         /* FDI must always be 2.7 GHz */
     263           0 :         if (HAS_DDI(dev)) {
     264           0 :                 pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL;
     265           0 :                 pipe_config->port_clock = 135000 * 2;
     266             : 
     267           0 :                 pipe_config->dpll_hw_state.wrpll = 0;
     268           0 :                 pipe_config->dpll_hw_state.spll =
     269             :                         SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC;
     270           0 :         }
     271             : 
     272           0 :         return true;
     273           0 : }
     274             : 
     275           0 : static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
     276             : {
     277           0 :         struct drm_device *dev = connector->dev;
     278           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     279           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     280             :         u32 adpa;
     281             :         bool ret;
     282             : 
     283             :         /* The first time through, trigger an explicit detection cycle */
     284           0 :         if (crt->force_hotplug_required) {
     285           0 :                 bool turn_off_dac = HAS_PCH_SPLIT(dev);
     286             :                 u32 save_adpa;
     287             : 
     288           0 :                 crt->force_hotplug_required = 0;
     289             : 
     290           0 :                 save_adpa = adpa = I915_READ(crt->adpa_reg);
     291             :                 DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
     292             : 
     293           0 :                 adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
     294           0 :                 if (turn_off_dac)
     295           0 :                         adpa &= ~ADPA_DAC_ENABLE;
     296             : 
     297           0 :                 I915_WRITE(crt->adpa_reg, adpa);
     298             : 
     299           0 :                 if (wait_for((I915_READ(crt->adpa_reg) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
     300             :                              1000))
     301             :                         DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
     302             : 
     303           0 :                 if (turn_off_dac) {
     304           0 :                         I915_WRITE(crt->adpa_reg, save_adpa);
     305           0 :                         POSTING_READ(crt->adpa_reg);
     306           0 :                 }
     307           0 :         }
     308             : 
     309             :         /* Check the status to see if both blue and green are on now */
     310           0 :         adpa = I915_READ(crt->adpa_reg);
     311           0 :         if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
     312           0 :                 ret = true;
     313             :         else
     314             :                 ret = false;
     315             :         DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret);
     316             : 
     317           0 :         return ret;
     318             : }
     319             : 
     320           0 : static bool valleyview_crt_detect_hotplug(struct drm_connector *connector)
     321             : {
     322           0 :         struct drm_device *dev = connector->dev;
     323           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     324           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     325             :         u32 adpa;
     326             :         bool ret;
     327             :         u32 save_adpa;
     328             : 
     329           0 :         save_adpa = adpa = I915_READ(crt->adpa_reg);
     330             :         DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa);
     331             : 
     332           0 :         adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER;
     333             : 
     334           0 :         I915_WRITE(crt->adpa_reg, adpa);
     335             : 
     336           0 :         if (wait_for((I915_READ(crt->adpa_reg) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0,
     337             :                      1000)) {
     338             :                 DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER");
     339           0 :                 I915_WRITE(crt->adpa_reg, save_adpa);
     340           0 :         }
     341             : 
     342             :         /* Check the status to see if both blue and green are on now */
     343           0 :         adpa = I915_READ(crt->adpa_reg);
     344           0 :         if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0)
     345           0 :                 ret = true;
     346             :         else
     347             :                 ret = false;
     348             : 
     349             :         DRM_DEBUG_KMS("valleyview hotplug adpa=0x%x, result %d\n", adpa, ret);
     350             : 
     351           0 :         return ret;
     352             : }
     353             : 
     354             : /**
     355             :  * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
     356             :  *
     357             :  * Not for i915G/i915GM
     358             :  *
     359             :  * \return true if CRT is connected.
     360             :  * \return false if CRT is disconnected.
     361             :  */
     362           0 : static bool intel_crt_detect_hotplug(struct drm_connector *connector)
     363             : {
     364           0 :         struct drm_device *dev = connector->dev;
     365           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     366             :         u32 stat;
     367             :         bool ret = false;
     368             :         int i, tries = 0;
     369             : 
     370           0 :         if (HAS_PCH_SPLIT(dev))
     371           0 :                 return intel_ironlake_crt_detect_hotplug(connector);
     372             : 
     373           0 :         if (IS_VALLEYVIEW(dev))
     374           0 :                 return valleyview_crt_detect_hotplug(connector);
     375             : 
     376             :         /*
     377             :          * On 4 series desktop, CRT detect sequence need to be done twice
     378             :          * to get a reliable result.
     379             :          */
     380             : 
     381           0 :         if (IS_G4X(dev) && !IS_GM45(dev))
     382           0 :                 tries = 2;
     383             :         else
     384             :                 tries = 1;
     385             : 
     386           0 :         for (i = 0; i < tries ; i++) {
     387             :                 /* turn on the FORCE_DETECT */
     388           0 :                 i915_hotplug_interrupt_update(dev_priv,
     389             :                                               CRT_HOTPLUG_FORCE_DETECT,
     390             :                                               CRT_HOTPLUG_FORCE_DETECT);
     391             :                 /* wait for FORCE_DETECT to go off */
     392           0 :                 if (wait_for((I915_READ(PORT_HOTPLUG_EN) &
     393             :                               CRT_HOTPLUG_FORCE_DETECT) == 0,
     394             :                              1000))
     395             :                         DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off");
     396             :         }
     397             : 
     398           0 :         stat = I915_READ(PORT_HOTPLUG_STAT);
     399           0 :         if ((stat & CRT_HOTPLUG_MONITOR_MASK) != CRT_HOTPLUG_MONITOR_NONE)
     400           0 :                 ret = true;
     401             : 
     402             :         /* clear the interrupt we just generated, if any */
     403           0 :         I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS);
     404             : 
     405           0 :         i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0);
     406             : 
     407           0 :         return ret;
     408           0 : }
     409             : 
     410           0 : static struct edid *intel_crt_get_edid(struct drm_connector *connector,
     411             :                                 struct i2c_adapter *i2c)
     412             : {
     413             :         struct edid *edid;
     414             : 
     415           0 :         edid = drm_get_edid(connector, i2c);
     416             : 
     417           0 :         if (!edid && !intel_gmbus_is_forced_bit(i2c)) {
     418             :                 DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n");
     419           0 :                 intel_gmbus_force_bit(i2c, true);
     420           0 :                 edid = drm_get_edid(connector, i2c);
     421           0 :                 intel_gmbus_force_bit(i2c, false);
     422           0 :         }
     423             : 
     424           0 :         return edid;
     425             : }
     426             : 
     427             : /* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */
     428           0 : static int intel_crt_ddc_get_modes(struct drm_connector *connector,
     429             :                                 struct i2c_adapter *adapter)
     430             : {
     431             :         struct edid *edid;
     432             :         int ret;
     433             : 
     434           0 :         edid = intel_crt_get_edid(connector, adapter);
     435           0 :         if (!edid)
     436           0 :                 return 0;
     437             : 
     438           0 :         ret = intel_connector_update_modes(connector, edid);
     439           0 :         kfree(edid);
     440             : 
     441           0 :         return ret;
     442           0 : }
     443             : 
     444           0 : static bool intel_crt_detect_ddc(struct drm_connector *connector)
     445             : {
     446           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     447           0 :         struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private;
     448             :         struct edid *edid;
     449             :         struct i2c_adapter *i2c;
     450             :         bool ret = false;
     451             : 
     452           0 :         BUG_ON(crt->base.type != INTEL_OUTPUT_ANALOG);
     453             : 
     454           0 :         i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
     455           0 :         edid = intel_crt_get_edid(connector, i2c);
     456             : 
     457           0 :         if (edid) {
     458           0 :                 bool is_digital = edid->input & DRM_EDID_INPUT_DIGITAL;
     459             : 
     460             :                 /*
     461             :                  * This may be a DVI-I connector with a shared DDC
     462             :                  * link between analog and digital outputs, so we
     463             :                  * have to check the EDID input spec of the attached device.
     464             :                  */
     465           0 :                 if (!is_digital) {
     466             :                         DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n");
     467             :                         ret = true;
     468           0 :                 } else {
     469             :                         DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n");
     470             :                 }
     471           0 :         } else {
     472             :                 DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [no valid EDID found]\n");
     473             :         }
     474             : 
     475           0 :         kfree(edid);
     476             : 
     477           0 :         return ret;
     478             : }
     479             : 
     480             : static enum drm_connector_status
     481           0 : intel_crt_load_detect(struct intel_crt *crt)
     482             : {
     483           0 :         struct drm_device *dev = crt->base.base.dev;
     484           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     485           0 :         uint32_t pipe = to_intel_crtc(crt->base.base.crtc)->pipe;
     486             :         uint32_t save_bclrpat;
     487             :         uint32_t save_vtotal;
     488             :         uint32_t vtotal, vactive;
     489             :         uint32_t vsample;
     490             :         uint32_t vblank, vblank_start, vblank_end;
     491             :         uint32_t dsl;
     492             :         uint32_t bclrpat_reg;
     493             :         uint32_t vtotal_reg;
     494             :         uint32_t vblank_reg;
     495             :         uint32_t vsync_reg;
     496             :         uint32_t pipeconf_reg;
     497             :         uint32_t pipe_dsl_reg;
     498             :         uint8_t st00;
     499             :         enum drm_connector_status status;
     500             : 
     501             :         DRM_DEBUG_KMS("starting load-detect on CRT\n");
     502             : 
     503           0 :         bclrpat_reg = BCLRPAT(pipe);
     504           0 :         vtotal_reg = VTOTAL(pipe);
     505           0 :         vblank_reg = VBLANK(pipe);
     506           0 :         vsync_reg = VSYNC(pipe);
     507           0 :         pipeconf_reg = PIPECONF(pipe);
     508           0 :         pipe_dsl_reg = PIPEDSL(pipe);
     509             : 
     510           0 :         save_bclrpat = I915_READ(bclrpat_reg);
     511           0 :         save_vtotal = I915_READ(vtotal_reg);
     512           0 :         vblank = I915_READ(vblank_reg);
     513             : 
     514           0 :         vtotal = ((save_vtotal >> 16) & 0xfff) + 1;
     515           0 :         vactive = (save_vtotal & 0x7ff) + 1;
     516             : 
     517           0 :         vblank_start = (vblank & 0xfff) + 1;
     518           0 :         vblank_end = ((vblank >> 16) & 0xfff) + 1;
     519             : 
     520             :         /* Set the border color to purple. */
     521           0 :         I915_WRITE(bclrpat_reg, 0x500050);
     522             : 
     523           0 :         if (!IS_GEN2(dev)) {
     524           0 :                 uint32_t pipeconf = I915_READ(pipeconf_reg);
     525           0 :                 I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER);
     526           0 :                 POSTING_READ(pipeconf_reg);
     527             :                 /* Wait for next Vblank to substitue
     528             :                  * border color for Color info */
     529           0 :                 intel_wait_for_vblank(dev, pipe);
     530           0 :                 st00 = I915_READ8(VGA_MSR_WRITE);
     531           0 :                 status = ((st00 & (1 << 4)) != 0) ?
     532             :                         connector_status_connected :
     533             :                         connector_status_disconnected;
     534             : 
     535           0 :                 I915_WRITE(pipeconf_reg, pipeconf);
     536           0 :         } else {
     537             :                 bool restore_vblank = false;
     538             :                 int count, detect;
     539             : 
     540             :                 /*
     541             :                 * If there isn't any border, add some.
     542             :                 * Yes, this will flicker
     543             :                 */
     544           0 :                 if (vblank_start <= vactive && vblank_end >= vtotal) {
     545           0 :                         uint32_t vsync = I915_READ(vsync_reg);
     546           0 :                         uint32_t vsync_start = (vsync & 0xffff) + 1;
     547             : 
     548             :                         vblank_start = vsync_start;
     549           0 :                         I915_WRITE(vblank_reg,
     550             :                                    (vblank_start - 1) |
     551             :                                    ((vblank_end - 1) << 16));
     552             :                         restore_vblank = true;
     553           0 :                 }
     554             :                 /* sample in the vertical border, selecting the larger one */
     555           0 :                 if (vblank_start - vactive >= vtotal - vblank_end)
     556           0 :                         vsample = (vblank_start + vactive) >> 1;
     557             :                 else
     558           0 :                         vsample = (vtotal + vblank_end) >> 1;
     559             : 
     560             :                 /*
     561             :                  * Wait for the border to be displayed
     562             :                  */
     563           0 :                 while (I915_READ(pipe_dsl_reg) >= vactive)
     564             :                         ;
     565           0 :                 while ((dsl = I915_READ(pipe_dsl_reg)) <= vsample)
     566             :                         ;
     567             :                 /*
     568             :                  * Watch ST00 for an entire scanline
     569             :                  */
     570             :                 detect = 0;
     571             :                 count = 0;
     572           0 :                 do {
     573           0 :                         count++;
     574             :                         /* Read the ST00 VGA status register */
     575           0 :                         st00 = I915_READ8(VGA_MSR_WRITE);
     576           0 :                         if (st00 & (1 << 4))
     577           0 :                                 detect++;
     578           0 :                 } while ((I915_READ(pipe_dsl_reg) == dsl));
     579             : 
     580             :                 /* restore vblank if necessary */
     581           0 :                 if (restore_vblank)
     582           0 :                         I915_WRITE(vblank_reg, vblank);
     583             :                 /*
     584             :                  * If more than 3/4 of the scanline detected a monitor,
     585             :                  * then it is assumed to be present. This works even on i830,
     586             :                  * where there isn't any way to force the border color across
     587             :                  * the screen
     588             :                  */
     589           0 :                 status = detect * 4 > count * 3 ?
     590             :                          connector_status_connected :
     591             :                          connector_status_disconnected;
     592             :         }
     593             : 
     594             :         /* Restore previous settings */
     595           0 :         I915_WRITE(bclrpat_reg, save_bclrpat);
     596             : 
     597           0 :         return status;
     598             : }
     599             : 
     600             : static enum drm_connector_status
     601           0 : intel_crt_detect(struct drm_connector *connector, bool force)
     602             : {
     603           0 :         struct drm_device *dev = connector->dev;
     604           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     605           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     606           0 :         struct intel_encoder *intel_encoder = &crt->base;
     607             :         enum intel_display_power_domain power_domain;
     608             :         enum drm_connector_status status;
     609           0 :         struct intel_load_detect_pipe tmp;
     610           0 :         struct drm_modeset_acquire_ctx ctx;
     611             : 
     612             :         DRM_DEBUG_KMS("[CONNECTOR:%d:%s] force=%d\n",
     613             :                       connector->base.id, connector->name,
     614             :                       force);
     615             : 
     616           0 :         power_domain = intel_display_port_power_domain(intel_encoder);
     617           0 :         intel_display_power_get(dev_priv, power_domain);
     618             : 
     619           0 :         if (I915_HAS_HOTPLUG(dev)) {
     620             :                 /* We can not rely on the HPD pin always being correctly wired
     621             :                  * up, for example many KVM do not pass it through, and so
     622             :                  * only trust an assertion that the monitor is connected.
     623             :                  */
     624           0 :                 if (intel_crt_detect_hotplug(connector)) {
     625             :                         DRM_DEBUG_KMS("CRT detected via hotplug\n");
     626             :                         status = connector_status_connected;
     627           0 :                         goto out;
     628             :                 } else
     629             :                         DRM_DEBUG_KMS("CRT not detected via hotplug\n");
     630             :         }
     631             : 
     632           0 :         if (intel_crt_detect_ddc(connector)) {
     633             :                 status = connector_status_connected;
     634           0 :                 goto out;
     635             :         }
     636             : 
     637             :         /* Load detection is broken on HPD capable machines. Whoever wants a
     638             :          * broken monitor (without edid) to work behind a broken kvm (that fails
     639             :          * to have the right resistors for HP detection) needs to fix this up.
     640             :          * For now just bail out. */
     641           0 :         if (I915_HAS_HOTPLUG(dev) && !i915.load_detect_test) {
     642             :                 status = connector_status_disconnected;
     643           0 :                 goto out;
     644             :         }
     645             : 
     646           0 :         if (!force) {
     647           0 :                 status = connector->status;
     648           0 :                 goto out;
     649             :         }
     650             : 
     651           0 :         drm_modeset_acquire_init(&ctx, 0);
     652             : 
     653             :         /* for pre-945g platforms use load detect */
     654           0 :         if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
     655           0 :                 if (intel_crt_detect_ddc(connector))
     656           0 :                         status = connector_status_connected;
     657           0 :                 else if (INTEL_INFO(dev)->gen < 4)
     658           0 :                         status = intel_crt_load_detect(crt);
     659             :                 else
     660             :                         status = connector_status_unknown;
     661           0 :                 intel_release_load_detect_pipe(connector, &tmp, &ctx);
     662           0 :         } else
     663             :                 status = connector_status_unknown;
     664             : 
     665           0 :         drm_modeset_drop_locks(&ctx);
     666           0 :         drm_modeset_acquire_fini(&ctx);
     667             : 
     668             : out:
     669           0 :         intel_display_power_put(dev_priv, power_domain);
     670           0 :         return status;
     671           0 : }
     672             : 
     673           0 : static void intel_crt_destroy(struct drm_connector *connector)
     674             : {
     675           0 :         drm_connector_cleanup(connector);
     676           0 :         kfree(connector);
     677           0 : }
     678             : 
     679           0 : static int intel_crt_get_modes(struct drm_connector *connector)
     680             : {
     681           0 :         struct drm_device *dev = connector->dev;
     682           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     683           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     684           0 :         struct intel_encoder *intel_encoder = &crt->base;
     685             :         enum intel_display_power_domain power_domain;
     686             :         int ret;
     687             :         struct i2c_adapter *i2c;
     688             : 
     689           0 :         power_domain = intel_display_port_power_domain(intel_encoder);
     690           0 :         intel_display_power_get(dev_priv, power_domain);
     691             : 
     692           0 :         i2c = intel_gmbus_get_adapter(dev_priv, dev_priv->vbt.crt_ddc_pin);
     693           0 :         ret = intel_crt_ddc_get_modes(connector, i2c);
     694           0 :         if (ret || !IS_G4X(dev))
     695             :                 goto out;
     696             : 
     697             :         /* Try to probe digital port for output in DVI-I -> VGA mode. */
     698           0 :         i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB);
     699           0 :         ret = intel_crt_ddc_get_modes(connector, i2c);
     700             : 
     701             : out:
     702           0 :         intel_display_power_put(dev_priv, power_domain);
     703             : 
     704           0 :         return ret;
     705             : }
     706             : 
     707           0 : static int intel_crt_set_property(struct drm_connector *connector,
     708             :                                   struct drm_property *property,
     709             :                                   uint64_t value)
     710             : {
     711           0 :         return 0;
     712             : }
     713             : 
     714           0 : static void intel_crt_reset(struct drm_connector *connector)
     715             : {
     716           0 :         struct drm_device *dev = connector->dev;
     717           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     718           0 :         struct intel_crt *crt = intel_attached_crt(connector);
     719             : 
     720           0 :         if (INTEL_INFO(dev)->gen >= 5) {
     721             :                 u32 adpa;
     722             : 
     723           0 :                 adpa = I915_READ(crt->adpa_reg);
     724           0 :                 adpa &= ~ADPA_CRT_HOTPLUG_MASK;
     725           0 :                 adpa |= ADPA_HOTPLUG_BITS;
     726           0 :                 I915_WRITE(crt->adpa_reg, adpa);
     727           0 :                 POSTING_READ(crt->adpa_reg);
     728             : 
     729             :                 DRM_DEBUG_KMS("crt adpa set to 0x%x\n", adpa);
     730           0 :                 crt->force_hotplug_required = 1;
     731           0 :         }
     732             : 
     733           0 : }
     734             : 
     735             : /*
     736             :  * Routines for controlling stuff on the analog port
     737             :  */
     738             : 
     739             : static const struct drm_connector_funcs intel_crt_connector_funcs = {
     740             :         .reset = intel_crt_reset,
     741             :         .dpms = drm_atomic_helper_connector_dpms,
     742             :         .detect = intel_crt_detect,
     743             :         .fill_modes = drm_helper_probe_single_connector_modes,
     744             :         .destroy = intel_crt_destroy,
     745             :         .set_property = intel_crt_set_property,
     746             :         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
     747             :         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
     748             :         .atomic_get_property = intel_connector_atomic_get_property,
     749             : };
     750             : 
     751             : static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = {
     752             :         .mode_valid = intel_crt_mode_valid,
     753             :         .get_modes = intel_crt_get_modes,
     754             :         .best_encoder = intel_best_encoder,
     755             : };
     756             : 
     757             : static const struct drm_encoder_funcs intel_crt_enc_funcs = {
     758             :         .destroy = intel_encoder_destroy,
     759             : };
     760             : 
     761           0 : static int intel_no_crt_dmi_callback(const struct dmi_system_id *id)
     762             : {
     763             :         DRM_INFO("Skipping CRT initialization for %s\n", id->ident);
     764           0 :         return 1;
     765             : }
     766             : 
     767             : static const struct dmi_system_id intel_no_crt[] = {
     768             :         {
     769             :                 .callback = intel_no_crt_dmi_callback,
     770             :                 .ident = "ACER ZGB",
     771             :                 .matches = {
     772             :                         DMI_MATCH(DMI_SYS_VENDOR, "ACER"),
     773             :                         DMI_MATCH(DMI_PRODUCT_NAME, "ZGB"),
     774             :                 },
     775             :         },
     776             :         {
     777             :                 .callback = intel_no_crt_dmi_callback,
     778             :                 .ident = "DELL XPS 8700",
     779             :                 .matches = {
     780             :                         DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
     781             :                         DMI_MATCH(DMI_PRODUCT_NAME, "XPS 8700"),
     782             :                 },
     783             :         },
     784             :         { }
     785             : };
     786             : 
     787           0 : void intel_crt_init(struct drm_device *dev)
     788             : {
     789             :         struct drm_connector *connector;
     790             :         struct intel_crt *crt;
     791             :         struct intel_connector *intel_connector;
     792           0 :         struct drm_i915_private *dev_priv = dev->dev_private;
     793             : 
     794             :         /* Skip machines without VGA that falsely report hotplug events */
     795           0 :         if (dmi_check_system(intel_no_crt))
     796           0 :                 return;
     797             : 
     798           0 :         crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL);
     799           0 :         if (!crt)
     800           0 :                 return;
     801             : 
     802           0 :         intel_connector = intel_connector_alloc();
     803           0 :         if (!intel_connector) {
     804           0 :                 kfree(crt);
     805           0 :                 return;
     806             :         }
     807             : 
     808           0 :         connector = &intel_connector->base;
     809           0 :         crt->connector = intel_connector;
     810           0 :         drm_connector_init(dev, &intel_connector->base,
     811             :                            &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
     812             : 
     813           0 :         drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs,
     814             :                          DRM_MODE_ENCODER_DAC);
     815             : 
     816           0 :         intel_connector_attach_encoder(intel_connector, &crt->base);
     817             : 
     818           0 :         crt->base.type = INTEL_OUTPUT_ANALOG;
     819           0 :         crt->base.cloneable = (1 << INTEL_OUTPUT_DVO) | (1 << INTEL_OUTPUT_HDMI);
     820           0 :         if (IS_I830(dev))
     821           0 :                 crt->base.crtc_mask = (1 << 0);
     822             :         else
     823           0 :                 crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
     824             : 
     825           0 :         if (IS_GEN2(dev))
     826           0 :                 connector->interlace_allowed = 0;
     827             :         else
     828           0 :                 connector->interlace_allowed = 1;
     829           0 :         connector->doublescan_allowed = 0;
     830             : 
     831           0 :         if (HAS_PCH_SPLIT(dev))
     832           0 :                 crt->adpa_reg = PCH_ADPA;
     833           0 :         else if (IS_VALLEYVIEW(dev))
     834           0 :                 crt->adpa_reg = VLV_ADPA;
     835             :         else
     836           0 :                 crt->adpa_reg = ADPA;
     837             : 
     838           0 :         crt->base.compute_config = intel_crt_compute_config;
     839           0 :         if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) {
     840           0 :                 crt->base.disable = pch_disable_crt;
     841           0 :                 crt->base.post_disable = pch_post_disable_crt;
     842           0 :         } else {
     843           0 :                 crt->base.disable = intel_disable_crt;
     844             :         }
     845           0 :         crt->base.enable = intel_enable_crt;
     846           0 :         if (I915_HAS_HOTPLUG(dev))
     847           0 :                 crt->base.hpd_pin = HPD_CRT;
     848           0 :         if (HAS_DDI(dev)) {
     849           0 :                 crt->base.get_config = hsw_crt_get_config;
     850           0 :                 crt->base.get_hw_state = intel_ddi_get_hw_state;
     851           0 :         } else {
     852           0 :                 crt->base.get_config = intel_crt_get_config;
     853           0 :                 crt->base.get_hw_state = intel_crt_get_hw_state;
     854             :         }
     855           0 :         intel_connector->get_hw_state = intel_connector_get_hw_state;
     856           0 :         intel_connector->unregister = intel_connector_unregister;
     857             : 
     858           0 :         drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
     859             : 
     860           0 :         drm_connector_register(connector);
     861             : 
     862           0 :         if (!I915_HAS_HOTPLUG(dev))
     863           0 :                 intel_connector->polled = DRM_CONNECTOR_POLL_CONNECT;
     864             : 
     865             :         /*
     866             :          * Configure the automatic hotplug detection stuff
     867             :          */
     868           0 :         crt->force_hotplug_required = 0;
     869             : 
     870             :         /*
     871             :          * TODO: find a proper way to discover whether we need to set the the
     872             :          * polarity and link reversal bits or not, instead of relying on the
     873             :          * BIOS.
     874             :          */
     875           0 :         if (HAS_PCH_LPT(dev)) {
     876             :                 u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT |
     877             :                                  FDI_RX_LINK_REVERSAL_OVERRIDE;
     878             : 
     879           0 :                 dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config;
     880           0 :         }
     881             : 
     882           0 :         intel_crt_reset(connector);
     883           0 : }

Generated by: LCOV version 1.13