drm/i915/dsi: add support for ICL+ native MIPI GPIO sequence

Starting from ICL, the default for MIPI GPIO sequences seems to be using
native GPIOs i.e. GPIOs available in the GPU. These native GPIOs reuse
many pins that quite frankly seem scary to poke based on the VBT
sequences. We pretty much have to trust that the board is configured
such that the relevant HPD, PP_CONTROL and GPIO bits aren't used for
anything else.

MIPI sequence v4 also adds a flag to fall back to non-native sequences.

v5:
- Wrap SHOTPLUG_CTL_DDI modification in spin_lock() in icp_irq_handler()
too (Ville)
- References instead of Closes issue 6131 because this does not fix everything

v4:
- Wrap SHOTPLUG_CTL_DDI modification in spin_lock_irq() (Ville)

v3:
- Fix -Wbitwise-conditional-parentheses (kernel test robot <lkp@intel.com>)

v2:
- Fix HPD pin output set (impacts GPIOs 0 and 5)
- Fix GPIO data output direction set (impacts GPIOs 4 and 9)
- Reduce register accesses to single intel_de_rwm()

References: https://gitlab.freedesktop.org/drm/intel/-/issues/6131
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20221219105955.4014451-1-jani.nikula@intel.com
(cherry picked from commit f087cfe6fcff58044f7aa3b284965af47f472fb0)
Cc: stable@vger.kernel.org # 6.1
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>

authored by Jani Nikula and committed by Rodrigo Vivi 963bbdb3 11ce8fd8

+95 -3
+91 -3
drivers/gpu/drm/i915/display/intel_dsi_vbt.c
··· 41 42 #include "i915_drv.h" 43 #include "i915_reg.h" 44 #include "intel_display_types.h" 45 #include "intel_dsi.h" 46 #include "intel_dsi_vbt.h" 47 #include "vlv_dsi.h" 48 #include "vlv_dsi_regs.h" 49 #include "vlv_sideband.h" ··· 379 drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n"); 380 } 381 382 static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) 383 { 384 struct drm_device *dev = intel_dsi->base.base.dev; ··· 465 struct intel_connector *connector = intel_dsi->attached_connector; 466 u8 gpio_source, gpio_index = 0, gpio_number; 467 bool value; 468 - 469 - drm_dbg_kms(&dev_priv->drm, "\n"); 470 471 if (connector->panel.vbt.dsi.seq_version >= 3) 472 gpio_index = *data++; ··· 478 else 479 gpio_source = 0; 480 481 /* pull up/down */ 482 value = *data++ & 1; 483 484 - if (DISPLAY_VER(dev_priv) >= 11) 485 icl_exec_gpio(connector, gpio_source, gpio_index, value); 486 else if (IS_VALLEYVIEW(dev_priv)) 487 vlv_exec_gpio(connector, gpio_source, gpio_number, value);
··· 41 42 #include "i915_drv.h" 43 #include "i915_reg.h" 44 + #include "intel_de.h" 45 #include "intel_display_types.h" 46 #include "intel_dsi.h" 47 #include "intel_dsi_vbt.h" 48 + #include "intel_gmbus_regs.h" 49 #include "vlv_dsi.h" 50 #include "vlv_dsi_regs.h" 51 #include "vlv_sideband.h" ··· 377 drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n"); 378 } 379 380 + enum { 381 + MIPI_RESET_1 = 0, 382 + MIPI_AVDD_EN_1, 383 + MIPI_BKLT_EN_1, 384 + MIPI_AVEE_EN_1, 385 + MIPI_VIO_EN_1, 386 + MIPI_RESET_2, 387 + MIPI_AVDD_EN_2, 388 + MIPI_BKLT_EN_2, 389 + MIPI_AVEE_EN_2, 390 + MIPI_VIO_EN_2, 391 + }; 392 + 393 + static void icl_native_gpio_set_value(struct drm_i915_private *dev_priv, 394 + int gpio, bool value) 395 + { 396 + int index; 397 + 398 + if (drm_WARN_ON(&dev_priv->drm, DISPLAY_VER(dev_priv) == 11 && gpio >= MIPI_RESET_2)) 399 + return; 400 + 401 + switch (gpio) { 402 + case MIPI_RESET_1: 403 + case MIPI_RESET_2: 404 + index = gpio == MIPI_RESET_1 ? HPD_PORT_A : HPD_PORT_B; 405 + 406 + /* 407 + * Disable HPD to set the pin to output, and set output 408 + * value. The HPD pin should not be enabled for DSI anyway, 409 + * assuming the board design and VBT are sane, and the pin isn't 410 + * used by a non-DSI encoder. 411 + * 412 + * The locking protects against concurrent SHOTPLUG_CTL_DDI 413 + * modifications in irq setup and handling. 414 + */ 415 + spin_lock_irq(&dev_priv->irq_lock); 416 + intel_de_rmw(dev_priv, SHOTPLUG_CTL_DDI, 417 + SHOTPLUG_CTL_DDI_HPD_ENABLE(index) | 418 + SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index), 419 + value ? SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(index) : 0); 420 + spin_unlock_irq(&dev_priv->irq_lock); 421 + break; 422 + case MIPI_AVDD_EN_1: 423 + case MIPI_AVDD_EN_2: 424 + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; 425 + 426 + intel_de_rmw(dev_priv, PP_CONTROL(index), PANEL_POWER_ON, 427 + value ? PANEL_POWER_ON : 0); 428 + break; 429 + case MIPI_BKLT_EN_1: 430 + case MIPI_BKLT_EN_2: 431 + index = gpio == MIPI_AVDD_EN_1 ? 0 : 1; 432 + 433 + intel_de_rmw(dev_priv, PP_CONTROL(index), EDP_BLC_ENABLE, 434 + value ? EDP_BLC_ENABLE : 0); 435 + break; 436 + case MIPI_AVEE_EN_1: 437 + case MIPI_AVEE_EN_2: 438 + index = gpio == MIPI_AVEE_EN_1 ? 1 : 2; 439 + 440 + intel_de_rmw(dev_priv, GPIO(dev_priv, index), 441 + GPIO_CLOCK_VAL_OUT, 442 + GPIO_CLOCK_DIR_MASK | GPIO_CLOCK_DIR_OUT | 443 + GPIO_CLOCK_VAL_MASK | (value ? GPIO_CLOCK_VAL_OUT : 0)); 444 + break; 445 + case MIPI_VIO_EN_1: 446 + case MIPI_VIO_EN_2: 447 + index = gpio == MIPI_VIO_EN_1 ? 1 : 2; 448 + 449 + intel_de_rmw(dev_priv, GPIO(dev_priv, index), 450 + GPIO_DATA_VAL_OUT, 451 + GPIO_DATA_DIR_MASK | GPIO_DATA_DIR_OUT | 452 + GPIO_DATA_VAL_MASK | (value ? GPIO_DATA_VAL_OUT : 0)); 453 + break; 454 + default: 455 + MISSING_CASE(gpio); 456 + } 457 + } 458 + 459 static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data) 460 { 461 struct drm_device *dev = intel_dsi->base.base.dev; ··· 384 struct intel_connector *connector = intel_dsi->attached_connector; 385 u8 gpio_source, gpio_index = 0, gpio_number; 386 bool value; 387 + bool native = DISPLAY_VER(dev_priv) >= 11; 388 389 if (connector->panel.vbt.dsi.seq_version >= 3) 390 gpio_index = *data++; ··· 398 else 399 gpio_source = 0; 400 401 + if (connector->panel.vbt.dsi.seq_version >= 4 && *data & BIT(1)) 402 + native = false; 403 + 404 /* pull up/down */ 405 value = *data++ & 1; 406 407 + drm_dbg_kms(&dev_priv->drm, "GPIO index %u, number %u, source %u, native %s, set to %s\n", 408 + gpio_index, gpio_number, gpio_source, str_yes_no(native), str_on_off(value)); 409 + 410 + if (native) 411 + icl_native_gpio_set_value(dev_priv, gpio_number, value); 412 + else if (DISPLAY_VER(dev_priv) >= 11) 413 icl_exec_gpio(connector, gpio_source, gpio_index, value); 414 else if (IS_VALLEYVIEW(dev_priv)) 415 vlv_exec_gpio(connector, gpio_source, gpio_number, value);
+3
drivers/gpu/drm/i915/i915_irq.c
··· 1974 if (ddi_hotplug_trigger) { 1975 u32 dig_hotplug_reg; 1976 1977 dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); 1978 1979 intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1980 ddi_hotplug_trigger, dig_hotplug_reg,
··· 1974 if (ddi_hotplug_trigger) { 1975 u32 dig_hotplug_reg; 1976 1977 + /* Locking due to DSI native GPIO sequences */ 1978 + spin_lock(&dev_priv->irq_lock); 1979 dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0); 1980 + spin_unlock(&dev_priv->irq_lock); 1981 1982 intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask, 1983 ddi_hotplug_trigger, dig_hotplug_reg,
+1
drivers/gpu/drm/i915/i915_reg.h
··· 5988 5989 #define SHOTPLUG_CTL_DDI _MMIO(0xc4030) 5990 #define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5991 #define SHOTPLUG_CTL_DDI_HPD_STATUS_MASK(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5992 #define SHOTPLUG_CTL_DDI_HPD_NO_DETECT(hpd_pin) (0x0 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5993 #define SHOTPLUG_CTL_DDI_HPD_SHORT_DETECT(hpd_pin) (0x1 << (_HPD_PIN_DDI(hpd_pin) * 4))
··· 5988 5989 #define SHOTPLUG_CTL_DDI _MMIO(0xc4030) 5990 #define SHOTPLUG_CTL_DDI_HPD_ENABLE(hpd_pin) (0x8 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5991 + #define SHOTPLUG_CTL_DDI_HPD_OUTPUT_DATA(hpd_pin) (0x4 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5992 #define SHOTPLUG_CTL_DDI_HPD_STATUS_MASK(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5993 #define SHOTPLUG_CTL_DDI_HPD_NO_DETECT(hpd_pin) (0x0 << (_HPD_PIN_DDI(hpd_pin) * 4)) 5994 #define SHOTPLUG_CTL_DDI_HPD_SHORT_DETECT(hpd_pin) (0x1 << (_HPD_PIN_DDI(hpd_pin) * 4))