Message ID | 1458821451-19079-2-git-send-email-shubhangi.shrivastava@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Mar 24, 2016 at 05:40:51PM +0530, Shubhangi Shrivastava wrote: > This patch sets the invert bit for hpd detection for each port > based on VBT configuration. Since each AOB can be designed to > depend on invert bit or not, it is expected if an AOB requires > invert bit, the user will set respective bit in VBT. > > v2: Separated VBT parsing from the rest of the logic. (Jani) > > v3: Moved setting invert bit logic to bxt_hpd_irq_setup() > and changed its logic to avoid looping twice. (Ville) > > v4: Changed the logic to mask out the bits first and then > set them to remove need of temporary variable. (Ville) > > v5: Moved defines to existing set of defines for the register > Changed logic to incorporate required breaks. (Ville) > > Signed-off-by: Sivakumar Thulasimani <sivakumar.thulasimani@intel.com> > Signed-off-by: Durgadoss R <durgadoss.r@intel.com> > Signed-off-by: Shubhangi Shrivastava <shubhangi.shrivastava@intel.com> > Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/i915/i915_drv.h | 2 ++ > drivers/gpu/drm/i915/i915_irq.c | 20 ++++++++++++++++++++ > drivers/gpu/drm/i915/i915_reg.h | 6 ++++++ > drivers/gpu/drm/i915/intel_bios.c | 32 ++++++++++++++++++++++++++++++++ > 4 files changed, 60 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 9d29ab0..86fb5cb 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -3396,6 +3396,8 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); > bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); > bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port); > bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); > +bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, > + enum port port); > > /* intel_opregion.c */ > #ifdef CONFIG_ACPI > diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c > index a55a7cc..8fbec3e 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -3504,6 +3504,26 @@ static void bxt_hpd_irq_setup(struct drm_device *dev) > hotplug = I915_READ(PCH_PORT_HOTPLUG); > hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE | > PORTA_HOTPLUG_ENABLE; > + > + DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n", > + hotplug, enabled_irqs); > + hotplug &= ~BXT_DDI_HPD_INVERT_MASK; > + > + /* > + * For BXT invert bit has to be set based on AOB design > + * for HPD detection logic, update it based on VBT fields. > + */ > + > + if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && > + intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) > + hotplug |= BXT_DDIA_HPD_INVERT; > + if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && > + intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) > + hotplug |= BXT_DDIB_HPD_INVERT; > + if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && > + intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) > + hotplug |= BXT_DDIC_HPD_INVERT; > + > I915_WRITE(PCH_PORT_HOTPLUG, hotplug); > } > > diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h > index f3ba43c..73a806c 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -6185,6 +6185,7 @@ enum skl_disp_power_wells { > /* digital port hotplug */ > #define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */ > #define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */ > +#define BXT_DDIA_HPD_INVERT (1 << 27) > #define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */ > #define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */ > #define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */ > @@ -6200,6 +6201,7 @@ enum skl_disp_power_wells { > #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) > #define PORTD_HOTPLUG_LONG_DETECT (2 << 16) > #define PORTC_HOTPLUG_ENABLE (1 << 12) > +#define BXT_DDIC_HPD_INVERT (1 << 11) > #define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */ > #define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */ > #define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */ > @@ -6210,6 +6212,7 @@ enum skl_disp_power_wells { > #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) > #define PORTC_HOTPLUG_LONG_DETECT (2 << 8) > #define PORTB_HOTPLUG_ENABLE (1 << 4) > +#define BXT_DDIB_HPD_INVERT (1 << 3) > #define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */ > #define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */ > #define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */ > @@ -6219,6 +6222,9 @@ enum skl_disp_power_wells { > #define PORTB_HOTPLUG_NO_DETECT (0 << 0) > #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) > #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) > +#define BXT_DDI_HPD_INVERT_MASK (BXT_DDIA_HPD_INVERT | \ > + BXT_DDIB_HPD_INVERT | \ > + BXT_DDIC_HPD_INVERT) > > #define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */ > #define PORTE_HOTPLUG_ENABLE (1 << 4) > diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c > index e2f636c..e015a95 100644 > --- a/drivers/gpu/drm/i915/intel_bios.c > +++ b/drivers/gpu/drm/i915/intel_bios.c > @@ -107,6 +107,38 @@ find_section(const void *_bdb, int section_id) > return NULL; > } > > +bool > +intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, > + enum port port) > +{ > + int i; > + > + if (WARN_ON_ONCE(!IS_BROXTON(dev_priv))) > + return false; > + > + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { > + > + if (!dev_priv->vbt.child_dev[i].common.hpd_invert) > + continue; > + > + switch (dev_priv->vbt.child_dev[i].common.dvo_port) { > + case DVO_PORT_DPA: > + case DVO_PORT_HDMIA: > + return port == PORT_A; > + case DVO_PORT_DPB: > + case DVO_PORT_HDMIB: > + return port == PORT_B; > + case DVO_PORT_DPC: > + case DVO_PORT_HDMIC: > + return port == PORT_C; That doesn't actually work. Eg. if called with port==PORT_B and there's a port A listed first in the VBT with hpd_invert==true, we'll end up returning false always for PORT_B regardless of what VBT says we should return for port B. > + default: > + break; > + } > + } > + > + return false; > +} > + > static void > fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, > const struct lvds_dvo_timing *dvo_timing) > -- > 2.6.1
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9d29ab0..86fb5cb 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3396,6 +3396,8 @@ bool intel_bios_is_tv_present(struct drm_i915_private *dev_priv); bool intel_bios_is_lvds_present(struct drm_i915_private *dev_priv, u8 *i2c_pin); bool intel_bios_is_port_edp(struct drm_i915_private *dev_priv, enum port port); bool intel_bios_is_dsi_present(struct drm_i915_private *dev_priv, enum port *port); +bool intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, + enum port port); /* intel_opregion.c */ #ifdef CONFIG_ACPI diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index a55a7cc..8fbec3e 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -3504,6 +3504,26 @@ static void bxt_hpd_irq_setup(struct drm_device *dev) hotplug = I915_READ(PCH_PORT_HOTPLUG); hotplug |= PORTC_HOTPLUG_ENABLE | PORTB_HOTPLUG_ENABLE | PORTA_HOTPLUG_ENABLE; + + DRM_DEBUG_KMS("Invert bit setting: hp_ctl:%x hp_port:%x\n", + hotplug, enabled_irqs); + hotplug &= ~BXT_DDI_HPD_INVERT_MASK; + + /* + * For BXT invert bit has to be set based on AOB design + * for HPD detection logic, update it based on VBT fields. + */ + + if ((enabled_irqs & BXT_DE_PORT_HP_DDIA) && + intel_bios_is_port_hpd_inverted(dev_priv, PORT_A)) + hotplug |= BXT_DDIA_HPD_INVERT; + if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && + intel_bios_is_port_hpd_inverted(dev_priv, PORT_B)) + hotplug |= BXT_DDIB_HPD_INVERT; + if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && + intel_bios_is_port_hpd_inverted(dev_priv, PORT_C)) + hotplug |= BXT_DDIC_HPD_INVERT; + I915_WRITE(PCH_PORT_HOTPLUG, hotplug); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index f3ba43c..73a806c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6185,6 +6185,7 @@ enum skl_disp_power_wells { /* digital port hotplug */ #define PCH_PORT_HOTPLUG _MMIO(0xc4030) /* SHOTPLUG_CTL */ #define PORTA_HOTPLUG_ENABLE (1 << 28) /* LPT:LP+ & BXT */ +#define BXT_DDIA_HPD_INVERT (1 << 27) #define PORTA_HOTPLUG_STATUS_MASK (3 << 24) /* SPT+ & BXT */ #define PORTA_HOTPLUG_NO_DETECT (0 << 24) /* SPT+ & BXT */ #define PORTA_HOTPLUG_SHORT_DETECT (1 << 24) /* SPT+ & BXT */ @@ -6200,6 +6201,7 @@ enum skl_disp_power_wells { #define PORTD_HOTPLUG_SHORT_DETECT (1 << 16) #define PORTD_HOTPLUG_LONG_DETECT (2 << 16) #define PORTC_HOTPLUG_ENABLE (1 << 12) +#define BXT_DDIC_HPD_INVERT (1 << 11) #define PORTC_PULSE_DURATION_2ms (0 << 10) /* pre-LPT */ #define PORTC_PULSE_DURATION_4_5ms (1 << 10) /* pre-LPT */ #define PORTC_PULSE_DURATION_6ms (2 << 10) /* pre-LPT */ @@ -6210,6 +6212,7 @@ enum skl_disp_power_wells { #define PORTC_HOTPLUG_SHORT_DETECT (1 << 8) #define PORTC_HOTPLUG_LONG_DETECT (2 << 8) #define PORTB_HOTPLUG_ENABLE (1 << 4) +#define BXT_DDIB_HPD_INVERT (1 << 3) #define PORTB_PULSE_DURATION_2ms (0 << 2) /* pre-LPT */ #define PORTB_PULSE_DURATION_4_5ms (1 << 2) /* pre-LPT */ #define PORTB_PULSE_DURATION_6ms (2 << 2) /* pre-LPT */ @@ -6219,6 +6222,9 @@ enum skl_disp_power_wells { #define PORTB_HOTPLUG_NO_DETECT (0 << 0) #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) +#define BXT_DDI_HPD_INVERT_MASK (BXT_DDIA_HPD_INVERT | \ + BXT_DDIB_HPD_INVERT | \ + BXT_DDIC_HPD_INVERT) #define PCH_PORT_HOTPLUG2 _MMIO(0xc403C) /* SHOTPLUG_CTL2 SPT+ */ #define PORTE_HOTPLUG_ENABLE (1 << 4) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index e2f636c..e015a95 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -107,6 +107,38 @@ find_section(const void *_bdb, int section_id) return NULL; } +bool +intel_bios_is_port_hpd_inverted(struct drm_i915_private *dev_priv, + enum port port) +{ + int i; + + if (WARN_ON_ONCE(!IS_BROXTON(dev_priv))) + return false; + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + + if (!dev_priv->vbt.child_dev[i].common.hpd_invert) + continue; + + switch (dev_priv->vbt.child_dev[i].common.dvo_port) { + case DVO_PORT_DPA: + case DVO_PORT_HDMIA: + return port == PORT_A; + case DVO_PORT_DPB: + case DVO_PORT_HDMIB: + return port == PORT_B; + case DVO_PORT_DPC: + case DVO_PORT_HDMIC: + return port == PORT_C; + default: + break; + } + } + + return false; +} + static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, const struct lvds_dvo_timing *dvo_timing)