| @@ -41,9 +41,11 @@ · 40 unmodified lines |
| 41 | 41 | |
| 42 | 42 | #include "i915_drv.h" |
| 43 | 43 | #include "i915_reg.h" |
| 44 | +#include "intel_de.h" |
| 44 | 45 | #include "intel_display_types.h" |
| 45 | 46 | #include "intel_dsi.h" |
| 46 | 47 | #include "intel_dsi_vbt.h" |
| 48 | +#include "intel_gmbus_regs.h" |
| 47 | 49 | #include "vlv_dsi.h" |
| 48 | 50 | #include "vlv_dsi_regs.h" |
| 49 | 51 | #include "vlv_sideband.h" |
| @@ -377,6 +379,85 @@ static void icl_exec_gpio(struct intel_connector *connector, · 327 unmodified lines |
| 377 | 379 | drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n"); |
| 378 | 380 | } |
| 379 | 381 | |
| 382 | +enum { |
| 383 | + MIPI_RESET_1 = 0, |
| 384 | + MIPI_AVDD_EN_1, |
| 385 | + MIPI_BKLT_EN_1, |
| 386 | + MIPI_AVEE_EN_1, |
| 387 | + MIPI_VIO_EN_1, |
| 388 | + MIPI_RESET_2, |
| 389 | + MIPI_AVDD_EN_2, |
| 390 | + MIPI_BKLT_EN_2, |
| 391 | + MIPI_AVEE_EN_2, |
| 392 | + MIPI_VIO_EN_2, |
| 393 | +}; |
| 394 | + |
| 395 | +static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, |
| 396 | + int gpio, bool value) |
| 397 | +{ |
| 398 | + int index; |
| 399 | + |
| 400 | + if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2)) |
| 401 | + return; |
| 402 | + |
| 403 | + switch (gpio) { |
| 404 | + case MIPI_RESET_1: |
| 405 | + case MIPI_RESET_2: |
| 406 | + index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B; |
| 407 | + |
| 408 | + /* |
| 409 | + * Disable HPD to set the pin to output, and set output |
| 410 | + * value. The HPD pin should not be enabled for DSI anyway, |
| 411 | + * assuming the board design and VBT are sane, and the pin isn't |
| 412 | + * used by a non-DSI encoder. |
| 413 | + * |
| 414 | + * The locking protects against concurrent SHOTPLUG_CTL_DDI |
| 415 | + * modifications in irq setup and handling. |
| 416 | + */ |
| 417 | + spin_lock_irq(&dev_priv->irq_lock); |
| 418 | + intel_de_rmw(dev_priv, SHOTPLUG_CTL_DDI, |
| 419 | + SHOTPLUG_CTL_DDI_HPD_ENABLE(index) | |
| 420 | + SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index), |
| 421 | + value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0); |
| 422 | + spin_unlock_irq(&dev_priv->irq_lock); |
| 423 | + break; |
| 424 | + case MIPI_AVDD_EN_1: |
| 425 | + case MIPI_AVDD_EN_2: |
| 426 | + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; |
| 427 | + |
| 428 | + intel_de_rmw(dev_priv, PP_CONTROL(index), PANEL_POWER_ON, |
| 429 | + value ? PANEL_POWER_ON : 0); |
| 430 | + break; |
| 431 | + case MIPI_BKLT_EN_1: |
| 432 | + case MIPI_BKLT_EN_2: |
| 433 | + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; |
| 434 | + |
| 435 | + intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, |
| 436 | + value ? EDP_BLC_ENABLE : 0); |
| 437 | + break; |
| 438 | + case MIPI_AVEE_EN_1: |
| 439 | + case MIPI_AVEE_EN_2: |
| 440 | + index = gpio == MIPI_AVEE_EN_1 ? 1 : 2; |
| 441 | + |
| 442 | + intel_de_rmw(dev_priv, GPIO(dev_priv, index), |
| 443 | + GPIO_CLOCK_VAL_OUT, |
| 444 | + GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT | |
| 445 | + GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0)); |
| 446 | + break; |
| 447 | + case MIPI_VIO_EN_1: |
| 448 | + case MIPI_VIO_EN_2: |
| 449 | + index = gpio == MIPI_VIO_EN_1 ? 1 : 2; |
| 450 | + |
| 451 | + intel_de_rmw(dev_priv, GPIO(dev_priv, index), |
| 452 | + GPIO_DATA_VAL_OUT, |
| 453 | + GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT | |
| 454 | + GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0)); |
| 455 | + break; |
| 456 | + default: |
| 457 | + MISSING_CASE(gpio); |
| 458 | + } |
| 459 | +} |
| 460 | + |
| 380 | 461 | static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) |
| 381 | 462 | { |
| 382 | 463 | struct drm_device *dev = intel_dsi->base.base.dev; |
| @@ -384,8 +465,7 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) · 1 unmodified line |
| 384 | 465 | struct intel_connector *connector = intel_dsi->attached_connector; |
| 385 | 466 | u8 gpio_source, gpio_index = 0, gpio_number; |
| 386 | 467 | bool value; |
| 387 | | − |
| 388 | | − drm_dbg_kms(&dev_priv->drm, "\n"); |
| 468 | + bool native = DISPLAY_VER(dev_priv) >= 11; |
| 389 | 469 | |
| 390 | 470 | if (connector->panel.vbt.dsi.seq_version >= 3) |
| 391 | 471 | gpio_index = *data++; |
| @@ -398,10 +478,18 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) · 6 unmodified lines |
| 398 | 478 | else |
| 399 | 479 | gpio_source = 0; |
| 400 | 480 | |
| 481 | + if (connector->panel.vbt.dsi.seq_version >= 4 && *data & BIT(1)) |
| 482 | + native = false; |
| 483 | + |
| 401 | 484 | /* pull up/down */ |
| 402 | 485 | value = *data++ & 1; |
| 403 | 486 | |
| 404 | | − if (DISPLAY_VER(dev_priv) >= 11) |
| 487 | + drm_dbg_kms(&dev_priv->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n", |
| 488 | + gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value)); |
| 489 | + |
| 490 | + if (native) |
| 491 | + icl_native_gpio_set_value(dev_priv, gpio_number, value); |
| 492 | + else if (DISPLAY_VER(dev_priv) >= 11) |
| 405 | 493 | icl_exec_gpio(connector, gpio_source, gpio_index, value); |
| 406 | 494 | else if (IS_VALLEYVIEW(dev_priv)) |
| 407 | 495 | vlv_exec_gpio(connector, gpio_source, gpio_number, value); |