Message ID | 1354370666-3802-3-git-send-email-przanoni@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Sat, Dec 1, 2012 at 2:04 PM, Paulo Zanoni <przanoni@gmail.com> wrote: > From: Paulo Zanoni <paulo.r.zanoni@intel.com> > > We need this code to init the PCH SSC refclk and the FDI registers. > The BIOS does this too and that's why VGA worked before this patch, > until you tried to suspend the machine... > > This patch implements the "Sequence to enable CLKOUT_DP for FDI usage > and configure PCH FDI/IO" from our documentation. > > Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > + if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00) > + is_sdv = true; Maybe have a IS_SDV() or IS_HSW_SDV() macro like we have a IS_ULT() one? The check should be on the PCH revision but hopefully there's a 1:1 correlation? > + if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) & > + FDI_MPHY_IOSFSB_RESET_STATUS, 100)) > + DRM_ERROR("FDI mPHY resert assert timeout\n"); s/resert/reset/ > + > + tmp = I915_READ(SOUTH_CHICKEN2); > + tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; > + I915_WRITE(SOUTH_CHICKEN2, tmp); > + > + if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & > + FDI_MPHY_IOSFSB_RESET_STATUS) == 0, > + 100)) > + DRM_ERROR("FDI mPHY reset de-assert timeout\n"); > + } When either of those two waits error out, we carry on the sequence. We should probably fail and disable the VGA output (one of those error paths that never get to be tested, yey! I don't know how well we support connectors disappearing)? > + tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK); > + tmp |= SBI_DBUFF0_ENABLE; > + intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK); Th ULT path is missing there. I double checked the programming, looks good. I'll follow up with an amended patch for the 2 first bikesheds, leave the error path alone, and add the ULT path as a separate patch.
Hi 2012/12/8 Damien Lespiau <damien.lespiau@intel.com>: > On Sat, Dec 1, 2012 at 2:04 PM, Paulo Zanoni <przanoni@gmail.com> wrote: >> From: Paulo Zanoni <paulo.r.zanoni@intel.com> >> >> We need this code to init the PCH SSC refclk and the FDI registers. >> The BIOS does this too and that's why VGA worked before this patch, >> until you tried to suspend the machine... >> >> This patch implements the "Sequence to enable CLKOUT_DP for FDI usage >> and configure PCH FDI/IO" from our documentation. >> >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > >> + if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00) >> + is_sdv = true; > > Maybe have a IS_SDV() or IS_HSW_SDV() macro like we have a IS_ULT() > one? The check should be on the PCH revision but hopefully there's a > 1:1 correlation? We should just remove this code in the future, maybe even now... I did not care too much about creating a macro since this is going to be killed. > >> + if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) & >> + FDI_MPHY_IOSFSB_RESET_STATUS, 100)) >> + DRM_ERROR("FDI mPHY resert assert timeout\n"); > > s/resert/reset/ > >> + >> + tmp = I915_READ(SOUTH_CHICKEN2); >> + tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; >> + I915_WRITE(SOUTH_CHICKEN2, tmp); >> + >> + if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & >> + FDI_MPHY_IOSFSB_RESET_STATUS) == 0, >> + 100)) >> + DRM_ERROR("FDI mPHY reset de-assert timeout\n"); >> + } > > When either of those two waits error out, we carry on the sequence. We > should probably fail and disable the VGA output (one of those error > paths that never get to be tested, yey! I don't know how well we > support connectors disappearing)? We have this "pattern" in many places: the doc tells us "wait for this bit or wait at least XXXms", then we wait using wait_for and print DRM_ERROR in case we timeout. In theory, even if we hit the timeout, we should be fine since we've already waited for the amount of time the spec tells us to wait... I'm not really sure what's the best thing to do here, but it really seems we're probably never hit the "fail" path. > >> + tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK); >> + tmp |= SBI_DBUFF0_ENABLE; >> + intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK); > > Th ULT path is missing there. The ULT will never reach this point, there's not VGA. > > I double checked the programming, looks good. I'll follow up with an > amended patch for the 2 first bikesheds, leave the error path alone, > and add the ULT path as a separate patch. > > -- > Damien
On Sun, Dec 09, 2012 at 07:35:13PM -0200, Paulo Zanoni wrote: > Hi > > 2012/12/8 Damien Lespiau <damien.lespiau@intel.com>: > > On Sat, Dec 1, 2012 at 2:04 PM, Paulo Zanoni <przanoni@gmail.com> wrote: > >> From: Paulo Zanoni <paulo.r.zanoni@intel.com> > >> > >> We need this code to init the PCH SSC refclk and the FDI registers. > >> The BIOS does this too and that's why VGA worked before this patch, > >> until you tried to suspend the machine... > >> > >> This patch implements the "Sequence to enable CLKOUT_DP for FDI usage > >> and configure PCH FDI/IO" from our documentation. > >> > >> Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com> > > > >> + if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00) > >> + is_sdv = true; > > > > Maybe have a IS_SDV() or IS_HSW_SDV() macro like we have a IS_ULT() > > one? The check should be on the PCH revision but hopefully there's a > > 1:1 correlation? > > We should just remove this code in the future, maybe even now... I did > not care too much about creating a macro since this is going to be > killed. Added a comment to remind us of that. > > > >> + if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) & > >> + FDI_MPHY_IOSFSB_RESET_STATUS, 100)) > >> + DRM_ERROR("FDI mPHY resert assert timeout\n"); > > > > s/resert/reset/ > > > >> + > >> + tmp = I915_READ(SOUTH_CHICKEN2); > >> + tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; > >> + I915_WRITE(SOUTH_CHICKEN2, tmp); > >> + > >> + if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & > >> + FDI_MPHY_IOSFSB_RESET_STATUS) == 0, > >> + 100)) > >> + DRM_ERROR("FDI mPHY reset de-assert timeout\n"); > >> + } > > > > When either of those two waits error out, we carry on the sequence. We > > should probably fail and disable the VGA output (one of those error > > paths that never get to be tested, yey! I don't know how well we > > support connectors disappearing)? > > We have this "pattern" in many places: the doc tells us "wait for this > bit or wait at least XXXms", then we wait using wait_for and print > DRM_ERROR in case we timeout. In theory, even if we hit the timeout, > we should be fine since we've already waited for the amount of time > the spec tells us to wait... I'm not really sure what's the best thing > to do here, but it really seems we're probably never hit the "fail" > path. Imo this is ok. If the hw is in a non-cooperative mood, there's not much we can do than detect it and hope for the best. > >> + tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK); > >> + tmp |= SBI_DBUFF0_ENABLE; > >> + intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK); > > > > Th ULT path is missing there. > > The ULT will never reach this point, there's not VGA. Added a comment. Another bikeshed: Can we have less magic here, or are the docs as opaque as the code here? I've merged it for now, but usually Dave' doesn't like this much magic in the code, so a fixup patch would be nice. Imo just giving the register some names should be good enough. Cheers, Daniel
On Mon, Dec 10, 2012 at 9:36 AM, Daniel Vetter <daniel@ffwll.ch> wrote: >> >> + tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK); >> >> + tmp |= SBI_DBUFF0_ENABLE; >> >> + intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK); >> > >> > Th ULT path is missing there. >> >> The ULT will never reach this point, there's not VGA. > > Added a comment. To go to the bottom of this, I wanted to understand why you can enable the PCH SSC. It is recommended to use the internal SSC source on ULT platforms. The PCH SSC source is then only used for clock bending. Fortunately the PLL Select bits in SPLL_CTL paper over this difference between the internal and PCH SSC sources, selecting the right one based on a fused bit. And Paulo does check if we have VGA at the start, so indeed, all is good (I believe)!
On Sun, Dec 9, 2012 at 9:35 PM, Paulo Zanoni <przanoni@gmail.com> wrote: > Hi > > 2012/12/8 Damien Lespiau <damien.lespiau@intel.com>: >> Maybe have a IS_SDV() or IS_HSW_SDV() macro like we have a IS_ULT() >> one? The check should be on the PCH revision but hopefully there's a >> 1:1 correlation? > > We should just remove this code in the future, maybe even now... I did > not care too much about creating a macro since this is going to be > killed. On the other hand, it's easy to grep for IS_SDV() rather than other more complex tests. We could even expand the macro to other platforms and have a single way to mark SDV code paths.
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index a129218..530db83 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -554,8 +554,7 @@ static int __i915_drm_thaw(struct drm_device *dev) /* KMS EnterVT equivalent */ if (drm_core_check_feature(dev, DRIVER_MODESET)) { - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) - ironlake_init_pch_refclk(dev); + intel_init_pch_refclk(dev); mutex_lock(&dev->struct_mutex); dev_priv->mm.suspended = 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8513e1c..65213bc 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1662,7 +1662,7 @@ extern void intel_modeset_setup_hw_state(struct drm_device *dev, extern bool intel_fbc_enabled(struct drm_device *dev); extern void intel_disable_fbc(struct drm_device *dev); extern bool ironlake_set_drps(struct drm_device *dev, u8 val); -extern void ironlake_init_pch_refclk(struct drm_device *dev); +extern void intel_init_pch_refclk(struct drm_device *dev); extern void gen6_set_rps(struct drm_device *dev, u8 val); extern void intel_detect_pch(struct drm_device *dev); extern int intel_trans_dp_port_sel(struct drm_crtc *crtc); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0760425..acf768d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3843,7 +3843,9 @@ #define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define FDI_BC_BIFURCATION_SELECT (1 << 12) #define SOUTH_CHICKEN2 0xc2004 -#define DPLS_EDP_PPS_FIX_DIS (1<<0) +#define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) +#define FDI_MPHY_IOSFSB_RESET_CTL (1<<12) +#define DPLS_EDP_PPS_FIX_DIS (1<<0) #define _FDI_RXA_CHICKEN 0xc200c #define _FDI_RXB_CHICKEN 0xc2010 @@ -4555,10 +4557,12 @@ #define SBI_SSCDIVINTPHASE_PROPAGATE (1<<0) #define SBI_SSCCTL 0x020c #define SBI_SSCCTL6 0x060C +#define SBI_SSCCTL_PATHALT (1<<3) #define SBI_SSCCTL_DISABLE (1<<0) #define SBI_SSCAUXDIV6 0x0610 #define SBI_SSCAUXDIV_FINALDIV2SEL(x) ((x)<<4) #define SBI_DBUFF0 0x2a00 +#define SBI_DBUFF0_ENABLE (1<<0) /* LPT PIXCLK_GATE */ #define PIXCLK_GATE 0xC6020 diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1f1c7a6..e87f4cc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4864,10 +4864,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, return ret; } -/* - * Initialize reference clocks when the driver loads - */ -void ironlake_init_pch_refclk(struct drm_device *dev) +static void ironlake_init_pch_refclk(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_mode_config *mode_config = &dev->mode_config; @@ -4981,6 +4978,180 @@ void ironlake_init_pch_refclk(struct drm_device *dev) } } +/* Sequence to enable CLKOUT_DP for FDI usage and configure PCH FDI I/O. */ +static void lpt_init_pch_refclk(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct drm_mode_config *mode_config = &dev->mode_config; + struct intel_encoder *encoder; + bool has_vga = false; + bool is_sdv = false; + u32 tmp; + + list_for_each_entry(encoder, &mode_config->encoder_list, base.head) { + switch (encoder->type) { + case INTEL_OUTPUT_ANALOG: + has_vga = true; + break; + } + } + + if (!has_vga) + return; + + if (IS_HASWELL(dev) && (dev->pci_device & 0xFF00) == 0x0C00) + is_sdv = true; + + tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp &= ~SBI_SSCCTL_DISABLE; + tmp |= SBI_SSCCTL_PATHALT; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + + udelay(24); + + tmp = intel_sbi_read(dev_priv, SBI_SSCCTL, SBI_ICLK); + tmp &= ~SBI_SSCCTL_PATHALT; + intel_sbi_write(dev_priv, SBI_SSCCTL, tmp, SBI_ICLK); + + if (!is_sdv) { + tmp = I915_READ(SOUTH_CHICKEN2); + tmp |= FDI_MPHY_IOSFSB_RESET_CTL; + I915_WRITE(SOUTH_CHICKEN2, tmp); + + if (wait_for_atomic_us(I915_READ(SOUTH_CHICKEN2) & + FDI_MPHY_IOSFSB_RESET_STATUS, 100)) + DRM_ERROR("FDI mPHY resert assert timeout\n"); + + tmp = I915_READ(SOUTH_CHICKEN2); + tmp &= ~FDI_MPHY_IOSFSB_RESET_CTL; + I915_WRITE(SOUTH_CHICKEN2, tmp); + + if (wait_for_atomic_us((I915_READ(SOUTH_CHICKEN2) & + FDI_MPHY_IOSFSB_RESET_STATUS) == 0, + 100)) + DRM_ERROR("FDI mPHY reset de-assert timeout\n"); + } + + tmp = intel_sbi_read(dev_priv, 0x8008, SBI_MPHY); + tmp &= ~(0xFF << 24); + tmp |= (0x12 << 24); + intel_sbi_write(dev_priv, 0x8008, tmp, SBI_MPHY); + + if (!is_sdv) { + tmp = intel_sbi_read(dev_priv, 0x808C, SBI_MPHY); + tmp &= ~(0x3 << 6); + tmp |= (1 << 6) | (1 << 0); + intel_sbi_write(dev_priv, 0x808C, tmp, SBI_MPHY); + } + + if (is_sdv) { + tmp = intel_sbi_read(dev_priv, 0x800C, SBI_MPHY); + tmp |= 0x7FFF; + intel_sbi_write(dev_priv, 0x800C, tmp, SBI_MPHY); + } + + tmp = intel_sbi_read(dev_priv, 0x2008, SBI_MPHY); + tmp |= (1 << 11); + intel_sbi_write(dev_priv, 0x2008, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2108, SBI_MPHY); + tmp |= (1 << 11); + intel_sbi_write(dev_priv, 0x2108, tmp, SBI_MPHY); + + if (is_sdv) { + tmp = intel_sbi_read(dev_priv, 0x2038, SBI_MPHY); + tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16); + intel_sbi_write(dev_priv, 0x2038, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2138, SBI_MPHY); + tmp |= (0x3F << 24) | (0xF << 20) | (0xF << 16); + intel_sbi_write(dev_priv, 0x2138, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x203C, SBI_MPHY); + tmp |= (0x3F << 8); + intel_sbi_write(dev_priv, 0x203C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x213C, SBI_MPHY); + tmp |= (0x3F << 8); + intel_sbi_write(dev_priv, 0x213C, tmp, SBI_MPHY); + } + + tmp = intel_sbi_read(dev_priv, 0x206C, SBI_MPHY); + tmp |= (1 << 24) | (1 << 21) | (1 << 18); + intel_sbi_write(dev_priv, 0x206C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x216C, SBI_MPHY); + tmp |= (1 << 24) | (1 << 21) | (1 << 18); + intel_sbi_write(dev_priv, 0x216C, tmp, SBI_MPHY); + + if (!is_sdv) { + tmp = intel_sbi_read(dev_priv, 0x2080, SBI_MPHY); + tmp &= ~(7 << 13); + tmp |= (5 << 13); + intel_sbi_write(dev_priv, 0x2080, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2180, SBI_MPHY); + tmp &= ~(7 << 13); + tmp |= (5 << 13); + intel_sbi_write(dev_priv, 0x2180, tmp, SBI_MPHY); + } + + tmp = intel_sbi_read(dev_priv, 0x208C, SBI_MPHY); + tmp &= ~0xFF; + tmp |= 0x1C; + intel_sbi_write(dev_priv, 0x208C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x218C, SBI_MPHY); + tmp &= ~0xFF; + tmp |= 0x1C; + intel_sbi_write(dev_priv, 0x218C, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2098, SBI_MPHY); + tmp &= ~(0xFF << 16); + tmp |= (0x1C << 16); + intel_sbi_write(dev_priv, 0x2098, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x2198, SBI_MPHY); + tmp &= ~(0xFF << 16); + tmp |= (0x1C << 16); + intel_sbi_write(dev_priv, 0x2198, tmp, SBI_MPHY); + + if (!is_sdv) { + tmp = intel_sbi_read(dev_priv, 0x20C4, SBI_MPHY); + tmp |= (1 << 27); + intel_sbi_write(dev_priv, 0x20C4, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x21C4, SBI_MPHY); + tmp |= (1 << 27); + intel_sbi_write(dev_priv, 0x21C4, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x20EC, SBI_MPHY); + tmp &= ~(0xF << 28); + tmp |= (4 << 28); + intel_sbi_write(dev_priv, 0x20EC, tmp, SBI_MPHY); + + tmp = intel_sbi_read(dev_priv, 0x21EC, SBI_MPHY); + tmp &= ~(0xF << 28); + tmp |= (4 << 28); + intel_sbi_write(dev_priv, 0x21EC, tmp, SBI_MPHY); + } + + tmp = intel_sbi_read(dev_priv, SBI_DBUFF0, SBI_ICLK); + tmp |= SBI_DBUFF0_ENABLE; + intel_sbi_write(dev_priv, SBI_DBUFF0, tmp, SBI_ICLK); +} + +/* + * Initialize reference clocks when the driver loads + */ +void intel_init_pch_refclk(struct drm_device *dev) +{ + if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) + ironlake_init_pch_refclk(dev); + else if (HAS_PCH_LPT(dev)) + lpt_init_pch_refclk(dev); +} + static int ironlake_get_refclk(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -8385,8 +8556,7 @@ static void intel_setup_outputs(struct drm_device *dev) intel_encoder_clones(encoder); } - if (HAS_PCH_IBX(dev) || HAS_PCH_CPT(dev)) - ironlake_init_pch_refclk(dev); + intel_init_pch_refclk(dev); drm_helper_move_panel_connectors_to_head(dev); }