Skip to content

Commit 963bbdb

Browse files
jnikularodrigovivi
authored andcommitted
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 f087cfe) Cc: stable@vger.kernel.org # 6.1 Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
1 parent 11ce8fd commit 963bbdb

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

drivers/gpu/drm/i915/display/intel_dsi_vbt.c

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,11 @@
4141

4242
#include "i915_drv.h"
4343
#include "i915_reg.h"
44+
#include "intel_de.h"
4445
#include "intel_display_types.h"
4546
#include "intel_dsi.h"
4647
#include "intel_dsi_vbt.h"
48+
#include "intel_gmbus_regs.h"
4749
#include "vlv_dsi.h"
4850
#include "vlv_dsi_regs.h"
4951
#include "vlv_sideband.h"
@@ -377,15 +379,93 @@ static void icl_exec_gpio(struct intel_connector *connector,
377379
drm_dbg_kms(&dev_priv->drm, "Skipping ICL GPIO element execution\n");
378380
}
379381

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+
380461
static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
381462
{
382463
struct drm_device *dev = intel_dsi->base.base.dev;
383464
struct drm_i915_private *dev_priv = to_i915(dev);
384465
struct intel_connector *connector = intel_dsi->attached_connector;
385466
u8 gpio_source, gpio_index = 0, gpio_number;
386467
bool value;
387-
388-
drm_dbg_kms(&dev_priv->drm, "\n");
468+
bool native = DISPLAY_VER(dev_priv) >= 11;
389469

390470
if (connector->panel.vbt.dsi.seq_version >= 3)
391471
gpio_index = *data++;
@@ -398,10 +478,18 @@ static const u8 *mipi_exec_gpio(struct intel_dsi *intel_dsi, const u8 *data)
398478
else
399479
gpio_source = 0;
400480

481+
if (connector->panel.vbt.dsi.seq_version >= 4 && *data & BIT(1))
482+
native = false;
483+
401484
/* pull up/down */
402485
value = *data++ & 1;
403486

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)
405493
icl_exec_gpio(connector, gpio_source, gpio_index, value);
406494
else if (IS_VALLEYVIEW(dev_priv))
407495
vlv_exec_gpio(connector, gpio_source, gpio_number, value);

drivers/gpu/drm/i915/i915_irq.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,7 +1974,10 @@ static void icp_irq_handler(struct drm_i915_private *dev_priv, u32 pch_iir)
19741974
if (ddi_hotplug_trigger) {
19751975
u32 dig_hotplug_reg;
19761976

1977+
/* Locking due to DSI native GPIO sequences */
1978+
spin_lock(&dev_priv->irq_lock);
19771979
dig_hotplug_reg = intel_uncore_rmw(&dev_priv->uncore, SHOTPLUG_CTL_DDI, 0, 0);
1980+
spin_unlock(&dev_priv->irq_lock);
19781981

19791982
intel_get_hpd_pins(dev_priv, &pin_mask, &long_mask,
19801983
ddi_hotplug_trigger, dig_hotplug_reg,

drivers/gpu/drm/i915/i915_reg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5988,6 +5988,7 @@
59885988

59895989
#define SHOTPLUG_CTL_DDI _MMIO(0xc4030)
59905990
#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))
59915992
#define SHOTPLUG_CTL_DDI_HPD_STATUS_MASK(hpd_pin) (0x3 << (_HPD_PIN_DDI(hpd_pin) * 4))
59925993
#define SHOTPLUG_CTL_DDI_HPD_NO_DETECT(hpd_pin) (0x0 << (_HPD_PIN_DDI(hpd_pin) * 4))
59935994
#define SHOTPLUG_CTL_DDI_HPD_SHORT_DETECT(hpd_pin) (0x1 << (_HPD_PIN_DDI(hpd_pin) * 4))

0 commit comments

Comments
 (0)