Message ID | 1457703818-22509-2-git-send-email-shubhangi.shrivastava@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Fri, 11 Mar 2016, Shubhangi Shrivastava <shubhangi.shrivastava@intel.com> wrote: > [ text/plain ] > 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) > > 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> > --- > drivers/gpu/drm/i915/i915_drv.h | 1 + > drivers/gpu/drm/i915/i915_irq.c | 21 ++++++++++++++++++++ > drivers/gpu/drm/i915/i915_reg.h | 8 ++++++++ > drivers/gpu/drm/i915/intel_bios.c | 40 +++++++++++++++++++++++++++++++++++++++ > 4 files changed, 70 insertions(+) > > diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h > index 1557d65..91963d24 100644 > --- a/drivers/gpu/drm/i915/i915_drv.h > +++ b/drivers/gpu/drm/i915/i915_drv.h > @@ -3334,6 +3334,7 @@ extern void intel_i2c_reset(struct drm_device *dev); > /* intel_bios.c */ > int intel_bios_init(struct drm_i915_private *dev_priv); > bool intel_bios_is_valid_vbt(const void *buf, size_t size); > +bool intel_bios_is_port_hpd_inverted(struct drm_device *dev, 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 53e5104..764d8f8 100644 > --- a/drivers/gpu/drm/i915/i915_irq.c > +++ b/drivers/gpu/drm/i915/i915_irq.c > @@ -36,6 +36,7 @@ > #include "i915_drv.h" > #include "i915_trace.h" > #include "intel_drv.h" > +#include "intel_bios.h" What for? I don't think you need this. > > /** > * DOC: interrupt handling > @@ -3503,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, PORT_A)) > + hotplug |= BXT_DDIA_HPD_INVERT; > + if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && > + intel_bios_is_port_hpd_inverted(dev, PORT_B)) > + hotplug |= BXT_DDIB_HPD_INVERT; > + if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && > + intel_bios_is_port_hpd_inverted(dev, 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 7dfc400..f80b870 100644 > --- a/drivers/gpu/drm/i915/i915_reg.h > +++ b/drivers/gpu/drm/i915/i915_reg.h > @@ -6213,6 +6213,14 @@ enum skl_disp_power_wells { > #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) > #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) > > +/* BXT hotplug control */ > +#define BXT_DDIA_HPD_INVERT (1 << 27) > +#define BXT_DDIC_HPD_INVERT (1 << 11) > +#define BXT_DDIB_HPD_INVERT (1 << 3) > +#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) > #define PORTE_HOTPLUG_STATUS_MASK (3 << 0) > diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c > index a26d4b4..d809700 100644 > --- a/drivers/gpu/drm/i915/intel_bios.c > +++ b/drivers/gpu/drm/i915/intel_bios.c > @@ -105,6 +105,46 @@ find_section(const void *_bdb, int section_id) > return NULL; > } > > +bool > +intel_bios_is_port_hpd_inverted(struct drm_device *dev, enum port port) You should pass in dev_priv directly, nothing here needs dev. > +{ > + struct drm_i915_private *dev_priv = dev->dev_private; > + int i; > + > + if (!IS_BROXTON(dev)) { > + DRM_ERROR("Bit inversion is not required in this platform\n"); If this happens we screwed up. If that shows up in dmesg out of context, it's pretty ambiguous. Please just do if (WARN_ON_ONCE(!IS_BROXTON(dev_priv))) return false; > + return false; > + } > + > + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { > + > + if (dev_priv->vbt.child_dev[i].common.hpd_invert == 1) { I think this reads better and reduces indent as: 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: > + if (port == PORT_A) > + return true; > + break; > + case DVO_PORT_DPB: > + case DVO_PORT_HDMIB: > + if (port == PORT_B) > + return true; > + break; > + case DVO_PORT_DPC: > + case DVO_PORT_HDMIC: > + if (port == PORT_C) > + return true; > + break; > + default: > + break; > + } > + } > + } > + > + return false; > +} > + > static void > fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, > const struct lvds_dvo_timing *dvo_timing)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1557d65..91963d24 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3334,6 +3334,7 @@ extern void intel_i2c_reset(struct drm_device *dev); /* intel_bios.c */ int intel_bios_init(struct drm_i915_private *dev_priv); bool intel_bios_is_valid_vbt(const void *buf, size_t size); +bool intel_bios_is_port_hpd_inverted(struct drm_device *dev, 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 53e5104..764d8f8 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -36,6 +36,7 @@ #include "i915_drv.h" #include "i915_trace.h" #include "intel_drv.h" +#include "intel_bios.h" /** * DOC: interrupt handling @@ -3503,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, PORT_A)) + hotplug |= BXT_DDIA_HPD_INVERT; + if ((enabled_irqs & BXT_DE_PORT_HP_DDIB) && + intel_bios_is_port_hpd_inverted(dev, PORT_B)) + hotplug |= BXT_DDIB_HPD_INVERT; + if ((enabled_irqs & BXT_DE_PORT_HP_DDIC) && + intel_bios_is_port_hpd_inverted(dev, 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 7dfc400..f80b870 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6213,6 +6213,14 @@ enum skl_disp_power_wells { #define PORTB_HOTPLUG_SHORT_DETECT (1 << 0) #define PORTB_HOTPLUG_LONG_DETECT (2 << 0) +/* BXT hotplug control */ +#define BXT_DDIA_HPD_INVERT (1 << 27) +#define BXT_DDIC_HPD_INVERT (1 << 11) +#define BXT_DDIB_HPD_INVERT (1 << 3) +#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) #define PORTE_HOTPLUG_STATUS_MASK (3 << 0) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index a26d4b4..d809700 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -105,6 +105,46 @@ find_section(const void *_bdb, int section_id) return NULL; } +bool +intel_bios_is_port_hpd_inverted(struct drm_device *dev, enum port port) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + if (!IS_BROXTON(dev)) { + DRM_ERROR("Bit inversion is not required in this platform\n"); + return false; + } + + for (i = 0; i < dev_priv->vbt.child_dev_num; i++) { + + if (dev_priv->vbt.child_dev[i].common.hpd_invert == 1) { + + switch (dev_priv->vbt.child_dev[i].common.dvo_port) { + case DVO_PORT_DPA: + case DVO_PORT_HDMIA: + if (port == PORT_A) + return true; + break; + case DVO_PORT_DPB: + case DVO_PORT_HDMIB: + if (port == PORT_B) + return true; + break; + case DVO_PORT_DPC: + case DVO_PORT_HDMIC: + if (port == PORT_C) + return true; + break; + default: + break; + } + } + } + + return false; +} + static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, const struct lvds_dvo_timing *dvo_timing)