1014 lines · c
1/*2 * Copyright © 2006-2007 Intel Corporation3 * Copyright (c) 2006 Dave Airlie <airlied@linux.ie>4 *5 * Permission is hereby granted, free of charge, to any person obtaining a6 * copy of this software and associated documentation files (the "Software"),7 * to deal in the Software without restriction, including without limitation8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,9 * and/or sell copies of the Software, and to permit persons to whom the10 * Software is furnished to do so, subject to the following conditions:11 *12 * The above copyright notice and this permission notice (including the next13 * paragraph) shall be included in all copies or substantial portions of the14 * Software.15 *16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER22 * 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#include <acpi/button.h>31#include <linux/acpi.h>32#include <linux/dmi.h>33#include <linux/i2c.h>34#include <linux/slab.h>35#include <linux/vga_switcheroo.h>36 37#include <drm/drm_atomic_helper.h>38#include <drm/drm_crtc.h>39#include <drm/drm_edid.h>40 41#include "i915_drv.h"42#include "i915_reg.h"43#include "intel_atomic.h"44#include "intel_backlight.h"45#include "intel_connector.h"46#include "intel_de.h"47#include "intel_display_types.h"48#include "intel_dpll.h"49#include "intel_fdi.h"50#include "intel_gmbus.h"51#include "intel_lvds.h"52#include "intel_lvds_regs.h"53#include "intel_panel.h"54#include "intel_pps_regs.h"55 56/* Private structure for the integrated LVDS support */57struct intel_lvds_pps {58 /* 100us units */59 int t1_t2;60 int t3;61 int t4;62 int t5;63 int tx;64 65 int divider;66 67 int port;68 bool powerdown_on_reset;69};70 71struct intel_lvds_encoder {72 struct intel_encoder base;73 74 bool is_dual_link;75 i915_reg_t reg;76 u32 a3_power;77 78 struct intel_lvds_pps init_pps;79 u32 init_lvds_val;80 81 struct intel_connector *attached_connector;82};83 84static struct intel_lvds_encoder *to_lvds_encoder(struct intel_encoder *encoder)85{86 return container_of(encoder, struct intel_lvds_encoder, base);87}88 89bool intel_lvds_port_enabled(struct drm_i915_private *i915,90 i915_reg_t lvds_reg, enum pipe *pipe)91{92 u32 val;93 94 val = intel_de_read(i915, lvds_reg);95 96 /* asserts want to know the pipe even if the port is disabled */97 if (HAS_PCH_CPT(i915))98 *pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK_CPT, val);99 else100 *pipe = REG_FIELD_GET(LVDS_PIPE_SEL_MASK, val);101 102 return val & LVDS_PORT_EN;103}104 105static bool intel_lvds_get_hw_state(struct intel_encoder *encoder,106 enum pipe *pipe)107{108 struct drm_i915_private *i915 = to_i915(encoder->base.dev);109 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);110 intel_wakeref_t wakeref;111 bool ret;112 113 wakeref = intel_display_power_get_if_enabled(i915, encoder->power_domain);114 if (!wakeref)115 return false;116 117 ret = intel_lvds_port_enabled(i915, lvds_encoder->reg, pipe);118 119 intel_display_power_put(i915, encoder->power_domain, wakeref);120 121 return ret;122}123 124static void intel_lvds_get_config(struct intel_encoder *encoder,125 struct intel_crtc_state *crtc_state)126{127 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);128 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);129 u32 tmp, flags = 0;130 131 crtc_state->output_types |= BIT(INTEL_OUTPUT_LVDS);132 133 tmp = intel_de_read(dev_priv, lvds_encoder->reg);134 if (tmp & LVDS_HSYNC_POLARITY)135 flags |= DRM_MODE_FLAG_NHSYNC;136 else137 flags |= DRM_MODE_FLAG_PHSYNC;138 if (tmp & LVDS_VSYNC_POLARITY)139 flags |= DRM_MODE_FLAG_NVSYNC;140 else141 flags |= DRM_MODE_FLAG_PVSYNC;142 143 crtc_state->hw.adjusted_mode.flags |= flags;144 145 if (DISPLAY_VER(dev_priv) < 5)146 crtc_state->gmch_pfit.lvds_border_bits =147 tmp & LVDS_BORDER_ENABLE;148 149 /* gen2/3 store dither state in pfit control, needs to match */150 if (DISPLAY_VER(dev_priv) < 4) {151 tmp = intel_de_read(dev_priv, PFIT_CONTROL(dev_priv));152 153 crtc_state->gmch_pfit.control |= tmp & PFIT_PANEL_8TO6_DITHER_ENABLE;154 }155 156 crtc_state->hw.adjusted_mode.crtc_clock = crtc_state->port_clock;157}158 159static void intel_lvds_pps_get_hw_state(struct drm_i915_private *dev_priv,160 struct intel_lvds_pps *pps)161{162 u32 val;163 164 pps->powerdown_on_reset = intel_de_read(dev_priv,165 PP_CONTROL(dev_priv, 0)) & PANEL_POWER_RESET;166 167 val = intel_de_read(dev_priv, PP_ON_DELAYS(dev_priv, 0));168 pps->port = REG_FIELD_GET(PANEL_PORT_SELECT_MASK, val);169 pps->t1_t2 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, val);170 pps->t5 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, val);171 172 val = intel_de_read(dev_priv, PP_OFF_DELAYS(dev_priv, 0));173 pps->t3 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, val);174 pps->tx = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, val);175 176 val = intel_de_read(dev_priv, PP_DIVISOR(dev_priv, 0));177 pps->divider = REG_FIELD_GET(PP_REFERENCE_DIVIDER_MASK, val);178 val = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, val);179 /*180 * Remove the BSpec specified +1 (100ms) offset that accounts for a181 * too short power-cycle delay due to the asynchronous programming of182 * the register.183 */184 if (val)185 val--;186 /* Convert from 100ms to 100us units */187 pps->t4 = val * 1000;188 189 if (DISPLAY_VER(dev_priv) < 5 &&190 pps->t1_t2 == 0 && pps->t5 == 0 && pps->t3 == 0 && pps->tx == 0) {191 drm_dbg_kms(&dev_priv->drm,192 "Panel power timings uninitialized, "193 "setting defaults\n");194 /* Set T2 to 40ms and T5 to 200ms in 100 usec units */195 pps->t1_t2 = 40 * 10;196 pps->t5 = 200 * 10;197 /* Set T3 to 35ms and Tx to 200ms in 100 usec units */198 pps->t3 = 35 * 10;199 pps->tx = 200 * 10;200 }201 202 drm_dbg(&dev_priv->drm, "LVDS PPS:t1+t2 %d t3 %d t4 %d t5 %d tx %d "203 "divider %d port %d powerdown_on_reset %d\n",204 pps->t1_t2, pps->t3, pps->t4, pps->t5, pps->tx,205 pps->divider, pps->port, pps->powerdown_on_reset);206}207 208static void intel_lvds_pps_init_hw(struct drm_i915_private *dev_priv,209 struct intel_lvds_pps *pps)210{211 u32 val;212 213 val = intel_de_read(dev_priv, PP_CONTROL(dev_priv, 0));214 drm_WARN_ON(&dev_priv->drm,215 (val & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS);216 if (pps->powerdown_on_reset)217 val |= PANEL_POWER_RESET;218 intel_de_write(dev_priv, PP_CONTROL(dev_priv, 0), val);219 220 intel_de_write(dev_priv, PP_ON_DELAYS(dev_priv, 0),221 REG_FIELD_PREP(PANEL_PORT_SELECT_MASK, pps->port) |222 REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, pps->t1_t2) |223 REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, pps->t5));224 225 intel_de_write(dev_priv, PP_OFF_DELAYS(dev_priv, 0),226 REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, pps->t3) |227 REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, pps->tx));228 229 intel_de_write(dev_priv, PP_DIVISOR(dev_priv, 0),230 REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, pps->divider) |231 REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(pps->t4, 1000) + 1));232}233 234static void intel_pre_enable_lvds(struct intel_atomic_state *state,235 struct intel_encoder *encoder,236 const struct intel_crtc_state *crtc_state,237 const struct drm_connector_state *conn_state)238{239 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);240 struct drm_i915_private *i915 = to_i915(encoder->base.dev);241 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);242 const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;243 enum pipe pipe = crtc->pipe;244 u32 temp;245 246 if (HAS_PCH_SPLIT(i915)) {247 assert_fdi_rx_pll_disabled(i915, pipe);248 assert_shared_dpll_disabled(i915, crtc_state->shared_dpll);249 } else {250 assert_pll_disabled(i915, pipe);251 }252 253 intel_lvds_pps_init_hw(i915, &lvds_encoder->init_pps);254 255 temp = lvds_encoder->init_lvds_val;256 temp |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP;257 258 if (HAS_PCH_CPT(i915)) {259 temp &= ~LVDS_PIPE_SEL_MASK_CPT;260 temp |= LVDS_PIPE_SEL_CPT(pipe);261 } else {262 temp &= ~LVDS_PIPE_SEL_MASK;263 temp |= LVDS_PIPE_SEL(pipe);264 }265 266 /* set the corresponsding LVDS_BORDER bit */267 temp &= ~LVDS_BORDER_ENABLE;268 temp |= crtc_state->gmch_pfit.lvds_border_bits;269 270 /*271 * Set the B0-B3 data pairs corresponding to whether we're going to272 * set the DPLLs for dual-channel mode or not.273 */274 if (lvds_encoder->is_dual_link)275 temp |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;276 else277 temp &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);278 279 /*280 * It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)281 * appropriately here, but we need to look more thoroughly into how282 * panels behave in the two modes. For now, let's just maintain the283 * value we got from the BIOS.284 */285 temp &= ~LVDS_A3_POWER_MASK;286 temp |= lvds_encoder->a3_power;287 288 /*289 * Set the dithering flag on LVDS as needed, note that there is no290 * special lvds dither control bit on pch-split platforms, dithering is291 * only controlled through the TRANSCONF reg.292 */293 if (DISPLAY_VER(i915) == 4) {294 /*295 * Bspec wording suggests that LVDS port dithering only exists296 * for 18bpp panels.297 */298 if (crtc_state->dither && crtc_state->pipe_bpp == 18)299 temp |= LVDS_ENABLE_DITHER;300 else301 temp &= ~LVDS_ENABLE_DITHER;302 }303 temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);304 if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)305 temp |= LVDS_HSYNC_POLARITY;306 if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)307 temp |= LVDS_VSYNC_POLARITY;308 309 intel_de_write(i915, lvds_encoder->reg, temp);310}311 312/*313 * Sets the power state for the panel.314 */315static void intel_enable_lvds(struct intel_atomic_state *state,316 struct intel_encoder *encoder,317 const struct intel_crtc_state *crtc_state,318 const struct drm_connector_state *conn_state)319{320 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);321 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);322 323 intel_de_rmw(dev_priv, lvds_encoder->reg, 0, LVDS_PORT_EN);324 325 intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), 0, PANEL_POWER_ON);326 intel_de_posting_read(dev_priv, lvds_encoder->reg);327 328 if (intel_de_wait_for_set(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 5000))329 drm_err(&dev_priv->drm,330 "timed out waiting for panel to power on\n");331 332 intel_backlight_enable(crtc_state, conn_state);333}334 335static void intel_disable_lvds(struct intel_atomic_state *state,336 struct intel_encoder *encoder,337 const struct intel_crtc_state *old_crtc_state,338 const struct drm_connector_state *old_conn_state)339{340 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);341 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);342 343 intel_de_rmw(dev_priv, PP_CONTROL(dev_priv, 0), PANEL_POWER_ON, 0);344 if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_ON, 1000))345 drm_err(&dev_priv->drm,346 "timed out waiting for panel to power off\n");347 348 intel_de_rmw(dev_priv, lvds_encoder->reg, LVDS_PORT_EN, 0);349 intel_de_posting_read(dev_priv, lvds_encoder->reg);350}351 352static void gmch_disable_lvds(struct intel_atomic_state *state,353 struct intel_encoder *encoder,354 const struct intel_crtc_state *old_crtc_state,355 const struct drm_connector_state *old_conn_state)356 357{358 intel_backlight_disable(old_conn_state);359 360 intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);361}362 363static void pch_disable_lvds(struct intel_atomic_state *state,364 struct intel_encoder *encoder,365 const struct intel_crtc_state *old_crtc_state,366 const struct drm_connector_state *old_conn_state)367{368 intel_backlight_disable(old_conn_state);369}370 371static void pch_post_disable_lvds(struct intel_atomic_state *state,372 struct intel_encoder *encoder,373 const struct intel_crtc_state *old_crtc_state,374 const struct drm_connector_state *old_conn_state)375{376 intel_disable_lvds(state, encoder, old_crtc_state, old_conn_state);377}378 379static void intel_lvds_shutdown(struct intel_encoder *encoder)380{381 struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);382 383 if (intel_de_wait_for_clear(dev_priv, PP_STATUS(dev_priv, 0), PP_CYCLE_DELAY_ACTIVE, 5000))384 drm_err(&dev_priv->drm,385 "timed out waiting for panel power cycle delay\n");386}387 388static enum drm_mode_status389intel_lvds_mode_valid(struct drm_connector *_connector,390 struct drm_display_mode *mode)391{392 struct intel_connector *connector = to_intel_connector(_connector);393 struct drm_i915_private *i915 = to_i915(connector->base.dev);394 const struct drm_display_mode *fixed_mode =395 intel_panel_fixed_mode(connector, mode);396 int max_pixclk = to_i915(connector->base.dev)->display.cdclk.max_dotclk_freq;397 enum drm_mode_status status;398 399 status = intel_cpu_transcoder_mode_valid(i915, mode);400 if (status != MODE_OK)401 return status;402 403 status = intel_panel_mode_valid(connector, mode);404 if (status != MODE_OK)405 return status;406 407 if (fixed_mode->clock > max_pixclk)408 return MODE_CLOCK_HIGH;409 410 return MODE_OK;411}412 413static int intel_lvds_compute_config(struct intel_encoder *encoder,414 struct intel_crtc_state *crtc_state,415 struct drm_connector_state *conn_state)416{417 struct drm_i915_private *i915 = to_i915(encoder->base.dev);418 struct intel_lvds_encoder *lvds_encoder = to_lvds_encoder(encoder);419 struct intel_connector *connector = lvds_encoder->attached_connector;420 struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode;421 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);422 unsigned int lvds_bpp;423 int ret;424 425 /* Should never happen!! */426 if (DISPLAY_VER(i915) < 4 && crtc->pipe == 0) {427 drm_err(&i915->drm, "Can't support LVDS on pipe A\n");428 return -EINVAL;429 }430 431 if (HAS_PCH_SPLIT(i915)) {432 crtc_state->has_pch_encoder = true;433 if (!intel_fdi_compute_pipe_bpp(crtc_state))434 return -EINVAL;435 }436 437 if (lvds_encoder->a3_power == LVDS_A3_POWER_UP)438 lvds_bpp = 8*3;439 else440 lvds_bpp = 6*3;441 442 /* TODO: Check crtc_state->max_link_bpp_x16 instead of bw_constrained */443 if (lvds_bpp != crtc_state->pipe_bpp && !crtc_state->bw_constrained) {444 drm_dbg_kms(&i915->drm,445 "forcing display bpp (was %d) to LVDS (%d)\n",446 crtc_state->pipe_bpp, lvds_bpp);447 crtc_state->pipe_bpp = lvds_bpp;448 }449 450 crtc_state->sink_format = INTEL_OUTPUT_FORMAT_RGB;451 crtc_state->output_format = INTEL_OUTPUT_FORMAT_RGB;452 453 /*454 * We have timings from the BIOS for the panel, put them in455 * to the adjusted mode. The CRTC will be set up for this mode,456 * with the panel scaling set up to source from the H/VDisplay457 * of the original mode.458 */459 ret = intel_panel_compute_config(connector, adjusted_mode);460 if (ret)461 return ret;462 463 if (adjusted_mode->flags & DRM_MODE_FLAG_DBLSCAN)464 return -EINVAL;465 466 ret = intel_panel_fitting(crtc_state, conn_state);467 if (ret)468 return ret;469 470 /*471 * XXX: It would be nice to support lower refresh rates on the472 * panels to reduce power consumption, and perhaps match the473 * user's requested refresh rate.474 */475 476 return 0;477}478 479/*480 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.481 */482static int intel_lvds_get_modes(struct drm_connector *_connector)483{484 struct intel_connector *connector = to_intel_connector(_connector);485 const struct drm_edid *fixed_edid = connector->panel.fixed_edid;486 487 /* Use panel fixed edid if we have one */488 if (!IS_ERR_OR_NULL(fixed_edid)) {489 drm_edid_connector_update(&connector->base, fixed_edid);490 491 return drm_edid_connector_add_modes(&connector->base);492 }493 494 return intel_panel_get_modes(connector);495}496 497static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = {498 .get_modes = intel_lvds_get_modes,499 .mode_valid = intel_lvds_mode_valid,500 .atomic_check = intel_digital_connector_atomic_check,501};502 503static const struct drm_connector_funcs intel_lvds_connector_funcs = {504 .detect = intel_panel_detect,505 .fill_modes = drm_helper_probe_single_connector_modes,506 .atomic_get_property = intel_digital_connector_atomic_get_property,507 .atomic_set_property = intel_digital_connector_atomic_set_property,508 .late_register = intel_connector_register,509 .early_unregister = intel_connector_unregister,510 .destroy = intel_connector_destroy,511 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,512 .atomic_duplicate_state = intel_digital_connector_duplicate_state,513};514 515static const struct drm_encoder_funcs intel_lvds_enc_funcs = {516 .destroy = intel_encoder_destroy,517};518 519static int intel_no_lvds_dmi_callback(const struct dmi_system_id *id)520{521 DRM_INFO("Skipping LVDS initialization for %s\n", id->ident);522 return 1;523}524 525/* These systems claim to have LVDS, but really don't */526static const struct dmi_system_id intel_no_lvds[] = {527 {528 .callback = intel_no_lvds_dmi_callback,529 .ident = "Apple Mac Mini (Core series)",530 .matches = {531 DMI_MATCH(DMI_SYS_VENDOR, "Apple"),532 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"),533 },534 },535 {536 .callback = intel_no_lvds_dmi_callback,537 .ident = "Apple Mac Mini (Core 2 series)",538 .matches = {539 DMI_MATCH(DMI_SYS_VENDOR, "Apple"),540 DMI_MATCH(DMI_PRODUCT_NAME, "Macmini2,1"),541 },542 },543 {544 .callback = intel_no_lvds_dmi_callback,545 .ident = "MSI IM-945GSE-A",546 .matches = {547 DMI_MATCH(DMI_SYS_VENDOR, "MSI"),548 DMI_MATCH(DMI_PRODUCT_NAME, "A9830IMS"),549 },550 },551 {552 .callback = intel_no_lvds_dmi_callback,553 .ident = "Dell Studio Hybrid",554 .matches = {555 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),556 DMI_MATCH(DMI_PRODUCT_NAME, "Studio Hybrid 140g"),557 },558 },559 {560 .callback = intel_no_lvds_dmi_callback,561 .ident = "Dell OptiPlex FX170",562 .matches = {563 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),564 DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex FX170"),565 },566 },567 {568 .callback = intel_no_lvds_dmi_callback,569 .ident = "AOpen Mini PC",570 .matches = {571 DMI_MATCH(DMI_SYS_VENDOR, "AOpen"),572 DMI_MATCH(DMI_PRODUCT_NAME, "i965GMx-IF"),573 },574 },575 {576 .callback = intel_no_lvds_dmi_callback,577 .ident = "AOpen Mini PC MP915",578 .matches = {579 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),580 DMI_MATCH(DMI_BOARD_NAME, "i915GMx-F"),581 },582 },583 {584 .callback = intel_no_lvds_dmi_callback,585 .ident = "AOpen i915GMm-HFS",586 .matches = {587 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),588 DMI_MATCH(DMI_BOARD_NAME, "i915GMm-HFS"),589 },590 },591 {592 .callback = intel_no_lvds_dmi_callback,593 .ident = "AOpen i45GMx-I",594 .matches = {595 DMI_MATCH(DMI_BOARD_VENDOR, "AOpen"),596 DMI_MATCH(DMI_BOARD_NAME, "i45GMx-I"),597 },598 },599 {600 .callback = intel_no_lvds_dmi_callback,601 .ident = "Aopen i945GTt-VFA",602 .matches = {603 DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"),604 },605 },606 {607 .callback = intel_no_lvds_dmi_callback,608 .ident = "Clientron U800",609 .matches = {610 DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),611 DMI_MATCH(DMI_PRODUCT_NAME, "U800"),612 },613 },614 {615 .callback = intel_no_lvds_dmi_callback,616 .ident = "Clientron E830",617 .matches = {618 DMI_MATCH(DMI_SYS_VENDOR, "Clientron"),619 DMI_MATCH(DMI_PRODUCT_NAME, "E830"),620 },621 },622 {623 .callback = intel_no_lvds_dmi_callback,624 .ident = "Asus EeeBox PC EB1007",625 .matches = {626 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer INC."),627 DMI_MATCH(DMI_PRODUCT_NAME, "EB1007"),628 },629 },630 {631 .callback = intel_no_lvds_dmi_callback,632 .ident = "Asus AT5NM10T-I",633 .matches = {634 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."),635 DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"),636 },637 },638 {639 .callback = intel_no_lvds_dmi_callback,640 .ident = "Hewlett-Packard HP t5740",641 .matches = {642 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),643 DMI_MATCH(DMI_PRODUCT_NAME, " t5740"),644 },645 },646 {647 .callback = intel_no_lvds_dmi_callback,648 .ident = "Hewlett-Packard t5745",649 .matches = {650 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),651 DMI_MATCH(DMI_PRODUCT_NAME, "hp t5745"),652 },653 },654 {655 .callback = intel_no_lvds_dmi_callback,656 .ident = "Hewlett-Packard st5747",657 .matches = {658 DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"),659 DMI_MATCH(DMI_PRODUCT_NAME, "hp st5747"),660 },661 },662 {663 .callback = intel_no_lvds_dmi_callback,664 .ident = "MSI Wind Box DC500",665 .matches = {666 DMI_MATCH(DMI_BOARD_VENDOR, "MICRO-STAR INTERNATIONAL CO., LTD"),667 DMI_MATCH(DMI_BOARD_NAME, "MS-7469"),668 },669 },670 {671 .callback = intel_no_lvds_dmi_callback,672 .ident = "Gigabyte GA-D525TUD",673 .matches = {674 DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),675 DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),676 },677 },678 {679 .callback = intel_no_lvds_dmi_callback,680 .ident = "Supermicro X7SPA-H",681 .matches = {682 DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"),683 DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"),684 },685 },686 {687 .callback = intel_no_lvds_dmi_callback,688 .ident = "Fujitsu Esprimo Q900",689 .matches = {690 DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),691 DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"),692 },693 },694 {695 .callback = intel_no_lvds_dmi_callback,696 .ident = "Intel D410PT",697 .matches = {698 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),699 DMI_MATCH(DMI_BOARD_NAME, "D410PT"),700 },701 },702 {703 .callback = intel_no_lvds_dmi_callback,704 .ident = "Intel D425KT",705 .matches = {706 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),707 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D425KT"),708 },709 },710 {711 .callback = intel_no_lvds_dmi_callback,712 .ident = "Intel D510MO",713 .matches = {714 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),715 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D510MO"),716 },717 },718 {719 .callback = intel_no_lvds_dmi_callback,720 .ident = "Intel D525MW",721 .matches = {722 DMI_MATCH(DMI_BOARD_VENDOR, "Intel"),723 DMI_EXACT_MATCH(DMI_BOARD_NAME, "D525MW"),724 },725 },726 {727 .callback = intel_no_lvds_dmi_callback,728 .ident = "Radiant P845",729 .matches = {730 DMI_MATCH(DMI_SYS_VENDOR, "Radiant Systems Inc"),731 DMI_MATCH(DMI_PRODUCT_NAME, "P845"),732 },733 },734 735 { } /* terminating entry */736};737 738static int intel_dual_link_lvds_callback(const struct dmi_system_id *id)739{740 DRM_INFO("Forcing lvds to dual link mode on %s\n", id->ident);741 return 1;742}743 744static const struct dmi_system_id intel_dual_link_lvds[] = {745 {746 .callback = intel_dual_link_lvds_callback,747 .ident = "Apple MacBook Pro 15\" (2010)",748 .matches = {749 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),750 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro6,2"),751 },752 },753 {754 .callback = intel_dual_link_lvds_callback,755 .ident = "Apple MacBook Pro 15\" (2011)",756 .matches = {757 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),758 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro8,2"),759 },760 },761 {762 .callback = intel_dual_link_lvds_callback,763 .ident = "Apple MacBook Pro 15\" (2012)",764 .matches = {765 DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),766 DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro9,1"),767 },768 },769 { } /* terminating entry */770};771 772struct intel_encoder *intel_get_lvds_encoder(struct drm_i915_private *i915)773{774 struct intel_encoder *encoder;775 776 for_each_intel_encoder(&i915->drm, encoder) {777 if (encoder->type == INTEL_OUTPUT_LVDS)778 return encoder;779 }780 781 return NULL;782}783 784bool intel_is_dual_link_lvds(struct drm_i915_private *i915)785{786 struct intel_encoder *encoder = intel_get_lvds_encoder(i915);787 788 return encoder && to_lvds_encoder(encoder)->is_dual_link;789}790 791static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder)792{793 struct drm_i915_private *i915 = to_i915(lvds_encoder->base.base.dev);794 struct intel_connector *connector = lvds_encoder->attached_connector;795 const struct drm_display_mode *fixed_mode =796 intel_panel_preferred_fixed_mode(connector);797 unsigned int val;798 799 /* use the module option value if specified */800 if (i915->display.params.lvds_channel_mode > 0)801 return i915->display.params.lvds_channel_mode == 2;802 803 /* single channel LVDS is limited to 112 MHz */804 if (fixed_mode->clock > 112999)805 return true;806 807 if (dmi_check_system(intel_dual_link_lvds))808 return true;809 810 /*811 * BIOS should set the proper LVDS register value at boot, but812 * in reality, it doesn't set the value when the lid is closed;813 * we need to check "the value to be set" in VBT when LVDS814 * register is uninitialized.815 */816 val = intel_de_read(i915, lvds_encoder->reg);817 if (HAS_PCH_CPT(i915))818 val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK_CPT);819 else820 val &= ~(LVDS_DETECTED | LVDS_PIPE_SEL_MASK);821 if (val == 0)822 val = connector->panel.vbt.bios_lvds_val;823 824 return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP;825}826 827static void intel_lvds_add_properties(struct drm_connector *connector)828{829 intel_attach_scaling_mode_property(connector);830}831 832/**833 * intel_lvds_init - setup LVDS connectors on this device834 * @i915: i915 device835 *836 * Create the connector, register the LVDS DDC bus, and try to figure out what837 * modes we can display on the LVDS panel (if present).838 */839void intel_lvds_init(struct drm_i915_private *i915)840{841 struct intel_display *display = &i915->display;842 struct intel_lvds_encoder *lvds_encoder;843 struct intel_connector *connector;844 const struct drm_edid *drm_edid;845 struct intel_encoder *encoder;846 i915_reg_t lvds_reg;847 u32 lvds;848 u8 ddc_pin;849 850 /* Skip init on machines we know falsely report LVDS */851 if (dmi_check_system(intel_no_lvds)) {852 drm_WARN(&i915->drm, !i915->display.vbt.int_lvds_support,853 "Useless DMI match. Internal LVDS support disabled by VBT\n");854 return;855 }856 857 if (!i915->display.vbt.int_lvds_support) {858 drm_dbg_kms(&i915->drm,859 "Internal LVDS support disabled by VBT\n");860 return;861 }862 863 if (HAS_PCH_SPLIT(i915))864 lvds_reg = PCH_LVDS;865 else866 lvds_reg = LVDS;867 868 lvds = intel_de_read(i915, lvds_reg);869 870 if (HAS_PCH_SPLIT(i915)) {871 if ((lvds & LVDS_DETECTED) == 0)872 return;873 }874 875 ddc_pin = GMBUS_PIN_PANEL;876 if (!intel_bios_is_lvds_present(display, &ddc_pin)) {877 if ((lvds & LVDS_PORT_EN) == 0) {878 drm_dbg_kms(&i915->drm,879 "LVDS is not present in VBT\n");880 return;881 }882 drm_dbg_kms(&i915->drm,883 "LVDS is not present in VBT, but enabled anyway\n");884 }885 886 lvds_encoder = kzalloc(sizeof(*lvds_encoder), GFP_KERNEL);887 if (!lvds_encoder)888 return;889 890 connector = intel_connector_alloc();891 if (!connector) {892 kfree(lvds_encoder);893 return;894 }895 896 lvds_encoder->attached_connector = connector;897 encoder = &lvds_encoder->base;898 899 drm_connector_init_with_ddc(&i915->drm, &connector->base,900 &intel_lvds_connector_funcs,901 DRM_MODE_CONNECTOR_LVDS,902 intel_gmbus_get_adapter(i915, ddc_pin));903 904 drm_encoder_init(&i915->drm, &encoder->base, &intel_lvds_enc_funcs,905 DRM_MODE_ENCODER_LVDS, "LVDS");906 907 encoder->enable = intel_enable_lvds;908 encoder->pre_enable = intel_pre_enable_lvds;909 encoder->compute_config = intel_lvds_compute_config;910 if (HAS_PCH_SPLIT(i915)) {911 encoder->disable = pch_disable_lvds;912 encoder->post_disable = pch_post_disable_lvds;913 } else {914 encoder->disable = gmch_disable_lvds;915 }916 encoder->get_hw_state = intel_lvds_get_hw_state;917 encoder->get_config = intel_lvds_get_config;918 encoder->update_pipe = intel_backlight_update;919 encoder->shutdown = intel_lvds_shutdown;920 connector->get_hw_state = intel_connector_get_hw_state;921 922 intel_connector_attach_encoder(connector, encoder);923 924 encoder->type = INTEL_OUTPUT_LVDS;925 encoder->power_domain = POWER_DOMAIN_PORT_OTHER;926 encoder->port = PORT_NONE;927 encoder->cloneable = 0;928 if (DISPLAY_VER(i915) < 4)929 encoder->pipe_mask = BIT(PIPE_B);930 else931 encoder->pipe_mask = ~0;932 933 drm_connector_helper_add(&connector->base, &intel_lvds_connector_helper_funcs);934 connector->base.display_info.subpixel_order = SubPixelHorizontalRGB;935 936 lvds_encoder->reg = lvds_reg;937 938 intel_lvds_add_properties(&connector->base);939 940 intel_lvds_pps_get_hw_state(i915, &lvds_encoder->init_pps);941 lvds_encoder->init_lvds_val = lvds;942 943 /*944 * LVDS discovery:945 * 1) check for EDID on DDC946 * 2) check for VBT data947 * 3) check to see if LVDS is already on948 * if none of the above, no panel949 */950 951 /*952 * Attempt to get the fixed panel mode from DDC. Assume that the953 * preferred mode is the right one.954 */955 mutex_lock(&i915->drm.mode_config.mutex);956 if (vga_switcheroo_handler_flags() & VGA_SWITCHEROO_CAN_SWITCH_DDC)957 drm_edid = drm_edid_read_switcheroo(&connector->base, connector->base.ddc);958 else959 drm_edid = drm_edid_read_ddc(&connector->base, connector->base.ddc);960 if (drm_edid) {961 if (drm_edid_connector_update(&connector->base, drm_edid) ||962 !drm_edid_connector_add_modes(&connector->base)) {963 drm_edid_connector_update(&connector->base, NULL);964 drm_edid_free(drm_edid);965 drm_edid = ERR_PTR(-EINVAL);966 }967 } else {968 drm_edid = ERR_PTR(-ENOENT);969 }970 intel_bios_init_panel_late(display, &connector->panel, NULL,971 IS_ERR(drm_edid) ? NULL : drm_edid);972 973 /* Try EDID first */974 intel_panel_add_edid_fixed_modes(connector, true);975 976 /* Failed to get EDID, what about VBT? */977 if (!intel_panel_preferred_fixed_mode(connector))978 intel_panel_add_vbt_lfp_fixed_mode(connector);979 980 /*981 * If we didn't get a fixed mode from EDID or VBT, try checking982 * if the panel is already turned on. If so, assume that983 * whatever is currently programmed is the correct mode.984 */985 if (!intel_panel_preferred_fixed_mode(connector))986 intel_panel_add_encoder_fixed_mode(connector, encoder);987 988 mutex_unlock(&i915->drm.mode_config.mutex);989 990 /* If we still don't have a mode after all that, give up. */991 if (!intel_panel_preferred_fixed_mode(connector))992 goto failed;993 994 intel_panel_init(connector, drm_edid);995 996 intel_backlight_setup(connector, INVALID_PIPE);997 998 lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder);999 drm_dbg_kms(&i915->drm, "detected %s-link lvds configuration\n",1000 lvds_encoder->is_dual_link ? "dual" : "single");1001 1002 lvds_encoder->a3_power = lvds & LVDS_A3_POWER_MASK;1003 1004 return;1005 1006failed:1007 drm_dbg_kms(&i915->drm, "No LVDS modes found, disabling.\n");1008 drm_connector_cleanup(&connector->base);1009 drm_encoder_cleanup(&encoder->base);1010 kfree(lvds_encoder);1011 intel_connector_free(connector);1012 return;1013}1014