Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright © 2006-2007 Intel Corporation
0003  * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>
0004  *
0005  * Permission is hereby granted, free of charge, to any person obtaining a
0006  * copy of this software and associated documentation files (the "Software"),
0007  * to deal in the Software without restriction, including without limitation
0008  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0009  * and/or sell copies of the Software, and to permit persons to whom the
0010  * Software is furnished to do so, subject to the following conditions:
0011  *
0012  * The above copyright notice and this permission notice (including the next
0013  * paragraph) shall be included in all copies or substantial portions of the
0014  * Software.
0015  *
0016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0017  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0018  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0019  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
0020  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
0021  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
0022  * DEALINGS IN THE SOFTWARE.
0023  *
0024  * Authors:
0025  *  Eric Anholt <eric@anholt.net>
0026  *      Dave Airlie <airlied@linux.ie>
0027  *      Jesse Barnes <jesse.barnes@intel.com>
0028  */
0029 
0030 #include <acpi/button.h>
0031 #include <linux/acpi.h>
0032 #include <linux/dmi.h>
0033 #include <linux/i2c.h>
0034 #include <linux/slab.h>
0035 #include <linux/vga_switcheroo.h>
0036 
0037 #include <drm/drm_atomic_helper.h>
0038 #include <drm/drm_crtc.h>
0039 #include <drm/drm_edid.h>
0040 
0041 #include "i915_drv.h"
0042 #include "intel_atomic.h"
0043 #include "intel_backlight.h"
0044 #include "intel_connector.h"
0045 #include "intel_de.h"
0046 #include "intel_display_types.h"
0047 #include "intel_dpll.h"
0048 #include "intel_fdi.h"
0049 #include "intel_gmbus.h"
0050 #include "intel_lvds.h"
0051 #include "intel_panel.h"
0052 
0053 /* Private structure for the integrated LVDS support */
0054 struct intel_lvds_pps {
0055     /* 100us units */
0056     int t1_t2;
0057     int t3;
0058     int t4;
0059     int t5;
0060     int tx;
0061 
0062     int divider;
0063 
0064     int port;
0065     bool powerdown_on_reset;
0066 };
0067 
0068 struct intel_lvds_encoder {
0069     struct intel_encoder base;
0070 
0071     bool is_dual_link;
0072     i915_reg_t reg;
0073     u32 a3_power;
0074 
0075     struct intel_lvds_pps init_pps;
0076     u32 init_lvds_val;
0077 
0078     struct intel_connector *attached_connector;
0079 };
0080 
0081 static struct intel_lvds_encoder *to_lvds_encoder(struct drm_encoder *encoder)
0082 {
0083     return container_of(encoder, struct intel_lvds_encoder, base.base);
0084 }
0085 
0086 bool intel_lvds_port_enabled(struct drm_i915_private *dev_priv,
0087                  i915_reg_t lvds_reg, enum pipe *pipe)
0088 {
0089     u32 val;
0090 
0091     val = intel_de_read(dev_priv, lvds_reg);
0092 
0093     /* asserts want to know the pipe even if the port is disabled */
0094     if (HAS_PCH_CPT(dev_priv))
0095         *pipe = (val & LVDS_PIPE_SEL_MASK_CPT) >> LVDS_PIPE_SEL_SHIFT_CPT;
0096     else
0097         *pipe = (val & LVDS_PIPE_SEL_MASK) >> LVDS_PIPE_SEL_SHIFT;
0098 
0099     return val & LVDS_PORT_EN;
0100 }
0101 
0102 static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,
0103                     enum pipe *pipe)
0104 {
0105     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
0106     struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
0107     intel_wakeref_t wakeref;
0108     bool ret;
0109 
0110     wakeref = intel_display_power_get_if_enabled(dev_priv,
0111                              encoder->power_domain);
0112     if (!wakeref)
0113         return false;
0114 
0115     ret = intel_lvds_port_enabled(dev_priv, lvds_encoder->reg, pipe);
0116 
0117     intel_display_power_put(dev_priv, encoder->power_domain, wakeref);
0118 
0119     return ret;
0120 }
0121 
0122 static void intel_lvds_get_config(struct intel_encoder *encoder,
0123                   struct intel_crtc_state *pipe_config)
0124 {
0125     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
0126     struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
0127     u32 tmp, flags = 0;
0128 
0129     pipe_config->output_types |= BIT(INTEL_OUTPUT_LVDS);
0130 
0131     tmp = intel_de_read(dev_priv, lvds_encoder->reg);
0132     if (tmp & LVDS_HSYNC_POLARITY)
0133         flags |= DRM_MODE_FLAG_NHSYNC;
0134     else
0135         flags |= DRM_MODE_FLAG_PHSYNC;
0136     if (tmp & LVDS_VSYNC_POLARITY)
0137         flags |= DRM_MODE_FLAG_NVSYNC;
0138     else
0139         flags |= DRM_MODE_FLAG_PVSYNC;
0140 
0141     pipe_config->hw.adjusted_mode.flags |= flags;
0142 
0143     if (DISPLAY_VER(dev_priv) < 5)
0144         pipe_config->gmch_pfit.lvds_border_bits =
0145             tmp & LVDS_BORDER_ENABLE;
0146 
0147     /* gen2/3 store dither state in pfit control, needs to match */
0148     if (DISPLAY_VER(dev_priv) < 4) {
0149         tmp = intel_de_read(dev_priv, PFIT_CONTROL);
0150 
0151         pipe_config->gmch_pfit.control |= tmp & PANEL_8TO6_DITHER_ENABLE;
0152     }
0153 
0154     pipe_config->hw.adjusted_mode.crtc_clock = pipe_config->port_clock;
0155 }
0156 
0157 static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,
0158                     struct intel_lvds_pps *pps)
0159 {
0160     u32 val;
0161 
0162     pps->powerdown_on_reset = intel_de_read(dev_priv, PP_CONTROL(0)) & PANEL_POWER_RESET;
0163 
0164     val = intel_de_read(dev_priv, PP_ON_DELAYS(0));
0165     pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val);
0166     pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);
0167     pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);
0168 
0169     val = intel_de_read(dev_priv, PP_OFF_DELAYS(0));
0170     pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);
0171     pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);
0172 
0173     val = intel_de_read(dev_priv, PP_DIVISOR(0));
0174     pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val);
0175     val = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, val);
0176     /*
0177      * Remove the BSpec specified +1 (100ms) offset that accounts for a
0178      * too short power-cycle delay due to the asynchronous programming of
0179      * the register.
0180      */
0181     if (val)
0182         val--;
0183     /* Convert from 100ms to 100us units */
0184     pps->t4 = val * 1000;
0185 
0186     if (DISPLAY_VER(dev_priv) <= 4 &&
0187         pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {
0188         drm_dbg_kms(&dev_priv->drm,
0189                 "Panel power timings uninitialized, "
0190                 "setting defaults\n");
0191         /* Set T2 to 40ms and T5 to 200ms in 100 usec units */
0192         pps->t1_t2 = 40 * 10;
0193         pps->t5 = 200 * 10;
0194         /* Set T3 to 35ms and Tx to 200ms in 100 usec units */
0195         pps->t3 = 35 * 10;
0196         pps->tx = 200 * 10;
0197     }
0198 
0199     drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "
0200         "divider %d port %d powerdown_on_reset %d\n",
0201         pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,
0202         pps->divider, pps->port, pps->powerdown_on_reset);
0203 }
0204 
0205 static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,
0206                    struct intel_lvds_pps *pps)
0207 {
0208     u32 val;
0209 
0210     val = intel_de_read(dev_priv, PP_CONTROL(0));
0211     drm_WARN_ON(&dev_priv->drm,
0212             (val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);
0213     if (pps->powerdown_on_reset)
0214         val |= PANEL_POWER_RESET;
0215     intel_de_write(dev_priv, PP_CONTROL(0), val);
0216 
0217     intel_de_write(dev_priv, PP_ON_DELAYS(0),
0218                REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) | REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) | REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5));
0219 
0220     intel_de_write(dev_priv, PP_OFF_DELAYS(0),
0221                REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) | REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx));
0222 
0223     intel_de_write(dev_priv, PP_DIVISOR(0),
0224                REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1));
0225 }
0226 
0227 static void intel_pre_enable_lvds(struct intel_atomic_state *state,
0228                   struct intel_encoder *encoder,
0229                   const struct intel_crtc_state *pipe_config,
0230                   const struct drm_connector_state *conn_state)
0231 {
0232     struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
0233     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
0234     struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
0235     const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
0236     enum pipe pipe = crtc->pipe;
0237     u32 temp;
0238 
0239     if (HAS_PCH_SPLIT(dev_priv)) {
0240         assert_fdi_rx_pll_disabled(dev_priv, pipe);
0241         assert_shared_dpll_disabled(dev_priv,
0242                         pipe_config->shared_dpll);
0243     } else {
0244         assert_pll_disabled(dev_priv, pipe);
0245     }
0246 
0247     intel_lvds_pps_init_hw(dev_priv, &lvds_encoder->init_pps);
0248 
0249     temp = lvds_encoder->init_lvds_val;
0250     temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;
0251 
0252     if (HAS_PCH_CPT(dev_priv)) {
0253         temp &= ~LVDS_PIPE_SEL_MASK_CPT;
0254         temp |= LVDS_PIPE_SEL_CPT(pipe);
0255     } else {
0256         temp &= ~LVDS_PIPE_SEL_MASK;
0257         temp |= LVDS_PIPE_SEL(pipe);
0258     }
0259 
0260     /* set the corresponsding LVDS_BORDER bit */
0261     temp &= ~LVDS_BORDER_ENABLE;
0262     temp |= pipe_config->gmch_pfit.lvds_border_bits;
0263 
0264     /*
0265      * Set the B0-B3 data pairs corresponding to whether we're going to
0266      * set the DPLLs for dual-channel mode or not.
0267      */
0268     if (lvds_encoder->is_dual_link)
0269         temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
0270     else
0271         temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
0272 
0273     /*
0274      * It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
0275      * appropriately here, but we need to look more thoroughly into how
0276      * panels behave in the two modes. For now, let's just maintain the
0277      * value we got from the BIOS.
0278      */
0279     temp &= ~LVDS_A3_POWER_MASK;
0280     temp |= lvds_encoder->a3_power;
0281 
0282     /*
0283      * Set the dithering flag on LVDS as needed, note that there is no
0284      * special lvds dither control bit on pch-split platforms, dithering is
0285      * only controlled through the PIPECONF reg.
0286      */
0287     if (DISPLAY_VER(dev_priv) == 4) {
0288         /*
0289          * Bspec wording suggests that LVDS port dithering only exists
0290          * for 18bpp panels.
0291          */
0292         if (pipe_config->dither && pipe_config->pipe_bpp == 18)
0293             temp |= LVDS_ENABLE_DITHER;
0294         else
0295             temp &= ~LVDS_ENABLE_DITHER;
0296     }
0297     temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
0298     if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
0299         temp |= LVDS_HSYNC_POLARITY;
0300     if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
0301         temp |= LVDS_VSYNC_POLARITY;
0302 
0303     intel_de_write(dev_priv, lvds_encoder->reg, temp);
0304 }
0305 
0306 /*
0307  * Sets the power state for the panel.
0308  */
0309 static void intel_enable_lvds(struct intel_atomic_state *state,
0310                   struct intel_encoder *encoder,
0311                   const struct intel_crtc_state *pipe_config,
0312                   const struct drm_connector_state *conn_state)
0313 {
0314     struct drm_device *dev = encoder->base.dev;
0315     struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
0316     struct drm_i915_private *dev_priv = to_i915(dev);
0317 
0318     intel_de_write(dev_priv, lvds_encoder->reg,
0319                intel_de_read(dev_priv, lvds_encoder->reg) | LVDS_PORT_EN);
0320 
0321     intel_de_write(dev_priv, PP_CONTROL(0),
0322                intel_de_read(dev_priv, PP_CONTROL(0)) | PANEL_POWER_ON);
0323     intel_de_posting_read(dev_priv, lvds_encoder->reg);
0324 
0325     if (intel_de_wait_for_set(dev_priv, PP_STATUS(0), PP_ON, 5000))
0326         drm_err(&dev_priv->drm,
0327             "timed out waiting for panel to power on\n");
0328 
0329     intel_backlight_enable(pipe_config, conn_state);
0330 }
0331 
0332 static void intel_disable_lvds(struct intel_atomic_state *state,
0333                    struct intel_encoder *encoder,
0334                    const struct intel_crtc_state *old_crtc_state,
0335                    const struct drm_connector_state *old_conn_state)
0336 {
0337     struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(&encoder->base);
0338     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
0339 
0340     intel_de_write(dev_priv, PP_CONTROL(0),
0341                intel_de_read(dev_priv, PP_CONTROL(0)) & ~PANEL_POWER_ON);
0342     if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_ON, 1000))
0343         drm_err(&dev_priv->drm,
0344             "timed out waiting for panel to power off\n");
0345 
0346     intel_de_write(dev_priv, lvds_encoder->reg,
0347                intel_de_read(dev_priv, lvds_encoder->reg) & ~LVDS_PORT_EN);
0348     intel_de_posting_read(dev_priv, lvds_encoder->reg);
0349 }
0350 
0351 static void gmch_disable_lvds(struct intel_atomic_state *state,
0352                   struct intel_encoder *encoder,
0353                   const struct intel_crtc_state *old_crtc_state,
0354                   const struct drm_connector_state *old_conn_state)
0355 
0356 {
0357     intel_backlight_disable(old_conn_state);
0358 
0359     intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);
0360 }
0361 
0362 static void pch_disable_lvds(struct intel_atomic_state *state,
0363                  struct intel_encoder *encoder,
0364                  const struct intel_crtc_state *old_crtc_state,
0365                  const struct drm_connector_state *old_conn_state)
0366 {
0367     intel_backlight_disable(old_conn_state);
0368 }
0369 
0370 static void pch_post_disable_lvds(struct intel_atomic_state *state,
0371                   struct intel_encoder *encoder,
0372                   const struct intel_crtc_state *old_crtc_state,
0373                   const struct drm_connector_state *old_conn_state)
0374 {
0375     intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);
0376 }
0377 
0378 static void intel_lvds_shutdown(struct intel_encoder *encoder)
0379 {
0380     struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
0381 
0382     if (intel_de_wait_for_clear(dev_priv, PP_STATUS(0), PP_CYCLE_DELAY_ACTIVE, 5000))
0383         drm_err(&dev_priv->drm,
0384             "timed out waiting for panel power cycle delay\n");
0385 }
0386 
0387 static enum drm_mode_status
0388 intel_lvds_mode_valid(struct drm_connector *connector,
0389               struct drm_display_mode *mode)
0390 {
0391     struct intel_connector *intel_connector = to_intel_connector(connector);
0392     const struct drm_display_mode *fixed_mode =
0393         intel_panel_fixed_mode(intel_connector, mode);
0394     int max_pixclk = to_i915(connector->dev)->max_dotclk_freq;
0395     enum drm_mode_status status;
0396 
0397     if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
0398         return MODE_NO_DBLESCAN;
0399 
0400     status = intel_panel_mode_valid(intel_connector, mode);
0401     if (status != MODE_OK)
0402         return status;
0403 
0404     if (fixed_mode->clock > max_pixclk)
0405         return MODE_CLOCK_HIGH;
0406 
0407     return MODE_OK;
0408 }
0409 
0410 static int intel_lvds_compute_config(struct intel_encoder *intel_encoder,
0411                      struct intel_crtc_state *pipe_config,
0412                      struct drm_connector_state *conn_state)
0413 {
0414     struct drm_i915_private *dev_priv = to_i915(intel_encoder->base.dev);
0415     struct intel_lvds_encoder *lvds_encoder =
0416         to_lvds_encoder(&intel_encoder->base);
0417     struct intel_connector *intel_connector =
0418         lvds_encoder->attached_connector;
0419     struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode;
0420     struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc);
0421     unsigned int lvds_bpp;
0422     int ret;
0423 
0424     /* Should never happen!! */
0425     if (DISPLAY_VER(dev_priv) < 4 && crtc->pipe == 0) {
0426         drm_err(&dev_priv->drm, "Can't support LVDS on pipe A\n");
0427         return -EINVAL;
0428     }
0429 
0430     if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)
0431         lvds_bpp = 8*3;
0432     else
0433         lvds_bpp = 6*3;
0434 
0435     if (lvds_bpp != pipe_config->pipe_bpp && !pipe_config->bw_constrained) {
0436         drm_dbg_kms(&dev_priv->drm,
0437                 "forcing display bpp (was %d) to LVDS (%d)\n",
0438                 pipe_config->pipe_bpp, lvds_bpp);
0439         pipe_config->pipe_bpp = lvds_bpp;
0440     }
0441 
0442     pipe_config->output_format = INTEL_OUTPUT_FORMAT_RGB;
0443 
0444     /*
0445      * We have timings from the BIOS for the panel, put them in
0446      * to the adjusted mode.  The CRTC will be set up for this mode,
0447      * with the panel scaling set up to source from the H/VDisplay
0448      * of the original mode.
0449      */
0450     ret = intel_panel_compute_config(intel_connector, adjusted_mode);
0451     if (ret)
0452         return ret;
0453 
0454     if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)
0455         return -EINVAL;
0456 
0457     if (HAS_PCH_SPLIT(dev_priv))
0458         pipe_config->has_pch_encoder = true;
0459 
0460     ret = intel_panel_fitting(pipe_config, conn_state);
0461     if (ret)
0462         return ret;
0463 
0464     /*
0465      * XXX: It would be nice to support lower refresh rates on the
0466      * panels to reduce power consumption, and perhaps match the
0467      * user's requested refresh rate.
0468      */
0469 
0470     return 0;
0471 }
0472 
0473 /*
0474  * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
0475  */
0476 static int intel_lvds_get_modes(struct drm_connector *connector)
0477 {
0478     struct intel_connector *intel_connector = to_intel_connector(connector);
0479 
0480     /* use cached edid if we have one */
0481     if (!IS_ERR_OR_NULL(intel_connector->edid))
0482         return drm_add_edid_modes(connector, intel_connector->edid);
0483 
0484     return intel_panel_get_modes(intel_connector);
0485 }
0486 
0487 static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {
0488     .get_modes = intel_lvds_get_modes,
0489     .mode_valid = intel_lvds_mode_valid,
0490     .atomic_check = intel_digital_connector_atomic_check,
0491 };
0492 
0493 static const struct drm_connector_funcs intel_lvds_connector_funcs = {
0494     .detect = intel_panel_detect,
0495     .fill_modes = drm_helper_probe_single_connector_modes,
0496     .atomic_get_property = intel_digital_connector_atomic_get_property,
0497     .atomic_set_property = intel_digital_connector_atomic_set_property,
0498     .late_register = intel_connector_register,
0499     .early_unregister = intel_connector_unregister,
0500     .destroy = intel_connector_destroy,
0501     .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
0502     .atomic_duplicate_state = intel_digital_connector_duplicate_state,
0503 };
0504 
0505 static const struct drm_encoder_funcs intel_lvds_enc_funcs = {
0506     .destroy = intel_encoder_destroy,
0507 };
0508 
0509 static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)
0510 {
0511     DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);
0512     return 1;
0513 }
0514 
0515 /* These systems claim to have LVDS, but really don't */
0516 static const struct dmi_system_id intel_no_lvds[] = {
0517     {
0518         .callback = intel_no_lvds_dmi_callback,
0519         .ident = "Apple Mac Mini (Core series)",
0520         .matches = {
0521             DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
0522             DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),
0523         },
0524     },
0525     {
0526         .callback = intel_no_lvds_dmi_callback,
0527         .ident = "Apple Mac Mini (Core 2 series)",
0528         .matches = {
0529             DMI_MATCH(DMI_SYS_VENDOR, "Apple"),
0530             DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),
0531         },
0532     },
0533     {
0534         .callback = intel_no_lvds_dmi_callback,
0535         .ident = "MSI IM-945GSE-A",
0536         .matches = {
0537             DMI_MATCH(DMI_SYS_VENDOR, "MSI"),
0538             DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),
0539         },
0540     },
0541     {
0542         .callback = intel_no_lvds_dmi_callback,
0543         .ident = "Dell Studio Hybrid",
0544         .matches = {
0545             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0546             DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),
0547         },
0548     },
0549     {
0550         .callback = intel_no_lvds_dmi_callback,
0551         .ident = "Dell OptiPlex FX170",
0552         .matches = {
0553             DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
0554             DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),
0555         },
0556     },
0557     {
0558         .callback = intel_no_lvds_dmi_callback,
0559         .ident = "AOpen Mini PC",
0560         .matches = {
0561             DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),
0562             DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),
0563         },
0564     },
0565     {
0566         .callback = intel_no_lvds_dmi_callback,
0567         .ident = "AOpen Mini PC MP915",
0568         .matches = {
0569             DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
0570             DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),
0571         },
0572     },
0573     {
0574         .callback = intel_no_lvds_dmi_callback,
0575         .ident = "AOpen i915GMm-HFS",
0576         .matches = {
0577             DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
0578             DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),
0579         },
0580     },
0581     {
0582         .callback = intel_no_lvds_dmi_callback,
0583                 .ident = "AOpen i45GMx-I",
0584                 .matches = {
0585                         DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),
0586                         DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),
0587                 },
0588         },
0589     {
0590         .callback = intel_no_lvds_dmi_callback,
0591         .ident = "Aopen i945GTt-VFA",
0592         .matches = {
0593             DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),
0594         },
0595     },
0596     {
0597         .callback = intel_no_lvds_dmi_callback,
0598         .ident = "Clientron U800",
0599         .matches = {
0600             DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
0601             DMI_MATCH(DMI_PRODUCT_NAME, "U800"),
0602         },
0603     },
0604     {
0605                 .callback = intel_no_lvds_dmi_callback,
0606                 .ident = "Clientron E830",
0607                 .matches = {
0608                         DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),
0609                         DMI_MATCH(DMI_PRODUCT_NAME, "E830"),
0610                 },
0611         },
0612         {
0613         .callback = intel_no_lvds_dmi_callback,
0614         .ident = "Asus EeeBox PC EB1007",
0615         .matches = {
0616             DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),
0617             DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),
0618         },
0619     },
0620     {
0621         .callback = intel_no_lvds_dmi_callback,
0622         .ident = "Asus AT5NM10T-I",
0623         .matches = {
0624             DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),
0625             DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),
0626         },
0627     },
0628     {
0629         .callback = intel_no_lvds_dmi_callback,
0630         .ident = "Hewlett-Packard HP t5740",
0631         .matches = {
0632             DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
0633             DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),
0634         },
0635     },
0636     {
0637         .callback = intel_no_lvds_dmi_callback,
0638         .ident = "Hewlett-Packard t5745",
0639         .matches = {
0640             DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
0641             DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),
0642         },
0643     },
0644     {
0645         .callback = intel_no_lvds_dmi_callback,
0646         .ident = "Hewlett-Packard st5747",
0647         .matches = {
0648             DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),
0649             DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),
0650         },
0651     },
0652     {
0653         .callback = intel_no_lvds_dmi_callback,
0654         .ident = "MSI Wind Box DC500",
0655         .matches = {
0656             DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),
0657             DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),
0658         },
0659     },
0660     {
0661         .callback = intel_no_lvds_dmi_callback,
0662         .ident = "Gigabyte GA-D525TUD",
0663         .matches = {
0664             DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
0665             DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
0666         },
0667     },
0668     {
0669         .callback = intel_no_lvds_dmi_callback,
0670         .ident = "Supermicro X7SPA-H",
0671         .matches = {
0672             DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),
0673             DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),
0674         },
0675     },
0676     {
0677         .callback = intel_no_lvds_dmi_callback,
0678         .ident = "Fujitsu Esprimo Q900",
0679         .matches = {
0680             DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
0681             DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),
0682         },
0683     },
0684     {
0685         .callback = intel_no_lvds_dmi_callback,
0686         .ident = "Intel D410PT",
0687         .matches = {
0688             DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
0689             DMI_MATCH(DMI_BOARD_NAME, "D410PT"),
0690         },
0691     },
0692     {
0693         .callback = intel_no_lvds_dmi_callback,
0694         .ident = "Intel D425KT",
0695         .matches = {
0696             DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
0697             DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),
0698         },
0699     },
0700     {
0701         .callback = intel_no_lvds_dmi_callback,
0702         .ident = "Intel D510MO",
0703         .matches = {
0704             DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
0705             DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),
0706         },
0707     },
0708     {
0709         .callback = intel_no_lvds_dmi_callback,
0710         .ident = "Intel D525MW",
0711         .matches = {
0712             DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),
0713             DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),
0714         },
0715     },
0716     {
0717         .callback = intel_no_lvds_dmi_callback,
0718         .ident = "Radiant P845",
0719         .matches = {
0720             DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),
0721             DMI_MATCH(DMI_PRODUCT_NAME, "P845"),
0722         },
0723     },
0724 
0725     { } /* terminating entry */
0726 };
0727 
0728 static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)
0729 {
0730     DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);
0731     return 1;
0732 }
0733 
0734 static const struct dmi_system_id intel_dual_link_lvds[] = {
0735     {
0736         .callback = intel_dual_link_lvds_callback,
0737         .ident = "Apple MacBook Pro 15\" (2010)",
0738         .matches = {
0739             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0740             DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),
0741         },
0742     },
0743     {
0744         .callback = intel_dual_link_lvds_callback,
0745         .ident = "Apple MacBook Pro 15\" (2011)",
0746         .matches = {
0747             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0748             DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),
0749         },
0750     },
0751     {
0752         .callback = intel_dual_link_lvds_callback,
0753         .ident = "Apple MacBook Pro 15\" (2012)",
0754         .matches = {
0755             DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
0756             DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),
0757         },
0758     },
0759     { } /* terminating entry */
0760 };
0761 
0762 struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *dev_priv)
0763 {
0764     struct intel_encoder *encoder;
0765 
0766     for_each_intel_encoder(&dev_priv->drm, encoder) {
0767         if (encoder->type == INTEL_OUTPUT_LVDS)
0768             return encoder;
0769     }
0770 
0771     return NULL;
0772 }
0773 
0774 bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv)
0775 {
0776     struct intel_encoder *encoder = intel_get_lvds_encoder(dev_priv);
0777 
0778     return encoder && to_lvds_encoder(&encoder->base)->is_dual_link;
0779 }
0780 
0781 static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)
0782 {
0783     struct drm_i915_private *dev_priv = to_i915(lvds_encoder->base.base.dev);
0784     struct intel_connector *connector = lvds_encoder->attached_connector;
0785     const struct drm_display_mode *fixed_mode =
0786         intel_panel_preferred_fixed_mode(connector);
0787     unsigned int val;
0788 
0789     /* use the module option value if specified */
0790     if (dev_priv->params.lvds_channel_mode > 0)
0791         return dev_priv->params.lvds_channel_mode == 2;
0792 
0793     /* single channel LVDS is limited to 112 MHz */
0794     if (fixed_mode->clock > 112999)
0795         return true;
0796 
0797     if (dmi_check_system(intel_dual_link_lvds))
0798         return true;
0799 
0800     /*
0801      * BIOS should set the proper LVDS register value at boot, but
0802      * in reality, it doesn't set the value when the lid is closed;
0803      * we need to check "the value to be set" in VBT when LVDS
0804      * register is uninitialized.
0805      */
0806     val = intel_de_read(dev_priv, lvds_encoder->reg);
0807     if (HAS_PCH_CPT(dev_priv))
0808         val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK_CPT);
0809     else
0810         val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK);
0811     if (val == 0)
0812         val = connector->panel.vbt.bios_lvds_val;
0813 
0814     return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;
0815 }
0816 
0817 /**
0818  * intel_lvds_init - setup LVDS connectors on this device
0819  * @dev_priv: i915 device
0820  *
0821  * Create the connector, register the LVDS DDC bus, and try to figure out what
0822  * modes we can display on the LVDS panel (if present).
0823  */
0824 void intel_lvds_init(struct drm_i915_private *dev_priv)
0825 {
0826     struct drm_device *dev = &dev_priv->drm;
0827     struct intel_lvds_encoder *lvds_encoder;
0828     struct intel_encoder *intel_encoder;
0829     struct intel_connector *intel_connector;
0830     struct drm_connector *connector;
0831     struct drm_encoder *encoder;
0832     struct edid *edid;
0833     i915_reg_t lvds_reg;
0834     u32 lvds;
0835     u8 pin;
0836     u32 allowed_scalers;
0837 
0838     /* Skip init on machines we know falsely report LVDS */
0839     if (dmi_check_system(intel_no_lvds)) {
0840         drm_WARN(dev, !dev_priv->vbt.int_lvds_support,
0841              "Useless DMI match. Internal LVDS support disabled by VBT\n");
0842         return;
0843     }
0844 
0845     if (!dev_priv->vbt.int_lvds_support) {
0846         drm_dbg_kms(&dev_priv->drm,
0847                 "Internal LVDS support disabled by VBT\n");
0848         return;
0849     }
0850 
0851     if (HAS_PCH_SPLIT(dev_priv))
0852         lvds_reg = PCH_LVDS;
0853     else
0854         lvds_reg = LVDS;
0855 
0856     lvds = intel_de_read(dev_priv, lvds_reg);
0857 
0858     if (HAS_PCH_SPLIT(dev_priv)) {
0859         if ((lvds & LVDS_DETECTED) == 0)
0860             return;
0861     }
0862 
0863     pin = GMBUS_PIN_PANEL;
0864     if (!intel_bios_is_lvds_present(dev_priv, &pin)) {
0865         if ((lvds & LVDS_PORT_EN) == 0) {
0866             drm_dbg_kms(&dev_priv->drm,
0867                     "LVDS is not present in VBT\n");
0868             return;
0869         }
0870         drm_dbg_kms(&dev_priv->drm,
0871                 "LVDS is not present in VBT, but enabled anyway\n");
0872     }
0873 
0874     lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);
0875     if (!lvds_encoder)
0876         return;
0877 
0878     intel_connector = intel_connector_alloc();
0879     if (!intel_connector) {
0880         kfree(lvds_encoder);
0881         return;
0882     }
0883 
0884     lvds_encoder->attached_connector = intel_connector;
0885 
0886     intel_encoder = &lvds_encoder->base;
0887     encoder = &intel_encoder->base;
0888     connector = &intel_connector->base;
0889     drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs,
0890                DRM_MODE_CONNECTOR_LVDS);
0891 
0892     drm_encoder_init(dev, &intel_encoder->base, &intel_lvds_enc_funcs,
0893              DRM_MODE_ENCODER_LVDS, "LVDS");
0894 
0895     intel_encoder->enable = intel_enable_lvds;
0896     intel_encoder->pre_enable = intel_pre_enable_lvds;
0897     intel_encoder->compute_config = intel_lvds_compute_config;
0898     if (HAS_PCH_SPLIT(dev_priv)) {
0899         intel_encoder->disable = pch_disable_lvds;
0900         intel_encoder->post_disable = pch_post_disable_lvds;
0901     } else {
0902         intel_encoder->disable = gmch_disable_lvds;
0903     }
0904     intel_encoder->get_hw_state = intel_lvds_get_hw_state;
0905     intel_encoder->get_config = intel_lvds_get_config;
0906     intel_encoder->update_pipe = intel_backlight_update;
0907     intel_encoder->shutdown = intel_lvds_shutdown;
0908     intel_connector->get_hw_state = intel_connector_get_hw_state;
0909 
0910     intel_connector_attach_encoder(intel_connector, intel_encoder);
0911 
0912     intel_encoder->type = INTEL_OUTPUT_LVDS;
0913     intel_encoder->power_domain = POWER_DOMAIN_PORT_OTHER;
0914     intel_encoder->port = PORT_NONE;
0915     intel_encoder->cloneable = 0;
0916     if (DISPLAY_VER(dev_priv) < 4)
0917         intel_encoder->pipe_mask = BIT(PIPE_B);
0918     else
0919         intel_encoder->pipe_mask = ~0;
0920 
0921     drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs);
0922     connector->display_info.subpixel_order = SubPixelHorizontalRGB;
0923     connector->interlace_allowed = false;
0924     connector->doublescan_allowed = false;
0925 
0926     lvds_encoder->reg = lvds_reg;
0927 
0928     /* create the scaling mode property */
0929     allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT);
0930     allowed_scalers |= BIT(DRM_MODE_SCALE_FULLSCREEN);
0931     allowed_scalers |= BIT(DRM_MODE_SCALE_CENTER);
0932     drm_connector_attach_scaling_mode_property(connector, allowed_scalers);
0933     connector->state->scaling_mode = DRM_MODE_SCALE_ASPECT;
0934 
0935     intel_lvds_pps_get_hw_state(dev_priv, &lvds_encoder->init_pps);
0936     lvds_encoder->init_lvds_val = lvds;
0937 
0938     /*
0939      * LVDS discovery:
0940      * 1) check for EDID on DDC
0941      * 2) check for VBT data
0942      * 3) check to see if LVDS is already on
0943      *    if none of the above, no panel
0944      */
0945 
0946     /*
0947      * Attempt to get the fixed panel mode from DDC.  Assume that the
0948      * preferred mode is the right one.
0949      */
0950     mutex_lock(&dev->mode_config.mutex);
0951     if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)
0952         edid = drm_get_edid_switcheroo(connector,
0953                     intel_gmbus_get_adapter(dev_priv, pin));
0954     else
0955         edid = drm_get_edid(connector,
0956                     intel_gmbus_get_adapter(dev_priv, pin));
0957     if (edid) {
0958         if (drm_add_edid_modes(connector, edid)) {
0959             drm_connector_update_edid_property(connector,
0960                                 edid);
0961         } else {
0962             kfree(edid);
0963             edid = ERR_PTR(-EINVAL);
0964         }
0965     } else {
0966         edid = ERR_PTR(-ENOENT);
0967     }
0968     intel_connector->edid = edid;
0969 
0970     intel_bios_init_panel(dev_priv, &intel_connector->panel, NULL,
0971                   IS_ERR(edid) ? NULL : edid);
0972 
0973     /* Try EDID first */
0974     intel_panel_add_edid_fixed_modes(intel_connector,
0975                      intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE,
0976                      false);
0977 
0978     /* Failed to get EDID, what about VBT? */
0979     if (!intel_panel_preferred_fixed_mode(intel_connector))
0980         intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
0981 
0982     /*
0983      * If we didn't get a fixed mode from EDID or VBT, try checking
0984      * if the panel is already turned on.  If so, assume that
0985      * whatever is currently programmed is the correct mode.
0986      */
0987     if (!intel_panel_preferred_fixed_mode(intel_connector))
0988         intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder);
0989 
0990     mutex_unlock(&dev->mode_config.mutex);
0991 
0992     /* If we still don't have a mode after all that, give up. */
0993     if (!intel_panel_preferred_fixed_mode(intel_connector))
0994         goto failed;
0995 
0996     intel_panel_init(intel_connector);
0997 
0998     intel_backlight_setup(intel_connector, INVALID_PIPE);
0999 
1000     lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);
1001     drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n",
1002             lvds_encoder->is_dual_link ? "dual" : "single");
1003 
1004     lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;
1005 
1006     return;
1007 
1008 failed:
1009     drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n");
1010     drm_connector_cleanup(connector);
1011     drm_encoder_cleanup(encoder);
1012     kfree(lvds_encoder);
1013     intel_connector_free(intel_connector);
1014     return;
1015 }