0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
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
0054 struct intel_lvds_pps {
0055
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
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
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
0178
0179
0180
0181 if (val)
0182 val--;
0183
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
0192 pps->t1_t2 = 40 * 10;
0193 pps->t5 = 200 * 10;
0194
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
0261 temp &= ~LVDS_BORDER_ENABLE;
0262 temp |= pipe_config->gmch_pfit.lvds_border_bits;
0263
0264
0265
0266
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
0275
0276
0277
0278
0279 temp &= ~LVDS_A3_POWER_MASK;
0280 temp |= lvds_encoder->a3_power;
0281
0282
0283
0284
0285
0286
0287 if (DISPLAY_VER(dev_priv) == 4) {
0288
0289
0290
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
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
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
0446
0447
0448
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
0466
0467
0468
0469
0470 return 0;
0471 }
0472
0473
0474
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
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
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 { }
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 { }
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
0790 if (dev_priv->params.lvds_channel_mode > 0)
0791 return dev_priv->params.lvds_channel_mode == 2;
0792
0793
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
0802
0803
0804
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
0819
0820
0821
0822
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
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
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
0940
0941
0942
0943
0944
0945
0946
0947
0948
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
0974 intel_panel_add_edid_fixed_modes(intel_connector,
0975 intel_connector->panel.vbt.drrs_type != DRRS_TYPE_NONE,
0976 false);
0977
0978
0979 if (!intel_panel_preferred_fixed_mode(intel_connector))
0980 intel_panel_add_vbt_lfp_fixed_mode(intel_connector);
0981
0982
0983
0984
0985
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
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 }